feat(agent): support no-evidence references
This commit is contained in:
@@ -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。
|
||||
- 最终答案不使用“排除”“确认没有”“不存在该问题”等过度表达。
|
||||
@@ -9,6 +9,8 @@
|
||||
| ISS-005 | 证据链补齐与降级契约收敛 | 高 | 已归档 | [ISS-005-evidence-trace-hardening.md](ISS-005-evidence-trace-hardening.md) |
|
||||
| ISS-006 | 固定诊断评测集与回归 Harness | 高 | 已归档 | [ISS-006-diagnosis-eval-harness.md](ISS-006-diagnosis-eval-harness.md) |
|
||||
| ISS-007 | Verifier 证据摘要保真与工具命中质量问题 | 高 | 已实施 | [ISS-007-verifier-evidence-summary-fidelity.md](ISS-007-verifier-evidence-summary-fidelity.md) |
|
||||
| ISS-008 | Executor 窄范围查询越界 | 中 | 已修复 | [ISS-008-executor-narrow-scope-overreach.md](ISS-008-executor-narrow-scope-overreach.md) |
|
||||
| ISS-009 | negative_observation 精确引用 no-evidence 结果 | 中 | 已修复 | [ISS-009-negative-observation-no-evidence-reference.md](ISS-009-negative-observation-no-evidence-reference.md) |
|
||||
| executor-evidence-attribution-hallucination | Executor 证据归因幻觉 | 高 | 待规划 | [executor-evidence-attribution-hallucination.md](executor-evidence-attribution-hallucination.md) |
|
||||
| executor-self-evidence-loop-design-note | Executor 自证循环与证据摘要链路设计记录 | 高 | 已形成方向 | [executor-self-evidence-loop-design-note.md](executor-self-evidence-loop-design-note.md) |
|
||||
| expand-diagnosis-eval-fixtures | 补齐固定诊断评测 fixture 与 baseline | 中 | 已归档 | [expand-diagnosis-eval-fixtures.md](expand-diagnosis-eval-fixtures.md) |
|
||||
|
||||
Reference in New Issue
Block a user