- 移动 session-dedup-knowledge-map OpenSpec 到 archive 目录 - 提交 ISS-001 遗留的 devflow 档案文件 - 更新 ISS-002 状态为已修复 - 新增 mvp/architecture/action-memory-relevance.md 设计文档 - 更新 mvp/README.md 文档导航 - 更新 devflow/index.md OpenSpec 链接指向 archive
2.8 KiB
2.8 KiB
Proposal: session-dedup-knowledge-map
问题
-
ISS-001 重复召回:
LookupKnowledgeTool每次调用完全无状态,同一 session 中同一文档可被重复召回 13+ 次,浪费 token、压缩上下文窗口、导致tool_call_count虚高。 -
Planner 缺少全局视野:Planner 不知道知识库里有哪些域,只能靠 Executor 反复试探,导致低效的"盲目检索"模式。
建议方案
Part A:工具层去重(彻底修复 ISS-001)
在 LookupKnowledgeTool 的 session 维度维护已召回文档 ID 集合。
每次检索时,过滤掉已召回的文档;相同 query 命中相同文档则直接跳过(返回"已在上下文中"提示)。
状态存储:ConcurrentHashMap<sessionId, Set<docKey>>,生命周期随 session(SessionContextHolder.clear() 时清理)。
Part B:知识图谱注入 Planner
启动时(KnowledgeIndexService.loadIndex() 完成后),将 L0 索引中的所有 KnowledgeEntry 聚合为域级摘要(knowledge map)。
每次构建 Planner prompt 时(buildChatPlannerAgent()),将 knowledge map 注入 system prompt,让 Planner 有"知识边界"。
聚合策略:按 category 字段分组,生成结构:
available_knowledge_domains:
- domain_id: "payment"
description: "..."
covers: [...]
document_count: N
when_to_retrieve: "..."
知识图谱的 description / when_to_retrieve 字段来源于:
- 选项 1:直接聚合 KnowledgeEntry 的 title/summary
- 选项 2:文档 frontmatter 中新增
domain_description/when_to_retrieve字段 - 选项 3:上传时 LLM 自动生成这两个字段
范围
In scope:
LookupKnowledgeTool:添加 session 级去重状态管理KnowledgeIndexService:添加buildKnowledgeMap()方法ChatService.buildChatPlannerAgent():注入 knowledge map 到 promptchat-planner-prompt.md:添加如何使用 knowledge map 的指令
Out of scope(本次不做):
EvaluationService.tool_call_count的统计口径调整(去重后虚高问题自然消失,但评分规则不改)- RRF 混合重排
- 文档 frontmatter 自动生成(上传时 LLM 生成,留 Phase 2)
风险
- Part A 引入 JVM 内存 Map,高并发时多 session 并发需线程安全
- Part B knowledge map 注入 Planner prompt 会增加每次请求的 token 消耗(固定开销)
- 文档
category字段缺失或不规范时,聚合结果可能混乱
上下文约束
SessionContextHolder是 ThreadLocal,异步路径不安全(已知限制,Part A 需确认同步路径)EvaluationService依赖tool_call_count,去重会降低此值(是修复,不是回归)KnowledgeEntry已有category字段,但当前数据库中的文档是否都有category需确认