Dropbox 开源 Witchcraft:Rust 重写的端侧语义搜索引擎,0.2.0 版支持 Windows GPU
Dropbox Witchcraft
Dropbox 发布 Witchcraft(原 Rust-Warp),用 safe Rust 从零重写斯坦福 XTR-Warp 语义搜索引擎,以单文件 SQLite 作为存储,可完全在本地运行,无需 API key、向量数据库、分块策略或重排序器。
(原名 Rust-Warp)
这是对斯坦福 XTR-Warp 语义搜索引擎(https://github.com/jlscheerer/xtr-warp)从零开始的安全 Rust 重新实现,使用单文件 SQLite 数据库作为后端存储,使其适合客户端部署。它完全独立地在你的设备上运行,无需 API 密钥、无需向量数据库、无需分块策略、无需花哨的重排序器,而且速度极快(在 NFCorpus 上端到端搜索延迟 p.95 为 14ms,NDCG@10 为 34%,在 Apple Macbook Pro M4 Max 上,比在服务器级硬件上运行的原始 XTR-WARP 快两倍以上。)
0.2.0 版本新增了对 Windows GPU 的原生支持,无需依赖 OpenVINO 等,磁盘索引格式更加紧凑,索引更新的可扩展性更好,搜索精度更高,并对 Pickbrain 智能体记忆工具进行了许多更新,其中包括能够在 MacOS 上注册为 launchd 服务,从而在后台保持索引更新,降低查询期间需要等待索引更新的风险。
先决条件
需要 uv、make 和 Rust 工具链。
构建与运行
默认构建使用我们的 ModernBERT 检索模型,具有 96 维 token 嵌入和 token 门控。make 会从版本化模型发布下载 safetensors 权重、配置和分词器的压缩归档到 assets/,并在本地派生出量化后的 GGUF 模型:
make warp-cli
下载使用带 curl 的公共 URL;无需 GitHub 账户或 GitHub CLI。
相同的权重支持未量化后端(make warp-cli ENCODER=modernbert)。这些权重源自 IBM 的Granite Embedding English R2,采用 Apache 2.0 许可。我们的微调和其他修改版权归 Dropbox Inc. 所有(Copyright (c) 2026),并受仓库的 Apache 2.0 许可覆盖。归档中包含仓库 LICENSE、上游 LICENSE.granite、标识我们修改的 NOTICE,以及用于验证下载的 SHA256SUMS。现有的本地资源会被保留。要使用你自己的检查点,请用 env/bin/python scripts/export_modernbert.py <checkpoint> assets 导出,然后用 cargo run -p quantize --release -- assets/modernbert.safetensors assets/modernbert.gguf 对其进行量化。
对于 Google 的原始 XTR 模型,运行 make warp-cli ENCODER=t5-quantized;随附的 Python 脚本会从 Hugging Face 下载其权重并将其量化为 GGUF。
创建索引:
为了测试,我们使用 XTR-Warp 的 BEIR 下载脚本下载 nfcorpus,并检查我们能否复现他们的结果。为方便起见,这里包含了 nfcorpus.tsv,因此你可以运行:
$ make nfcorpus
导入所有 nfcorpus 文档后,将创建嵌入,并用它们更新索引。
所有状态都会持久化在 mydb.sqlite 中,你可以中止索引器,它会从上次中断的地方继续。要重新开始,只需删除 mydb.sqlite 即可。
你可以用以下命令重新运行 nfcorpus 评分结果:
$ make nfcorpus-score
查询索引
有了索引后,你可以用以下命令查询:
$ ./warp-cli query "does milk intake cause acne in teenagers?"
希望你能得到一堆相关答案。你也可以尝试其他变体,除了 "query",你还可以使用 "hybrid",它将语义搜索与 sqlite 自带的 BM25 搜索功能相结合。
Pickbrain:对你的 AI 编码会话进行语义搜索
作为示例包含的是 pickbrain(见上方截图),这是一个 CLI,可将你的 Pi、Claude Code 和 OpenAI Codex 会话记录、记忆文件以及撰写的文档索引到 Witchcraft 数据库中,以实现快速语义搜索。曾经想过“我修复 auth 中间件的那次对话是什么?”——pickbrain 能找到它,并让你直接恢复该会话。
make pickbrain
./pickbrain auth middleware fix # search across all sessions (auto-ingests new sessions)
./pickbrain --session <UUID> auth # search within one session
./pickbrain --dump <UUID> # print full conversation
将 PRE_INGEST_COMMAND 设置为在 pickbrain 检查新会话之前运行的 shell 命令(例如来自另一台主机的 rsync)。将 EXTRA_CODEX_DIRS、EXTRA_CLAUDE_DIRS 或 EXTRA_PI_DIRS 设置为额外的数据目录,在 Unix 上用 : 分隔,在 Windows 上用 ; 分隔。每个条目的布局应分别与 ~/.codex、~/.claude 或 ~/.pi/agent 相同。Pickbrain 会将这些目录与默认目录一起扫描。
scripts/sync_codex_sessions.sh 接受一个 SSH 主机和一个绝对本地目录。它只复制会话 *.jsonl 文件,并将主机写入 pickbrain.remote。Pickbrain 将这些结果标记为已下载;在浏览器中按 r 可查看该主机的 SSH 命令。
PRE_INGEST_COMMAND="$PWD/scripts/sync_codex_sessions.sh your-ssh-alias $HOME/.pickbrain/remote-codex" \ EXTRA_CODEX_DIRS="$HOME/.pickbrain/remote-codex" ./pickbrain auth middleware fix
对于现有的额外 Codex 目录,将其 SSH 主机名填入 <extra-codex-dir>/pickbrain.remote 以标记这些会话。
源代码位于 examples/pickbrain/,演示了如何将 Witchcraft 作为库使用:文档摄取、嵌入、索引和混合搜索。要将 pickbrain 安装为 Pi 的技能/扩展,以及作为 Claude Code 和 Codex 的技能:
make pickbrain-install
要自动摄取,请以监视模式运行 Pickbrain:
make pickbrain
./pickbrain --watch
pickbrain --watch 监视本地 Claude、Codex 和 Pi 目录、配置的额外目录,以及 macOS 上 Slack 的 IndexedDB blob。它使用原生通知,等待 30 秒无变化,并将延迟上限设为五分钟。设置 --delay SECONDS 和 --max-delay SECONDS 以调整这些间隔。它在启动时检查未完成的工作,并在通知丢失时重新扫描。新的或重新创建的源目录会被自动检测到。
在 macOS 上,FSEvents 可能会推迟对 Codex 保持打开的会话文件的通知。监视器还会在每个静默延迟间隔(默认 30 秒)检查会话文件大小和更改时间。这仅读取元数据;当检测到更改且防抖延迟到期时,摄取才会开始。
监视器使用 --ingest-only --quiet 生成自己的可执行文件,一次一个子进程。它将每次完成的运行记录为 pickbrain: no changes 或 pickbrain: ingested and indexed N documents。计数指已处理的文档(对话轮次和文件),包括从已更改会话中重新读取的文档。摘要出现在索引成功之后;错误保持可见。监视器会保留摄取期间到达的更改以供另一次处理。失败的子进程会在静默延迟后重试。模型内存和 GPU 资源属于子进程,并在其退出时释放;监视模式在数据库、模型或 GPU 初始化之前进入,并在通知和元数据检查之间等待。Pickbrain 的数据库、日志和水位标记不会触发摄取。正常的摄取锁也能防止交互式 Pickbrain 运行。不完整的无头摄取即使源水位标记已经推进也会重试。
make pickbrain-install 将单个二进制文件安装到 ~/bin,然后注册或更新后台监视器。要直接注册现有二进制文件,请运行:
pickbrain --register
注册会立即启动监视器,并在登录时启动,使用 macOS 用户 LaunchAgent(com.dropbox.pickbrain)、Linux 用户 systemd 服务(pickbrain.service)或 Windows 任务计划程序登录任务(Pickbrain-<user SID>)。它在后续注册时替换相同的作业。--delay 和 --max-delay 也可与 --register 一起使用。注册会保存当前工作目录、PATH、源目录设置、PICKBRAIN_DIR、WARP_ASSETS 和 PRE_INGEST_COMMAND 到 ~/.pickbrain/watch.json,以便后台作业可以在你的 shell 之外使用相同的设置。重新注册以更改它们。日志(包括摄取摘要和错误)会写入 ~/.pickbrain/watch.log:
tail -f ~/.pickbrain/watch.log
在 macOS 上,使用
launchctl bootout gui/$(id -u)/com.dropbox.pickbrain 停止任务;移除
~/Library/LaunchAgents/com.dropbox.pickbrain.plist 以防止在下次登录时启动。在 Linux 上使用 systemctl --user disable --now pickbrain.service;在 Windows 上,
在任务计划程序中停止并删除命名任务。Linux 注册需要
运行中的用户 systemd 管理器。在 Windows 上,当 HOME 未设置时,USERPROFILE 提供主目录。
监视器使用其自身的可执行文件路径,因此符号链接和
PATH 解析无需配置。远程主机仍需要单独的
定期同步任务,因为本地文件系统通知无法检测
这些主机上的更改。
这会将二进制文件放到你的 PATH 中,并安装技能/扩展定义,
这样你就可以直接从 Pi、Claude Code 或 Codex 使用 pickbrain 来回答需要
全局了解你所有项目的问题:
更多构建信息
功能标志
构建时,必须恰好启用一个编码器后端:
t5-quantized-- 通过 candle 使用 GGUF 量化权重modernbert-quantized-- GGUF ModernBERT 权重(默认)modernbert-- 全精度 ModernBERT 权重
其他标志:
metal-- Candle Metal 加速neso-metal-- Neso 生成的 Metal 内核neso-d3d12-- Neso 生成的 D3D12 内核fbgemm-- fbgemm-rs 打包 GEMM(bf16 权重,在 x86 上更快)hybrid-dequant-- F32 注意力 + Q4K FFN,带融合 gated-gelu(x86,需要fbgemm)napi-- 通过 napi-rs 的 Node.js 原生模块python-- 通过 PyO3/maturin 的 Python 扩展模块embed-assets-- 将权重烘焙进二进制文件progress-- CLI 进度条
Neso GPU 内核以压缩归档形式缓存在 kernels/out/ 中,并嵌入
到二进制文件中。当 Neso 环境可用时(位于
../neso 或 NESO_DIR),Cargo 会重新构建它们;否则它会使用已检入的缓存,包括其
Rust 加载器。此回退不需要 Python、Neso 或着色器编译器。Metal 在两种 Mac 架构上
都使用标量内核;Windows 使用 DXIL 缓存。
要在更改内核后刷新缓存,请在安装 Neso 的情况下运行 make neso-kernels-metal-nosimd
和 make neso-kernels-hlsl。缓存生成还需要 zstd。
平台特定推荐功能(这些是 make 自动使用的功能):
- Apple Silicon:
modernbert-quantized,neso-metal - Intel Mac (x86_64):
modernbert-quantized,neso-metal - Intel Windows (x86_64):
modernbert-quantized,neso-d3d12 - Linux x86_64 (CPU):
modernbert-quantized,fbgemm,hybrid-dequant - Linux x86_64 (CUDA):
modernbert-quantized,cuda - Linux ARM (Graviton, Pi, Ampere):
modernbert-quantized(fbgemm/hybrid-dequant仅限 x86)
作为 Python 模块使用
为你的当前平台构建 wheel(自动选择正确的后端功能):
make python-wheel
或者直接安装到仓库管理的 virtualenv 中以供开发:
make python-dev
Makefile 会自动选择正确的功能集(Apple Silicon 上为 metal,
Intel 上为 fbgemm,hybrid-dequant,带 GPU 的 Linux 上为 cuda)。该 wheel 适用于
Python 3.8+,包括 3.14+。
要构建/安装扩展并运行 Python 测试套件:
make python-test
覆盖 PYTHON_TEST_ARGS 以传递自定义 pytest 参数,例如
make python-test PYTHON_TEST_ARGS="-q tests/test_witchcraft.py"。
然后在 Python 中:
import witchcraft wc = witchcraft.Witchcraft('/path/to/db.sqlite', '/path/to/assets') # Add documents (fire-and-forget, processed by background thread) wc.add('550e8400-e29b-41d4-a716-446655440000', '2024-01-15T10:00:00Z', '{"source": "dropbox"}', 'The document text goes here') # Build pending embeddings and index data; blocks until complete wc.index() # Hybrid semantic + BM25 search results = wc.search('does milk intake cause acne?', threshold=0.3, top_k=5) for r in results: print(r['score'], r['body']) # Score individual sentences against a query scores = wc.score('acne and diet', ['milk causes acne', 'exercise helps skin']) # Shut down the background indexer cleanly wc.shutdown()
search 返回一个字典列表,键为:score、metadata、body、idx、date。
作为 Node 模块使用
make module
在 target/release/warp-macos-universal.node 构建通用 macOS 二进制文件
(由 aarch64 + x86_64 构建经 lipo 合并,并使用适合平台的功能)。
要在另一个项目中使用:
cd /path/to/your-project
npm install /path/to/witchcraft
然后在 JavaScript 中:
const { Witchcraft } = require('warp'); const wc = new Witchcraft('/path/to/db.sqlite', '/path/to/assets');
单元测试和代码覆盖率
cargo install cargo-nextest
cargo install cargo-llvm-cov
cargo install llvm-tools-preview
make test
注意 nextest 是必需的,简单地使用 "cargo test" 会导致 随机测试失败,因为各个测试在同一进程中运行, 导致“历史效应”。
准备 PR
在提交 PR 之前,请确保
make test
和
make nfcorpus
运行,并且
make nfcorpus-score
运行并在 0.31-0.33 范围内得分
注意 nextest 是必需的,简单地使用 "cargo test" 会导致 随机测试失败,因为各个测试在同一进程中运行, 导致“历史效应”。
TRECCOVID
TRECCOVID 按需从 BEIR trec-covid 归档准备:
make treccovid-files
make treccovid
make treccovid-score
make treccovid 从 mydb.sqlite 构建 datasets/treccovid.tsv,并且
make treccovid-score 对测试查询运行 treccovid-score.sh 并
打印 NDCG@10。
评分完全在 Rust 中运行,无需 Python 或 pytrec_eval:
make trec-score
target/release/trec-score output.txt testset/nfcorpus/collection_map.json testset/nfcorpus/qrels.test.json
该工具读取 querycsv 结果,并使用 trec_eval 的
线性相关性增益打印平均 NDCG@10。可选的第四个参数可更改截断值。
当结果已包含原始文档
ID 时,使用 JSON null 集合映射。与之前的评分器一样,它对已提交且具有 qrels 的查询取平均;
空结果计为零,缺失或未评判的查询被排除。
该独立工作区工具在构建时无需编码器功能、权重或 GPU
依赖。NFCorpus、TRECCOVID、SciFact 和 Spotlight 评分均使用它。
许可证
除非另有说明:
Copyright (c) 2026 Dropbox Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
来源:Hacker News · github.com

