88 lines
3.3 KiB
Markdown
88 lines
3.3 KiB
Markdown
# 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。
|