edit | blame | history | raw

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:搜索时显示关联文档链接
  1. 调整 kb-search 技能:
  • 优先使用 kb-cli
  • Python 脚本降级为备选方案

2. 方案选择

2.1 候选方案

方案 描述 优点 缺点
A. 最小改动 在 SearchResult 结构体上加可选字段 改动小,向后兼容,逻辑清晰
B. 分层增强 创建 Enhancer 接口,搜索管道模式 扩展性强 过度设计
C. 独立命令 新增 kb search-detail 子命令 职责清晰 重复代码多

2.2 决策

选择方案 A:最小改动

理由:
1. 改动最小,只改 search.gooutput/formatter.go
2. 向后兼容,现有脚本不受影响
3. 逻辑简单,容易理解和维护
4. 不需要过度设计


3. 数据结构改动

3.1 SearchResult 结构体

文件: internal/search/engine.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

type SearchOptions struct {
    Expanded    []string
    Symptom     []string
    TopN        int
    WithContent bool   // 新增
    WithLinks   bool   // 新增
}

3.3 Search 函数逻辑

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)

func (s *Store) GetNodeContent(id int64) (string, []string, []string, error)

返回:(content, tags, entities, error)

4.2 关联链接获取

新增方法: store.GetNodeLinks(nodeID)

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

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

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 输出

[
  {
    "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 降级方案

## 降级方案

仅当 kb-cli 不可用时,使用 kb-search.py:

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 集成测试

# 测试基础搜索
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 方法
  1. 搜索逻辑改动
  • 修改 Search 函数,增加内容获取和链接获取逻辑
  1. CLI 命令改动
  • 新增 --with-content--with-links flag
  • 传递给 SearchOptions
  1. 输出格式化改动
  • 修改 FormatTableFormatJSON 方法
  • 支持内容和链接的输出
  1. 测试
  • 单元测试
  • 集成测试
  • 对比测试
  1. 技能文档更新
  • 更新 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