Files

189 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 会话级去重与知识域地图
文档级去重 + 知识域地图注入 Planner,解决 ISS-001 Executor 重复召回同一文档问题。
---
## 一、整体架构
本 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 做粗粒度检索决策 │
└─────────────────────────────────────────────┘
```
---
## 二、Part A:工具层去重
### RetrievedDocTracker
session 级已召回文档追踪组件,将去重责任从 LLM 移交到工具层。
```java
ConcurrentHashMap<String, Set<String>> retrieved
key: sessionId
value: Set<filePath>
```
| 方法 | 作用 |
|------|------|
| `isAlreadyRetrieved(sessionId, filePath)` | 检查文档是否已召回 |
| `markRetrieved(sessionId, filePath)` | 记录已召回文档 |
| `clearSession(sessionId)` | 清理会话记录(SessionContextHolder.clear 触发) |
### 去重流程
```
lookup_knowledge(query)
→ L0 检索 → 命中一批文档
→ 遍历结果,过滤 isAlreadyRetrieved=true 的文档
→ 剩余文档作为 primary/supplement 返回
→ 实际返回的文档调用 markRetrieved
```
---
## 三、Part B:知识域地图
### Frontmatter 新增字段
文档上传时 LLM 自动生成以下两个字段:
```yaml
covers: ["支付失败排查", "扣款无回调"] # 业务场景标签
when_to_retrieve: "用户描述支付失败、超时时" # 文档级检索时机
```
### knowledge_domain 表
```sql
CREATE TABLE knowledge_domain (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
domain_id VARCHAR(64) NOT NULL UNIQUE,
description VARCHAR(256),
when_to_retrieve TEXT,
document_count INT DEFAULT 0,
updated_at DATETIME,
created_at DATETIME
);
```
### Knowledge Map(注入 Planner 的 YAML)
```yaml
available_knowledge_domains:
- domain_id: "payment"
description: "支付链路问题排查"
when_to_retrieve: "用户问题涉及支付、退款、对账时检索;优先检索一次,勿重复"
documents:
- title: "支付失败排查手册"
covers: ["支付超时", "扣款无回调"]
- title: "退款处理指南"
covers: ["退款未到账", "退款状态异常"]
- domain_id: "infrastructure"
...
```
### 注入链路
```
文档上传/删除
→ KnowledgeDomainService.onDocumentChange(category)
→ 读取同域所有文档的 when_to_retrieve
→ LLM 聚合为 domain.when_to_retrieve
→ 写入 knowledge_domain 表
应用启动
→ KnowledgeIndexService.loadIndex()
→ 加载 knowledge_domain → 无记录则触发聚合
→ ChatService.buildChatPlannerAgent() 注入 prompt
Planner prompt 中包含知识域地图
→ Planner 做粗粒度检索决策("查 payment 域")
→ Executor 收到步骤后执行具体检索
```
---
## 四、关键设计决策
| 决策 | 方案 | 原因 |
|------|------|------|
| 域级 when_to_retrieve 存 DB | 持久化 | 避免每次重启调 LLM,文档变更时只重算受影响域 |
| 文档级 when_to_retrieve 存 metadata JSON | 沿用现有路径 | 无需新增数据库字段 |
| RetrievedDocTracker 独立于 SessionContextHolder | 职责分离 | SessionContextHolder 只持有 sessionId,Tracker 是业务状态 |
| Planner 只看域级 | 分层决策 | 文档级 when_to_retrieve 留 Executor 筛选(Phase 2) |
| LLM 调用同步执行 | 上传时即时生成 | 接受约 1-2s 延迟,保证数据库和 L0 索引立即一致 |
---
## 五、Agent 边界
```
Planner 角色:知道"有什么域"
└─ 知识域地图:选定要检索的域(一次规划)
Executor 角色:知道"做了什么"
└─ 行动记忆:域级 + 文档级去重(ISS-002 升级为双层记忆)
```
Part B(知识域地图)只注入 Planner prompt,**不注入 Executor prompt**。Executor 只通过 RetrievedDocTracker 知道自己已检索了哪些文档,不需要知道全局域有哪些。
---
## 六、数据库变更
### V009
```sql
CREATE TABLE knowledge_domain (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
domain_id VARCHAR(64) NOT NULL UNIQUE,
description VARCHAR(256),
when_to_retrieve TEXT,
document_count INT DEFAULT 0,
updated_at DATETIME,
created_at DATETIME
);
```
---
## 七、参考资料
- **架构文档**:`mvp/architecture/knowledge-retrieval-architecture.md`
- **使用指南**:`mvp/architecture/knowledge-retrieval-usage.md`
- **OpenSpec**:`openspec/changes/archive/2026-06-30-session-dedup-knowledge-map/`