# kb-cli 增强与 kb-search 技能调整设计 **日期:** 2026-07-26 **状态:** 已批准 --- ## 1. 背景与目标 ### 1.1 背景 kb-cli(Go 实现)已完成基础功能,与 Python 版 kb-search.py 对比测试显示: - **kb-cli 优势:** 索引正常(768 文件),搜索快速(8ms),结果准确 - **kb-search.py 问题:** 索引为空(update-index 返回 0 条),搜索返回空结果 用户决策:优先使用 kb-cli,Python 脚本暂时保留作为备选。 ### 1.2 目标 1. **给 kb-cli 增加两个功能:** - `--with-content`:搜索时返回完整文件内容 - `--with-links`:搜索时显示关联文档链接 2. **调整 kb-search 技能:** - 优先使用 kb-cli - Python 脚本降级为备选方案 --- ## 2. 方案选择 ### 2.1 候选方案 | 方案 | 描述 | 优点 | 缺点 | |------|------|------|------| | **A. 最小改动** | 在 SearchResult 结构体上加可选字段 | 改动小,向后兼容,逻辑清晰 | 无 | | B. 分层增强 | 创建 Enhancer 接口,搜索管道模式 | 扩展性强 | 过度设计 | | C. 独立命令 | 新增 `kb search-detail` 子命令 | 职责清晰 | 重复代码多 | ### 2.2 决策 **选择方案 A:最小改动** 理由: 1. 改动最小,只改 `search.go` 和 `output/formatter.go` 2. 向后兼容,现有脚本不受影响 3. 逻辑简单,容易理解和维护 4. 不需要过度设计 --- ## 3. 数据结构改动 ### 3.1 SearchResult 结构体 **文件:** `internal/search/engine.go` ```go type SearchResult struct { ID int64 `json:"id"` Path string `json:"path"` Title string `json:"title"` Section string `json:"section"` Score int `json:"score"` // 新增可选字段 Content string `json:"content,omitempty"` // --with-content 时填充 Links []string `json:"links,omitempty"` // --with-links 时填充 } ``` ### 3.2 SearchOptions 结构体 **文件:** `internal/search/engine.go` ```go type SearchOptions struct { Expanded []string Symptom []string TopN int WithContent bool // 新增 WithLinks bool // 新增 } ``` ### 3.3 Search 函数逻辑 ```go func Search(store *index.Store, keywords []string, opts SearchOptions) ([]SearchResult, error) { // 1. 执行 FTS5 搜索 ftsResults, err := store.FTSSearch(allKeywords, 100) if err != nil { return nil, err } // 2. 评分和排序 results := scoreAndSort(ftsResults, keywords, opts) // 3. 限制返回数量 if opts.TopN > 0 && len(results) > opts.TopN { results = results[:opts.TopN] } // 4. 增强结果(新增) for i := range results { // 获取内容 if opts.WithContent { content, _, _, err := store.GetNodeContent(results[i].ID) if err == nil { results[i].Content = content } } // 获取关联链接 if opts.WithLinks { links, err := store.GetNodeLinks(results[i].ID) if err == nil { results[i].Links = links } } } return results, nil } ``` --- ## 4. 数据获取逻辑 ### 4.1 内容获取 **已有方法:** `store.GetNodeContent(id)` ```go func (s *Store) GetNodeContent(id int64) (string, []string, []string, error) ``` 返回:`(content, tags, entities, error)` ### 4.2 关联链接获取 **新增方法:** `store.GetNodeLinks(nodeID)` ```go func (s *Store) GetNodeLinks(nodeID int64) ([]string, error) { query := ` SELECT n.path FROM edges e JOIN nodes n ON n.id = e.to_node WHERE e.from_node = ? AND e.relation = 'wikilink' ` rows, err := s.db.Query(query, nodeID) if err != nil { return nil, err } defer rows.Close() var links []string for rows.Next() { var path string if err := rows.Scan(&path); err != nil { return nil, err } links = append(links, path) } return links, nil } ``` **查询逻辑:** - 查询 `edges` 表,`relation='wikilink'` - 返回目标节点的 `path`(即关联文档路径) --- ## 5. CLI 命令改动 ### 5.1 新增 flag **文件:** `cmd/search.go` ```go var ( withContent bool withLinks bool ) func init() { // ... 现有 flag searchCmd.Flags().BoolVar(&withContent, "with-content", false, "返回完整文件内容") searchCmd.Flags().BoolVar(&withLinks, "with-links", false, "显示关联文档链接") } ``` ### 5.2 传递给 SearchOptions ```go func runSearch(cmd *cobra.Command, args []string) error { opts := search.SearchOptions{ Expanded: expanded, Symptom: symptom, TopN: topN, WithContent: withContent, WithLinks: withLinks, } results, err := search.Search(store, args, opts) // ... } ``` --- ## 6. 输出格式化改动 ### 6.1 表格输出 **文件:** `internal/output/formatter.go` **基础输出(无增强):** ``` 路径 标题 板块 得分 -------------------------------------------------- FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6 ``` **带内容(--with-content):** ``` 路径 标题 板块 得分 -------------------------------------------------- FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6 --- 内容 --- # 扫码验证气瓶充装 ## 问题描述 ... ``` **带链接(--with-links):** ``` 路径 标题 板块 得分 -------------------------------------------------- FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6 --- 关联文档 --- - 典型案例/充装异常案例.md - 文档/电子秤平台/平台文档/023-充装统计与票据核对.md ``` **两者都有(--with-content --with-links):** ``` 路径 标题 板块 得分 -------------------------------------------------- FAQ/充装类/087-xxx.md 扫码验证气瓶充装 FAQ 6 --- 内容 --- # 扫码验证气瓶充装 ... --- 关联文档 --- - 典型案例/充装异常案例.md ``` ### 6.2 JSON 输出 ```json [ { "id": 1577, "path": "FAQ/充装类/087-xxx.md", "title": "扫码验证气瓶充装", "section": "FAQ", "score": 6, "content": "# 扫码验证气瓶充装\n\n## 问题描述\n...", "links": [ "典型案例/充装异常案例.md", "文档/电子秤平台/平台文档/023-充装统计与票据核对.md" ] } ] ``` --- ## 7. kb-search 技能调整 ### 7.1 优先级策略 1. **优先使用 kb-cli:** `kb search "关键词" --with-content --top 3` 2. **降级到 kb-search.py:** 仅当 kb-cli 不可用时 ### 7.2 技能文档改动 **核心工具:** - 从 `kb-search.py` 改为 `kb` **命令示例:** ```bash # 基础搜索 kb search "充装规格" --top 5 # 带内容 kb search "充装规格" --with-content --top 3 # 带链接 kb search "充装规格" --with-links --top 3 # 带扩展词和症状词 kb search "充装" --expanded "重量 规格" --symptom "报错 无法启动" --with-content --top 3 ``` **保留内容:** - `--expanded`、`--symptom` 用法说明 - 搜索策略(术语映射、关键词选择) - 最佳实践(决策树、案例) **移到降级方案:** - kb-search.py 完整用法移到"降级方案"章节 ### 7.3 降级方案 ```markdown ## 降级方案 仅当 kb-cli 不可用时,使用 kb-search.py: ```bash export KB_VAULT=/home/aisim-p/aisim/note/001/笔记001 python3 ~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.py search "关键词" --with-content --top 3 ``` 注意:kb-search.py 当前有索引问题,可能返回空结果。 ``` --- ## 8. 测试计划 ### 8.1 单元测试 - 测试 `SearchResult` 结构体的 JSON 序列化(`omitempty` 行为) - 测试 `GetNodeLinks` 方法 ### 8.2 集成测试 ```bash # 测试基础搜索 kb search "充装" --top 5 # 测试带内容 kb search "充装" --with-content --top 3 # 测试带链接 kb search "充装" --with-links --top 3 # 测试两者都有 kb search "充装" --with-content --with-links --top 3 # 测试 JSON 输出 kb search "充装" --with-content --json --top 3 ``` ### 8.3 对比测试 与 Python 版对比: ```bash # Go 版 kb search "充装" --with-content --top 3 # Python 版 python3 kb-search.py search "充装" --with-content --top 3 ``` --- ## 9. 实施步骤 1. **数据结构改动** - 修改 `SearchResult` 结构体 - 修改 `SearchOptions` 结构体 - 实现 `GetNodeLinks` 方法 2. **搜索逻辑改动** - 修改 `Search` 函数,增加内容获取和链接获取逻辑 3. **CLI 命令改动** - 新增 `--with-content` 和 `--with-links` flag - 传递给 `SearchOptions` 4. **输出格式化改动** - 修改 `FormatTable` 和 `FormatJSON` 方法 - 支持内容和链接的输出 5. **测试** - 单元测试 - 集成测试 - 对比测试 6. **技能文档更新** - 更新 kb-search 技能文档 - 调整优先级策略 --- ## 10. 风险与缓解 | 风险 | 缓解措施 | |------|----------| | 内容获取慢(大量文件) | 限制 `--top N`,默认 10 | | 链接查询慢 | 使用索引,查询 `edges` 表 | | JSON 输出过大 | `omitempty` 标签,不填充时不输出 | | 向后兼容 | 新增字段为可选,不影响现有脚本 | --- ## 11. 成功标准 1. ✅ kb-cli 支持 `--with-content` 和 `--with-links` 2. ✅ 输出格式正确(表格和 JSON) 3. ✅ 性能可接受(< 100ms) 4. ✅ kb-search 技能文档更新完成 5. ✅ 对比测试通过(优于 Python 版) --- ## 12. 附录 ### 12.1 相关文件 - `internal/search/engine.go` - 搜索逻辑 - `internal/index/sqlite.go` - 数据库操作 - `internal/output/formatter.go` - 输出格式化 - `cmd/search.go` - CLI 命令 - `~/.hermes/skills/kb-knowledge/kb-search/SKILL.md` - 技能文档 ### 12.2 参考 - Python 版 kb-search.py:`~/.hermes/skills/kb-knowledge/kb-search/scripts/kb-search.py` - SQLite 数据模型:`docs/superpowers/specs/2026-07-26-kb-cli-design.md`