Skip to content

Latest commit

 

History

History
45 lines (30 loc) · 5.49 KB

File metadata and controls

45 lines (30 loc) · 5.49 KB

v0.19.0:检索与索引基建——派生索引 + 全库混合检索(FTS-only 可发布)

状态:已实施(2026-09-03;真机验收待执行) 依据:v0.19 检索与发现层设计(已批准,[ ] 已归档) · ADR-029(已接受) · REQ-258 · REQ-262(部分)

一句话

在既有事实源(notes/fragments)旁新增派生索引(kb_chunks + FTS5 影子表 kb_fts + kb_meta):保存/删除/升笔记经生命周期钩子保持索引一致,reindex_all 一键兜底,kb_search 以 FTS5 全库检索(LIKE 旧链零改动保留);无 embedding 也完整可用(v0.19.3 前 FTS-only 精度,引擎状态如实展示)。

本批已交付

层 内容
纯函数 kb_chunk(heading-aware 节级切块:≤3 空格缩进/16 '#' CommonMark 口径、围栏与缩进代码内不认标题、≤800 字符硬切不吞字、char 区间与文本严格连续——15 用例)· kb_fts(中文 BM25 切词口径校准定案 = trigram + 停用字切段 + 36 字滑窗短语 OR + 2 字词 LIKE 补充 + FTS 语法兜底 LIKE;RRF 融合函数 TDD 先行(v0.19.3 合流预留);snippet ==命中== 全站高亮协议同构——17 用例)
数据层 kb_chunks(多态源双可空 FK + CHECK)/ kb_fts(tokenize='trigram')/ kb_meta 三表 DDL(db_migrations 幂等,既有表零改动)· kb_index(影子表同事务双写收敛模块、不依赖触发器;删除先清影子表 FK 级联仅兜底;kb_meta 失败计数/最近错误软记录不阻断主链路)
生命周期 笔记:create/update_note(正文变化才重建——纯标题零写)/versioned_save(保存收口事务内)/delete(先清后删,knowledge_links 同款位置);碎片:create 一次性入块/delete/promote_fragment_to_note(事务内清碎片块 + 建笔记块)
重建/统计 kb_reindex_all(后台线程 + 逐源进度回调;单源失败软记录继续;启动清失败计数落格式版本——碎片全量重建先清后写修复幂等)+ kb_index_stats(块数/源数/脏源(含孤儿检测)/版本不符/失败计数/last_error)
命令层 kb_search(输入校验 ≤500 字符;命中含 note_id/fragment_id/标题/组名/节标题/snippet/score_kind)· kb_index_stats · kb_reindex_all(Channel 进度事件 Progress/Done/Failed——与聊天流事件同构)

关键校准/实现决定(偏离 spec 草案字面处如实登记)

  1. 中文 BM25 切词口径(spec 遗留 spike 项):索引 tokenizer 用 trigram(非草案默认 unicode61 remove_diacritics)——unicode61 将连续中文句整段视为单 token,整句/子串查询全部落空;trigram 免分词器且 bundled SQLite ≥3.34 已含(FTS5 使能核查同时完成:libsqlite3-sys 0.30.1 bundled 恒编 -DSQLITE_ENABLE_FTS5,含运行时测试覆盖)。代价:<3 字符 token 无法入 MATCH → 查询规划把 2 字词(如"配色")转 kb_chunks LIKE 子串扫描(个人库毫秒级,纯派生表不动 notes 旧链)。
  2. 保存钩子时序(spec 草案:"保存后 spawn_blocking 静默重索引"):改为保存事务内同步重建——Db 连接本由 Mutex 串行,异步线程只把毫秒级开销移出事务却引入"同笔记两次快速保存 → 旧内容后写覆盖新内容"的索引乱序竞态;同步事务内重建零竞态且不阻塞 UI 的量级不变。失败仍软记录(error_count/last_error 角标可见),保存不反悔。
  3. chunk 源 = 净化后正文(notes.content/fragments.text 全部,归档碎片文本仍在库属素材);标题不在 chunk 源内(ADR-029 决策 2 字面)——标题检索继续由既有 LIKE 链承担。

测试与验收

  • kb 纯函数/数据层 54 用例全绿(-- kb_ 过滤实测):切块矩阵(标题/围栏/缩进/空文/800 硬切/字符区间连续性);FTS 查询规划(停用字切段/滑窗展开/双引擎 AND);RRF(空集/双列/并列稳定/截断);snippet(大小写不敏感/多词/省略号);生命周期(建改删/versioned_save/promote/删除清块);reindex_all(幂等/孤儿自愈/FK-off 极端写入口兜底/进度到顶);kb_search(trigram 子串命中/2 字 LIKE/组名溯源/空查询诚实空)
  • 验证:cargo test / clippy 全绿(本批域);全量套件 3 例预存失败(budget_allocator pack_fragments 截断断言 + note_filter golden 2 例——与本次变更域无关,dev HEAD 基线同现,登记观察);既有 LIKE 搜索命令零改动

验收(用户真机,待执行)

  • 编辑/删除笔记后"即时一致";设置→学习库 统计与重建按钮可全量修复(角标如实)
  • 无 embedding 模型时以 FTS 精度工作(引擎状态显示"词法引擎就绪 · 语义未接入")
  • 回归:既有搜索/笔记/碎片流程零回归

关联与后续

  • 设计/ADR:v0.19 设计规格 §五/§六 · ADR-029 · REQ-258/REQ-262(FTS 使能核查 + 中文校准部分落地)
  • 后续:v0.19.1 读路径 A(学习库问答——kb_search/索引即其本地命中链)· v0.19.2 读路径 B · v0.19.3 语义增强(embedding——RRF 已备)

待办

  • 真机验收(重建/角标/精度/回归)
  • kb_fts trigram 在超长单查询(滑窗 OR 膨胀)的性能观察——个人库量级预期毫秒,若超限再收紧滑窗范围(当前 ≤6 字窗仅对 >6 字段展开)