feat: archive mvp demo trace acceptance

This commit is contained in:
zhuyongxin
2026-07-03 16:25:00 +08:00
parent 5b827fe90e
commit 6919092b83
24 changed files with 1343 additions and 2 deletions
+268
View File
@@ -0,0 +1,268 @@
# MVP Agent 工程决策记录
本文记录 MVP 实现过程中已经落地的一些关键修复、取舍和工程判断。目标不是写流水账,而是沉淀面试时可以讲清楚的 Agent 工程思路。
---
## 1. 统一流式与非流式 Chat 主链路
### 背景
早期 `/api/chat` 和 `/api/chat_stream` 是两条不同实现:
- 非流式接口会走复杂度判断,并可能进入 Planner / Executor / Verifier 多 Agent 流程。
- 流式接口直接创建单个 ReactAgent,然后 `agent.stream()` 输出 token。
这导致两个接口表面都是 chat,实际能力不一致:流式接口不会进入 verifier、不会沉淀完整诊断链路,也不容易和 `diagnosis_session`、`tool_invocation` 对齐。
### 决策
将两个接口统一到同一条核心链路:
```text
getOrCreateSession
-> 读取会话历史
-> ChatService.executeChatWithStrategy(...)
-> 写回会话历史
```
接口差异只保留在传输层:
- `/api/chat` 返回完整 JSON。
- `/api/chat_stream` 通过 SSE 分块发送最终答案。
### 取舍
这样会牺牲原来的 token 级实时流式体验,但换来业务行为一致、诊断链路一致、Verifier 和 evidence trace 一致。
对 MVP 来说,优先保证“同一个问题不因接口不同而进入不同智能链路”,比 token 级流式更重要。
---
## 2. 会话 ID 与诊断链路统一
### 背景
原实现中:
- `ChatController` 用前端传入的 `Id` 在 JVM 内存里维护历史消息。
- `ChatService` 每次执行又生成新的 8 位 sessionId,作为 `diagnosis_session` 和工具调用追踪 ID。
这会造成前端会话、后端诊断会话、工具证据链三者分裂。
### 决策
将前端 chat session id 作为后端诊断链路的主 session id:
- Redis `SessionContext` 保存聊天历史。
- `diagnosis_session.session_id` 复用同一个 id。
- `RunnableConfig.metadata.sessionId` 和 `SessionContextHolder` 也使用同一个 id。
- `tool_invocation`、`agent_step`、verifier evaluation 都可按同一 session id 串起来。
### 企业级意义
Agent 系统最怕“答得出来但查不清”。统一 session id 后,一次用户请求可以完整追踪:
```text
用户问题 -> Agent 步骤 -> 工具调用 -> Verifier 判断 -> 最终答案 -> 用户反馈
```
这是可观测、可审计、可复盘的基础。
---
## 3. 引入统一 ToolInvocationRecorder
### 背景
Verifier 需要结构化证据链,但原实现只有 `lookup_knowledge` 主动写入 `tool_invocation`。
`query_logs`、`query_metrics` 虽然返回 JSON,但没有统一落库,导致 verifier 看不到日志、指标等 evidence tool 的稳定记录。
### 决策
新增 `ToolInvocationRecorder`,作为所有 evidence tool 的统一落库入口。
当前接入:
- `lookup_knowledge`
- `query_logs`
- `query_metrics`
记录字段包括:
- tool name
- input params
- output preview
- output length
- success
- error message
- duration
- trace id / domain details
### 企业级意义
这一步把 Agent 从“模型说它查过”推进到“系统能证明它查过”。
后续 verifier 不应该依赖模型自由文本回忆工具调用,而应该消费结构化 trace summary。
---
## 4. Verifier 作为事实约束层
### 背景
普通 Agent 很容易在工具调用后直接生成答案,但企业场景更关心:
- 关键结论有没有证据
- 证据是直接证据还是间接支持
- 哪些事实缺口需要人工介入
- 工具失败时是否诚实降级
### 决策
保留 Planner / Executor / Verifier 三角色:
- Planner 负责拆解问题。
- Executor 负责执行查询与形成初稿。
- Verifier 负责基于 `tool_trace_summary` 做事实核查。
Verifier 输出结构化 JSON,包括:
- verdict
- groundedness_score
- critical_fact_count
- facts_checked
- rationale
### 取舍
Verifier 会增加一次模型调用成本,但换来可解释性和质量约束。对企业级 Agent 来说,这是值得的。
---
## 5. 从手写编排切换到 SupervisorAgent
### 背景
之前 `ChatService.executeChatComplex()` 中构建了 `SupervisorAgent`,但实际仍然手写调用:
```text
planner -> executor -> verifier
```
这会造成代码与设计不一致,维护者容易误以为当前已经由 Supervisor 调度。
### 决策
复杂问题真正切换到 `SupervisorAgent.invoke(...)`。
Supervisor 负责路由:
```text
chat_supervisor -> chat_planner
chat_supervisor -> chat_executor
chat_supervisor -> chat_verifier
chat_supervisor -> FINISH
```
外层仍保留:
- verifier 输出解析
- PASS / LOW_CONFID / REJECT 判定
- retry context
- fallback
- evaluation 入库
### 验证
新增离线专项测试 `ChatServiceSupervisorAgentTest`,使用 scripted `ChatModel` 验证真实 SupervisorAgent 路由顺序,不依赖真实 LLM、MySQL、Redis。
### 企业级意义
这让项目不只是“自己写 if/else 多 Agent”,而是使用框架原生 multi-agent orchestration,同时保留业务层的质量门控。
---
## 6. 文档上传路径语义统一
### 背景
上传文档时,`DocumentManagementService.saveToLocal()` 返回带 `knowledge_base` 前缀的路径。
而 `KnowledgeIndexService.readDocument()` 又执行:
```java
Paths.get(knowledgeBasePath, filePath)
```
这可能拼出:
```text
knowledge_base/knowledge_base/...
```
最终表现为 L0 命中文档,但读取原文失败。
### 决策
统一路径语义:
- 新上传文档存相对 `knowledge.base-path` 的路径,例如 `payment/runbook.md`。
- `readDocument()` 兼容新旧路径:
- 相对路径
- 已带 base path 的旧相对路径
- 绝对路径
### 企业级意义
知识库检索不能只看“命中”,还要保证命中后的内容可读、可引用、可追踪。
这是 RAG / Agent 系统里很典型的工程细节:检索质量问题不一定来自模型,也可能来自路径、元数据、索引和原文之间的语义不一致。
---
## 7. MVP 阶段的优先级取舍
当前主动暂缓的问题:
- 敏感配置外置与密钥轮换
- CORS / Redis 反序列化安全边界
- 默认 `mvn test` 离线化
原因不是这些不重要,而是当前目标是先跑通并讲清楚 MVP Agent 工程闭环。
短期优先目标:
```text
可演示 -> 可观测 -> 可验证 -> 可复盘
```
安全和完整测试体系属于企业落地必须项,但可以在 MVP 主链路稳定后作为下一阶段补齐。
---
## 8. 后续建议
下一阶段建议聚焦“可复现 MVP Demo”:
1. 增加 `local-demo` 或 `mvp-demo` profile。
2. 准备固定诊断 case,例如“支付接口超时”。
3. 提供一键初始化知识库样例。
4. 提供一键触发复杂诊断请求的脚本。
5. 增加 trace 查询接口:
```text
GET /api/diagnosis/{sessionId}/trace
```
该接口聚合:
- diagnosis_session
- agent_step
- tool_invocation
- verifier evaluation
- final answer
- feedback
这样 MVP 就能从“功能实现”升级为“企业级 Agent 工程作品”。