- 周皓9小时前
zg(zvec-grep)把 向量语义检索、BM25 关键词检索和 ripgrep 精确匹配装进了同一个本地命令行工具,同时通过 MCP 提供给 Claude Code、Codex、Cursor 等 AI Agent 使用。0.3.0 版本用 Rust 完整替换了原来的 Node.js 实现:安装包体积减少 79.5%,CLI 启动耗时减少 82.5%,索引构建耗时减少 64.5%,构建期峰值内存降低 53.2%。
项目地址:https://github.com/zvec-ai/zvec-grep
一、zg 是什么
zg(zvec-grep)是阿里巴巴开源的本地检索工具,面向人和 AI Agent,把向量语义检索、BM25 关键词检索和 ripgrep 精确匹配整合到同一个入口。
rg 是很多 Rust 开发者每天都在用的工具。函数名、配置项、报错信息这类明确目标,用 rg 查又快又准,而且能搜全。
但现在越来越多的检索请求来自 AI Agent,输入也从明确的符号变成了自然语言:“启动时怎么恢复主题偏好?”“用户权限在哪里校验?”。代码里对应的实现可能叫 hydratePreferences,文档里可能写成“账号授权与审批”,和问题本身没有一个相同的词。这种时候只用文本匹配,要么漏掉,要么把范围放得很大,得到一堆没有排序的匹配行。Agent 只能反复换关键词、搜索、读文件,工具调用次数、耗时和 Token 都会上去。
zg(zvec-grep) 就是为这个问题做的本地检索工具。它保留 rg 精确、快速、可以穷尽匹配的优点,再补上语义发现、相关性排序和上下文组织:
一个入口,多种检索:向量语义检索、BM25、二者混合检索(RRF 融合排序),以及 rg 风格的精确/正则匹配。可以先按语义找方向,再按关键词收窄,最后用正则精确核对。
理解代码结构:借助 tree-sitter 解析 C/C++、Go、Java、JavaScript/TypeScript、Python、Rust 等语言,按符号、签名和层级切分;Markdown 按标题和章节切分;JSON、TOML、YAML、CSV 等文本数据也能参与检索。
结果紧凑、来源可查:默认返回排序后的紧凑预览,每条结果带文件路径和行号,需要时再读全文,避免无关内容塞满 Agent 的上下文。
默认本地运行:文件扫描、Embedding、索引和检索默认都在本机完成。内置多种端侧模型,远程 Embedding 必须经过用户明确授权才会启用。
人和 Agent 共用一份索引:zg 底层用 Zvec https://github.com/alibaba/zvec 嵌入式向量数据库同时存放向量索引和 BM25 索引,不用另外部署数据库服务。CLI 和 MCP 读写的是同一份索引,并支持增量更新和自动刷新。
在代码仓库问答 SWE-QA-Bench 和深度研究问答 BrowseComp-Plus 的配对 A/B 评测中(同一 Agent、同一模型、同一 Prompt,只比较是否接入 zg):
SWE-QA-Bench:工具调用减少一半以上,输入 Token 减少近一半,评审得分提高 1.50 分;
BrowseComp-Plus:准确率从 98.67% 提高到 99.00%,输入 Token 减少 37.56%,工具调用减少 43.52%,Agent 耗时减少 38.58%。
二、从 Node.js 到 Rust:重写带来了什么
为什么重写
zg 的前几个版本(0.2.x)用 TypeScript/Node.js 实现。对一个高频调用的命令行检索工具来说,这个运行时有几个绕不开的成本:
每次单独调用 CLI 都要启动 Node.js 运行时并加载 JS 模块,Agent 连续调用时,这部分时间会累积起来;
部分索引路径要在 JavaScript 普通数组和 TypedArray 之间转换,还要在 worker 线程之间传数据,带来额外的复制和临时内存分配;
安装包要带上整套 JS 依赖和原生插件,体积很大。
大型工作区和 Agent 工作流对索引耗时、查询延迟和资源占用都很敏感,所以我们用 Rust 重写了整条核心执行链路。
性能对比
测试环境:Apple M3 Pro、18 GB 内存、macOS 27.2,Node.js v24.16.0。索引数据集使用 BEIR 中的 SciFact、NFCorpus、ArguAna 和 FiQA 四个公开语料,共 75,128 篇文档。两个版本使用同一个本地 Embedding 模型,都走 CPU 推理,Embedding 并发设为 4。
指标
Node.js 0.2.2
Rust 0.3.0
改善安装包体积(含依赖)
167.5 MiB
34.3 MiB
减少 79.5%CLI 启动耗时
153.1 ms
26.8 ms
减少 82.5%索引构建总耗时
219.13 s
77.84 s
减少 64.5%平均构建峰值内存(RSS)
4,210.26 MiB
1,968.61 MiB
降低 53.2%平均检索耗时(MCP)
20.93 ms
14.88 ms
减少 28.9%换算成实际体验:四个语料的首次建索引时间从约 3 分 39 秒缩短到约 1 分 18 秒;构建期峰值内存从约 4.11 GiB 降到约 1.92 GiB,而且四组测试每一组都下降了。本机同时开着编辑器、Agent 和其他开发工具时,这部分内存节省很明显。
性能从哪里来
原生启动:直接运行编译好的原生程序,不再需要初始化 Node.js 运行时和加载 JS 模块。CLI 冷启动从 153 ms 降到 27 ms。
计算路径更直接:文本编码和向量计算在原生代码中完成,使用明确的数值类型和连续内存数组,编译器更容易优化计算循环。
减少中间转换:计算结果一直以原生数值数组的形式存在,不再在 JS 普通数组和 TypedArray 之间来回转换,数据复制和临时分配都少了。
共享资源、统一调度:在支持的本地推理路径上,各计算线程共享已加载的分词器和模型数据,避免重复初始化,任务由原生线程池统一调度。
三、上手:安装与使用
- 安装
zg 目前通过 npm 分发(后续会支持其他安装方式),运行时直接执行原生程序,不依赖 Node.js。支持 macOS、Linux 和 Windows。
npm install -g/zvec-grep --allow-scripts=/zvec-grep
zg --version安装依赖 npm 的 postinstall 脚本把原生程序放入合适位置和按需下载 CUDA,所以要加上 --allow-scripts 允许它运行。
- 接入 AI Agent(可选)
自动发现本机已安装的 Agent 并配置 MCP
zg --install
也可以指定目标,例如 Claude Code / Codex / OpenCode
zg --install --target claude --yes
zg --install --target codex --yes目前支持的目标包括 claude、codex、opencode、cursor、qwen、qoder、copilot、vscode、grok、pi。配置完成后重新连接 Agent,Agent 会根据问题自己判断什么时候调用 zg。
- 建立索引
cd your-repository
默认使用面向代码的轻量本地模型 local/potion-code-16m-v2
zg --index
查看索引覆盖范围、Embedding 模型和存储状态
zg --status
索引保存在工作区根目录下的 .zvec-grep/。之后文件有变化时只做增量处理,内容没变的文件不会重新计算 Embedding。如果要换模型,用 zg --index --rebuild --embedding <model> 重建索引。
在交互式终端里,即使跳过这一步直接搜索,zg 也会先引导你选模型并建好索引。脚本或 CI 这类非交互环境不会自动建索引,需要先显式执行 zg --index。
- 检索
自然语言 / 语义检索(默认混合检索:向量 + BM25,RRF 融合排序)
zg "where is the connection pool timeout configured"
zg "用户权限在哪里校验"只走 BM25 关键词检索,或只走向量检索
zg --fts "AuthService"
zg --vector "retry with exponential backoff"同时执行多个查询,--fuse 把多组结果合并后统一排序
zg --hybrid "connection pool" --hybrid "socket timeout" --fuse
用 rg 风格做精确/正则匹配(不需要索引)
zg --rg -n "AuthService" src
zg --rg -F "fn main(" crates限定范围:文件类型、glob、条数
zg "error handling for invalid config" -t rust -g 'crates/**' --limit 5
调整预览详细程度:none / short(默认)/ full / detail
zg --preview detail "how indexing jobs are scheduled" --limit 3
- 示例:用小说测试一下
mkdir zg-mystery && cd zg-mystery
curl --retry 3 --retry-all-errors --progress-bar -fL \
-o alice-in-wonderland.txt https://raw.githubusercontent.com/GITenberg/Alice-s-Adventures-in-Wonderland_11/master/11.txt \
-o sherlock-holmes.txt https://raw.githubusercontent.com/GITenberg/The-Memoirs-of-Sherlock-Holmes_834/master/834.txt语料是英文小说,换用面向文本检索的本地模型
zg --index --embedding local/potion-retrieval-32m
zg --preview detail "An unseen creature left a few marks. What did the detective infer?" --limit 3
查询里没有出现 Holmes、weasel、foot-marks 这些原文用词,zg 依然会把《福尔摩斯回忆录》中《驼背人》里根据脚印推断动物的段落排在最前面,并给出具体行号。
四、写在最后
zg 0.3.0 是 Rust 版的第一个正式版本。接下来我们会继续推进图检索与重排、PDF/Office 等更多内容格式、更高的上下文效率,以及本地模型和索引的性能优化。
欢迎 Rust 社区的朋友试用,也欢迎提 Issue、PR,或者分享你在大型代码库、知识库和 Agent 工作流里的使用情况:
GitHub:https://github.com/zvec-ai/zvec-grep
文档:https://zvec.org/zh/docs/zvec-grep/
Rust 版发布博客:https://zvec.org/zh/blog/2026-11-03-zvec-grep-rust/
开源发布博客:https://zvec.org/zh/blog/2026-08-28-zvec-grep-open-source/
如果觉得有用,欢迎给项目点个 Star。
主楼 - 彭白9小时前
这个 Rust 重写后性能提升很大,请问内存降低主要是得益于什么优化措施?
- 彭天9小时前
之前用 Rust 重写搜索工具也遇到过内存优化问题,这种替换方案确实能大幅提升性能。
- 萧映雪9小时前
建议在配置文件中增加
memory_limit参数,允许用户自定义索引构建时的内存使用上限。