refactor(harness): remove legacy agent architecture

This commit is contained in:
zhuyongxin
2026-07-22 18:02:01 +08:00
parent bc36248cd8
commit 8ee7cc0b70
148 changed files with 3091 additions and 13889 deletions
@@ -0,0 +1,291 @@
# 反馈与自评估架构
**更新日期**:2026-07-10
**状态**:当前可运行架构
**参考历史文档**:`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"]
Invocation --> TraceSummary["ToolTraceSummaryService"]
Gatekeeper --> Verifier["chat_verifier"]
TraceSummary --> 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": {},
"tool_trace_summary": []
},
"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"] --> Summary["ToolTraceSummaryService"]
Invocation --> EvidenceRefs["retrieval_details.evidence_refs"]
EvidenceRefs --> Gatekeeper
Gatekeeper --> GateResult["gatekeeper_result"]
Summary --> Evidence["tool_trace_summary"]
GateResult --> Verifier["chat_verifier"]
ExecutorOutput --> Verifier
Evidence --> 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 与证据绑定 |
| `gatekeeper_result` | 引用真实性校验结果 |
| `composer_output` | 最终表达的解析状态和摘要 |
| `tool_trace_summary` | 本次校验使用的工具调用导航索引 |
ChatService 根据 verdict 决定:
- `PASS`:把允许表达的 claims 交给 Composer 输出。
- `LOW_CONFID`:必要时构造 `retry_context` 补证据;否则输出低置信提示。
- `REJECT`:降级输出,只保留已确认信息。
边界:
- `executor_final_answer` 只作为 debug/fallback 上下文;结构化输出有效时,Verifier 不得从中抽取额外确认事实。
- `$.no_evidence` 只能表达“当前查询未检索到匹配证据”,不能表达“已排除/确认没有”。
## 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。