个人知识搜索
使用 qmd 搜索个人知识库、笔记、文档和会议记录
概述
qmd 是一款本地、设备端的个人知识库搜索引擎。它索引 Markdown 笔记、会议记录、文档和任何文本文件,然后提供结合关键词匹配、语义理解和 LLM 驱动重排序的混合搜索——全部在本地运行,无需云端依赖。
由 Tobi Lütke 创建。MIT 许可证。
使用场景
- 用户要求搜索笔记、文档、知识库或会议记录
- 用户想在大量 Markdown/文本文件集合中查找内容
- 用户需要语义搜索("查找关于 X 概念的笔记"),而不仅是关键词 grep
- 用户已设置 qmd 集合并希望查询它们
- 用户要求搭建本地知识库或文档搜索系统
- 关键词:"搜索笔记"、"在文档中查找"、"知识库"、"qmd"
前置条件
Node.js >= 22(必需)
# 检查版本
node --version # 必须 >= 22
# macOS — 通过 Homebrew 安装或升级
brew install node@22
# Linux — 使用 NodeSource 或 nvm
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# 或使用 nvm:
nvm install 22 && nvm use 22
SQLite 扩展支持(仅 macOS)
macOS 系统自带的 SQLite 不支持扩展加载。通过 Homebrew 安装:
brew install sqlite
安装 qmd
npm install -g @tobilu/qmd
# 或使用 Bun:
bun install -g @tobilu/qmd
首次运行会自动下载 3 个本地 GGUF 模型(约 2GB):
| 模型 | 用途 | 大小 |
|---|---|---|
| embeddinggemma-300M-Q8_0 | 向量嵌入 | ~300MB |
| qwen3-reranker-0.6b-q8_0 | 结果重排序 | ~640MB |
| qmd-query-expansion-1.7B | 查询扩展 | ~1.1GB |
验证安装
qmd --version
qmd status
快速参考
| 命令 | 功能 | 速度 |
|---|---|---|
qmd search "query" | BM25 关键词搜索(无需模型) | ~0.2s |
qmd vsearch "query" | 语义向量搜索(1个模型) | ~3s |
qmd query "query" | 混合搜索 + 重排序(全部3个模型) | ~2-3s 热启动, ~19s 冷启动 |
qmd get | 获取完整文档内容 | 即时 |
qmd multi-get "glob" | 批量获取多个文件 | 即时 |
qmd collection add --name | 添加目录为集合 | 即时 |
qmd context add "描述" | 添加上下文元数据以改善检索 | 即时 |
qmd embed | 生成/更新向量嵌入 | 不定 |
qmd status | 显示索引健康状态和集合信息 | 即时 |
qmd mcp | 启动 MCP 服务器(stdio) | 持久 |
qmd mcp --http --daemon | 启动 MCP 服务器(HTTP,模型常驻内存) | 持久 |
安装配置工作流
1. 添加集合
将 qmd 指向包含文档的目录:
# 添加笔记目录
qmd collection add ~/notes --name notes
# 添加项目文档
qmd collection add ~/projects/myproject/docs --name project-docs
# 添加会议记录
qmd collection add ~/meetings --name meetings
# 列出所有集合
qmd collection list
2. 添加上下文描述
上下文元数据帮助搜索引擎理解每个集合包含什么内容。这能显著提升检索质量:
qmd context add qmd://notes "个人笔记、想法和日志"
qmd context add qmd://project-docs "主项目的技术文档"
qmd context add qmd://meetings "会议记录和行动项"
3. 生成嵌入
qmd embed
此命令处理所有集合中的文档并生成向量嵌入。添加新文档或集合后需要重新运行。
4. 验证
qmd status # 显示索引健康状态、集合统计、模型信息
搜索模式
快速关键词搜索(BM25)
适用于:精确术语、代码标识符、名称、已知短语。
无需加载模型——近乎即时的结果。
qmd search "authentication middleware"
qmd search "handleError async"
语义向量搜索
适用于:自然语言问题、概念性查询。
加载嵌入模型(首次查询约 3 秒)。
qmd vsearch "限流器如何处理突发流量"
qmd vsearch "改善引导流程的想法"
混合搜索 + 重排序(最佳质量)
适用于:质量要求高的重要查询。
使用全部 3 个模型——查询扩展、并行 BM25+向量、重排序。
qmd query "关于数据库迁移做了什么决定"
结构化多模式查询
在单个查询中组合不同的搜索类型以获得精确结果:
# BM25 精确术语 + 向量概念搜索
qmd query $'lex: rate limiternvec: 节流在高负载下如何工作'
# 带查询扩展
qmd query $'expand: database migration plannlex: "schema change"'
查询语法(lex/BM25 模式)
| 语法 | 效果 | 示例 |
|---|---|---|
term | 前缀匹配 | perf 匹配 "performance" |
"phrase" | 精确短语 | "rate limiter" |
-term | 排除术语 | performance -sports |
HyDE(假设文档嵌入)
对于复杂主题,写出你期望答案的样子:
qmd query $'hyde: 迁移计划分为三个阶段。首先,添加新列而不删除旧列。然后回填数据。最后切换并删除遗留列。'
限定集合范围
qmd search "query" --collection notes
qmd query "query" --collection project-docs
输出格式
qmd search "query" --json # JSON 输出(最适合解析)
qmd search "query" --limit 5 # 限制结果数量
qmd get "#abc123" # 按文档 ID 获取
qmd get "path/to/file.md" # 按文件路径获取
qmd get "file.md:50" -l 100 # 获取指定行范围
qmd multi-get "journals/*.md" --json # 按 glob 批量获取
MCP 集成(推荐)
qmd 提供 MCP 服务器,通过原生 MCP 客户端直接向 Agent 提供搜索工具。这是首选的集成方式——配置后,Agent 自动获得 qmd 工具,无需每次加载此技能。
选项 A:Stdio 模式(简单)
添加到 ~/.hermes/config.yaml:
mcp_servers:
qmd:
command: "qmd"
args: ["mcp"]
timeout: 30
connect_timeout: 45
这会注册工具:mcp_qmd_search、mcp_qmd_vsearch、mcp_qmd_deep_search、mcp_qmd_get、mcp_qmd_status。
权衡:模型在首次搜索调用时加载(约 19 秒冷启动),然后在此会话中保持热加载。偶尔使用可以接受。
选项 B:HTTP 守护进程模式(快速,推荐重度使用)
单独启动 qmd 守护进程——它让模型常驻内存:
# 启动守护进程(跨 Agent 重启持久存在)
qmd mcp --http --daemon
# 默认运行在 http://localhost:8181
然后配置 Agent 通过 HTTP 连接:
mcp_servers:
qmd:
url: "http://localhost:8181/mcp"
timeout: 30
权衡:运行时占用约 2GB 内存,但每次查询都很快(约 2-3 秒)。最适合频繁搜索的用户。
保持守护进程运行
macOS(launchd)
cat > ~/Library/LaunchAgents/com.qmd.daemon.plist << 'EOF'
Label
com.qmd.daemon
ProgramArguments
qmd
mcp
--http
--daemon
RunAtLoad
KeepAlive
StandardOutPath
/tmp/qmd-daemon.log
StandardErrorPath
/tmp/qmd-daemon.log
EOF
launchctl load ~/Library/LaunchAgents/com.qmd.daemon.plist
Linux(systemd 用户服务)
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/qmd-daemon.service << 'EOF'
[Unit]
Description=QMD MCP Daemon
After=network.target
[Service]
ExecStart=qmd mcp --http --daemon
Restart=on-failure
RestartSec=10
Environment=PATH=/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now qmd-daemon
systemctl --user status qmd-daemon
MCP 工具参考
连接后,以下工具可用为 mcp_qmd_*:
| MCP 工具 | 对应命令 | 描述 |
|---|---|---|
mcp_qmd_search | qmd search | BM25 关键词搜索 |
mcp_qmd_vsearch | qmd vsearch | 语义向量搜索 |
mcp_qmd_deep_search | qmd query | 混合搜索 + 重排序 |
mcp_qmd_get | qmd get | 按 ID 或路径获取文档 |
mcp_qmd_status | qmd status | 索引健康状态和统计 |
MCP 工具接受结构化 JSON 查询进行多模式搜索:
{
"searches": [
{"type": "lex", "query": "authentication middleware"},
{"type": "vec", "query": "用户登录如何验证"}
],
"collections": ["project-docs"],
"limit": 10
}
CLI 使用(无 MCP 时)
当未配置 MCP 时,直接通过终端使用 qmd:
terminal(command="qmd query '关于 API 重新设计做了什么决定' --json", timeout=30)
对于安装和管理任务,始终使用终端:
terminal(command="qmd collection add ~/Documents/notes --name notes")
terminal(command="qmd context add qmd://notes '个人研究笔记和想法'")
terminal(command="qmd embed")
terminal(command="qmd status")
搜索流水线工作原理
了解内部原理有助于选择正确的搜索模式:
- 查询扩展(Query Expansion)——微调的 1.7B 模型生成 2 个替代查询。原始查询在融合中获得 2 倍权重。
- 并行检索(Parallel Retrieval)——BM25(SQLite FTS5)和向量搜索在所有查询变体上同时运行。
- RRF 融合(RRF Fusion)——倒数排名融合(k=60)合并结果。Top 排名加成:#1 得 +0.05,#2-3 得 +0.02。
- LLM 重排序(LLM Reranking)——qwen3-reranker 对前 30 个候选评分(0.0-1.0)。
- 位置感知混合(Position-Aware Blending)——排名 1-3:75% 检索 / 25% 重排序。排名 4-10:60/40。排名 11+:40/60(对长尾更信任重排序)。
智能分块(Smart Chunking):文档在自然断点(标题、代码块、空行)处分割,目标约 900 个 token,15% 重叠。代码块永远不会在中间被分割。
最佳实践
- 始终添加上下文描述——
qmd context add能显著提升检索准确性。描述每个集合包含什么。 - 添加文档后重新嵌入——向集合添加新文件后必须重新运行
qmd embed。 - 用
qmd search求速度——需要快速关键词查找(代码标识符、精确名称)时,BM25 即时且无需模型。 - 用
qmd query求质量——问题具有概念性或用户需要最佳结果时,使用混合搜索。 - 优先使用 MCP 集成——配置后,Agent 自动获得原生工具,无需每次加载此技能。
- 频繁使用推荐守护进程模式——如果用户经常搜索知识库,推荐 HTTP 守护进程设置。
- 结构化搜索中第一个查询获得 2 倍权重——组合 lex 和 vec 时,将最重要/最确定的查询放在前面。
常见问题
"首次运行时模型下载"
正常现象——qmd 首次使用时自动下载约 2GB 的 GGUF 模型。这是一次性操作。
冷启动延迟(约 19 秒)
这发生在模型未加载到内存时。解决方案:
- 使用 HTTP 守护进程模式(
qmd mcp --http --daemon)保持热加载 - 不需要模型时使用
qmd search(仅 BM25) - MCP stdio 模式在首次搜索时加载模型,会话期间保持热加载
macOS:"unable to load extension"
安装 Homebrew SQLite:brew install sqlite
然后确保它在 PATH 中优先于系统 SQLite。
"No collections found"
运行 qmd collection add --name 添加目录,然后运行 qmd embed 索引它们。
嵌入模型覆盖(CJK/多语言)
为非英文内容设置 QMD_EMBED_MODEL 环境变量:
export QMD_EMBED_MODEL="your-multilingual-model"
数据存储
- 索引和向量:
~/.cache/qmd/index.sqlite - 模型:首次运行时自动下载到本地缓存
- 无云依赖——一切在本地运行
参考资料
安装指南
复制下方命令,在终端运行即可安装:
使用指南
安装完成后,在对话框中直接使用此技能。