Files
zhuyongxin a1c896ebda chore(docs): 归档 ISS-001 session-dedup-knowledge-map + ISS-002 mvp 文档
- 移动 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
2026-07-01 18:27:04 +08:00

6.7 KiB
Raw Permalink Blame History

Design: session-dedup-knowledge-map

1. 整体架构

本 change 包含两个独立但互补的部分:

Part A: 工具层去重
  LookupKnowledgeTool
    ├── 维护 ConcurrentHashMap<sessionId, Set<filePath>>(JVM 内)
    ├── 每次检索前过滤已召回文档
    └── SessionContextHolder.clear() 时同步清理

Part B: 知识图谱
  ┌─────────────────────────────────────────────┐
  │ 文档上传 (DocumentManagementService)         │
  │   → LLM 生成 doc.covers + doc.when_to_retrieve │
  │   → 存入 api_document.metadata             │
  │   → 触发域级重算 (KnowledgeDomainService)   │
  └─────────────────────────────────────────────┘
         ↓
  ┌─────────────────────────────────────────────┐
  │ 域级聚合 (KnowledgeDomainService)            │
  │   → 读取同域所有文档的 when_to_retrieve      │
  │   → LLM 生成 domain.when_to_retrieve        │
  │   → 存入 knowledge_domain 表                │
  └─────────────────────────────────────────────┘
         ↓
  ┌─────────────────────────────────────────────┐
  │ 启动 (KnowledgeIndexService.loadIndex)       │
  │   → 加载 knowledge_domain 表                │
  │   → 某域无记录则触发域级生成                 │
  └─────────────────────────────────────────────┘
         ↓
  ┌─────────────────────────────────────────────┐
  │ Planner prompt (ChatService)                │
  │   → 注入 knowledge map(域级)               │
  │   → Planner 做粗粒度检索决策                 │
  └─────────────────────────────────────────────┘

2. 数据结构定义

2.1 Frontmatter 新增字段

# 新增两个字段,其余不变
covers: ["支付失败排查", "扣款无回调"]      # List<String>:业务场景标签,Planner 决策用
when_to_retrieve: "用户描述支付失败、超时时" # String:文档级检索时机,LLM 上传时生成

对应 Frontmatter.java 新增两个字段:

  • List<String> covers
  • String whenToRetrieve

对应 KnowledgeEntry.java 新增两个字段(同上)。

2.2 knowledge_domain 表(新表)

CREATE TABLE knowledge_domain (
    id          BIGINT AUTO_INCREMENT PRIMARY KEY,
    domain_id   VARCHAR(64)  NOT NULL UNIQUE,   -- category 值,如 "payment"
    description VARCHAR(256),                   -- 域描述(聚合自文档 summary)
    when_to_retrieve TEXT,                       -- 域级检索时机(LLM 生成)
    document_count INT DEFAULT 0,               -- 该域当前文档数
    updated_at  DATETIME,
    created_at  DATETIME
);

2.3 knowledge map 结构(注入 Planner 的 YAML 文本)

available_knowledge_domains:
  - domain_id: "payment"
    description: "支付链路问题排查"
    when_to_retrieve: "用户问题涉及支付、退款、对账时检索;优先检索一次,勿重复"
    documents:
      - title: "支付失败排查手册"
        covers: ["支付超时", "扣款无回调"]
      - title: "退款处理指南"
        covers: ["退款未到账", "退款状态异常"]
  - domain_id: "infrastructure"
    ...

3. 新增组件

3.1 KnowledgeDomainService(新类)

职责:域级聚合与存储

buildDomainSummary(category)
  → 读取同域所有 KnowledgeEntry(含 when_to_retrieve)
  → 拼装 prompt,调用 LLM
  → 写入 knowledge_domain 表

buildKnowledgeMap()
  → 读取所有 knowledge_domain 记录
  → 拼装 YAML 文本(含 documents 列表)
  → 返回 String(供 Planner prompt 注入)

onDocumentChange(category)
  → 调用 buildDomainSummary(category)(只重算受影响域)

3.2 RetrievedDocTracker(新类,或内联入 LookupKnowledgeTool)

职责:session 级已召回文档追踪

ConcurrentHashMap<String, Set<String>> retrieved
  key: sessionId
  value: Set<filePath>

isAlreadyRetrieved(sessionId, filePath) → boolean
markRetrieved(sessionId, filePath)
clearSession(sessionId)   ← 由 SessionContextHolder.clear() 触发

4. 改动文件清单

文件 改动类型 说明
LookupResult.java 修改 新增 message 字段(去重提示文本)
Frontmatter.java 修改 新增 covers、whenToRetrieve
KnowledgeEntry.java 修改 新增 covers、whenToRetrieve
FrontmatterParser.java 修改 解析新字段
DocumentManagementService.java 修改 upload 时调 LLM 生成文档级字段;upload/delete 后触发域级重算
KnowledgeIndexService.java 修改 loadIndex 时加载域级数据;若域无记录则触发生成
KnowledgeDomainService.java 新增 域聚合、LLM 调用、DB 读写、buildKnowledgeMap
KnowledgeDomain.java(entity) 新增 knowledge_domain 表映射
KnowledgeDomainRepository.java 新增 JPA Repository
LookupKnowledgeTool.java 修改 集成 RetrievedDocTracker,检索前过滤,检索后标记
SessionContextHolder.java 修改 clear() 时通知 RetrievedDocTracker
RetrievedDocTracker.java 新增 session 级去重状态管理
ChatService.java 修改 buildChatPlannerAgent 注入 knowledge map
chat-planner-prompt.md 修改 添加 knowledge map 使用规则
V009__add_knowledge_domain.sql 新增 Flyway 建表脚本

5. 关键决策记录

  1. 域级 when_to_retrieve 存 DB:避免每次重启调 LLM;文档变更时只重算受影响域
  2. 文档级 when_to_retrieve 存 metadata JSON:沿用现有 frontmatter 存储路径,无需新字段
  3. RetrievedDocTracker 独立于 SessionContextHolder:SessionContextHolder 只持有 sessionId,Tracker 是业务状态,职责分离;clear() 时通过 Tracker.clearSession() 联动
  4. Planner 只看域级:文档级 when_to_retrieve 留 Executor 筛选(Phase 2),MVP 不暴露给 Planner
  5. LLM 调用同步执行:上传时同步生成,接受约 1-2s 延迟,保证数据库和 L0 索引立即一致