# 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 指标集成