qmd 详解:Shopify CEO 开源的本地 Markdown 搜索引擎
给 AI 代理喂"对的上下文"越来越重要,而多数方案要把笔记、文档传上云端。Shopify CEO Tobias Lütke(GitHub ID:tobi)开源的 qmd 给出了另一条路:一个完全跑在本地的迷你 CLI 搜索引擎,专门检索 Markdown 笔记、会议纪要与文档,把 BM25 全文检索、向量语义检索与 LLM 重排装进一条命令,还内置 MCP 服务供 Claude 等代理直接调用。本文从安装、三档搜索、混合检索原理到代理集成,完整拆解。
1、项目概述
qmd(Query Markup Documents)是一个本地运行的文档搜索引擎 CLI。仓库约 28.9k Star、1.8k Fork、666 次提交,MIT 协议。一句话定位:全本地(笔记不出机器)、三档搜索、为代理工作流而生。
技术要点:
- TypeScript 编写,需 Node.js 22+ 或 Bun 1.0+
- 存储:SQLite 一文件搞定——FTS5 做 BM25 全文 + sqlite-vec 做向量索引
- 推理:node-llama-cpp 跑本地 GGUF 模型,共约 2GB,无需联网 API
- 可选 tree-sitter,对代码文件做 AST 级智能分块
2、安装、配置与模型
安装就是一条全局 npm / bun 命令,模型首次使用时自动下载。
// 安装(Node.js 22+ 或 Bun 1.0+)
npm install -g @tobilu/qmd
// 或
bun install -g @tobilu/qmd
// 免安装直接跑
npx @tobilu/qmd --help三个本地模型(自动下载到 ~/.cache/qmd/models/):
- embeddinggemma-300M(约 300MB):生成嵌入向量
- qwen3-reranker-0.6b(约 640MB):检索结果重排
- qmd-query-expansion-1.7B(约 1.1GB):查询扩展,官方微调
配置要点:
1. 全局配置在 ~/.config/qmd/index.yml,集合、模型、钩子都写在这里
2. 项目级索引用 qmd init 生成 .qmd/index.yml,随仓库提交
3. macOS 需要先 brew install sqlite
4. 可用 models 配置块或环境变量换用其他 HuggingFace 模型
3、三档搜索:search / vsearch / query
qmd 把检索分成由快到好的三档,按场景选用。
// 关键词搜索(BM25,最快)
qmd search "project timeline"
// 语义搜索(向量,能理解同义与改述)
qmd vsearch "how to deploy"
// 混合检索 + LLM 重排(质量最好)
qmd query "quarterly planning process"三档定位:
1. search:纯 FTS5 关键词匹配,毫秒级响应,适合记得关键词时
2. vsearch:向量语义匹配,问法不同也能找到,需先 qmd embed
3. query:扩展查询 + 双路检索 + 重排的完整流水线,问答质量最好
4. 语义与混合档都要先生成嵌入(见第 5 节)
4、混合检索流水线原理
query 命令背后是一条五步流水线,把"关键词"与"语义"两路优势融合起来。
流水线五步:
1. 查询扩展:微调的 1.7B 模型把问题改写成多个变体,原查询权重加倍
2. 双路并行:每个变体同时跑 FTS5 与向量检索
3. RRF 融合:用 Reciprocal Rank Fusion(k=60,另加榜首加成)合并两路排名
4. LLM 重排:取前 30 候选,0.6B 重排模型逐个判断相关性并给置信度
5. 位置感知混合:前 3 名给检索结果 75% 权重,4-10 名 60%,11 名以后 40%
分块与索引:
- 文档切成约 900 token 的块,块间 15% 重叠,按标题、代码围栏打分选断点
- 代码文件可用 tree-sitter 按 AST 分块(--chunk-strategy auto)
- 索引流程:glob 收文件 → 解析标题 → 内容哈希 → 生成 6 位 docid → 入库并建 FTS 索引
5、集合、上下文与嵌入
检索之前,先把要搜的目录登记成"集合",并给它们挂上帮 LLM 选库的"上下文"描述。
// 把目录登记为集合
qmd collection add ~/notes --name notes
qmd collection add ~/Documents/meetings --name meetings
// 给集合挂描述性上下文(帮 LLM 判断该查哪个库)
qmd context add qmd://notes "Personal notes and ideas"
// 生成向量嵌入(用语义/混合搜索前先跑)
qmd embed
// 重新索引(会先执行配置的 update 钩子,如 git pull)
qmd update管理要点:
1. collection add 登记目录,可再配 glob 模式、忽略规则、默认是否包含
2. update 钩子可在重索引前执行 git pull 等命令,保持语料最新
3. context 是官方强调的关键特性:给集合或路径写清"里面是什么"
4. 文档变动后 qmd update 重索引,再 qmd embed 补嵌入
6、检索读取与代理输出
搜到只是第一步,qmd 还提供精确读取与多种代理友好输出。
// 按路径 / docid / 行号读取
qmd get "meetings/2024-01-15.md"
qmd get "#abc123"
qmd get "#abc123:120:40" // 从第 120 行起取 40 行
// 批量读取(支持通配符)
qmd multi-get "journals/2025-05*.md"
// 限定集合、只出文件列表、按分数过滤
qmd search "API" -c notes -c docs
qmd search "API" --all --files --min-score 0.3
// 代理友好:JSON 输出 + 得分解释
qmd search "authentication" --json -n 10
qmd query --json --explain "quarterly reports"读取要点:
1. get 支持路径、#docid、#docid:起始行:行数 三种定位方式
2. multi-get 用通配符一次读多个文档
3. -c 限定集合,--files 只列路径,--min-score 过滤低分结果
4. 输出格式含 cli / json / csv / md / xml / files,--explain 可看得分构成
7、MCP 服务、安全与工程化
qmd 内置 MCP 服务,可被 Claude Desktop / Claude Code 等代理当工具调用;安全与评测能力也一应俱全。
// 启动 MCP 服务(stdio 模式,接入 Claude 等)
qmd mcp
// 或 HTTP 模式(提供 /mcp、/query 接口与 /health 健康检查)
qmd mcp --http --port 8080
// 查看索引健康状态
qmd statusMCP 与安全:
- MCP 工具集:query、get、multi_get、status 四个
- HTTP 模式校验 Origin / Host 头,防 DNS rebinding 攻击,可用环境变量配置白名单
- 仓库里提交的 .qmd 配置若含外部路径、自定义模型或更新命令,需 qmd trust 显式批准
工程化能力:
- qmd bench:用 JSON fixture 评测 precision@k、recall、MRR、F1
- qmd doctor 体检环境,qmd init 建项目级索引
- 可作为 SDK 在 Node / Bun 里调用:createStore()、search()、get() 等
- 结果带可点击链接,跳转 VS Code / Cursor / Zed / Sublime 对应位置
8、总结
qmd 是 Shopify CEO Tobias Lütke 开源的本地文档搜索引擎,28.9k Star、MIT 协议。它用 SQLite 一个文件承载 FTS5 与 sqlite-vec 双索引,配三个本地 GGUF 模型(嵌入、重排、查询扩展,共约 2GB),提供 BM25、向量、混合重排三档搜索;混合档经查询扩展、双路检索、RRF 融合与位置感知重排,质量最佳。集合与上下文管理语料,get / multi-get 精确读取,--json 与 MCP 服务无缝对接 AI 代理,全程数据不出本机。
对于笔记、纪要、文档密集且在意隐私的开发者:npm 全局装上 qmd,把笔记目录登记成集合并写好 context,跑一次 embed 后用 query 体验混合检索;用 Claude 的再执行 qmd mcp 把它接成代理工具。把它当作"本地版 RAG 检索层"来用,与知识图谱类工具互补,是给 AI 代理喂本地上下文的实用方案。

