# 反馈与自评估架构 **更新日期**:2026-07-17 **状态**:当前可运行架构 **参考历史文档**:`archive/2026-07-05-legacy/confidence-feedback.md` ## 1. 定位 反馈架构包含两条闭环: 1. 系统自评估:基于当前 run 的工具调用、Gatekeeper、Verifier、Composer、AIOps 规则检查,写入 `diagnosis_run.self_evaluation`。 2. 用户反馈:用户标记 `useful` 或 `not_useful`,优先写入 `diagnosis_run.feedback`,其中 `useful` 会沉淀案例。 当前重要边界: - `status` 表示执行状态,不表示答案质量。 - `feedback` 表示用户反馈,不覆盖 `status`。 - `self_evaluation` 是 JSON 容器,内部按来源分层,不再把所有评分字段平铺在根节点。 ## 2. 总体闭环 ```mermaid flowchart TD Answer["Chat / AIOps final answer"] --> Run["diagnosis_run.answer"] subgraph SelfEval["Self evaluation"] Invocation["tool_invocation"] --> RuleEval["EvaluationService: rule_evaluation"] Invocation --> EvidenceRefs["evidence_refs"] EvidenceRefs --> Gatekeeper["ExecutorGatekeeperService"] Gatekeeper --> Projection["VerifiedInputNode"] Projection --> Verifier["chat_verifier"] Verifier --> VerifierEval["verifier_evaluation"] Verifier --> Composer["chat_composer"] Composer --> VerifierEval Invocation --> AiOpsRule["AiOpsRuleEvaluationService"] AiOpsRule --> AiOpsEval["aiops_rule_evaluation"] end RuleEval --> Merge["SelfEvaluationMergeService"] VerifierEval --> Merge AiOpsEval --> Merge Merge --> SelfJson["diagnosis_run.self_evaluation"] subgraph UserFeedback["User feedback"] UI["Feedback bar"] --> API["POST /api/feedback"] API --> FeedbackService["FeedbackService"] FeedbackService --> FeedbackField["diagnosis_run.feedback"] FeedbackService --> Useful{"feedback == useful?"} Useful -->|yes| CaseService["CaseLibraryService.createFromRun"] CaseService --> Case["case_library"] Useful -->|no| BadCase["Bad case by feedback=not_useful"] end Run --> UI ``` ## 3. self_evaluation JSON `SelfEvaluationMergeService` 统一维护当前运行的 `diagnosis_run.self_evaluation`。历史兼容数据可能仍存在于 `diagnosis_session.self_evaluation`,但新 Chat/AIOps 执行不再写旧表。 当前结构: ```json { "rule_evaluation": { "evidence_score": 65, "source": "rule", "factors": [] }, "verifier_evaluation": { "verdict": "PASS", "groundedness_score": 0.8, "critical_fact_count": 2, "claim_checks": [], "facts_checked": [], "rationale": "...", "round": 1, "traceability_version": "v1", "executor_output_parse_status": {}, "executor_structured_output": {}, "gatekeeper_result": {}, "composer_output": {}, "verified_evidence": [] }, "aiops_rule_evaluation": { "verdict": "...", "checks": [] } } ``` 兼容逻辑: - 如果旧 JSON 根节点包含 `evidence_score`,会被包进 `rule_evaluation`。 - 如果旧 JSON 根节点包含 `verdict` / `groundedness_score`,会被包进 `verifier_evaluation`。 ## 4. 规则评分 `EvaluationService` 只消费 `tool_invocation` 和 session 状态,输出 `rule_evaluation`。 定位: - 衡量证据收集充分度。 - 不直接证明答案是否推理正确。 - 不依赖 LLM。 规则: | 规则名 | 条件 | 分数变化 | |---|---|---| | `execution_failed` | session status = `FAILED` | 直接 0 | | `no_tool_call` | 没有工具调用 | 直接 0 | | `has_successful_tool_call` | 至少一次工具成功 | +30 | | `l0_exact_match` | 任意工具调用有 L0 命中 | +35 | | `l1_semantic_match` | 无 L0 命中但有 L1 命中 | +20 | | `retrieval_no_hit` | 有检索调用但无命中 | -10 | | `all_tool_calls_failed` | 工具全部失败 | -20 | 最终分数裁剪到 `[0, 100]`。 说明: - 当前 `rule_evaluation` 是异步写入,失败时 `self_evaluation` 可能暂时为空或缺少该节点。 - L0/L1 分支互斥:有 L0 命中时优先记 L0。 - 更强的答案真实性校验由 Chat Verifier 承担。 ## 5. Chat Verifier 自评估 Chat 自评估分三步: 1. Gatekeeper 用代码校验 Executor 的引用是否真实。 2. Verifier 判断已验真的 `evidence_excerpt` 是否能推出 `claim_text`。 3. Composer 只把 Verifier 允许表达的内容写成最终用户答复。 ```mermaid flowchart LR ExecutorOutput["executor_evidence_v2"] --> Gatekeeper["ExecutorGatekeeperService"] Invocation["tool_invocation"] --> EvidenceRefs["retrieval_details.evidence_refs"] EvidenceRefs --> Gatekeeper Gatekeeper --> GateResult["gatekeeper_result"] GateResult --> Projection["VerifiedInputNode"] ExecutorOutput --> Projection Projection --> VerifiedOutput["verified_executor_output + verified_evidence"] VerifiedOutput --> Verifier["chat_verifier"] Verifier --> Output["verifier_output JSON"] Output --> Composer["chat_composer"] Composer --> ComposerOutput["composer_output"] Output --> Merge["SelfEvaluationMergeService.mergeVerifierEvaluation"] ComposerOutput --> Merge Merge --> Run["diagnosis_run.self_evaluation.verifier_evaluation"] ``` Verifier 输出: | 字段 | 说明 | |---|---| | `verdict` | `PASS` / `LOW_CONFID` / `REJECT` | | `groundedness_score` | 关键事实证据支撑度 | | `critical_fact_count` | 关键事实数量 | | `claim_checks` | 对 Executor 结构化 claims 的逐条可推导性判断 | | `facts_checked` | 逐条事实校验 | | `rationale` | 判定原因 | | `executor_structured_output` | Executor 输出的结构化 claims 与证据绑定 | | `verified_evidence` | Gatekeeper 通过并投影给 Verifier 的最小 matched evidence | | `gatekeeper_result` | 引用真实性校验结果 | | `composer_output` | 最终表达的解析状态和摘要 | ChatService 根据 verdict 决定: - `PASS`:把允许表达的 claims 交给 Composer 输出。 - `LOW_CONFID`:必要时构造 `retry_context` 补证据;否则输出低置信提示。 - `REJECT`:降级输出,只保留已确认信息。 边界: - `executor_final_answer` 只作为 debug/fallback 上下文;结构化输出有效时,Verifier 不得从中抽取额外确认事实。 - `$.no_evidence` 只能表达“当前查询未检索到匹配证据”,不能表达“已排除/确认没有”。 - `run.orchestrationTrace` 是独立的 StateGraph 路由摘要,不属于 `self_evaluation`;历史 `tool_trace_summary` 仅用于旧 Run/fixture 只读兼容,不是当前 Verifier 输入。 ## 6. AIOps 规则自评估 AIOps 当前使用 `AiOpsRuleEvaluationService`,结果写入 `aiops_rule_evaluation`。 检查重点: - 是否有最终报告。 - payload 模式是否聚焦输入告警。 - 是否调用 `lookup_knowledge`、日志、指标等证据工具。 - 是否把无关活跃告警扩展成主诊断对象。 这是轻量规则检查,不等价于完整 LLM Verifier。完整 AIOps Verifier 是后续增强项。 ## 7. 用户反馈 API ```text POST /api/feedback Content-Type: application/json { "runId": "run-xxx", "sessionId": "xxx", "feedback": "useful" | "not_useful" } ``` 响应: ```json { "success": true, "message": "反馈已记录", "runId": "run-xxx", "fallbackToLatestRun": false, "caseId": "uuid 或 null" } ``` 后端行为: | feedback | 行为 | |---|---| | `useful` | 写入 `DiagnosisRun.feedback`,调用 `CaseLibraryService.createFromRun` | | `not_useful` | 写入 `DiagnosisRun.feedback`,不改变 run status | | 其他值 | 返回 HTTP 400 | 兼容行为: - 请求带 `runId` 时,后端验证 `runId` 属于 `sessionId`。 - 请求缺少 `runId` 且存在 run-backed 数据时,后端绑定 latest run,并返回 `fallbackToLatestRun=true` 和实际 `runId`。 - 仅当没有 `diagnosis_run` 但存在历史 `diagnosis_session` 时,才使用历史 fallback;该路径不声明 latest-run fallback。 ## 8. 案例沉淀 `useful` 反馈会生成或复用 `case_library` 记录。 字段映射: | CaseLibrary 字段 | 来源 | |---|---| | `caseId` | UUID | | `diagnosisId` | 新数据为 `DiagnosisRun.runId`;历史数据可能为 `DiagnosisSession.sessionId` | | `sourceType` | `AUTO` | | `faultCategory` | 当前固定为 `GENERAL` | | `title` | `query` 前 100 字符 | | `rootCause` | `answer` | | `solution` | `answer` | | `createdBy` | `system` | 幂等性: ```text case_library.diagnosisId == runId -> existing case: return existing -> missing case: create new ``` ## 9. Trace 呈现 Trace API 会展示: - `feedback` - `hasFeedback` - `hasVerifierEvaluation` - `hasAiOpsRuleEvaluation` - session、step、tool invocation 明细 这让一次诊断可以被分成三种视角查看: | 视角 | 数据来源 | |---|---| | 执行是否成功 | `diagnosis_run.status` | | 证据是否充分 | `self_evaluation.rule_evaluation` / `verifier_evaluation` | | 用户是否认可 | `diagnosis_run.feedback` | ## 10. 后续增强 近期优先: 1. 将 `rule_evaluation` 与 `verifier_evaluation` 在 Trace API 中结构化展示。 2. 将 ISS-008 / ISS-009 这类 E2E 通过样例固化进 diagnosis eval fixtures。 3. `not_useful` 反馈沉淀 bad case,而不是只写字段。 4. useful 案例自动提取 faultCategory、errorCode、service、rootCause、solution。 5. AIOps 引入 LLM Verifier。 6. 把反馈和 eval baseline 打通,形成可回归的质量改进闭环。 暂不优先: - 用用户反馈直接修改 session status。 - 仅凭 `evidence_score` 判断答案正确。 - 在没有人工审核时自动把 bad case 反向写入 Prompt。