docs(mvp): 添加知识库检索架构和使用文档
新增文档: - mvp/architecture/knowledge-retrieval-architecture.md * 架构位置和数据流说明 * L0+L1 混合检索流程图 * 核心组件详细设计 * 与现有架构的集成方式 * 性能指标和可观测性 - mvp/architecture/knowledge-retrieval-usage.md * 快速开始指南 * 文档格式要求和最佳实践 * 使用场景和示例 * 故障排查和性能优化 * 维护知识库的完整流程 更新文档: - mvp/README.md - 添加知识库检索文档入口 完善 MVP 架构文档,为后续开发和维护提供完整参考
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
### 架构设计
|
### 架构设计
|
||||||
- [Agent 架构设计](architecture/agent-architecture.md) - Agent 协作 + Skill + Harness
|
- [Agent 架构设计](architecture/agent-architecture.md) - Agent 协作 + Skill + Harness
|
||||||
|
- [知识库检索架构](architecture/knowledge-retrieval-architecture.md) - L0+L1 混合检索架构 ⭐新增
|
||||||
|
- [知识库检索使用指南](architecture/knowledge-retrieval-usage.md) - 文档编写和使用说明 ⭐新增
|
||||||
- [会话管理](architecture/session-management.md) - Redis + MySQL 会话管理
|
- [会话管理](architecture/session-management.md) - Redis + MySQL 会话管理
|
||||||
- [实施规划](architecture/implementation-plan.md) - 分阶段实施计划
|
- [实施规划](architecture/implementation-plan.md) - 分阶段实施计划
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,409 @@
|
|||||||
|
# 知识库检索架构说明
|
||||||
|
|
||||||
|
## 一、架构位置
|
||||||
|
|
||||||
|
知识库检索是 Agent 工具层的一部分,为所有 Agent 提供知识查询能力。
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent 层
|
||||||
|
├── Supervisor Agent
|
||||||
|
├── Planner Agent
|
||||||
|
├── SubAgents (ExternalApi, InternalError, Database...)
|
||||||
|
└── Verifier Agent
|
||||||
|
↓ 调用
|
||||||
|
工具层 (Tools)
|
||||||
|
├── searchDoc (文档检索 - L1 向量检索)
|
||||||
|
├── lookup_knowledge (混合检索 - L0+L1) ← 新增
|
||||||
|
├── queryLogs (日志查询)
|
||||||
|
├── queryTrace (链路追踪)
|
||||||
|
└── queryOrder (订单查询)
|
||||||
|
↓ 依赖
|
||||||
|
服务层 (Services)
|
||||||
|
├── VectorSearchService (L1 语义检索 - Milvus)
|
||||||
|
├── KnowledgeIndexService (L0 精确匹配 - 内存) ← 新增
|
||||||
|
├── FrontmatterParser (元数据解析) ← 新增
|
||||||
|
└── DocumentManagementService (文档管理)
|
||||||
|
↓ 持久化
|
||||||
|
数据层
|
||||||
|
├── MySQL (api_document + metadata 字段) ← 增强
|
||||||
|
├── Milvus (向量索引)
|
||||||
|
└── Local Files (knowledge_base/) ← 新增
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、L0+L1 混合检索架构
|
||||||
|
|
||||||
|
### 2.1 检索流程
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent 调用 lookup_knowledge(query)
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ LookupKnowledgeTool │
|
||||||
|
│ (工具入口) │
|
||||||
|
└────────────┬────────────────────────────┘
|
||||||
|
│
|
||||||
|
↓
|
||||||
|
┌────────────────┐
|
||||||
|
│ Step 1: L0 精确匹配 │ < 10ms
|
||||||
|
│ (内存索引) │
|
||||||
|
└────────┬───────────┘
|
||||||
|
│
|
||||||
|
┌───────┴────────┐
|
||||||
|
│ │
|
||||||
|
唯一匹配 多个/零个匹配
|
||||||
|
│ │
|
||||||
|
↓ ↓
|
||||||
|
高置信度 低置信度
|
||||||
|
(不调用L1) (调用L1补充)
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────────┐
|
||||||
|
│ │ Step 2: L1 语义检索 │ 200-500ms
|
||||||
|
│ │ (Milvus) │
|
||||||
|
│ └──────────┬─────────┘
|
||||||
|
│ │
|
||||||
|
└────────┬───────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ Step 3: 组装结果 │
|
||||||
|
│ primary + supplement │
|
||||||
|
└─────────────────────┘
|
||||||
|
↓
|
||||||
|
返回给 Agent
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 数据流
|
||||||
|
|
||||||
|
```
|
||||||
|
文档上传流程:
|
||||||
|
POST /api/documents/upload
|
||||||
|
↓
|
||||||
|
DocumentManagementService.uploadDocument()
|
||||||
|
↓
|
||||||
|
1. 文本提取
|
||||||
|
2. 保存原始文件 → knowledge_base/{category}/{filename}
|
||||||
|
3. 解析 frontmatter (FrontmatterParser)
|
||||||
|
4. 分块 → 向量化 → Milvus 索引 (L1)
|
||||||
|
5. 元数据存 MySQL (metadata 字段 JSON)
|
||||||
|
6. 更新 L0 内存索引 (KnowledgeIndexService)
|
||||||
|
↓
|
||||||
|
完成
|
||||||
|
|
||||||
|
文档查询流程:
|
||||||
|
Agent 调用 lookup_knowledge("ERR_TIMEOUT")
|
||||||
|
↓
|
||||||
|
KnowledgeIndexService.exactMatch()
|
||||||
|
↓
|
||||||
|
遍历内存索引 (keywords 精确匹配)
|
||||||
|
↓
|
||||||
|
找到唯一匹配 → 读取本地文件 (前 2000 字符)
|
||||||
|
↓
|
||||||
|
返回 primary (高置信度)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、核心组件说明
|
||||||
|
|
||||||
|
### 3.1 FrontmatterParser
|
||||||
|
|
||||||
|
**职责**:解析 Markdown 文件头的 YAML frontmatter
|
||||||
|
|
||||||
|
**输入**:
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: 支付网关错误码定义
|
||||||
|
keywords: [ERR_TIMEOUT, 超时, 支付网关]
|
||||||
|
summary: 记录了支付网关所有核心错误码的含义及排查方向
|
||||||
|
category: api
|
||||||
|
---
|
||||||
|
|
||||||
|
# 正文内容
|
||||||
|
```
|
||||||
|
|
||||||
|
**输出**:
|
||||||
|
```java
|
||||||
|
Frontmatter {
|
||||||
|
title: "支付网关错误码定义",
|
||||||
|
keywords: ["ERR_TIMEOUT", "超时", "支付网关"],
|
||||||
|
summary: "...",
|
||||||
|
category: "api"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 KnowledgeIndexService
|
||||||
|
|
||||||
|
**职责**:维护 L0 内存索引,提供精确关键词匹配
|
||||||
|
|
||||||
|
**核心方法**:
|
||||||
|
- `@PostConstruct loadIndex()` - 启动时扫描 knowledge_base/
|
||||||
|
- `exactMatch(String query)` - 精确匹配(不区分大小写)
|
||||||
|
- `readDocument(String filePath, int maxChars)` - 读取文档内容
|
||||||
|
- `addToIndex(KnowledgeEntry entry)` - 添加到索引
|
||||||
|
- `removeFromIndex(String filePath)` - 从索引移除
|
||||||
|
|
||||||
|
**数据结构**:
|
||||||
|
```java
|
||||||
|
List<KnowledgeEntry> knowledgeIndex = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
KnowledgeEntry {
|
||||||
|
filePath: "knowledge_base/api/payment-errors.md",
|
||||||
|
title: "支付网关错误码定义",
|
||||||
|
keywords: ["ERR_TIMEOUT", "超时", "支付网关"],
|
||||||
|
summary: "...",
|
||||||
|
category: "api"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 LookupKnowledgeTool
|
||||||
|
|
||||||
|
**职责**:L0+L1 混合检索工具,Agent 可调用
|
||||||
|
|
||||||
|
**工具定义**:
|
||||||
|
```java
|
||||||
|
@Tool(description = "查询知识库文档。优先精确匹配关键词,未命中或多个匹配时自动补充语义相关片段。" +
|
||||||
|
"参数 query: 查询关键词,例如 'ERR_TIMEOUT'、'支付网关超时'")
|
||||||
|
public LookupResult lookupKnowledge(String query)
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回格式**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"found": true,
|
||||||
|
"primary": {
|
||||||
|
"content": "文档内容(前 2000 字符)",
|
||||||
|
"source": "knowledge_base/api/payment-errors.md",
|
||||||
|
"matchType": "exact_L0",
|
||||||
|
"confidence": "high"
|
||||||
|
},
|
||||||
|
"supplement": {
|
||||||
|
"content": "语义相关片段(L1)",
|
||||||
|
"source": "metadata",
|
||||||
|
"matchType": "semantic_L1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、与现有架构的集成
|
||||||
|
|
||||||
|
### 4.1 Agent 使用场景
|
||||||
|
|
||||||
|
**ExternalApiSubAgent** (接口专家):
|
||||||
|
```
|
||||||
|
诊断步骤:
|
||||||
|
1. 提取错误码(如 "ERR_TIMEOUT")
|
||||||
|
2. 调用 lookup_knowledge("ERR_TIMEOUT")
|
||||||
|
3. 获得完整错误码定义和排查方向
|
||||||
|
4. 结合日志/链路追踪进行分析
|
||||||
|
```
|
||||||
|
|
||||||
|
**DatabaseSubAgent** (数据库专家):
|
||||||
|
```
|
||||||
|
诊断步骤:
|
||||||
|
1. 识别数据库问题(如 "连接池满")
|
||||||
|
2. 调用 lookup_knowledge("HikariCP")
|
||||||
|
3. 获得连接池配置最佳实践
|
||||||
|
4. 提供优化建议
|
||||||
|
```
|
||||||
|
|
||||||
|
**Planner Agent** (规划者):
|
||||||
|
```
|
||||||
|
规划阶段:
|
||||||
|
1. 分析问题类型
|
||||||
|
2. 调用 lookup_knowledge("故障诊断")
|
||||||
|
3. 获得标准诊断流程
|
||||||
|
4. 制定排查策略
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 与现有工具对比
|
||||||
|
|
||||||
|
| 工具 | 检索方式 | 响应时间 | 适用场景 | 置信度 |
|
||||||
|
|------|---------|---------|---------|--------|
|
||||||
|
| searchDoc | L1 语义检索 | 200-500ms | 模糊查询、语义理解 | 依赖相似度 |
|
||||||
|
| lookup_knowledge | L0+L1 混合 | < 10ms (高置信) | 精确关键词 + 语义补充 | high/low |
|
||||||
|
|
||||||
|
**推荐使用策略**:
|
||||||
|
- 已知精确关键词(错误码、配置项)→ `lookup_knowledge`
|
||||||
|
- 模糊描述、需要语义理解 → `searchDoc`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、数据库变更
|
||||||
|
|
||||||
|
### 5.1 api_document 表增强
|
||||||
|
|
||||||
|
**新增字段**:
|
||||||
|
```sql
|
||||||
|
ALTER TABLE api_document
|
||||||
|
ADD COLUMN metadata TEXT COMMENT 'Frontmatter 元数据 (JSON)';
|
||||||
|
```
|
||||||
|
|
||||||
|
**字段说明**:
|
||||||
|
- 类型:TEXT(最大 64KB)
|
||||||
|
- 格式:JSON 字符串
|
||||||
|
- 内容:frontmatter 解析结果
|
||||||
|
|
||||||
|
**示例数据**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "支付网关错误码定义",
|
||||||
|
"keywords": ["ERR_TIMEOUT", "超时", "支付网关"],
|
||||||
|
"summary": "记录了支付网关所有核心错误码的含义及排查方向",
|
||||||
|
"category": "api",
|
||||||
|
"version": "1.0",
|
||||||
|
"author": "zhangsan"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 filePath 字段用途变更
|
||||||
|
|
||||||
|
**原用途**:存储相对路径或 URL
|
||||||
|
|
||||||
|
**新用途**:存储本地文件绝对路径
|
||||||
|
```
|
||||||
|
knowledge_base/api/payment-errors.md
|
||||||
|
knowledge_base/infrastructure/redis-config.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**用途**:
|
||||||
|
1. L0 索引读取完整文档
|
||||||
|
2. 支持未来的章节锚点功能
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、配置说明
|
||||||
|
|
||||||
|
### 6.1 application.yml 新增配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
knowledge:
|
||||||
|
base-path: knowledge_base/
|
||||||
|
```
|
||||||
|
|
||||||
|
**说明**:
|
||||||
|
- 相对于项目根目录
|
||||||
|
- 启动时递归扫描此目录
|
||||||
|
- 建议按 category 组织子目录
|
||||||
|
|
||||||
|
### 6.2 目录结构规范
|
||||||
|
|
||||||
|
```
|
||||||
|
knowledge_base/
|
||||||
|
├── api/ # API 相关文档
|
||||||
|
│ └── payment-errors.md
|
||||||
|
├── infrastructure/ # 基础设施配置
|
||||||
|
│ ├── redis-config.md
|
||||||
|
│ ├── mysql-connection-pool.md
|
||||||
|
│ └── flyway-best-practices.md
|
||||||
|
├── domain/ # 领域知识
|
||||||
|
│ └── spring-ai-tool-best-practices.md
|
||||||
|
└── troubleshooting/ # 故障排查
|
||||||
|
└── fault-diagnosis-process.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、性能指标
|
||||||
|
|
||||||
|
### 7.1 查询性能
|
||||||
|
|
||||||
|
| 场景 | L0 耗时 | L1 耗时 | 总耗时 |
|
||||||
|
|------|---------|---------|--------|
|
||||||
|
| 唯一匹配(高置信) | < 5ms | 0 (不调用) | < 10ms |
|
||||||
|
| 多个匹配(低置信) | < 5ms | 200-500ms | < 500ms |
|
||||||
|
| 未匹配(仅L1) | < 5ms | 200-500ms | < 500ms |
|
||||||
|
|
||||||
|
### 7.2 索引性能
|
||||||
|
|
||||||
|
| 指标 | 实测值 | 目标值 |
|
||||||
|
|------|--------|--------|
|
||||||
|
| 启动扫描时间 | < 20ms (6 个文档) | < 1s (500 个文档) |
|
||||||
|
| 内存占用 | < 1MB (6 个文档) | < 5MB (500 个文档) |
|
||||||
|
| L0 匹配时间 | < 5ms | < 10ms |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、可观测性
|
||||||
|
|
||||||
|
### 8.1 日志追踪
|
||||||
|
|
||||||
|
所有查询都带 requestId(8 位 UUID),可追踪完整流程:
|
||||||
|
|
||||||
|
```
|
||||||
|
[a1b2c3d4] 收到知识库查询请求: query=ERR_TIMEOUT
|
||||||
|
[a1b2c3d4] L0精确匹配完成: matches=1, time=2ms
|
||||||
|
[a1b2c3d4] 置信度判断: highConfidence=true, reason=唯一匹配
|
||||||
|
[a1b2c3d4] L0唯一匹配,跳过L1检索
|
||||||
|
[a1b2c3d4] 查询完成: found=true, confidence=high, totalTime=5ms
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 关键指标
|
||||||
|
|
||||||
|
**监控指标**:
|
||||||
|
- L0 查询耗时(P50/P95/P99)
|
||||||
|
- L1 调用频率(低置信度比例)
|
||||||
|
- 查询总耗时(端到端)
|
||||||
|
- 高置信度命中率
|
||||||
|
|
||||||
|
**告警阈值**:
|
||||||
|
- 查询总耗时 > 2s
|
||||||
|
- L0 索引加载失败
|
||||||
|
- 高置信度命中率 < 20%
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、限制与注意事项
|
||||||
|
|
||||||
|
### 9.1 MVP 阶段限制
|
||||||
|
|
||||||
|
1. **L0 索引无持久化**
|
||||||
|
- 应用重启需要重新扫描
|
||||||
|
- 缓解:启动扫描通常 < 1s
|
||||||
|
|
||||||
|
2. **章节锚点未实现**
|
||||||
|
- sectionTitle 参数预留
|
||||||
|
- availableSections 返回 null
|
||||||
|
|
||||||
|
3. **批量导入不支持**
|
||||||
|
- 当前仅支持单文件上传
|
||||||
|
|
||||||
|
### 9.2 最佳实践
|
||||||
|
|
||||||
|
1. **编写高质量 frontmatter**
|
||||||
|
- keywords 精准且全面
|
||||||
|
- 避免关键词重复(导致多匹配)
|
||||||
|
|
||||||
|
2. **知识库目录组织**
|
||||||
|
- 按 category 分类
|
||||||
|
- 文件命名语义化
|
||||||
|
|
||||||
|
3. **监控告警配置**
|
||||||
|
- 慢查询告警
|
||||||
|
- L0 索引加载失败告警
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、后续增强方向(Phase 2)
|
||||||
|
|
||||||
|
1. **章节锚点**
|
||||||
|
- 支持 sectionTitle 参数
|
||||||
|
- 直接定位到文档特定章节
|
||||||
|
|
||||||
|
2. **L0 索引持久化**
|
||||||
|
- 序列化到文件
|
||||||
|
- 避免重启扫描
|
||||||
|
|
||||||
|
3. **批量导入工具**
|
||||||
|
- 支持目录批量导入
|
||||||
|
- 进度监控
|
||||||
|
|
||||||
|
4. **知识库管理 API**
|
||||||
|
- CRUD 接口
|
||||||
|
- 在线编辑
|
||||||
|
|
||||||
|
5. **向量化元数据**
|
||||||
|
- title/summary 也参与 L1 检索
|
||||||
|
- 提升语义检索准确度
|
||||||
@@ -0,0 +1,477 @@
|
|||||||
|
# 知识库检索使用指南
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 文档格式要求
|
||||||
|
|
||||||
|
所有知识库文档必须包含 YAML frontmatter:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
title: 文档标题(必填)
|
||||||
|
keywords: [关键词1, 关键词2, 关键词3](必填)
|
||||||
|
summary: 文档摘要(必填)
|
||||||
|
category: api(可选)
|
||||||
|
version: 1.0(可选)
|
||||||
|
author: zhangsan(可选)
|
||||||
|
---
|
||||||
|
|
||||||
|
# 正文内容
|
||||||
|
|
||||||
|
这里是文档的正文...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 上传文档
|
||||||
|
|
||||||
|
**API 端点**:
|
||||||
|
```
|
||||||
|
POST /api/documents/upload
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
|
||||||
|
参数:
|
||||||
|
- file: Markdown 文件
|
||||||
|
- category: 分类(如 api, infrastructure, domain, troubleshooting)
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:9900/api/documents/upload \
|
||||||
|
-F "file=@payment-errors.md" \
|
||||||
|
-F "category=api"
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"docId": "abc123-def456-...",
|
||||||
|
"status": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Agent 调用
|
||||||
|
|
||||||
|
在 Agent 对话中,工具会自动可用:
|
||||||
|
|
||||||
|
```
|
||||||
|
用户:ERR_TIMEOUT 是什么错误?
|
||||||
|
|
||||||
|
Agent 内部:
|
||||||
|
1. 调用 lookup_knowledge("ERR_TIMEOUT")
|
||||||
|
2. L0 精确匹配找到 payment-errors.md
|
||||||
|
3. 返回完整错误码定义(高置信度)
|
||||||
|
|
||||||
|
Agent 回复:
|
||||||
|
ERR_TIMEOUT 是支付网关超时错误。
|
||||||
|
原因:...
|
||||||
|
排查方向:...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 编写知识库文档
|
||||||
|
|
||||||
|
### Frontmatter 字段说明
|
||||||
|
|
||||||
|
#### 必填字段
|
||||||
|
|
||||||
|
**title**(标题)
|
||||||
|
```yaml
|
||||||
|
title: 支付网关错误码定义
|
||||||
|
```
|
||||||
|
- 简洁明了,能准确描述文档内容
|
||||||
|
- 建议 10-30 字
|
||||||
|
|
||||||
|
**keywords**(关键词列表)
|
||||||
|
```yaml
|
||||||
|
keywords: [ERR_TIMEOUT, 超时, 支付网关, 错误码]
|
||||||
|
```
|
||||||
|
- 用于 L0 精确匹配
|
||||||
|
- 包含所有可能的查询词
|
||||||
|
- 建议 3-10 个关键词
|
||||||
|
- 既要精确(ERR_TIMEOUT),也要通用(超时)
|
||||||
|
|
||||||
|
**summary**(摘要)
|
||||||
|
```yaml
|
||||||
|
summary: 记录了支付网关所有核心错误码的含义、原因分析及排查方向
|
||||||
|
```
|
||||||
|
- 一句话描述文档用途
|
||||||
|
- 建议 30-100 字
|
||||||
|
|
||||||
|
#### 可选字段
|
||||||
|
|
||||||
|
**category**(分类)
|
||||||
|
```yaml
|
||||||
|
category: api
|
||||||
|
```
|
||||||
|
- 推荐值:api, infrastructure, domain, troubleshooting
|
||||||
|
- 用于目录组织
|
||||||
|
|
||||||
|
**version**(版本)
|
||||||
|
```yaml
|
||||||
|
version: 1.0
|
||||||
|
```
|
||||||
|
- 文档版本号
|
||||||
|
- 便于追踪更新
|
||||||
|
|
||||||
|
**author**(作者)
|
||||||
|
```yaml
|
||||||
|
author: zhangsan
|
||||||
|
```
|
||||||
|
- 文档维护者
|
||||||
|
|
||||||
|
### 关键词设计技巧
|
||||||
|
|
||||||
|
#### ✅ 好的关键词设计
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
keywords: [ERR_TIMEOUT, 超时, 支付网关, timeout, 网关超时, 支付超时]
|
||||||
|
```
|
||||||
|
|
||||||
|
**特点**:
|
||||||
|
- 包含精确术语(ERR_TIMEOUT)
|
||||||
|
- 包含通用描述(超时)
|
||||||
|
- 包含组合词(网关超时、支付超时)
|
||||||
|
- 包含英文(timeout)
|
||||||
|
|
||||||
|
#### ❌ 不好的关键词设计
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
keywords: [错误, 问题]
|
||||||
|
```
|
||||||
|
|
||||||
|
**问题**:
|
||||||
|
- 太宽泛,导致多个文档匹配
|
||||||
|
- Agent 获得低置信度结果
|
||||||
|
|
||||||
|
### 文档内容建议
|
||||||
|
|
||||||
|
#### 结构化内容
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# 支付网关错误码定义
|
||||||
|
|
||||||
|
## ERR_TIMEOUT
|
||||||
|
|
||||||
|
**错误说明**:支付网关调用超时
|
||||||
|
|
||||||
|
**可能原因**:
|
||||||
|
1. 网络延迟
|
||||||
|
2. 支付网关响应慢
|
||||||
|
3. 本地超时配置过短
|
||||||
|
|
||||||
|
**排查步骤**:
|
||||||
|
1. 检查网络连通性
|
||||||
|
2. 查看支付网关监控
|
||||||
|
3. 检查超时配置
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
- 增加超时时间
|
||||||
|
- 优化网络链路
|
||||||
|
- 联系支付网关排查
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 包含实际示例
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 配置示例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
payment:
|
||||||
|
gateway:
|
||||||
|
timeout: 5000ms # 推荐 5 秒
|
||||||
|
retry: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 日志示例
|
||||||
|
|
||||||
|
```
|
||||||
|
2026-06-24 10:00:00 ERROR PaymentService - ERR_TIMEOUT: 支付请求超时
|
||||||
|
orderId: 12345, timeout: 3000ms
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
### 场景 1: 错误码查询
|
||||||
|
|
||||||
|
**用户输入**:
|
||||||
|
```
|
||||||
|
ERR_TIMEOUT 是什么意思?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Agent 流程**:
|
||||||
|
1. 调用 `lookup_knowledge("ERR_TIMEOUT")`
|
||||||
|
2. L0 精确匹配 → 唯一匹配 → 高置信度
|
||||||
|
3. 返回完整文档内容(前 2000 字符)
|
||||||
|
4. Agent 基于文档内容回答
|
||||||
|
|
||||||
|
**响应时间**:< 10ms
|
||||||
|
|
||||||
|
### 场景 2: 配置项查询
|
||||||
|
|
||||||
|
**用户输入**:
|
||||||
|
```
|
||||||
|
Redis 连接池怎么配置?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Agent 流程**:
|
||||||
|
1. 调用 `lookup_knowledge("Redis")`
|
||||||
|
2. L0 精确匹配 → 可能多个匹配 → 低置信度
|
||||||
|
3. 同时调用 L1 语义检索补充
|
||||||
|
4. 返回 primary (L0) + supplement (L1)
|
||||||
|
5. Agent 综合两份结果回答
|
||||||
|
|
||||||
|
**响应时间**:< 500ms
|
||||||
|
|
||||||
|
### 场景 3: 流程查询
|
||||||
|
|
||||||
|
**用户输入**:
|
||||||
|
```
|
||||||
|
如何排查生产故障?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Agent 流程**:
|
||||||
|
1. 调用 `lookup_knowledge("故障排查")`
|
||||||
|
2. L0 精确匹配 → 找到故障诊断文档
|
||||||
|
3. 返回标准诊断流程
|
||||||
|
4. Agent 按照流程指导用户
|
||||||
|
|
||||||
|
### 场景 4: 最佳实践查询
|
||||||
|
|
||||||
|
**用户输入**:
|
||||||
|
```
|
||||||
|
Spring AI 工具怎么写?
|
||||||
|
```
|
||||||
|
|
||||||
|
**Agent 流程**:
|
||||||
|
1. 调用 `lookup_knowledge("Spring AI")`
|
||||||
|
2. L0 + L1 混合检索
|
||||||
|
3. 返回最佳实践文档
|
||||||
|
4. Agent 提供具体建议和代码示例
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 维护知识库
|
||||||
|
|
||||||
|
### 文档更新流程
|
||||||
|
|
||||||
|
1. **修改本地文件**
|
||||||
|
```bash
|
||||||
|
vim knowledge_base/api/payment-errors.md
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **重新上传**
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:9900/api/documents/upload \
|
||||||
|
-F "file=@payment-errors.md" \
|
||||||
|
-F "category=api"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **验证更新**
|
||||||
|
- 重启应用(L0 索引重建)
|
||||||
|
- 或等待下次部署
|
||||||
|
|
||||||
|
### 文档删除
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DELETE /api/documents/{docId}
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意**:
|
||||||
|
- 同时删除 MySQL 记录
|
||||||
|
- 删除 Milvus 向量索引
|
||||||
|
- 删除本地文件
|
||||||
|
- 从 L0 索引移除
|
||||||
|
|
||||||
|
### 查看已索引文档
|
||||||
|
|
||||||
|
启动日志中查看:
|
||||||
|
```
|
||||||
|
[INFO] 开始扫描知识库目录: knowledge_base/
|
||||||
|
[DEBUG] 文档已加入索引: title=支付网关错误码定义
|
||||||
|
[DEBUG] 文档已加入索引: title=Redis 缓存配置指南
|
||||||
|
[INFO] 知识库索引加载完成,共 6 个文档
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 问题 1: 文档未被索引
|
||||||
|
|
||||||
|
**症状**:
|
||||||
|
- 上传成功,但 Agent 查询不到
|
||||||
|
|
||||||
|
**排查**:
|
||||||
|
1. 检查 frontmatter 格式是否正确
|
||||||
|
2. 查看启动日志是否有 WARN
|
||||||
|
3. 确认文件保存位置
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
```bash
|
||||||
|
# 检查文件是否存在
|
||||||
|
ls knowledge_base/api/payment-errors.md
|
||||||
|
|
||||||
|
# 检查 frontmatter 格式
|
||||||
|
head -20 knowledge_base/api/payment-errors.md
|
||||||
|
|
||||||
|
# 重启应用重建索引
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 2: 总是调用 L1(低置信度)
|
||||||
|
|
||||||
|
**症状**:
|
||||||
|
- 查询耗时 > 200ms
|
||||||
|
- 日志显示调用 L1
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- L0 未匹配(关键词不在 keywords 中)
|
||||||
|
- L0 多个匹配(关键词重复)
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
```yaml
|
||||||
|
# 检查关键词是否覆盖查询词
|
||||||
|
keywords: [ERR_TIMEOUT, 超时, timeout]
|
||||||
|
|
||||||
|
# 避免关键词过于宽泛
|
||||||
|
❌ keywords: [错误, 问题] # 太宽泛
|
||||||
|
✅ keywords: [ERR_TIMEOUT, 超时] # 精准
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题 3: 查询返回不完整
|
||||||
|
|
||||||
|
**症状**:
|
||||||
|
- 文档内容被截断
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- 文档过长,L0 只返回前 2000 字符
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
1. 将长文档拆分成多个短文档
|
||||||
|
2. 每个文档聚焦一个主题
|
||||||
|
3. 或等待 Phase 2 章节锚点功能
|
||||||
|
|
||||||
|
### 问题 4: 启动扫描很慢
|
||||||
|
|
||||||
|
**症状**:
|
||||||
|
- 应用启动时间过长
|
||||||
|
|
||||||
|
**原因**:
|
||||||
|
- knowledge_base/ 文件过多
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
```bash
|
||||||
|
# 检查文档数量
|
||||||
|
find knowledge_base -name "*.md" | wc -l
|
||||||
|
|
||||||
|
# 清理无用文档
|
||||||
|
rm knowledge_base/.backup/*.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**参考指标**:
|
||||||
|
- 500 个文档:< 1s
|
||||||
|
- 1000 个文档:可能需要优化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 性能优化
|
||||||
|
|
||||||
|
### 优化关键词匹配率
|
||||||
|
|
||||||
|
**目标**:提高高置信度命中率(减少 L1 调用)
|
||||||
|
|
||||||
|
**方法**:
|
||||||
|
1. 分析查询日志,找到常见查询词
|
||||||
|
2. 将常见查询词加入 keywords
|
||||||
|
3. 定期审查和优化 keywords
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
```bash
|
||||||
|
# 查看低置信度查询
|
||||||
|
grep "confidence=low" logs/application.log | \
|
||||||
|
awk -F'query=' '{print $2}' | \
|
||||||
|
awk -F',' '{print $1}' | \
|
||||||
|
sort | uniq -c | sort -rn
|
||||||
|
```
|
||||||
|
|
||||||
|
### 减少文档数量
|
||||||
|
|
||||||
|
**策略**:
|
||||||
|
- 删除过时文档
|
||||||
|
- 合并相似文档
|
||||||
|
- 归档不常用文档
|
||||||
|
|
||||||
|
### 监控关键指标
|
||||||
|
|
||||||
|
**配置监控**:
|
||||||
|
- L0 查询耗时(目标 < 10ms)
|
||||||
|
- L1 调用频率(目标 < 30%)
|
||||||
|
- 高置信度命中率(目标 > 70%)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 最佳实践总结
|
||||||
|
|
||||||
|
### ✅ 推荐做法
|
||||||
|
|
||||||
|
1. **关键词全面**
|
||||||
|
- 包含精确术语和通用描述
|
||||||
|
- 包含英文和中文
|
||||||
|
- 包含常见拼写变体
|
||||||
|
|
||||||
|
2. **文档聚焦**
|
||||||
|
- 一个文档一个主题
|
||||||
|
- 避免大而全的文档
|
||||||
|
|
||||||
|
3. **结构化内容**
|
||||||
|
- 使用清晰的标题层次
|
||||||
|
- 包含实际示例
|
||||||
|
- 提供具体步骤
|
||||||
|
|
||||||
|
4. **定期维护**
|
||||||
|
- 定期审查和更新
|
||||||
|
- 删除过时内容
|
||||||
|
- 优化关键词
|
||||||
|
|
||||||
|
### ❌ 避免做法
|
||||||
|
|
||||||
|
1. **关键词模糊**
|
||||||
|
```yaml
|
||||||
|
❌ keywords: [错误, 问题]
|
||||||
|
✅ keywords: [ERR_TIMEOUT, 超时]
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **文档过长**
|
||||||
|
```markdown
|
||||||
|
❌ 一个文档包含 50 个错误码定义(会被截断)
|
||||||
|
✅ 每个错误码一个文档,或按类型分组
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **缺少实际示例**
|
||||||
|
```markdown
|
||||||
|
❌ Redis 配置很重要,需要优化
|
||||||
|
✅
|
||||||
|
```yaml
|
||||||
|
spring:
|
||||||
|
redis:
|
||||||
|
lettuce:
|
||||||
|
pool:
|
||||||
|
max-active: 8
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **长期不更新**
|
||||||
|
- 定期审查(建议每季度)
|
||||||
|
- 删除过时内容
|
||||||
|
- 添加新的常见问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- **架构文档**:`mvp/architecture/knowledge-retrieval-architecture.md`
|
||||||
|
- **可观测性**:`.docs/knowledge-observability.md`
|
||||||
|
- **Handoff 文档**:`handoff/2026-06-24-lookup-knowledge-integration.md`
|
||||||
|
- **OpenSpec**:`openspec/changes/lookup-knowledge-integration/`
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
Coding Agent 执行清单:L0+L1 混合检索 MVP 实现
|
||||||
|
你可以直接将以下完整的指令文档复制给你的 Coding Agent(如 Claude Code、Cursor),让它严格按照此规范实现。
|
||||||
|
|
||||||
|
📋 任务总览
|
||||||
|
在现有的 Milvus 向量检索(L1)基础之上,新增一层基于 Markdown 文件头的精确匹配检索(L0),构建一个“先精确、后语义”的混合检索工具 lookup_knowledge。
|
||||||
|
|
||||||
|
一、文件头规范定义
|
||||||
|
所有存放在 knowledge_base/ 目录下的 .md 知识库文档,必须在文件最顶部添加 YAML Frontmatter(被 --- 包裹),包含以下字段:
|
||||||
|
---
|
||||||
|
title: 支付网关错误码定义 # 【必填】文档标题
|
||||||
|
keywords: [ERR_TIMEOUT, 超时, 支付网关] # 【必填】核心关键词数组,用于精确匹配
|
||||||
|
summary: 记录了支付网关所有核心错误码的含义及排查方向。 # 【必填】文档一句话摘要,用于辅助匹配
|
||||||
|
sections: # 【可选】大文件的章节锚点,用于渐进式读取
|
||||||
|
超时排查: "## 1. 超时类错误"
|
||||||
|
限流排查: "## 2. 限流类错误"
|
||||||
|
---
|
||||||
|
# 这里是 Markdown 正文内容...
|
||||||
|
约束:
|
||||||
|
|
||||||
|
文件头必须在文件的最顶部,前面不能有空行。
|
||||||
|
keywords 仅需包含错误码、服务名、专有名词等适合精确匹配的词,不需要长句。
|
||||||
|
|
||||||
|
二、索引模块:启动加载与热更新
|
||||||
|
|
||||||
|
解析依赖:使用 python-frontmatter 库解析 MD 文件头。
|
||||||
|
启动扫描:项目启动时,递归扫描 knowledge_base/ 目录下所有 .md 文件,提取元数据。
|
||||||
|
内存结构:将提取的元数据组装为一个全局列表 KNOWLEDGE_INDEX,结构如下:
|
||||||
|
KNOWLEDGE_INDEX = [
|
||||||
|
{
|
||||||
|
"file": "knowledge_base/payment/errors.md",
|
||||||
|
"title": "支付网关错误码定义",
|
||||||
|
"keywords": ["ERR_TIMEOUT", "超时", "支付网关"],
|
||||||
|
"summary": "记录了...",
|
||||||
|
"sections": {"超时排查": "## 1. 超时类错误"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
热更新监听:使用 watchdog 库监听 knowledge_base/ 目录。当 .md 文件被新增或修改时,重新解析该文件头,并增量更新内存中的 KNOWLEDGE_INDEX 字典。
|
||||||
|
|
||||||
|
三、工具函数实现:lookup_knowledge
|
||||||
|
实现一个名为 lookup_knowledge 的工具供 Agent 调用。
|
||||||
|
1. 函数签名
|
||||||
|
def lookup_knowledge(query_text: str, section_title: str = None) -> dict:
|
||||||
|
2. 执行逻辑(严格按顺序执行)
|
||||||
|
Step 1: Layer 0 精确匹配(前置导航)
|
||||||
|
遍历 KNOWLEDGE_INDEX,将 query_text 与每个条目做大小写不敏感的匹配:
|
||||||
|
|
||||||
|
匹配规则:检查 query_text 是否包含 keywords 数组中的任一词汇;或者 query_text 是否与 summary 有一定的文本重合度(防自然语言漏匹配)。
|
||||||
|
命中处理:
|
||||||
|
|
||||||
|
如果命中,获取该条目的 file 路径。
|
||||||
|
如果传入了 section_title:通过正则表达式,从文件正文中截取 sections[section_title] 对应的标题及其下方段落内容返回。
|
||||||
|
如果未传入 section_title:直接 open() 读取文件内容,截取前 2000 字符返回。
|
||||||
|
标记 match_type: "exact_L0"。
|
||||||
|
|
||||||
|
Step 2: Layer 1 语义检索补充(原 RAG)
|
||||||
|
|
||||||
|
触发条件:无论 L0 是否命中,都调用现有的 Milvus 向量检索逻辑(BGE-M3 embedding + Milvus search),获取 Top-1 的相关 Chunk。
|
||||||
|
目的:作为补充上下文,提供语义关联信息。
|
||||||
|
标记:match_type: "semantic_L1"。
|
||||||
|
|
||||||
|
Step 3: 结果组装与返回
|
||||||
|
将 L0 和 L1 的结果组装成统一格式返回给 Agent。如果两层均无结果,found 置为 False。
|
||||||
|
3. 返回格式规范
|
||||||
|
{
|
||||||
|
"found": true,
|
||||||
|
"primary": {
|
||||||
|
"content": "文档前2000字或指定section内容...",
|
||||||
|
"source": "knowledge_base/payment/errors.md",
|
||||||
|
"match_type": "exact_L0"
|
||||||
|
},
|
||||||
|
"supplement": {
|
||||||
|
"content": "Milvus检索到的Top-1语义片段...",
|
||||||
|
"source": "其他文档路径",
|
||||||
|
"match_type": "semantic_L1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(注:如果 L0 未命中,primary 字段为 null,仅返回 supplement。)
|
||||||
|
|
||||||
|
四、Agent 工具注册定义
|
||||||
|
将 lookup_knowledge 注册为 Agent 可用的工具,工具描述 JSON 如下:
|
||||||
|
{
|
||||||
|
"name": "lookup_knowledge",
|
||||||
|
"description": "查询知识库文档。系统会先尝试通过关键词精确匹配完整文档,并自动补充语义相关的片段。如果已知具体的文档章节,可传入 section_title 获取特定段落。",
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"query_text": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "查询关键词,例如 'ERR_TIMEOUT'、'支付网关超时'"
|
||||||
|
},
|
||||||
|
"section_title": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "可选。如果primary结果返回了sections目录,可通过指定章节标题来获取该章节的详细内容,避免读取大文件超出长度限制。"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["query_text"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
五、实施与验收标准
|
||||||
|
请 Coding Agent 按以下步骤实施并自测:
|
||||||
|
|
||||||
|
安装依赖:pip install python-frontmatter watchdog
|
||||||
|
按照规范实现文件头解析与 watchdog 监听逻辑。
|
||||||
|
改造现有 Agent 代码,按上述逻辑实现 lookup_knowledge。
|
||||||
|
验收用例 1(L0 命中):创建带文件头的 MD,调用 lookup_knowledge("ERR_TIMEOUT"),验证返回的 primary 是否为完整 MD 内容,supplement 是否为 Milvus 的检索结果。
|
||||||
|
验收用例 2(L0 未命中):调用 lookup_knowledge("如何处理系统异常"),验证 primary 是否为 null,supplement 是否正常返回语义结果。
|
||||||
|
验收用例 3(热更新):在程序运行期间修改 MD 的文件头 keywords,再次查询验证内存索引是否已更新。
|
||||||
Reference in New Issue
Block a user