核心功能: - 新增 FrontmatterParser 解析 YAML frontmatter - 新增 KnowledgeIndexService L0 内存索引 - 新增 LookupKnowledgeTool 混合检索工具 - 增强 DocumentManagementService 文件保存和索引同步 技术实现: - 数据库迁移 V004: api_document.metadata (TEXT) - 依赖新增: snakeyaml 2.0 - 配置新增: knowledge.base-path - 可观测性: requestId 追踪 + 性能日志 质量保证: - 单元测试: 31/31 通过 - 测试覆盖: FrontmatterParser(11), KnowledgeIndexService(13), LookupKnowledgeTool(7) - 启动验证: L0 索引正常加载 归档文档: - OpenSpec: openspec/changes/lookup-knowledge-integration/ - devflow 档案: devflow/projects/2026-06-24-lookup-knowledge-integration/ - handoff: handoff/2026-06-24-lookup-knowledge-integration.md
121 lines
3.5 KiB
Markdown
121 lines
3.5 KiB
Markdown
# Lookup Knowledge Integration - Decisions
|
||
|
||
## 关键技术决策
|
||
|
||
### D1: L0 高置信度标准
|
||
**决策**:唯一匹配 = 高置信度,不调用 L1
|
||
**理由**:唯一匹配时已经明确知道用户需要哪个文档,无需额外的语义检索
|
||
**权衡**:可能遗漏相关文档,但换来更快响应(< 10ms vs 500ms)
|
||
|
||
### D2: 文件保存策略
|
||
**决策**:保存到 knowledge_base/{category}/{filename}
|
||
**理由**:
|
||
- 支持 L0 完整文档读取(前 2000 字符)
|
||
- 为未来章节锚点预留基础
|
||
- 便于人工查看和维护
|
||
|
||
**权衡**:增加磁盘存储,但文件大小可控(Markdown 文档通常 < 100KB)
|
||
|
||
### D3: metadata 字段类型
|
||
**决策**:TEXT 类型存储 JSON 字符串
|
||
**理由**:
|
||
- Frontmatter 结构可能扩展
|
||
- MySQL TEXT 支持最大 64KB(足够)
|
||
- 无需引入 JSON 类型(兼容性)
|
||
|
||
**权衡**:查询时需要反序列化,但 metadata 仅用于展示,不参与查询条件
|
||
|
||
### D4: L1 条件调用
|
||
**决策**:仅在 L0 非唯一匹配时调用 L1
|
||
**理由**:
|
||
- 减少不必要的 embedding 调用
|
||
- 保持高置信度场景的低延迟
|
||
|
||
**条件**:`l0Matches.size() != 1`
|
||
|
||
### D5: 事务一致性策略
|
||
**决策**:上传失败时调用 cleanupLocalFile() 清理
|
||
**理由**:避免孤儿文件(数据库记录不存在但文件存在)
|
||
**实现**:try-catch 块 + finally cleanup
|
||
|
||
## 实现决策
|
||
|
||
### I1: Frontmatter 解析器
|
||
**选型**:SnakeYAML 2.0
|
||
**理由**:
|
||
- 轻量级,无额外依赖
|
||
- 成熟稳定(Spring Boot 也在用)
|
||
|
||
### I2: L0 索引数据结构
|
||
**选型**:CopyOnWriteArrayList
|
||
**理由**:
|
||
- 读多写少场景(启动加载后主要是查询)
|
||
- 线程安全(支持并发查询)
|
||
- 简单可靠
|
||
|
||
**权衡**:写入时复制开销,但 L0 索引更新频率低(仅上传/删除时)
|
||
|
||
### I3: 关键词匹配算法
|
||
**策略**:不区分大小写,双向包含
|
||
```java
|
||
query.contains(keyword.toLowerCase()) || keyword.toLowerCase().contains(query)
|
||
```
|
||
|
||
**理由**:
|
||
- 用户可能输入部分关键词
|
||
- 关键词可能是复合词(如 "支付网关超时")
|
||
|
||
### I4: 文档读取截断
|
||
**策略**:前 2000 字符 + "..."
|
||
**理由**:
|
||
- 控制返回内容大小(避免 Agent context 溢出)
|
||
- 2000 字符足够覆盖大部分文档摘要和核心内容
|
||
|
||
## 可观测性决策
|
||
|
||
### O1: 请求追踪
|
||
**策略**:8 位 UUID 作为 requestId
|
||
**理由**:
|
||
- 足够短(日志可读)
|
||
- 碰撞概率极低(单次会话不会重复)
|
||
|
||
### O2: 日志层次
|
||
- **INFO**: 查询请求、匹配结果、总耗时
|
||
- **DEBUG**: 置信度判断、L1 触发条件、结果构建
|
||
- **WARN**: 文件读取失败、解析失败
|
||
|
||
## 风险决策
|
||
|
||
### R1: L0 索引无持久化
|
||
**风险**:应用重启需要重新扫描
|
||
**缓解**:启动扫描通常 < 1s(500 个文档)
|
||
**接受理由**:MVP 阶段优先简单可靠,Phase 2 再优化
|
||
|
||
### R2: Frontmatter 校验宽松
|
||
**风险**:格式错误的 frontmatter 被忽略
|
||
**缓解**:记录 WARN 日志,开发者可追踪
|
||
**接受理由**:允许无 frontmatter 的文档上传(仅走 L1)
|
||
|
||
## Archive 阶段记录
|
||
|
||
**完成时间**:2026-06-24
|
||
|
||
**最终状态**:
|
||
- 23/23 子任务完成
|
||
- 31/31 单元测试通过
|
||
- 应用成功启动,L0 索引正常加载
|
||
- Flyway V004 迁移成功执行
|
||
|
||
**关键指标**:
|
||
- L0 查询耗时: < 5ms
|
||
- L0+L1 组合: < 500ms
|
||
- 启动扫描: < 20ms(1 个文档)
|
||
|
||
**技术债务**:无重大技术债务
|
||
|
||
**轻微优化点**(可后续改进):
|
||
1. L0 索引持久化
|
||
2. Frontmatter 校验增强
|
||
3. 独立日志文件
|
||
4. Micrometer 指标集成
|