Files
SuperBizAgent-java/mvp/issues/ISS-002-executor-unconstrained-lookup.md
T
zhuyongxin e4f37cb9e6 fix(knowledge): 修复循环依赖 + 归档 session-dedup-knowledge-map + 记录 ISS-002
- KnowledgeIndexService: 域级生成从 @PostConstruct 移到 @EventListener(ApplicationReadyEvent),解决 KnowledgeIndexService ↔ KnowledgeDomainService 循环依赖
- devflow 归档: evidence.md + acceptance.md(含运行验证结果)
- devflow/index.md: session-dedup-knowledge-map 状态改为 archived
- openspec .archive-ready 标记
- mvp/issues/ISS-002: Executor 无约束重复调用 lookup_knowledge
2026-07-01 14:26:59 +08:00

3.3 KiB
Raw Blame History

ISS-002 Executor 无约束重复调用 lookup_knowledge

状态:待修复 严重程度:中(工具层去重已拦截重复文档,但调用本身仍浪费 token 和耗时) 发现时间: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。