docs(mvp): organize mvp documentation
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# ISS-001 Executor 重复召回同一文档
|
||||
|
||||
**状态**:已修复(2026-06-30)
|
||||
**严重程度**:中(影响 token 消耗和上下文质量,不影响功能正确性)
|
||||
**发现时间**:2026-06-30
|
||||
**修复版本**:session-dedup-knowledge-map
|
||||
**历史架构文档**:[会话级去重与知识域地图](../../architecture/archive/2026-07-05-legacy/session-dedup-knowledge-map.md)
|
||||
|
||||
---
|
||||
|
||||
## 现象
|
||||
|
||||
单次对话中 `lookup_knowledge` 被调用 20 次,其中"故障诊断流程规范"被重复召回约 13 次,多个文档被重复召回 3-6 次。
|
||||
|
||||
```
|
||||
tool_invocation 记录(db8bfa0f):
|
||||
L0 命中"故障诊断流程规范" × 13
|
||||
L0+L1 命中"MySQL 数据库连接池配置" × 5
|
||||
L1 命中性能类故障 × 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 根本原因
|
||||
|
||||
**两个层面同时缺失去重机制:**
|
||||
|
||||
1. **工具层无去重**:`LookupKnowledgeTool` 每次独立检索,不感知调用历史,同一查询关键词必然返回同一文档
|
||||
2. **Agent 层无记忆**:Executor Prompt 未要求跟踪已使用文档,LLM 每步倾向于"再确认一下",反复触发相同检索
|
||||
|
||||
**调用链路:**
|
||||
|
||||
```
|
||||
Planner step 0:制定排查计划
|
||||
Executor step 0:检索知识库 → 命中故障诊断流程规范
|
||||
Executor step 1:继续检索 → 又命中故障诊断流程规范(不知道已取过)
|
||||
Executor step 3:继续检索 → 又命中故障诊断流程规范
|
||||
... (重复 13 次)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 影响
|
||||
|
||||
- **Token 浪费**:同一文档内容反复塞入上下文,多 Agent 场景尤为明显
|
||||
- **上下文窗口压缩**:重复内容占用有效 token 空间,可能导致有用信息被截断
|
||||
- **evidence_score 失真**:`tool_call_count` 虚高,规则评分中"成功调用次数"被膨胀
|
||||
|
||||
---
|
||||
|
||||
## 修法方向
|
||||
|
||||
### 方案 A:Prompt 层约束(简单,优先验证)
|
||||
|
||||
在 `chat-executor-prompt.md` 中加规则:
|
||||
|
||||
```
|
||||
已检索过的文档不要重复检索。每次调用 lookup_knowledge 前,
|
||||
先检查对话历史中是否已有该文档的内容,有则直接使用,不再重复调用。
|
||||
```
|
||||
|
||||
优点:不改代码,立即可验证
|
||||
缺点:依赖 LLM 遵守指令,不保证 100% 生效
|
||||
|
||||
### 方案 B:工具层去重(可靠,推荐长期方案)
|
||||
|
||||
`LookupKnowledgeTool` 在 session 维度维护已召回文档 ID 集合,检索结果返回前过滤掉已召回的文档。
|
||||
|
||||
优点:彻底解决,不依赖 LLM
|
||||
缺点:需要改工具代码,需要 session 级状态传递
|
||||
|
||||
### 建议
|
||||
|
||||
MVP 阶段先做**方案 A**验证效果,若重复率明显下降则保留;
|
||||
若 LLM 不稳定遵守,再升级到**方案 B**。
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
|
||||
- `src/main/resources/prompts/chat-executor-prompt.md`
|
||||
@@ -0,0 +1,87 @@
|
||||
# ISS-002 Executor 无约束重复调用 lookup_knowledge
|
||||
|
||||
**状态**:已修复
|
||||
**严重程度**:中(工具层去重已拦截重复文档,但调用本身仍浪费 token 和耗时)
|
||||
**发现时间**:2026-07-01
|
||||
**修复时间**:2026-07-01
|
||||
**关联**:ISS-001(Part A 已修,Part B 注入范围不足)
|
||||
|
||||
---
|
||||
|
||||
## 现象
|
||||
|
||||
ISS-001 修复后,session 级去重(RetrievedDocTracker)生效,同一文档不再重复召回内容。但 Executor 在单次会话中仍调用 `lookup_knowledge` 20+ 次,大部分被去重拦截返回"已检索过"。
|
||||
|
||||
实测日志(session `7c517329`,2026-07-01 13:53):
|
||||
|
||||
```
|
||||
Executor 调用 lookup_knowledge ~20 次
|
||||
去重拦截 11 次:
|
||||
- infrastructure/mysql-connection-pool.md × 6
|
||||
- api/payment-errors.md × 5
|
||||
有效检索仅 2-3 次(首次命中各域时)
|
||||
```
|
||||
|
||||
Executor 用不同的 query 变体反复查同一个域,因为 LLM 觉得"需要更多细节"。
|
||||
|
||||
---
|
||||
|
||||
## 根本原因
|
||||
|
||||
**knowledge map 和检索约束只注入了 Planner prompt,未注入 Executor prompt。**
|
||||
|
||||
当前注入范围:
|
||||
|
||||
| 组件 | knowledge map | 每域最多一次约束 |
|
||||
|------|:---:|:---:|
|
||||
| Planner prompt | 已注入 | 已注入 |
|
||||
| Executor prompt | **未注入** | **未注入** |
|
||||
|
||||
调用链路:
|
||||
|
||||
```
|
||||
Supervisor → Planner:规划一次,输出"查 infrastructure 域 + api 域"
|
||||
Supervisor → Executor:执行步骤(ReactAgent,自主决定调用工具)
|
||||
Executor step 1:lookup("MySQL 连接池配置") → 命中 infrastructure 域 ✓
|
||||
Executor step 2:lookup("HikariCP 参数调优") → 去重拦截 ✗
|
||||
Executor step 3:lookup("连接池耗尽排查步骤") → 去重拦截 ✗
|
||||
Executor step 4:lookup("支付超时排查") → 命中 api 域 ✓
|
||||
Executor step 5:lookup("ERR_TIMEOUT 错误码") → 去重拦截 ✗
|
||||
...(反复用不同变体查同域)
|
||||
```
|
||||
|
||||
Executor 看不到"每个域只查一次"的约束,也不知道已有哪些域被检索过。
|
||||
|
||||
---
|
||||
|
||||
## 影响
|
||||
|
||||
- **Token 浪费**:每次去重拦截仍需走完 L0+L1 检索流程,再返回"已检索过";LLM 也要处理这个返回信息
|
||||
- **耗时增加**:每次冗余调用约 400-500ms(L0+L1 检索 + 向量查询),20 次冗余调用浪费约 10s
|
||||
- **LLM 行为低效**:Executor 花大量 step 在重复检索上,而不是基于已有信息推理
|
||||
|
||||
---
|
||||
|
||||
## 修法方向
|
||||
|
||||
### 方案 A:Executor prompt 注入 knowledge map + 检索约束
|
||||
|
||||
在 `chat-executor-prompt.md` 或 `buildChatExecutorAgent()` 中:
|
||||
1. 注入 knowledge map(与 Planner 相同的 YAML)
|
||||
2. 添加规则:"每个域最多调用一次 lookup_knowledge;已检索过的域不要再用不同关键词重复检索"
|
||||
|
||||
优点:与 Planner 对齐,LLM 能理解域级边界
|
||||
缺点:仍依赖 LLM 遵守指令(但比纯 Prompt 约束强,因为有 knowledge map 做锚点)
|
||||
|
||||
### 方案 B:工具层硬限制(session + 域级计数)
|
||||
|
||||
在 `RetrievedDocTracker` 中增加域级计数:`ConcurrentHashMap<sessionId, Map<domain, count>>`。
|
||||
当某域检索次数 > 1 时,直接在 `LookupKnowledgeTool` 入口返回"该域已检索过,不允许再次调用"。
|
||||
|
||||
优点:100% 可靠,不依赖 LLM
|
||||
缺点:需改动 RetrievedDocTracker + LookupKnowledgeTool,需要从 filePath 反查 domain
|
||||
|
||||
### 建议
|
||||
|
||||
**先做方案 A**(改动小,与已有 knowledge map 注入逻辑一致),观察效果。
|
||||
如果 LLM 仍不遵守,再升级到方案 B。
|
||||
@@ -0,0 +1,137 @@
|
||||
# ISS-005 证据链补齐与降级契约收敛
|
||||
|
||||
**状态**:进行中(sm-flow)
|
||||
**严重程度**:高
|
||||
**发现时间**:2026-07-04
|
||||
**来源**:P1-A 面试打磨项 / 基于 ISS-003 的当前实现复核
|
||||
**关联**:ISS-003(Verifier 证据链、失败路径可验证性)、`chat-verifier-agent`、`mvp-demo-trace-acceptance`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
当前 MVP 已具备:
|
||||
|
||||
- `lookup_knowledge`、`query_logs`、`query_metrics` 的工具调用落库
|
||||
- Verifier 基于 `tool_trace_summary` 做事实核查
|
||||
- `LOW_CONFID` / `REJECT` 的用户侧降级输出
|
||||
- trace API 可回放 session、agent_step、tool_invocation 和 self_evaluation
|
||||
|
||||
但如果目标是拿这个项目去面试 Agent 工程师,当前实现仍有一个明显短板:
|
||||
|
||||
**证据链已经“有了”,但还没有被收敛成清晰、稳定、可测试的工程契约。**
|
||||
|
||||
这会直接影响三个面试问题的回答质量:
|
||||
|
||||
1. 工具失败时系统会怎样降级?
|
||||
2. Verifier 看到的 evidence 到底是否一致、可审计?
|
||||
3. 这些失败路径和降级行为有没有稳定测试,而不是只靠 runtime 演示?
|
||||
|
||||
---
|
||||
|
||||
## 当前现状复核
|
||||
|
||||
### 1. 工具落库入口已经存在,但契约不统一
|
||||
|
||||
- `QueryLogsTools` 和 `QueryMetricsTools` 通过 `ToolInvocationRecorder.recordEvidenceTool(...)` 记录 evidence tool 调用。
|
||||
- `LookupKnowledgeTool` 仍保留独立的 `saveToolInvocation(...)` 路径,自己构造 `ToolInvocation` 实体。
|
||||
|
||||
这意味着:
|
||||
|
||||
- evidence tool 的公共字段有一套约定
|
||||
- knowledge retrieval 又有一套定制字段拼装
|
||||
|
||||
两者都能工作,但**没有形成统一的“证据调用记录契约”**。
|
||||
|
||||
### 2. 失败 / 无结果 / 去重命中的语义不够显式
|
||||
|
||||
当前实现里:
|
||||
|
||||
- `query_logs` 未命中时会返回 `success=false` + `"未找到匹配的日志"`
|
||||
- `query_metrics` 失败时会返回 `success=false`
|
||||
- `lookup_knowledge` 去重命中时会返回 `found=false`,但 `tool_invocation.success=true`
|
||||
- `ToolTraceSummaryService` 通过 `success`、`relevanceLevel`、`dedupReason` 等字段做启发式摘要
|
||||
|
||||
这些行为在代码里是分散成立的,但**没有被定义成统一契约**,导致:
|
||||
|
||||
- Verifier 能看到的“失败”和“无证据”边界不够稳定
|
||||
- 评测时难以明确统计哪些是“调用失败”、哪些是“无命中”、哪些是“已检索过”
|
||||
|
||||
### 3. ChatService 的降级路径有实现,但测试矩阵不完整
|
||||
|
||||
`ChatService` 已处理:
|
||||
|
||||
- `verifier_output` 缺失或无法解析 → fallback `LOW_CONFID`
|
||||
- `REJECT` → degraded output
|
||||
- `LOW_CONFID` → disclaimer output
|
||||
|
||||
但目前缺少成体系的专项验证,尤其是:
|
||||
|
||||
- Verifier 输出非法 JSON
|
||||
- evidence tool 查询失败
|
||||
- knowledge lookup 无有效证据
|
||||
- fallback 文案是否只基于 verifier 缺口拼装
|
||||
|
||||
---
|
||||
|
||||
## 影响
|
||||
|
||||
- **面试表达弱化**:你能讲“我有 trace”,但还不能很硬地讲“我的失败路径是有契约和测试保护的”。
|
||||
- **评测基础不稳**:后续 P1-B 做 case-based harness 时,统计口径会受 evidence 语义不一致影响。
|
||||
- **Verifier 可审计性打折**:当前实现可用,但 still relies on code convention,而不是一份明确收敛后的工程协议。
|
||||
|
||||
---
|
||||
|
||||
## 本 issue 目标
|
||||
|
||||
P1-A 只做三件事:
|
||||
|
||||
1. 收敛 evidence tool 的落库契约,让 `lookup_knowledge`、`query_logs`、`query_metrics` 的公共语义一致。
|
||||
2. 明确失败 / 无证据 / 去重 / verifier 非法输出等降级契约,让 `ToolTraceSummaryService` 和 `ChatService` 面向统一状态工作。
|
||||
3. 增加专项离线测试,覆盖证据摘要与关键降级路径。
|
||||
|
||||
---
|
||||
|
||||
## 范围
|
||||
|
||||
### In scope
|
||||
|
||||
- `ToolInvocationRecorder` 契约增强
|
||||
- `LookupKnowledgeTool` 入库路径收敛
|
||||
- `QueryLogsTools` / `QueryMetricsTools` evidence 语义对齐
|
||||
- `ToolTraceSummaryService` 对失败 / no-hit / mixed evidence 的摘要规则收敛
|
||||
- `ChatService` 对 verifier 非法输出与降级输出的专项测试
|
||||
- 与该 change 直接相关的文档、OpenSpec、devflow 记录
|
||||
|
||||
### Out of scope
|
||||
|
||||
- 不引入新的数据库表或 schema 变更
|
||||
- 不扩展新的 evidence tool
|
||||
- 不做 P1-B 评测集 / harness
|
||||
- 不做前端 trace UI
|
||||
- 不处理敏感配置和默认 `mvn test` 离线化
|
||||
|
||||
---
|
||||
|
||||
## 预期结果
|
||||
|
||||
完成后,项目在面试里应能更清楚地表述为:
|
||||
|
||||
```text
|
||||
我不仅把 Agent 的工具调用落到了库里,
|
||||
还把 evidence trace、失败语义和 verifier 降级路径收敛成了稳定契约,
|
||||
并用离线测试覆盖了这些关键失败场景。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `src/main/java/com/superbiz/agent/service/ToolInvocationRecorder.java`
|
||||
- `src/main/java/com/superbiz/agent/tool/LookupKnowledgeTool.java`
|
||||
- `src/main/java/com/superbiz/agent/agent/tool/QueryLogsTools.java`
|
||||
- `src/main/java/com/superbiz/agent/agent/tool/QueryMetricsTools.java`
|
||||
- `src/main/java/com/superbiz/agent/service/ToolTraceSummaryService.java`
|
||||
- `src/main/java/com/superbiz/agent/service/ChatService.java`
|
||||
- `src/test/java/com/superbiz/agent/service/ChatServiceSequentialAgentTest.java`
|
||||
- `src/test/java/com/superbiz/agent/tool/LookupKnowledgeToolTest.java`
|
||||
@@ -0,0 +1,99 @@
|
||||
# ISS-006 固定诊断评测集与回归 Harness
|
||||
|
||||
**状态**:进行中(sm-flow)
|
||||
**严重程度**:高
|
||||
**发现时间**:2026-07-04
|
||||
**来源**:P1-B 面试打磨项
|
||||
**依赖**:ISS-005 / `evidence-trace-hardening`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
MVP 已经具备可追溯证据链、Verifier 质量门禁、trace API 和固定 demo 流程。上一阶段 `evidence-trace-hardening` 进一步统一了 evidence tool 的状态语义,让系统能稳定区分:
|
||||
|
||||
- `supported`
|
||||
- `no_evidence`
|
||||
- `deduped`
|
||||
- `failed`
|
||||
|
||||
下一步需要证明 Agent 在一组固定诊断场景下的表现,而不是只依赖单次 demo。
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
当前项目能演示一次支付超时诊断,但还缺少稳定的评测基线:
|
||||
|
||||
- 每次改 prompt、工具、Verifier 或检索逻辑后,无法快速判断是否退化。
|
||||
- 只能人工看 trace,缺少结构化通过 / 失败结果。
|
||||
- 缺少面试时能展示的指标,如 evidence coverage、verdict 分布、工具调用数量和耗时。
|
||||
|
||||
---
|
||||
|
||||
## 目标
|
||||
|
||||
建立一个轻量的固定 case 评测 harness,用于验证 MVP Agent 的诊断质量和证据链完整性。
|
||||
|
||||
第一版不做 LLM-as-judge,优先做规则化校验:
|
||||
|
||||
- 固定 5 个 MVP 诊断 case
|
||||
- 每个 case 定义 expected root-cause keywords、required evidence tools、allowed verdicts
|
||||
- 基于 trace 结果校验 evidence coverage、verifier evaluation、tool invocation、final answer shape
|
||||
- 输出 JSON 和 Markdown 报告
|
||||
|
||||
---
|
||||
|
||||
## 范围
|
||||
|
||||
### In scope
|
||||
|
||||
- 评测 case 定义文件
|
||||
- trace 规则校验器
|
||||
- eval runner 或测试入口
|
||||
- JSON / Markdown 报告输出
|
||||
- demo 文档和 devflow 记录
|
||||
|
||||
### Out of scope
|
||||
|
||||
- 不引入 LLM-as-judge
|
||||
- 不要求完整离线 LLM runtime
|
||||
- 不新增生产 API
|
||||
- 不修改 Chat 主链路
|
||||
- 不修改 evidence trace 运行时语义
|
||||
|
||||
---
|
||||
|
||||
## 预期面试表达
|
||||
|
||||
完成后可以这样描述:
|
||||
|
||||
```text
|
||||
我不仅有一个可演示的 Agent,还给它建立了固定 case 的回归评测。
|
||||
每次修改 prompt、工具或 verifier 后,都可以跑同一批诊断 case,
|
||||
检查证据覆盖、verdict 分布、工具调用成本和关键结论是否退化。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 初始候选 case
|
||||
|
||||
| Case | 目标 |
|
||||
| --- | --- |
|
||||
| payment-timeout | 支付接口超时,验证知识库 + 日志 + 指标证据 |
|
||||
| mysql-pool-exhausted | 数据库连接池耗尽,验证日志和知识库证据 |
|
||||
| redis-timeout | Redis 连接超时,验证日志依赖证据 |
|
||||
| slow-response | P99 响应时间过高,验证指标 + 慢请求日志 |
|
||||
| jvm-memory-risk | JVM 内存 / OOM 风险,验证指标 + 系统事件日志 |
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `mvp/demo/README.md`
|
||||
- `mvp/demo/payment-timeout-acceptance.md`
|
||||
- `src/main/java/com/superbiz/agent/service/DiagnosisTraceService.java`
|
||||
- `src/main/java/com/superbiz/agent/service/ToolTraceSummaryService.java`
|
||||
- `src/main/java/com/superbiz/agent/domain/entity/DiagnosisSession.java`
|
||||
- `src/main/java/com/superbiz/agent/domain/entity/ToolInvocation.java`
|
||||
- `openspec/specs/evidence-trace-hardening/spec.md`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,308 @@
|
||||
# ISS-008 Executor 窄范围查询越界
|
||||
|
||||
**严重程度**:中
|
||||
**状态**:已修复
|
||||
**发现时间**:2026-07-08
|
||||
**关联**:
|
||||
- `ISS-007-verifier-evidence-summary-fidelity`
|
||||
- `executor-structured-output-v2`
|
||||
- `executor-evidence-attribution-hallucination`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
当前 Chat 诊断链路已经演进为:
|
||||
|
||||
```text
|
||||
Planner
|
||||
-> Executor
|
||||
-> VerifierInputHook / Gatekeeper
|
||||
-> Verifier
|
||||
-> Composer
|
||||
```
|
||||
|
||||
其中 Executor 的定位已经从“生成最终诊断答案”收敛为:
|
||||
|
||||
```text
|
||||
证据收集 + 微观事实提炼
|
||||
```
|
||||
|
||||
但在窄范围问题中,Executor 仍可能把用户只要求确认的一件事扩展成多条 claim,例如用户只问 `HighCPUUsage`,Executor 可能顺手输出内存、连接池、数据库或修复建议相关内容。
|
||||
|
||||
这类问题不一定是证据伪造。很多时候工具返回里确实有其它信息,但它们不属于当前用户问题的范围。Gatekeeper 只能校验证据引用真假,不能完整承担“用户意图范围控制”;Verifier 虽然可以降级,但会增加链路负担。
|
||||
|
||||
因此本 issue 采用低成本的 Prompt-first 修复:先收紧 Executor prompt,不改 Planner,不引入 `scope_contract`。
|
||||
|
||||
---
|
||||
|
||||
## 问题类型
|
||||
|
||||
### 1. 窄范围查询越界
|
||||
|
||||
用户问题只要求确认一个服务、告警、日志、订单或时间窗口,但 Executor 输出了用户未要求的 claim。
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
只确认 payment-service 是否存在 HighCPUUsage,不要分析订单、OOM、数据库慢查询、连接池或 user-service。
|
||||
```
|
||||
|
||||
错误输出包括:
|
||||
|
||||
- `HighMemoryUsage`
|
||||
- `SlowResponse`
|
||||
- `order-123`
|
||||
- `HikariCP`
|
||||
- `DB / database`
|
||||
- `user-service`
|
||||
|
||||
### 2. Observation 变成 Diagnosis
|
||||
|
||||
Executor 本应输出观察事实,却输出根因、风险、修复建议或经验推断。
|
||||
|
||||
错误输出包括:
|
||||
|
||||
- “CPU 过高是请求超时的根因”
|
||||
- “建议扩容”
|
||||
- “通常这种情况是数据库慢查询导致”
|
||||
- “存在内存泄漏风险”
|
||||
|
||||
### 3. Runbook 通用知识变成当前事实
|
||||
|
||||
Runbook、Skill、知识库可以指导要查什么,但不能直接变成本次环境已发生的事实。
|
||||
|
||||
错误输出包括:
|
||||
|
||||
```text
|
||||
Runbook 中说 HighCPUUsage 常见原因是流量突增,所以当前环境发生了流量突增。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 修复决策
|
||||
|
||||
本期只修 Executor prompt。
|
||||
|
||||
### 本期做
|
||||
|
||||
1. 强化 Executor 单一职责:证据收集 + 微观事实提炼。
|
||||
2. 增加 `角色边界 HARD-GATE`。
|
||||
3. 增加 `窄范围确认任务 HARD-GATE`。
|
||||
4. 增加工具使用边界,避免为补全故事而扩展检索。
|
||||
5. 增加输出前自检,要求输出 JSON 前删除越界 claim。
|
||||
|
||||
### 本期不做
|
||||
|
||||
1. 不改 Planner。
|
||||
2. 不新增 `scope_contract`。
|
||||
3. 不解析 Planner 输出中的 scope。
|
||||
4. 不做 Gatekeeper scope 校验。
|
||||
5. 不改多 Agent 编排。
|
||||
|
||||
---
|
||||
|
||||
## 设计原则
|
||||
|
||||
### Claim 要少,Evidence 可以多
|
||||
|
||||
窄范围任务下,Executor 应输出最少必要 claim,通常 1 条,最多 2 条。
|
||||
|
||||
但 claim 数量限制不限制 `evidence_bindings` 数量。一条核心 claim 可以绑定多条直接相关证据。
|
||||
|
||||
```text
|
||||
正确:
|
||||
1 条 claim + 多条 evidence_bindings
|
||||
|
||||
错误:
|
||||
为了展示多条证据,把同一个观察事实拆成多条 claim
|
||||
```
|
||||
|
||||
### 只输出当前问题范围内的 Observation
|
||||
|
||||
窄范围任务下,`claims` 只能使用:
|
||||
|
||||
- `observation`
|
||||
- `negative_observation`
|
||||
|
||||
禁止使用:
|
||||
|
||||
- `root_cause`
|
||||
- `risk`
|
||||
- `recommendation`
|
||||
- 其它建议类或诊断类 claim
|
||||
|
||||
### 证据不足时不要补故事
|
||||
|
||||
如果工具没有返回可被精确引用的证据:
|
||||
|
||||
```text
|
||||
source_invocation_id + raw_path + evidence_excerpt
|
||||
```
|
||||
|
||||
Executor 不应生成 confirmed claim,应写入 `missing_info`。
|
||||
|
||||
---
|
||||
|
||||
## Prompt 修复点
|
||||
|
||||
已更新:
|
||||
|
||||
- `src/main/resources/prompts/chat-executor-prompt.md`
|
||||
|
||||
核心新增约束:
|
||||
|
||||
1. `角色边界 HARD-GATE`
|
||||
2. `窄范围确认任务 HARD-GATE`
|
||||
3. `工具使用边界`
|
||||
4. `输出前自检`
|
||||
5. 条目级 `raw_path` 强约束:同一条工具数组项只能绑定一次,禁止输出 `$.alerts[0].alert_name`、`$.alerts[0].state` 等字段级子路径。
|
||||
|
||||
---
|
||||
|
||||
## 验证结果
|
||||
|
||||
### 2026-07-08 E2E 验证
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 payment-service 是否存在 HighCPUUsage,不要分析订单123、OOM、数据库慢查询、连接池或 user-service。
|
||||
```
|
||||
|
||||
第一次验证发现:
|
||||
|
||||
- Executor 已经只输出 `payment-service + HighCPUUsage` 相关 observation,没有输出越界 claim。
|
||||
- 但 Executor 额外生成了字段级 `raw_path`:
|
||||
- `$.alerts[0].alert_name`
|
||||
- `$.alerts[0].state`
|
||||
- 当前 Gatekeeper 只支持条目级路径 `$.alerts[i]` / `$.logs[i]` / `$.evidence_blocks[i]`,因此判定为 `REJECT`。
|
||||
|
||||
已追加 prompt 约束:
|
||||
|
||||
```text
|
||||
同一条工具数组项只能绑定一次。
|
||||
不要为了引用其中多个字段而拆成多个 evidence_bindings。
|
||||
raw_path 禁止指向字段级子路径。
|
||||
```
|
||||
|
||||
第二次验证结果:
|
||||
|
||||
```text
|
||||
sessionId: iss008-narrow-highcpu-rerun-20260708-215510
|
||||
verdict: PASS
|
||||
groundedness_score: 1.0
|
||||
gatekeeper_result.status: pass
|
||||
gatekeeper_result.severity: none
|
||||
claim_count: 1
|
||||
claim_type: observation
|
||||
forbidden_hits: none
|
||||
```
|
||||
|
||||
Executor claim:
|
||||
|
||||
```text
|
||||
payment-service 当前存在 HighCPUUsage 告警,CPU 使用率持续超过 80%,当前值为 92%,告警状态为 firing,已持续 25 分钟。
|
||||
```
|
||||
|
||||
最终答案未出现以下排除项:
|
||||
|
||||
- `HighMemoryUsage`
|
||||
- `SlowResponse`
|
||||
- `order-123`
|
||||
- `订单123`
|
||||
- `OOM`
|
||||
- `DB / database`
|
||||
- `HikariCP`
|
||||
- `connection pool / 连接池`
|
||||
- `user-service`
|
||||
|
||||
---
|
||||
|
||||
## 验收标准
|
||||
|
||||
### 1. HighCPUUsage 窄范围
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 payment-service 是否存在 HighCPUUsage,不要分析订单123、OOM、数据库慢查询、连接池或 user-service。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `claims` 只围绕 `payment-service + HighCPUUsage`。
|
||||
- 不出现 `HighMemoryUsage`。
|
||||
- 不出现 `SlowResponse`。
|
||||
- 不出现 `order-123`。
|
||||
- 不出现 `OOM`。
|
||||
- 不出现 `DB / database`。
|
||||
- 不出现 `HikariCP / connection pool`。
|
||||
- 不出现 `user-service`。
|
||||
|
||||
### 2. HighMemoryUsage 窄范围
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 order-service 是否存在 HighMemoryUsage。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 可以输出内存使用率、告警状态、持续时间等观察事实。
|
||||
- 不输出“内存泄漏已确认”。
|
||||
- 不输出扩容、重启、修改 JVM 参数等修复建议。
|
||||
|
||||
### 3. SlowResponse 窄范围
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 user-service 是否存在 SlowResponse 告警和慢请求日志。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 可以绑定 alert 和 logs 多条证据。
|
||||
- 不推断数据库连接池耗尽。
|
||||
- 不推断下游服务故障。
|
||||
|
||||
### 4. 用户明确排除项
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只看 order-service 支付失败日志,不要分析 HikariCP。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- `claim_text` 不出现 HikariCP 确认结论。
|
||||
- 最终答案不出现 HikariCP 确认结论。
|
||||
|
||||
### 5. 证据不足
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 inventory-service 是否存在 HikariCP 连接池耗尽日志。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 如果工具返回 `logs=[]`,Executor 不编造 positive claim。
|
||||
- 输出 `negative_observation` 或 `missing_info`。
|
||||
- 不返回 `generic-service` 占位事实。
|
||||
|
||||
---
|
||||
|
||||
## 后续增强
|
||||
|
||||
如果 Prompt-first 后仍不稳定,再考虑:
|
||||
|
||||
1. Planner 输出 `scope_contract`。
|
||||
2. Gatekeeper 增加 scope 校验。
|
||||
3. eval fixture 增加 forbidden claim 自动断言。
|
||||
|
||||
本期暂不进入这些改造。
|
||||
@@ -0,0 +1,239 @@
|
||||
# ISS-009 negative_observation 精确引用 no-evidence 结果
|
||||
|
||||
**严重程度**:中
|
||||
**状态**:已修复
|
||||
**发现时间**:2026-07-08
|
||||
**关联**:
|
||||
- `ISS-007-verifier-evidence-summary-fidelity`
|
||||
- `ISS-008-executor-narrow-scope-overreach`
|
||||
- `executor-structured-output-v2`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
ISS-007 已经把正向证据引用收敛为:
|
||||
|
||||
```text
|
||||
source_invocation_id + raw_path + evidence_excerpt
|
||||
```
|
||||
|
||||
Gatekeeper 通过 `tool_invocation.retrieval_details.evidence_refs` 校验 Executor 引用是否真实存在。
|
||||
|
||||
但负向观察存在一个缺口:当工具明确返回“没查到”时,结果通常是空数组:
|
||||
|
||||
```json
|
||||
{
|
||||
"logs": [],
|
||||
"total": 0,
|
||||
"message": "未找到匹配的日志"
|
||||
}
|
||||
```
|
||||
|
||||
这时没有 `$.logs[0]`、`$.alerts[0]` 或 `$.evidence_blocks[0]` 可以引用。Executor 如果输出 `negative_observation`,Gatekeeper 无法稳定验证它引用的“无证据结果”,容易降级为 `LOW_CONFID` 或 `REJECT`。
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
用户问:
|
||||
|
||||
```text
|
||||
只确认 inventory-service 是否存在 HikariCP 连接池耗尽日志。
|
||||
```
|
||||
|
||||
工具返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"logs": [],
|
||||
"total": 0,
|
||||
"message": "未找到匹配的日志"
|
||||
}
|
||||
```
|
||||
|
||||
合理 claim 是:
|
||||
|
||||
```json
|
||||
{
|
||||
"claim_type": "negative_observation",
|
||||
"claim_text": "未检索到 inventory-service 的 HikariCP 连接池耗尽日志。"
|
||||
}
|
||||
```
|
||||
|
||||
但旧设计只支持正向数组项:
|
||||
|
||||
```text
|
||||
$.alerts[i]
|
||||
$.logs[i]
|
||||
$.evidence_blocks[i]
|
||||
```
|
||||
|
||||
因此负向观察缺少可回溯的精确引用点。
|
||||
|
||||
---
|
||||
|
||||
## 修复决策
|
||||
|
||||
给 no-hit / no-evidence 结果增加一等证据引用:
|
||||
|
||||
```json
|
||||
{
|
||||
"raw_path": "$.no_evidence",
|
||||
"text": "query_logs returned no evidence; evidence_status=no_evidence; query=inventory-service HikariCP; topic=application-logs; total=0; message=未找到匹配的日志"
|
||||
}
|
||||
```
|
||||
|
||||
Executor 可以引用:
|
||||
|
||||
```json
|
||||
{
|
||||
"tool_name": "query_logs",
|
||||
"source_invocation_id": 123,
|
||||
"raw_path": "$.no_evidence",
|
||||
"evidence_excerpt": "query_logs returned no evidence; query=inventory-service HikariCP; total=0; evidence_status=no_evidence"
|
||||
}
|
||||
```
|
||||
|
||||
### 语义边界
|
||||
|
||||
`$.no_evidence` 只表示:
|
||||
|
||||
```text
|
||||
该工具对当前查询返回无匹配证据。
|
||||
```
|
||||
|
||||
它不表示:
|
||||
|
||||
- 问题绝对不存在。
|
||||
- 根因被排除。
|
||||
- 系统已经健康。
|
||||
- 没有必要继续排查。
|
||||
|
||||
---
|
||||
|
||||
## 实施范围
|
||||
|
||||
### 已修改
|
||||
|
||||
- `ToolInvocationRecorder`
|
||||
- `query_logs` no-hit 时生成 `evidence_refs[0].raw_path="$.no_evidence"`。
|
||||
- `query_metrics` no-hit 时生成 `evidence_refs[0].raw_path="$.no_evidence"`。
|
||||
- `lookup_knowledge` no-hit 且无 evidence blocks 时生成 `evidence_refs[0].raw_path="$.no_evidence"`。
|
||||
- `ExecutorGatekeeperService`
|
||||
- 复用既有 `evidence_refs` 校验逻辑,无需新增特殊分支。
|
||||
- `$.no_evidence` 和普通 raw_path 一样必须存在于 `retrieval_details.evidence_refs`。
|
||||
- `chat-executor-prompt.md`
|
||||
- 明确 `negative_observation` 必须引用 `$.no_evidence`。
|
||||
- 明确没有实际工具调用时禁止使用 `$.no_evidence`。
|
||||
|
||||
### 未修改
|
||||
|
||||
- 不新增数据库表。
|
||||
- 不新增复杂 metadata。
|
||||
- 不改变 Planner。
|
||||
- 不改变 Agent 编排。
|
||||
|
||||
---
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. `query_logs` 返回 `logs=[] / total=0 / evidence_status=no_evidence` 时,`tool_invocation.retrieval_details.evidence_refs` 包含:
|
||||
|
||||
```json
|
||||
{
|
||||
"raw_path": "$.no_evidence"
|
||||
}
|
||||
```
|
||||
|
||||
2. Executor 输出 `negative_observation` 并引用 `$.no_evidence` 时,Gatekeeper 可以校验通过。
|
||||
|
||||
3. Executor 如果用 `$.no_evidence` 搭配正向证据文本,例如 `HikariCP active=50/50`,Gatekeeper 必须拒绝。
|
||||
|
||||
4. `$.no_evidence` 不得被解释为“问题绝对不存在”,只能表达“当前查询未检索到匹配证据”。
|
||||
|
||||
5. HikariCP negative E2E:
|
||||
|
||||
```text
|
||||
只确认 inventory-service 是否存在 HikariCP 连接池耗尽日志。
|
||||
```
|
||||
|
||||
期望:
|
||||
|
||||
- 工具返回 no-hit。
|
||||
- 不返回 `generic-service`。
|
||||
- Executor 输出 `negative_observation`。
|
||||
- `raw_path="$.no_evidence"`。
|
||||
- Gatekeeper `pass/none`。
|
||||
- Verifier 不误判为正向 HikariCP 证据。
|
||||
|
||||
---
|
||||
|
||||
## 验证记录
|
||||
|
||||
### 2026-07-08 单元测试
|
||||
|
||||
命令:
|
||||
|
||||
```text
|
||||
mvn '-Dtest=ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,QueryLogsToolsTest' test
|
||||
```
|
||||
|
||||
结果:
|
||||
|
||||
```text
|
||||
Tests run: 23, Failures: 0, Errors: 0, Skipped: 0
|
||||
BUILD SUCCESS
|
||||
```
|
||||
|
||||
覆盖点:
|
||||
|
||||
- `query_logs` no-hit 生成 `$.no_evidence`。
|
||||
- `query_metrics` no-hit 生成 `$.no_evidence`。
|
||||
- `lookup_knowledge` no-hit 生成 `$.no_evidence`。
|
||||
- Gatekeeper 可以校验 `$.no_evidence`。
|
||||
- 多个 no-evidence 调用存在时,Gatekeeper 可按 `tool_name + raw_path + evidence_excerpt` 唯一回填 `source_invocation_id`。
|
||||
- `negative_observation` 混绑正向 `$.logs[i]` 会被拒绝。
|
||||
- HikariCP negative mock 不返回 `generic-service`。
|
||||
|
||||
### 2026-07-08 E2E 验证
|
||||
|
||||
输入:
|
||||
|
||||
```text
|
||||
只确认 inventory-service 是否存在 HikariCP 连接池耗尽日志。
|
||||
```
|
||||
|
||||
最终通过 session:
|
||||
|
||||
```text
|
||||
sessionId: iss009-hikari-negative-latest-20260708-232428
|
||||
verdict: PASS
|
||||
groundedness_score: 1.0
|
||||
gatekeeper_result.status: pass
|
||||
gatekeeper_result.severity: none
|
||||
claim_count: 1
|
||||
claim_type: negative_observation
|
||||
raw_path: $.no_evidence
|
||||
generic_service_hit: false
|
||||
overstate_hit: false
|
||||
```
|
||||
|
||||
Executor claim:
|
||||
|
||||
```text
|
||||
当前查询未检索到 inventory-service 的 HikariCP 连接池耗尽日志。
|
||||
```
|
||||
|
||||
最终答案:
|
||||
|
||||
```text
|
||||
本次查询在 inventory-service 中未发现 HikariCP 连接池耗尽的日志记录,检索结果未匹配到相关证据。
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- Executor 仍可能输出多个 `$.no_evidence` binding。
|
||||
- 如果 `source_invocation_id` 缺失,Gatekeeper 会按 `tool_name + raw_path + evidence_excerpt` 唯一匹配真实 invocation 并写入 warning。
|
||||
- 最终答案不使用“排除”“确认没有”“不存在该问题”等过度表达。
|
||||
@@ -0,0 +1,73 @@
|
||||
# Diagnosis Eval Baseline Diff
|
||||
|
||||
**状态**:已归档
|
||||
**严重程度**:中
|
||||
**发现时间**:2026-07-05
|
||||
**来源**:P1-B follow-up
|
||||
**依赖**:`diagnosis-eval-harness`, `expand-diagnosis-eval-fixtures`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
现在项目已经有固定诊断 case、完整 fixture 和 baseline report。下一步需要把 baseline 真正用起来:每次改 Agent 后,把新的 report 和 baseline report 做对比。
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
当前 baseline 只能告诉我们“标准状态是什么”,但还不能自动告诉我们“这次改动有没有变差”。
|
||||
|
||||
典型问题包括:
|
||||
|
||||
- pass rate 是否下降。
|
||||
- 某个 case 是否从通过变失败。
|
||||
- 某个 evidence tool 是否从覆盖变成缺失。
|
||||
- verifier verdict 分布是否异常变化。
|
||||
- 平均工具调用数和耗时是否明显上升。
|
||||
|
||||
---
|
||||
|
||||
## 目标
|
||||
|
||||
新增一个 deterministic baseline diff 能力,用代码比较两份 `DiagnosisEvalReport`。
|
||||
|
||||
完成后应该做到:
|
||||
|
||||
- 输入 baseline report 和 current report。
|
||||
- 输出结构化 diff。
|
||||
- 标出 regression、improvement 和普通 changed。
|
||||
- 支持 JSON 和 Markdown 输出。
|
||||
- 文档说明面试时怎么解释这套回归判断。
|
||||
|
||||
---
|
||||
|
||||
## 范围
|
||||
|
||||
### In scope
|
||||
|
||||
- report-level diff 数据结构。
|
||||
- aggregate 指标比较。
|
||||
- case-level 指标比较。
|
||||
- JSON / Markdown diff writer。
|
||||
- focused tests 和 eval 文档。
|
||||
|
||||
### Out of scope
|
||||
|
||||
- 不运行真实 Agent。
|
||||
- 不生成新 trace。
|
||||
- 不引入 LLM-as-judge。
|
||||
- 不改现有 evaluator 评分规则。
|
||||
|
||||
---
|
||||
|
||||
## 面试表达
|
||||
|
||||
可以这样讲:
|
||||
|
||||
```text
|
||||
我不是只保存了一份 baseline,而是加了 baseline diff。
|
||||
每次改 prompt、tool、retrieval 或 verifier 后,
|
||||
我都能把新 report 和 baseline 比较,
|
||||
直接看到哪些 case 退化、哪些证据缺失、成本有没有上升。
|
||||
```
|
||||
@@ -0,0 +1,83 @@
|
||||
# Expand Diagnosis Eval Fixtures
|
||||
|
||||
**状态**:已归档
|
||||
**严重程度**:中
|
||||
**发现时间**:2026-07-04
|
||||
**来源**:P1-B follow-up
|
||||
**依赖**:`diagnosis-eval-harness`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
`diagnosis-eval-harness` 已经把固定 case、trace evaluator、JSON / Markdown report 和字段文档搭起来了。
|
||||
|
||||
现在还差一步:5 条固定诊断 case 里,只有 2 条有 fixture,另外 3 条还是 missing 状态。这个状态可以验证 evaluator 的错误报告能力,但还不能作为完整 baseline 展示。
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
当前 baseline 还不够完整:
|
||||
|
||||
- `redis-timeout` 没有对应 trace fixture。
|
||||
- `slow-response` 没有对应 trace fixture。
|
||||
- `jvm-memory-risk` 没有对应 trace fixture。
|
||||
- 仓库里还没有一份固定的 baseline JSON / Markdown 报告可供对比。
|
||||
|
||||
---
|
||||
|
||||
## 目标
|
||||
|
||||
补齐固定诊断评测集,让它从“框架可跑”变成“基准可用”。
|
||||
|
||||
完成后应该做到:
|
||||
|
||||
- 5 条固定 case 都能加载到对应 fixture。
|
||||
- evaluator 能输出完整 baseline report。
|
||||
- baseline report 被保存到仓库,后续 Agent 改动可以拿它做对比。
|
||||
- 文档说明怎么重新生成和怎么看报告。
|
||||
|
||||
---
|
||||
|
||||
## 范围
|
||||
|
||||
### In scope
|
||||
|
||||
- 补齐 3 个缺失 fixture。
|
||||
- 保存 baseline JSON / Markdown 报告。
|
||||
- 更新 eval 文档。
|
||||
- 补充测试,确保 case 文件引用的 fixture 都存在。
|
||||
|
||||
### Out of scope
|
||||
|
||||
- 不新增 case 数量。
|
||||
- 不改生产 Agent 主链路。
|
||||
- 不引入 LLM-as-judge。
|
||||
- 不启动真实 MySQL、Redis、Milvus 或 LLM。
|
||||
|
||||
---
|
||||
|
||||
## 面试表达
|
||||
|
||||
可以这样讲:
|
||||
|
||||
```text
|
||||
我先搭了评测 harness,然后把固定 case 的 trace fixture 补齐,
|
||||
生成一份可复现的 baseline report。
|
||||
这样以后每次改 prompt、tool 或 verifier,
|
||||
都能看固定诊断集有没有行为回退,而不是只靠人工感觉。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `mvp/eval/cases/diagnosis-cases.json`
|
||||
- `mvp/eval/fixtures/`
|
||||
- `mvp/eval/reports/`
|
||||
- `mvp/eval/README.md`
|
||||
- `mvp/eval/schema.md`
|
||||
- `src/main/java/com/superbiz/agent/eval/DiagnosisTraceEvaluator.java`
|
||||
- `src/test/java/com/superbiz/agent/eval/DiagnosisTraceEvaluatorTest.java`
|
||||
- `openspec/specs/diagnosis-eval-harness/spec.md`
|
||||
@@ -0,0 +1,53 @@
|
||||
# MVP Demo Interview Runbook
|
||||
|
||||
**状态**:已归档
|
||||
**严重程度**:中
|
||||
**发现时间**:2026-07-05
|
||||
**来源**:Plan C
|
||||
**依赖**:`mvp-demo-trace-acceptance`, `evidence-trace-hardening`, `diagnosis-eval-harness`
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
项目已经有 Agent 主链路、证据 trace、Verifier、反馈、eval baseline,但这些材料分散在不同目录。面试时真正需要的是一个能快速跑、快速讲清楚的 demo 入口。
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
当前 demo 还不够“面试友好”:
|
||||
|
||||
- 启动、请求、trace、反馈步骤分散在文档里。
|
||||
- 没有固定请求 payload 文件。
|
||||
- 没有一键跑 payment-timeout demo 的脚本。
|
||||
- 没有把 trace 字段和面试讲法对应起来的 walkthrough。
|
||||
|
||||
---
|
||||
|
||||
## 目标
|
||||
|
||||
把 Plan C 落地成 `mvp/demo` 下的可复现 demo 包:
|
||||
|
||||
- 固定支付超时请求。
|
||||
- 一键执行 chat、trace、feedback。
|
||||
- 保存 demo 输出,便于复盘。
|
||||
- 提供面试讲解稿和 trace 检查清单。
|
||||
|
||||
---
|
||||
|
||||
## 范围
|
||||
|
||||
### In scope
|
||||
|
||||
- `mvp/demo` 文档。
|
||||
- `mvp/demo/requests` 请求文件。
|
||||
- `mvp/demo/scripts` PowerShell 脚本。
|
||||
- `mvp/demo/output` 目录说明。
|
||||
|
||||
### Out of scope
|
||||
|
||||
- 不新增后端 API。
|
||||
- 不改 Agent prompt。
|
||||
- 不扩 eval harness。
|
||||
- 不处理密钥外置和完整离线化。
|
||||
Reference in New Issue
Block a user