跳转到内容

混合检索策略

混合检索策略:Claude-Mem 的具体实现

学习目标

本章聚焦 Claude-Mem 如何同时使用 SQLite FTS5 和 Chroma 向量数据库进行混合检索。建议先阅读前置知识,下文直接聚焦具体落地方案。

前置知识

本章涉及混合检索的通用原理,建议先阅读:

项目实践

SQLite FTS5 全文搜索

Claude-Mem 的 SQLite 数据库使用 FTS5 虚拟表实现快速全文搜索。搜索覆盖以下字段:

  • observations.text — 观察的主要文本内容
  • observations.title — 观察标题
  • observations.narrative — 叙述性描述
  • observations.facts — 关键事实列表
  • session_summaries 的各文本字段

FTS5 支持布尔查询语法(AND、OR、NOT、前缀匹配),适合精确关键词检索。

Chroma 向量同步

ChromaSync 类(src/services/sync/ChromaSync.ts,约 36KB)负责将 SQLite 中的观察和摘要同步到 Chroma 向量数据库:

关键设计:

  1. 水位线机制ChromaSyncState 记录每个项目最后同步的观察 ID,每次同步只处理新增部分
  2. 每项目独立集合:集合名格式为 cm__{sanitized_project_name},确保不同项目的向量隔离
  3. 批量写入BATCH_SIZE = 100,避免单次请求过大
  4. 元数据过滤:Chroma 文档携带 projecttypememory_session_id 等元数据,支持查询时过滤

Chroma 通过 MCP 调用

Claude-Mem 不直接嵌入 Chroma SDK,而是通过 MCP 工具调用与 Chroma 交互:

  • ChromaMcpManager 管理 Chroma MCP 服务器的连接
  • 通过 @modelcontextprotocol/sdk 的 Client 调用 chroma_querychroma_add 等工具
  • 好处:Chroma 作为独立进程运行,不阻塞 Worker 主进程

混合搜索策略

当 Agent 执行 search 工具时,Claude-Mem 的搜索管线按以下顺序执行:

  1. FTS5 查询:将用户查询转为 FTS5 语法,获取匹配结果
  2. 结果格式化:将 SQLite 行转为紧凑的索引格式(ID + 标题 + 日期 + 类型)
  3. Chroma 补充(可选):在 FTS5 结果不足时,通过 Chroma 语义搜索补充
  4. 去重合并:按相关性评分排序,返回 Top-K

问题与规避

Chroma 进程管理

问题:Chroma 依赖 Python 环境,需要通过 uv(Python 包管理器)管理。

规避:Claude-Mem 在 Setup Hook 中检查并自动安装 uv,通过 uv 安装和运行 Chroma。Worker Service 启动时检查 Chroma MCP 服务器的健康状态。

集合名 sanitization

问题:Chroma 集合名有严格的命名限制(仅允许字母、数字、点、下划线、连字符)。

规避ChromaSync 构造函数中将项目名通过正则替换为安全格式:cm__{sanitized_name},并将非法字符替换为下划线。

设计取舍

为什么用 MCP 调用 Chroma 而非直接 SDK?

  • 优势:Chroma 作为独立进程,崩溃不影响 Worker;可以通过 MCP 协议切换不同的向量数据库后端
  • 代价:额外的进程间通信开销
  • 替代方案:直接使用 chromadb Python SDK 或 JS binding。Claude-Mem 选择 MCP 路径以保持进程隔离和可扩展性

参考来源