📋 什么是 QMD Search?
QMD (Query Markdown Document) 是一个基于 RAG (Retrieval-Augmented Generation) 的智能文档查询系统,专为 Markdown 文档库设计。
核心定位:
- 📚 Obsidian/Markdown 文档的语义搜索引擎
- 🔍 支持关键词匹配 + 语义理解的混合检索
- 🧠 可选 LLM 增强(Query Expansion + Reranking)
- 🚀 本地运行,数据完全私有
🏗️ 核心架构
┌─────────────────────────────────────────────────────────┐
│ QMD Search 系统 │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ 文档索引层 │ │ 检索引擎 │ │ LLM 增强层 │ │
│ │ - Markdown │ │ - BM25 FTS5 │ │ - Query │ │
│ │ - 分块 │─▶│ - 向量检索 │─▶│ Expansion │ │
│ │ - Embedding│ │ | - RRF 融合 │ │ - Rerank │ │
│ └─────────────┘ └──────────────┘ └────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ SQLite 数据库 │ │
│ │ - FTS5 全文索引 │ │
│ │ - sqlite-vec │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
🔬 工作原理
1️⃣ 文档索引流程
用户添加文档
│
▼
读取 Markdown 文件
│
├──▶ 提取元数据(标题、标签、创建时间)
│
├──▶ 文档分块(Chunking)
│ - 按段落/标题分割
│ - 保留上下文继承关系
│
├──▶ 生成 Embedding 向量
│ - 使用 Sentence Transformers
│ - 默认模型:all-MiniLM-L6-v2
│
└──▶ 存储到数据库
- 原文 → SQLite FTS5(全文索引)
- 向量 → sqlite-vec(向量索引)
- 元数据 → 关系表
2️⃣ 混合检索流程(Hybrid Search)
用户查询:"如何在 Obsidian 中配置同步?"
│
├─────────────────────┬─────────────────────┐
│ │ │
▼ ▼ ▼
BM25 全文检索 向量语义检索 LLM Query Expansion
(关键词匹配) (语义相似度) (可选,扩展查询)
│ │ │
│ 返回 Top 20 │ 返回 Top 20 │ 生成 3-5 个变体
│ │ │
└─────────────────────┴─────────────────────┘
│
▼
Reciprocal Rank Fusion (RRF)
融合两个结果列表
│
▼
Position-Aware Blending
根据位置调整最终分数
│
▼
LLM Rerank(可选)
使用 LLM 重新排序 Top 40
│
▼
返回最终 Top 10 结果
🎯 核心算法详解
1. BM25 全文检索
技术栈:SQLite FTS5
-- 查询示例
SELECT
d.title,
d.path,
bm25(documents_fts, 10.0, 1.0) as bm25_score
FROM documents_fts f
JOIN documents d ON d.id = f.rowid
WHERE documents_fts MATCH 'Obsidian 同步'
ORDER BY bm25_score ASC -- BM25 分数越低越好(负数)
特点:
- ✅ 精确匹配关键词
- ✅ 支持布尔逻辑(AND、OR、短语)
- ✅ 速度快,适合精确查询
- ❌ 无法理解语义(”同步” ≠ “sync”)
2. 向量语义检索
技术栈:sqlite-vec + Sentence Transformers
# 生成查询向量
query_embedding = model.encode("如何在 Obsidian 中配置同步?")
# 向量相似度搜索(余弦相似度)
SELECT
d.title,
d.path,
vec_distance_cosine(query_vec, embedding) as similarity
FROM documents d
ORDER BY similarity DESC
LIMIT 20
特点:
- ✅ 理解语义(”同步” ≈ “sync” ≈ “备份”)
- ✅ 支持跨语言匹配
- ✅ 能找到相关但关键词不同的文档
- ❌ 可能遗漏精确匹配
3. RRF (Reciprocal Rank Fusion)
目的:融合 BM25 和向量检索的结果
公式:
RRF Score = Σ (1 / (k + rank_i))
其中:
- rank_i = 文档在第 i 个结果列表中的排名
- k = 60(经验值,防止分母过小)
示例:
文档 A: BM25 排名 3, 向量排名 5
RRF Score = 1/(60+3) + 1/(60+5) = 0.0159 + 0.0154 = 0.0313
文档 B: BM25 排名 1, 向量排名 15
RRF Score = 1/(60+1) + 1/(60+15) = 0.0164 + 0.0133 = 0.0297
→ 文档 A 排名更高(在两个列表中都表现稳定)
优势:
- ✅ 无需归一化不同分数
- ✅ 平衡两种检索方式
- ✅ 对异常值不敏感
4. LLM 增强(可选)
Query Expansion(查询扩展)
# 原始查询
query = "Obsidian 同步配置"
# LLM 生成的变体
expanded_queries = [
"Obsidian 如何设置自动同步",
"Obsidian sync configuration",
"Obsidian 多设备数据同步方法",
"Obsidian 云端备份设置"
]
# 对每个变体执行检索,合并结果
触发条件:
- 初始检索结果分数较低(< 0.85)
- 结果分布分散(无明显高分文档)
Rerank(重排序)
# 从混合检索中获取 Top 40 候选
candidates = hybrid_search(query, limit=40)
# 使用 LLM 评估相关性
reranked = llm.rerank(query, candidates)
# 返回 Top 10
return reranked[:10]
常用模型:
- Cohere Rerank
- BGE Reranker
- 自定义 LLM(GPT-4、Claude 等)
💻 使用方法
安装
# 使用 pipx 安装(推荐,隔离环境)
pipx install qmd
# 或从源码安装
pip install -e .
基本配置
# 1. 添加文档集合(Collection)
qmd add obsidian-vault --path ~/opt/Obsidian_vault --pattern "*.md"
# 2. 更新索引
qmd update
# 3. 查看状态
qmd status
搜索命令
# 基础搜索
qmd search "如何在 Obsidian 中配置同步"
# 限定集合
qmd search "同步配置" --collection obsidian-vault
# 指定结果数量
qmd search "同步" --limit 5
# 显示完整文档内容
qmd search "同步" --full
# 显示行号
qmd search "同步" --line-numbers
# 输出为 JSON
qmd search "同步" --format json
# 输出为 Markdown
qmd search "同步" --format md
深度搜索(Hybrid + Rerank)
# 使用 query 命令执行深度搜索
qmd query "如何在 Obsidian 中配置同步"
# 等价于
qmd search "如何在 Obsidian 中配置同步" --full --rerank
管理 Collections
# 列出所有集合
qmd list
qmd ls
# 重命名集合
qmd collection rename old-name new-name
# 删除集合
qmd remove collection-name
# 清理数据库(删除孤立向量)
qmd cleanup
文件监听(自动更新索引)
# 启动监听模式
qmd watch
# 监听特定集合
qmd watch --collection obsidian-vault
功能:
- 📝 检测文件新增/修改/删除
- 🔄 自动更新索引
- 🚀 实时生效,无需手动
qmd update
⚡ 高效使用技巧
1. 优化查询语句
# ✅ 好的查询
qmd search "Obsidian 同步 配置 多设备" # 关键词明确
qmd search "如何设置自动备份" # 自然语言
# ❌ 避免过于宽泛
qmd search "同步" # 太短,结果过多
qmd search "配置" # 缺少上下文
2. 使用 Collection 过滤
# 工作文档
qmd search "项目规范" -c work-notes
# 个人笔记
qmd search "读书笔记" -c personal
# 技术文档
qmd search "API 设计" -c tech-docs
优势:
- 🎯 缩小搜索范围
- ⚡ 提升搜索速度
- 📊 结果更精准
3. 利用标签和元数据
在 Markdown 中使用标准 Frontmatter:
---
created: 2026-04-15
tags: [obsidian, 同步,配置]
category: 技术文档
---
# 文档标题
搜索时:
qmd search "tags:obsidian 同步"
qmd search "category:技术文档 配置"
4. 组合使用 BM25 和语义搜索
# 精确匹配优先
qmd search "npm install 命令" --format files
# 语义理解优先
qmd query "怎么安装 Node.js 包" # 使用 LLM 增强
5. 输出格式选择
# 快速浏览(默认 CLI)
qmd search "同步"
# 获取文件列表(用于脚本)
qmd search "同步" --format files
# 导入到其他工具
qmd search "同步" --format json | jq '.[].file'
# 生成报告
qmd search "同步" --format md > 搜索结果.md
6. 定期维护
# 每周更新索引
qmd update
# 每月清理数据库
qmd cleanup
# 查看索引状态
qmd status
🔧 高级配置
自定义 Embedding 模型
# 编辑配置文件 ~/.config/qmd/config.yaml
embedding:
model: "BAAI/bge-small-zh-v1.5" # 中文优化
dimension: 512
推荐模型:
- 英文:
all-MiniLM-L6-v2(快)、bge-large-en(准) - 中文:
bge-small-zh-v1.5、text2vec-base-chinese
调整分块策略
# config.yaml
chunking:
max_length: 512 # 最大 chunk 长度
overlap: 50 # 重叠字符数
by_paragraph: true # 按段落分割
启用 LLM Rerank
# config.yaml
llm:
backend: "ollama"
model: "bge-reranker"
rerank_top_k: 10
📊 性能优化建议
| 场景 | 建议 |
|---|---|
| 文档库 < 1000 篇 | 默认配置即可 |
| 文档库 > 5000 篇 | 使用 --collection 过滤 |
| 需要精确匹配 | 优先使用 qmd search |
| 需要语义理解 | 使用 qmd query(带 Rerank) |
| 实时性要求高 | 启用 qmd watch 监听 |
| 批量处理 | 使用 --format json 导出 |
🆚 与其他工具对比
| 工具 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| QMD | 本地运行、支持中文、混合检索 | 需要索引时间 | Obsidian/Markdown 文档库 |
| Obsidian 内置搜索 | 无需配置、实时 | 仅关键词匹配 | 小型笔记库 |
| Elasticsearch | 分布式、高性能 | 配置复杂、资源占用高 | 企业级搜索 |
| Algolia | 云端、开箱即用 | 收费、数据外传 | SaaS 应用 |
💡 最佳实践
- 定期更新索引 – 设置 cron 任务每天更新
- 使用 Collection 分类 – 按主题/项目分离文档
- 启用文件监听 – 写作时自动索引
- 混合使用 search 和 query – 根据需求选择
- 优化 Frontmatter – 添加标签和元数据提升检索精度