内容
# Obsidian 搜索工具 — 本地优先的语义搜索三件套
> **简体中文**
将你的 Obsidian 笔记库转变为 **可语义搜索、支持 AI 聊天的知识库**,所有操作都在本地进行,无需云端索引,无需将笔记发送到云端进行搜索,也无需每次查询的 API 调用费用。
由一位医生开发,用于研究数千份临床笔记,但 **领域无关**:只需指向任何 Markdown 笔记库(研究、法律、工程、个人 Wiki),它就能工作。

### 使用方式(共享索引)
该仓库提供了 **两个前端,共用同一个本地 LanceDB 索引和检索核心**,您可以选择使用其中一个或两个:
- **`vault-search-obsidian`** — Obsidian 插件(在侧边栏中提供搜索、相关笔记、聊天功能),通过一个小型本地 API 服务器进行通信。 → [快速入门](#vault-search-obsidian--obsidian-插件)
- **`vault-search-mcp`** — MCP 服务器,通过工具(`vault_search`、`vault_similar`、`vault_stats`、`textbook_search`)向 Claude Code 或任何 MCP 客户端公开相同的搜索功能,无需 Obsidian。 → [快速入门](#vault-search-mcp--从-claude-code-或任何-mcp-客户端使用)
两者都重用了相同的 `server/` 核心(索引、评分、个性化 PageRank、知识图谱),因此您可以只索引一次,并在任何地方查询。
## 三件套
| 工具 | 功能 | 支持 |
|---|---|---|
| 🔍 **Vault Search** | 输入自然语言问题(任何语言),获取最 **语义相关** 的笔记段落 — 而不是关键词匹配。 | LanceDB 向量搜索 + 本地嵌入 |
| 🔗 **Related Notes** | 一个实时的侧边栏,阅读或选择文本时,显示您可能忘记的相关笔记 — 揭示整个笔记库中的隐藏链接。 | 相同的索引,“查找相似”模式 |
| 💬 **Vault Chat** | 与您的笔记聊天(RAG)。三种模式:**Vault**(仅限笔记,100% 本地且免费)、**Hybrid**(笔记 + AI 知识)、**Free**(开放聊天 + 文献搜索)。 | 本地 LLM 或 Claude 订阅 |
所有这三个功能都位于 Obsidian 侧边栏中。相同的索引还为 **MCP 服务器** 提供了功能,因此 Claude Code 等编码代理可以将您的笔记库作为工具进行搜索。
### 截图
| 🔍 Vault Search | 🔗 Related Notes |
|---|---|
|  |  |
| 💬 Vault Chat | 👁 上下文预览 |
|---|---|
|  |  |
## 为什么存在
Obsidian 内置搜索是词汇搜索 — 它找到您输入的单词。但您很少记得几个月前编写的笔记中的确切单词。语义搜索通过 **含义** 查找笔记:搜索 `"如何管理脊髓损伤后的弛缓性膀胱"`,它会找到您标题为 `神经源性膀胱` 的笔记,即使这些确切的单词从未出现过。
设计优先级是 **本地优先和私有**:
- **嵌入在本地运行**,通过 [Ollama](https://ollama.com)(`bge-m3`,双语,CPU友好)。您的笔记文本从未被发送到任何地方进行索引或搜索。
- **Vault 模式聊天完全本地且免费** — 本地 LLM 使用检索的笔记回答,无需支付任何费用。
- **混合/免费聊天可选** 调用 `claude` CLI,以便您可以使用已经付费的 Claude 订阅,而不是建立(并为每个令牌付费)原始 API 密钥。
## 工作原理
```
┌─────────────────────────────────────────┐
Obsidian ◄────► │ 插件(侧边栏):搜索 · 相关 · 聊天│
└───────────────────┬─────────────────────┘
│ HTTP(localhost:3789)
▼
┌─────────────────────────────────────────┐
│ api_server.py (FastAPI) │
│ /search /similar /chat /reindex │
└──────┬───────────────────────┬───────────┘
│ │
嵌入查询 RAG 上下文
▼ ▼
┌────────────────────────┐ ┌──────────────────────────┐
│ Ollama (bge-m3) │ │ Vault 模式 → 本地 LLM │
│ → 向量 │ │ 混合/免费 → `claude` CLI │
└───────────┬────────────┘ └──────────────────────────┘
▼
┌────────────────────────┐
│ LanceDB 向量索引 │ ◄── indexer.py (按标题分段笔记,
│ (~/.vault-search) │ 嵌入,存储;增量更新)
└────────────────────────┘
相同的索引 + 评分也通过 mcp_server.py (MCP) 提供给编码代理。
```
- **`indexer.py`**遍历您的笔记库,按标题将每个笔记分成块,使用 `bge-m3` 嵌入,并存储在本地 **LanceDB** 表中。重新运行是增量(内容哈希缓存)。
- **`scoring.py`** 使用可选的 **路径权重**(信任某些文件夹更多)、**时间**(较新的笔记排名更高)和 **关系** 提升,对原始向量命中进行重新排序。
- **`ppr.py`** 通过 `[[wiki-link]]` 图谱,根据 **个性化 PageRank** 对笔记进行排名 — 一种 HippoRAG / LinearRAG 风格的随机游走重启算法。它为 **相关笔记** 和多跳 **查询扩展**(在最佳语义命中上播种行走),显示相关笔记,而纯向量相似性会忽略这些笔记。在作者的笔记库中,这将稀疏桥召回@10 从 ~60% 提升到 ~84%,相比天真的 1 跳 / 共享链接扩展。
- **`api_server.py`** 为插件提供服务:语义搜索、查找相似、单笔记重新索引和聊天(带有检索增强的上下文)。
- **`mcp_server.py`** 向 MCP 客户端(例如 Claude Code)公开相同的搜索功能,分别为 `vault_search`、`vault_similar`、`vault_stats`。
## 先决条件
| 要求 | 备注 |
|---|---|
| **Python 3.10+** | 用于服务器。 |
| **[Ollama](https://ollama.com)** 在本地运行 | 提供嵌入(和可选的本地聊天)。`bge-m3` 在 **CPU** 上运行良好 — 只有批量索引时 GPU 才会加速。 |
| **Obsidian** | 使用侧边栏插件。服务器也可以通过 MCP/HTTP API 在无头模式下使用。 |
| **Claude CLI** *(可选)* | 仅用于混合/免费聊天。Vault 模式聊天使用本地模型代替。 |
| **一台常开的机器** *(可选)* | 如果您想在手机或其他设备上使用搜索/聊天,请在始终在线的 PC/NAS 上运行服务器。对于单机使用,只需在打开 Obsidian 时启动它。 |
拉取嵌入模型:
```bash
ollama pull bge-m3
# 可选,用于零成本的本地 Vault 模式聊天:
ollama pull gemma2:9b
```
## 安装
### 步骤 0 — 共享核心(为任一前端执行此操作)
```bash
git clone https://github.com/drpwchen/vault-search.git
cd vault-search
pip install -r requirements.txt
cp env.example .env # 然后编辑 .env — 将 VAULT_PATH 设置为您的笔记库
cd server
python indexer.py # 构建索引(后续运行为增量)
```
如果您尚未执行 `ollama pull bge-m3`(请参见 [先决条件](#先决条件))。现在选择以下一个或两个前端。
### `vault-search-obsidian` — Obsidian 插件
启动本地 API 服务器,然后安装插件:
```bash
python server/api_server.py # 提供 http://localhost:3789
cp -r plugin "<YOUR_VAULT>/.obsidian/plugins/vault-search-plugin"
```
在 Obsidian 中:**设置 → 社区插件 → 启用“Vault Semantic Search”**。打开其设置并确认 **API 服务器 URL** 为 `http://localhost:3789`。会出现三个工具栏图标:🔍 搜索,💬 聊天,🔗 相关笔记。
> 插件附带 `data.json.example`。Obsidian 在首次运行时会写入其实际的 `data.json`;请勿提交包含 API 密钥的 `data.json`。
### `vault-search-mcp` — 从 Claude Code(或任何 MCP 客户端)使用
无需 Obsidian,无需 API 服务器 — 只需将 MCP 服务器注册到您在步骤 0 中构建的索引:
```bash
claude mcp add vault-search -- python "/abs/path/to/server/mcp_server.py"
```
现在 Claude Code(或任何 MCP 客户端)可以调用 `vault_search`、`vault_similar`、`vault_stats`,以及(如果您索引了参考语料库)`textbook_search`,所有这些都依赖于相同的本地索引、个性化 PageRank 扩展和重新排序。
## 配置
所有配置都由环境变量驱动(请参见 **`env.example`** 获取完整的注释列表)。唯一必需的变量是 `VAULT_PATH`。重点:
| 变量 | 默认值 | 用途 |
|---|---|---|
| `VAULT_PATH` | — *(必需)* | 您的笔记库的绝对路径。 |
| `VAULT_SEARCH_DATA_DIR` | `~/.vault-search` | 索引/缓存/日志存储位置。 |
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama 端点。 |
| `VAULT_SEARCH_EMBEDDING_MODEL` | `bge-m3` | 笔记库嵌入模型。 |
| `VAULT_SEARCH_API_PORT` | `3789` | API 服务器端口。 |
| `CLAUDE_CMD` | `claude` | 用于混合/免费聊天的 CLI。 |
| `VAULT_SEARCH_CHAT_MODEL` | `gemma2:9b` | Vault 模式聊天的本地模型。 |
| `VAULT_SEARCH_PERSONA` / `_LANGUAGE` | generic | 自定义助手的角色和回复语言。 |
| `VAULT_SEARCH_PATH_WEIGHTS` | `{}` | 在排名中提升/降低文件夹。 |
| `VAULT_SEARCH_EXCLUDE_PATTERNS` | *(无)* | 默认情况下隐藏派生笔记(草稿,草拟)以避免搜索。 |
## 可选附加功能
<details>
<summary><b>次要参考语料库(教科书/手册)</b></summary>
如果您将大量长篇参考文档(转换的 PDF、手动文档)与笔记分开存放,请使用父子分块索引以实现精确命中 **和** 周围上下文:
```bash
export VAULT_SEARCH_TEXTBOOK_PATH=/path/to/reference-md
ollama pull qwen3-embedding:0.6b
cd server && python textbook_indexer.py
```
添加一个 `textbook_search` 工具(MCP + HTTP)。可选地,使用提升文件对受信任的来源进行排名更高 — 请参见 `examples/source_boost.example.json` 和 `VAULT_SEARCH_SOURCE_BOOST`。
</details>
<details>
<summary><b>知识图谱(维基链接 + 实体)</b></summary>
```bash
cd server
python graph_builder.py # 将 [[wiki-links]] 解析为邻接图
python graph_builder.py --ner # 可选:scispaCy/NER 实体提取
```
当存在时,维基链接图驱动 `ppr.py` 中的 **个性化 PageRank** 检索(相关笔记 + 查询扩展),并且搜索结果会通过链接笔记和提取的关系丰富。NER 步骤需要 `scispacy`(请参见 `requirements.txt`)。PPR 本身是纯 Python,仅需要维基链接图(阶段 A)— 无需 NER。
</details>
## 适应您的设置(替代方案)
该项目围绕 **带有 GPU 的常开 PC + Claude 订阅** 构建,但这些都不是必需的。请选择与您匹配的行:
| 您没有… | 请改为 |
|---|---|
| **GPU** | 无 — `bge-m3` 在 CPU 上嵌入。对于巨大的笔记库,索引速度较慢,但搜索速度即时。较小的模型(`nomic-embed-text`)更轻量;请相应地设置 `VAULT_SEARCH_EMBEDDING_MODEL`(和 `_DIM`)并重新索引。 |
| **Claude 订阅** | 使用 **Vault 模式** 进行聊天 — 它完全在本地 Ollama 模型(`VAULT_SEARCH_CHAT_MODEL`)上运行,无需支付任何费用。请设置 `CLAUDE_CMD=` 为空以禁用基于 Claude 的模式。 |
| **常开机器** | 只需在打开 Obsidian 时启动 `api_server.py`(或将其包装在登录项 / `systemd --user` / 任务调度器条目中)。搜索仅在您使用它时需要服务器。 |
| **可访问的第二台设备** | 在家用电脑或 NAS 上运行服务器,将插件的 **API 服务器 URL** 设置为该主机,并设置 **API 密钥**(服务器上的 `VAULT_API_KEY` 环境变量 + 插件设置中的匹配密钥),以便只有您可以查询它。 |
| **根本不想运行服务器** | 只需将 **MCP 服务器** 与 Claude Code 从终端一起使用 — 无需 FastAPI 进程,无需插件。 |
想使用云端嵌入器代替 Ollama?嵌入调用在 `indexer.py` / `api_server.py` 中隔离(`client.embed(...)`);请用任何提供商替换它并保留相同的 LanceDB 管道。
## 安全说明
- API 服务器支持 **API 密钥**(`X-API-Key`)。请在服务器上设置 `VAULT_API_KEY`(环境变量)或 `~/.vault-search/api_key.txt`,并在插件设置中设置匹配的密钥。**始终** 在服务器可通过 `localhost` 以外的访问时设置一个。
- `.env`、`plugin/data.json` 和整个 `~/.vault-search/` 数据目录都被 git 忽略。永远不要提交机密或索引。
- 混合/免费聊天通过 **拒绝工具列表** 以子进程运行 `claude` CLI(无文件写入,无 shell)— 它只能读取您传递给它的上下文并调用只读文学工具。
## 仓库布局
```
server/ 索引 · 评分 · ppr · api_server · mcp_server (核心三件套)
textbook_indexer · graph_builder (可选附加功能)
config.py (所有设置,环境变量驱动)
plugin/ main.js · manifest.json · styles.css (Obsidian 插件)
examples/ source_boost.example.json
docs/images/ 截图
env.example 复制到 .env
```
## 作者
由 **陈品伟 医生** 构建 — 一位需要在自己的笔记中找到东西的医生。
🌐 [drpwchen.com](https://drpwchen.com) · 🐙 [github.com/drpwchen](https://github.com/drpwchen)
## 许可证
MIT — 请参见 [LICENSE](./LICENSE)。欢迎贡献和问题。