关于 quillrag
quillrag 是面向希望在编辑器中搜索笔记、文档和代码用户的本地 RAG MCP 服务。Rust 单文件二进制内置 MiniLM,结合稠密检索与 BM25,无运行时依赖,安装后无需网络访问。
主要功能
- 01Rust 静态单文件二进制
- 02内置 MiniLM 嵌入模型
- 03稠密检索与 BM25 混合搜索
- 04目录增量索引
- 05无需网络的本地运行
适用场景
- 01在编辑器中搜索个人笔记
- 02检索相关项目文档
- 03按含义和关键词查找代码或文本
MCP 相关
它通过 stdio 向 MCP 客户端提供索引、混合搜索、状态查看和清除工具。客户端可连接该服务,搜索本地已索引的文件。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
quillrag
一个文件。零依赖。编辑器还没加载完,它就已准备就绪。
单个静态二进制文件中的本地 RAG 引擎——内置编译好的 MiniLM 嵌入模型,支持稠密检索与 BM25 混合检索,原生支持 MCP。无需 Node、Python,无需在首次查询时下载模型。
为什么选择 quillrag
| 约 20 ms 即可就绪 | MCP 握手在模型加载前就已完成 |
| 零运行时依赖 | 永远无需 Node、Python、pip/npm 或下载模型 |
| 混合检索 | 稠密余弦相似度 ⊕ BM25,并使用倒数排名融合(Reciprocal Rank Fusion)进行融合 |
| 从设计上保护隐私 | 安装后不会执行任何网络操作 |
| 一个文件,支持三种操作系统 | 约 105 MB(模型内置其中),由 CI 为 linux/macOS/Windows 构建 |
快速开始
# 1. grab a prebuilt binary (or cargo install --path .)
gh release download --repo Ayush-yadav11/quillrag -p '*linux*'
tar xzf quillrag-x86_64-linux.tar.gz && chmod +x quillrag
# 2. point it at any folder of notes/docs/code
./quillrag index ~/notes # incremental walk
# 3. ask it something
./quillrag search "how does backpropagation work"
也可以直接将其接入 Claude Desktop / Cursor,让 AI 在对话过程中搜索你的笔记——配置如下。
$ ./quillrag serve --data-dir ~/.local/share/quillrag
2026-08-26 INFO quillrag 0.1.2 ready in 41ms <- handshake-ready before the model loads
为什么它很快
| 阶段 | 耗时 |
|---|---|
| 二进制文件启动 + MCP 初始化 | 约 20 ms(实测:仅打开存储并注册工具) |
首次调用 rag_search / rag_index | 额外约 300 ms,一次性开销(mmap safetensors,构建 BERT 计算图) |
| 后续搜索 | 每次查询 约 25 ms(双核 CPU,小型语料库) |
| 重新索引未更改的语料库 | 几乎为零(使用 FNV 内容哈希跳过) |
嵌入模型采用延迟加载:MCP 握手和 rag_status 都不会触发模型加载,因此编辑器会看到一个即时就绪的服务。
安装
从最新发布版本下载预构建压缩包——Windows x86_64、macOS Apple Silicon 和 Linux x86_64 版本都会由 CI 在每个版本标签上构建:
# linux/macOS example: fetch + extract the latest release
gh release download --repo Ayush-yadav11/quillrag -p '*linux*' | tar xz
chmod +x quillrag && ./quillrag --version
**Linux 要求:**v0.1.6 二进制文件由 Ubuntu 24.04 运行器构建,并链接 glibc 2.39(
pidfd_spawnp/pidfd_getpid)。在较旧的发行版上(glibc < 2.39,例如 Ubuntu 22.04),请改用本地工具链从源码构建:cargo install --path .。
或者从源码构建:
cargo install --path .
CI 使用的交叉编译目标:x86_64-unknown-linux-gnu、
aarch64-apple-darwin、x86_64-pc-windows-msvc。
接入编辑器
Claude Desktop / Cursor / 任何 MCP 客户端:
{
"mcpServers": {
"quillrag": {
"command": "/usr/local/bin/quillrag",
"args": ["serve"],
"env": { "QUILLRAG_DATA": "~/.local/share/quillrag" }
}
}
}
或者直接运行 ./quillrag serve,并让任何 stdio 客户端连接它。
工具
| 工具 | 功能 |
|---|---|
rag_index | 增量索引目录或文件。跳过未更改的文件,只重新生成有差异部分的嵌入。清理操作仅针对你传入的目录:从其他根目录索引的文档不会受影响。会跟踪符号链接的文件/目录。 |
rag_search | 混合检索:稠密 MiniLM 余弦相似度 + BM25 关键词检索,并使用倒数排名融合(Reciprocal Rank Fusion)进行融合。返回带来源路径的排序文本块。 |
rag_status | 文档/文本块数量、已索引字节数、文件类型细分。 |
rag_clear | 清除所有内容。 |
对应的命令行用法(使用相同的引擎):
quillrag index ~/notes # incremental walk
quillrag search "auth flow" -k 5 # one-shot search
quillrag status # stats
quillrag clear # wipe
设计
- 嵌入:candle(纯 Rust),
运行
sentence-transformers/all-MiniLM-L6-v2—— 掩码平均池化 + L2 归一化,在 CPU 上的数值结果与 sentence-transformers 一致。权重通过include_bytes!嵌入二进制文件,并在首次加载时从物化缓存中进行内存映射。 - 存储:单个 redb 文件 —— 分块文本、 原始 f32 向量、文档元数据。原子提交;崩溃安全。
- 关键词:tantivy BM25 辅助 索引,每轮索引时重建(对于小规模数据而言开销很低)。
- 融合:倒数排名融合(Reciprocal Rank Fusion,
Σ 1/(60+rank))—— 无需调整分数尺度, 对不同类型的排名具有较强鲁棒性。 - 分块:优先按段落切分,上限为 1000 个字符,重叠 120 个字符; 超长段落则在句子边界处强制切分。
默认索引的文件类型
md markdown txt rst json yaml yml toml csv tsv html htm xml log rs py js jsx ts tsx go c h cpp hpp java rb sh bash zsh sql proto graphql dockerfile makefile ini cfg conf env —— 可通过 -e ext1,ext2 / "extensions": [...] 扩展。
忽略的目录:所有点目录(.git .obsidian .vscode …),以及
node_modules target dist build venv __pycache__ vendor。
可选格式(库功能)
嵌入该引擎的应用(default-features = false)可通过 IndexHooks 提取器索引更多格式:
| 功能 | 新增内容 |
|---|---|
pdf | PdfExtractor:文本层 PDF,每页一个段落;搜索结果包含 page。 |
ocr | Ocr、ImageExtractor(png/jpg/webp/bmp/gif),以及通过 PdfExtractor::with_ocr 对扫描版 PDF 页面进行 OCR。捆绑 ocrs 模型(约 12 MB,CC BY-SA 4.0,参见 assets/ocr/NOTICE.md);仅支持英语和基础拉丁文本。 |
可读取但不包含文本的文件会记录为空文档,因此未更改的文件不会在每轮扫描时重复进行 OCR(IndexOptions::retry_empty
会重新检查它们)。
索引行为
quillrag index ~/notes # incremental walk of one root
quillrag index ~/notes --no-prune # add/update without deleting anything
quillrag index ~/notes --force # re-embed this root, preserve other roots
- 清理范围仅限索引根目录。 从
~/work-docs索引的文档,在使用相同数据目录对~/personal-notes运行quillrag index后仍会保留。只有曾位于遍历目录下、之后又消失的文件才会被清理。因扩展名或大小限制而排除的现有文件仍会保留在索引中。--no-prune会禁用删除,包括通过 MCP 的no_prune禁用。--force只会重新嵌入选定的来源。使用clear可显式清空存储。成功扫描但未找到文件时会发出警告,并可能清理该根目录下最后一个文件。 - 会跟随符号链接。 基于符号链接源目录构建的暂存树可正常索引。循环链接、失效链接和不可读目录会在修改存储前中止遍历。路径会保留符号链接别名,因此同时索引别名及其目标会创建独立条目。
- 每处理 128 个分块的嵌入批次就会记录进度(stderr),让耗时较长的 CPU 索引过程也能清楚显示仍在运行。
升级现有索引
旧版批量索引可能会将文档路径与错误的分块关联起来。仅凭已存储的索引无法重建这些关联。请根据源文件创建新的数据目录,验证搜索结果,然后将客户端切换到该目录。验证通过前,请保留旧目录。这也会移除旧版的相对路径键;新版索引器会保留这些键,而不会猜测其原始工作目录。新键均为绝对路径。包含 .. 的路径会通过文件系统解析;对于基于符号链接的根目录,请使用稳定的路径写法。重新索引也会刷新 BM25 辅助索引。
隐私与占用
所有操作都在本地运行:嵌入、存储、搜索。没有任何内容会离开设备——安装后完全不存在网络代码路径。
二进制文件约 105 MB(模型内置其中)。空闲时常驻内存约 120 MB,批量嵌入期间会升至约 250 MB。
扩展性与限制
quillrag 将所有内容存储在单个 redb 文件中,并通过对所有向量进行精确的单线程线性扫描来执行稠密检索——目前还没有 ANN 索引。因此,相关限制是查询延迟,而非存储容量。存储可扩展到数百万个分块;每次查询的检索速度为 O(N)。
| 语料库 | 向量数 | 近似 RAM(f32) | 稳态查询 |
|---|---|---|---|
| 1K 个分块 | 1K | ~1.5 MB | ~25 ms(实测) |
| 10K 个分块 | 10K | ~15 MB | ~250 ms(外推) |
| 100K 个分块 | 100K | ~154 MB | ~2–5 s(外推) |
| 1M 个分块 | 1M | ~1.5 GB | 20–60 s(外推——没有 ANN 就不可行) |
**已在包含 1K 个分块的语料库上验证(5/5 项测试,包括真实的 JSON-RPC-over-stdio 端到端测试);上面 1K 以上的数值是根据 O(N) 稠密扫描成本外推得出,并非实测。**你可以使用合成扩展性探测工具(src/bin/quillbench.rs)在自己的硬件上测量这一曲线——运行 cargo build --release && ./target/release/quillbench。
实际使用中的含义:
- **非常适合:**个人/本地知识库、项目文档、笔记、代码——最多可处理数万级分块,同时保持亚秒级至交互式延迟。
- **超出理想范围:**数十万以上分块的语料库,如果需要交互式(<200 ms)检索,就需要 ANN 索引(参见路线图)。
从相关性角度看,它与常见替代方案的对比:
- **仅使用嵌入(例如原始 FAISS flat/简单向量存储):**与 quillrag 的稠密检索路径一样,受限于
all-MiniLM-L6-v2的效果上限;但 quillrag 增加了 BM25 + RRF 融合,在关键词密集型查询(错误代码、ID、精确标记)上表现更好。quillrag 没有重排器或元数据过滤,而 llama-index 提供了这些功能。 - llama-index 本地后端:功能上类似的混合检索(BM25 + 向量 + RRF)。相较于 llama-index 丰富的重排、父子分块和查询扩展功能,quillrag 选择了零依赖的单个二进制文件和即时启动。在标准数据集(BEIR/MS MARCO)上的相关性尚未经过基准测试——参见跟踪 ANN 和相关性基线的未解决议题。
路线图
quillrag 目前刻意保持精简。最重要的突破是添加近似最近邻索引:
- 在稠密向量上使用 ANN(HNSW / IVF)——将 O(N) 扫描变为亚毫秒级 ANN 查询,使单机上的交互式处理上限从 ~10K 个分块提升至数百万个。
- 量化(PQ / SQ)——将向量 RAM 从每维 4 bytes 降至约 1 byte,因此 1M 个分块约占 380 MB,而非 1.5 GB。
- 多线程扫描——并行化当前的精确检索路径,作为过渡方案。
- 重排器钩子——可选地对融合后的 top-k 结果进行交叉编码器重排。
- 相关性基准测试——与 llama-index 基线比较 BEIR / MS MARCO nDCG@10。
在此跟踪 ANN 工作:议题 #1——“ANN index for <1M chunks。”
常见问题
真的只有一个文件吗? 是的。MiniLM 权重和分词器通过 include_bytes! 编译进二进制文件中。无需 npm install、无需 Python,也无需在首次查询时下载模型。二进制文件约为 105 MB,因为其中包含模型。
为什么启动这么快? 嵌入模型是延迟加载的。MCP 握手和 rag_status 都不会触碰它,因此编辑器约 20 ms 就能看到已就绪的服务。模型只会在首次执行 rag_search / rag_index 时加载(一次性耗时约 300 ms)。
它能处理的最大语料有多大? 已验证可处理 1K 个块(每次查询约 25 ms)。该架构可扩展至数百万个已存储的块;目前交互式检索可处理数万个块,而 ANN 索引(路线图)将把上限扩展至 1M 以上。
这与 llama-index 有何不同? 混合检索质量相近,但 quillrag 是单个静态二进制文件,没有运行时或依赖开销,且启动迅速。llama-index 提供重排器、更复杂的分块和查询扩展功能,而 quillrag 目前还不具备这些功能。
会索引哪些文件类型? md markdown txt rst json yaml yml toml csv tsv html htm xml log rs py js jsx ts tsx go c h cpp hpp java rb sh bash zsh sql proto graphql dockerfile makefile ini cfg conf env——使用 -e 扩展。
它会向外发送数据吗? 不会。安装后没有任何网络代码路径。
更新日志
- v0.1.6:按根目录范围清理、可用的
--no-prune、按源范围执行的--force、支持符号链接遍历且发现失败时安全退出、绝对源键,以及正确的部分批次进度。修复了批量写入时文档与块关联错乱,以及 BM25 结果路径缺失的问题。请按照上文说明,将旧索引重建到一个新目录中。 - v0.1.5:已撤回的草稿版本。初始安全修复并不完整;请勿在生产环境中使用此标签。
- v0.1.4 — 多线程推理 + 批量索引。
- v0.1.3 — 重写 MCP 工具说明,使其更清晰地阐述参数语义和行为(只读 / 破坏性标志、使用指南);将 server.json 纳入代码库,以便发布到 MCP Registry。
- v0.1.2 — 索引时跳过所有点号开头的目录(
.obsidian插件配置不再污染结果);首次实现完全自动化的 3 平台 CI 发布。 *升级说明:*运行一次quillrag clear,然后重新索引。 - v0.1.1 — 通过 CI 构建的 linux/macos/windows 发布制品及校验和。
- v0.1.0 — 首次公开发布;由 pocketrag 更名而来。
开发
cargo test --release # unit + end-to-end with real model inference
cargo run -- serve # dev server
RUST_LOG=debug cargo run ... # verbose logs (stderr only)
许可证:MIT。assets/ocr/ 下的可选 OCR 模型采用 CC BY-SA 4.0 许可;
请参阅 assets/ocr/NOTICE.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。