Files
SuperBizAgent-java/devflow/projects/2026-06-29-confidence-feedback/decisions.md
T

5.9 KiB
Raw Blame History

decisions.md — confidence-feedback

Question Pool(grill 阶段)

# 问题 模式 状态
Q1 置信度由谁计算 user-interview 已确认
Q2 反馈触发哪些后端操作 user-interview 已确认
Q3 CaseLibrary 结构化字段从哪里填 evidence-driven 已确认(方案变更)
Q4 验收口径 user-interview 已确认

Evidence-Driven 结论

Q3:CaseLibrary 内容来源

初始结论:从 agent_step.thought 提取(grill 阶段)

修正(apply 阶段讨论后):

  • 代码证据:agent_step.thought 截断为 2000 字符,modelOutput 截断为 500 字符,均不是完整答案
  • ChatService.executeChat 第 269 行已有完整答案 answer = response.getText(),但未持久化
  • 决策:给 DiagnosisSession 加 answer TEXT 字段,Flyway V008 迁移,案例内容直接从 session.answer 取

User-Interview 确认记录

Q1 — 置信度由谁评估

  • 用户原话(grill):"两者都要:规则兜底 + Verifier 主打分"
  • apply 后修正:讨论后决定去掉 LLM 自评,仅用规则引擎(见"apply 阶段决策")
  • 最终实现:EvaluationService 纯规则,预留 llm_opinion 扩展位

Q2 — 反馈触发操作

  • 用户原话:"写入 DiagnosisSession.feedback 字段, not_useful → 打 BAD_CASE 标记"
  • apply 后修正:BAD_CASE 不改 status,feedback 字段本身即为标记(见"apply 阶段决策")
  • 最终实现:FeedbackService 只写 feedback + 可选写 case_library,不改 status

Q4 — 验收口径

  • 用户原话:"端到端可验证:发一次 chat → 查 DB 看 selfEvaluation 有值 → 提交 feedback → 查 DB 看 feedback + case_library"
  • 确认状态:已确认,未变化

Apply 阶段决策(post-grill 重要变更)

决策 A:DiagnosisSession 加 answer 字段

  • 问题:案例沉淀需要完整答案,agent_step.thought 被截断,不可用
  • 决策:新增 answer LONGTEXT 字段,ChatService SUCCESS 分支写入
  • 影响:V008 Flyway 迁移,CaseLibraryService 直接读 session.answer

决策 B:去掉 LLM 自评,只用规则引擎

  • 问题:LLM 评估自己的答案系统性偏高分;多一次调用消耗 token;Verifier Agent 当前未实现
  • 决策:MVP 阶段仅用基于 tool_invocation 的规则引擎
  • 理由:规则可解释、可复现、不撒谎;Verifier 留待诊断全链路实现时再做
  • 预留:selfEvaluation JSON 结构保留 llm_opinion 扩展位,代码底部注释说明接入点

决策 C:BAD_CASE 不改 status 字段

  • 问题:status 是执行状态语义(RUNNING/SUCCESS/FAILED),BAD_CASE 是质量标签,两个维度不同;覆盖 status 会破坏统计
  • 决策:not_useful 通过 feedback 字段本身标识,查 BadCase 用 WHERE feedback = 'not_useful'

决策 D:评分字段重命名为 evidence_score

  • 问题:原名 confidence 容易误解为"答案准确性",实际衡量的是"证据收集充分度"
  • 决策:重命名为 evidence_score,明确语义边界
  • 边界说明:工具调用能证明 Agent 有尝试收集证据,但无法证明答案无幻觉;这个分数过滤最差情况(无工具调用就给答案),不能识别"调用了工具但结论仍错误"

决策 E:规则输入来源仅限 tool_invocation 事实

  • 问题:DateTimeTools、QueryMetricsTools 等非检索工具调用未写入 tool_invocation
  • 接受:evidence_score 定义本来就是检索证据充分度,非检索工具排除在外是合理的,不是 bug
  • 已知限制:调用了时间工具但 evidence_score = 0 的 session 存在

架构审计记录

  • 接口影响:POST /api/feedback 是新接口(L2);ChatService 主流程返回值不变(L1)
  • 时序验证:tool_invocation 在工具执行时同步写入,evaluate @Async 在 Agent 完成后触发,无竞态问题
  • 已接受风险:
    • @Async 失败时 selfEvaluation 保持 null,前端需处理 null
    • 案例结构化字段(faultCategory 等)暂时填 GENERAL,后续可人工补充
    • LLM 自评预留但未实现,Phase 2 再迭代

决策 F:ChatResult record + ChatResponse.sessionId 回传

  • 问题:ChatService 内部生成 8 位 sessionId,但从不返回给前端;前端用自己的 sessionId 调 feedback 接口,后端查不到 session(400)
  • 决策:新增 ChatResult(answer, sessionId) record,executeChatWithStrategy 链路全部返回 ChatResult;ChatResponse 增加 sessionId 字段;前端读取并闭包绑定至对应消息的反馈按钮
  • 影响:ChatService 三个方法签名变更(内部链路),ChatController 调用方更新,前端 app.js 读取新字段

决策 G:反馈 sessionId 闭包绑定而非全局变量

  • 问题:最初实现用 this.lastSessionId 全局变量,多轮对话时点击早期消息的反馈按钮会提交最新 sessionId
  • 决策:createFeedbackBar(sessionId) 接收 sessionId 参数,submitFeedback(feedback, bar, sessionId) 直接用传入值,不读全局状态
  • 效果:每条 AI 回复绑定自己那轮的 sessionId,多轮对话下行为正确

项目技术栈清单

  • ChatModel 注入:@Autowired ChatModel chatModel,通过 ModelRoutingConfig 路由
  • Repository:Spring Data JPA,Optional<T> 返回,方法命名约定
  • DTO:独立文件放 dto/ 包
  • 异步:新建 AsyncConfig.java 加 @EnableAsync(项目原无此配置)
  • 无 MQ,无加密,工具类直接用 UUID.randomUUID()
  • 日志:SLF4J Logger,LoggerFactory.getLogger()
  • ToolInvocationRepository.findBySessionId 已有,可直接用

参考实现文件

  • ChatService.java:executeChat/executeChatComplex 流程
  • CaseLibraryRepository.findByDiagnosisId:幂等检查用
  • DiagnosisSessionRepository.findBySessionId
  • ToolInvocationRepository.findBySessionId