在日常开发与知识管理工作中,如何高效检索本地文档始终是刚性需求。传统方案往往依赖云端服务或重量级数据库,而 QMD(Query Markup Documents)作为一款完全离线的迷你 CLI 搜索引擎,巧妙地将 BM25 全文搜索、向量化语义检索与大语言模型重排序融为一体,为知识库、会议笔记、技术文档等场景提供了轻量且高效的本地检索方案。
核心架构:三层检索管道
QMD 的设计目标非常明确:在个人设备上构建可离线运行的全文本检索系统,同时保证搜索质量。其架构核心是一条混合检索管道,包含以下三个关键层次。
第一层是 BM25 全文检索。QMD 基于 SQLite FTS5 实现 BM25 排名算法,这是一种经典的词频 - 逆文档频率变体,能够快速定位包含查询关键词的文档。BM25 的优势在于对关键词匹配极其敏感,响应速度通常在毫秒级别,适合需要快速定位精确匹配的场景。
第二层是向量化语义搜索。QMD 通过 node-llama-cpp 加载 GGUF 格式的嵌入模型(默认使用 embeddinggemma-300M-Q8_0),将文档和查询转换为高维向量,然后计算余弦相似度。这种方式能够捕捉语义相近但用词不同的文档,例如搜索「用户登录」时,文档中出现「身份验证」的内容同样可能被召回。
第三层是 LLM 重排序。当用户使用 qmd query 命令时,系统会将前 30 名候选文档交给轻量级的重排序模型(qwen3-reranker-0.6b-q8_0)进行二次判断。该模型以交叉编码方式评估每个文档与查询的相关性,输出 0 到 1 的置信度分数,最终与检索阶段的分数进行加权融合。
查询扩展与融合策略
单纯的检索管道容易受到词不匹配问题的困扰,QMD 为此引入了两项关键优化。
查询扩展机制使用微调过的 Qwen3-1.7B 模型(qmd-query-expansion-1.7B-q4_k_m)自动生成查询变体。当用户输入「项目时间线」时,模型可能生成「里程碑规划」「进度安排」等替代表达,随后这些表达会并行执行 BM25 和向量搜索,结果合并后进入下一阶段。这种设计显著提升了长尾查询和口语化表达的召回率。
融合策略采用倒数排名融合(RRF)算法,并将原始查询的权重设为 2 倍,同时为各列表中排名前三的文档提供 +0.05 到 +0.02 的分数加成。融合后会进入重排序阶段,最终采用位置感知 blending:排名前三的结果 75% 信任检索分数、25% 信任重排序分数;排名四到十的为 60% 对 40%;排名十一以后的则为 40% 对 60%。这种差异化策略既保护了精确匹配不被稀释,又让语义相关的候选文档有机会脱颖而出。
智能文档分块与上下文管理
高效的检索离不开合理的文档切分策略。QMD 默认将文档分割为约 900 个 token 的块,相邻块之间保留 15% 的重叠以保持上下文连续性。与简单按固定长度切分不同,QMD 采用基于得分的智能断点检测算法,优先在 Markdown 标题、代码块分隔符、水平线等语义边界处切分。例如,H1 标题得分为 100,H2 为 90,代码块起始符为 80,空白行仅为 20。算法在接近 900 token 上限时,会在前后 200 token 窗口内寻找得分最高的断点,确保语义单元的完整性。
对于代码文件,QMD 还支持基于 tree-sitter 的 AST 感知分块。当启用 --chunk-strategy auto 参数时,系统会为函数定义、类声明、导入语句等节点赋予较高得分,从而在语法结构边界处切分,这对搜索特定函数或类的实现尤为有效。目前支持 TypeScript、JavaScript、Python、Go、Rust 等语言。
上下文管理是 QMD 的另一项特色功能。用户可以通过 qmd context add 命令为集合或特定路径添加描述性元数据,例如将「/notes」标记为「个人笔记与想法」,将「/work/docs」标记为「工作文档」。这些上下文信息会在搜索结果中返回,帮助大语言模型更好地理解文档来源和用途,从而在 Agent 工作流中做出更准确的决策。
部署与集成方案
QMD 以 Node.js 包的形式发布,支持 Node.js 22+ 或 Bun 1.0+ 运行环境。全局安装后,用户可以通过简单的命令添加集合、生成嵌入、执行搜索。例如:
# 添加文档集合
qmd collection add ~/notes --name notes
# 生成向量嵌入
qmd embed
# 混合搜索(最高质量)
qmd query "项目规划"
# 纯关键词搜索(最快)
qmd search "API 文档"
对于 AI Agent 集成,QMD 暴露了完整的 MCP(Model Context Protocol)服务器,支持 stdio 和 HTTP 两种传输模式。通过配置 Claude Desktop 或 Claude Code 的插件系统,可以直接将 QMD 作为工具调用,实现「搜索 - 读取 - 分析」的自动化工作流。搜索结果支持 JSON、CSV、Markdown 等多种输出格式,便于程序化处理。
值得注意的是,QMD 的所有模型均为本地加载,首次使用时会自动从 HuggingFace 下载约 2GB 的 GGUF 文件并缓存到 ~/.cache/qmd/models/ 目录。全部运算在本地完成,无需网络连接。对于需要处理中文、日文等多语言文档的场景,可以通过设置 QMD_EMBED_MODEL 环境变量切换到 Qwen3-Embedding-0.6B 模型,以获得更好的多语言覆盖。
工程实践建议
在实际部署中,有几个参数值得特别关注。搜索结果数量默认 5 条,但如果是程序调用建议通过 -n 参数增加到 10 到 20 条,并配合 --min-score 阈值过滤低相关度结果。重排序阶段默认开启,若对延迟敏感且对召回质量要求稍低,可以使用 qmd search 或 qmd vsearch 跳过重排序步骤。索引更新建议定期执行 qmd update,新增文件会自动纳入索引,已删除文件会被标记清理。
对于代码仓库场景,推荐启用 --chunk-strategy auto 以获得基于函数和类的精准切分效果。对于文档密集的知识库场景,建议为每个顶层目录添加上下文描述,这不仅能提升搜索相关性,还能在 Agent 场景中提供有价值的来源信息。
小结
QMD 通过将传统 BM25 检索与现代向量化语义搜索相结合,再引入轻量级 LLM 进行查询扩展和结果重排序,形成了一套兼顾速度与质量的本地检索方案。其完全离线运行、零外部依赖的特性,使其成为个人知识管理、开发者文档检索、会议笔记整理等场景的理想选择。借助于 MCP 协议的支持,QMD 还能无缝融入 AI Agent 工作流,为自动化信息获取提供基础设施层面的支撑。