VOL.001 · 创刊号Token 天团 API

Token 天团

—— 一份关于代码与生活的个人刊物 ——

技术教程工具

zg(zvec-grep)使用指南:把 ripgrep、BM25 和语义搜索装进一条命令

ripgrep(rg)是所有开发者的肌肉记忆——但它有个天花板:你只知道意思、不知道措辞时,它无能为力。「处理用户余额扣成负数的那段逻辑在哪?」这种问题,rg 只能靠你猜出 balance、deduct 之类的词碰运气。反过来,纯向量搜索又会漏掉精确标识符,还常常不给你源码位置,等于让 LLM 猜。

zg(zvec-grep,阿里 Zvec 团队开源,Apache 2.0)的答案很直接:别选,全都要。它把 ripgrep、BM25 和向量语义搜索统一在一个本地优先的命令行界面后面,人能用、AI 代理能用,还共享同一份索引。Rust 实现正在 rust/ 目录并行开发中,目前的 TypeScript 版要求 Node.js 22+。

一、三种检索为什么必须混合

zg 的三路检索在融合排序后输出带源位置的紧凑证据

检索方式 擅长 天生短板
ripgrep 精确文本、正则 找不到「意思相近但措辞不同」的内容
BM25 关键词词法排序 同上,且不懂同义
向量语义 按含义发现、跨措辞召回 会漏精确标识符,需要嵌入模型

zg 的融合排序把三者合并成带源码位置的紧凑证据。官方基准里最说明问题的数字不是「答得多好」,而是输入 token 和工具调用次数同时下降——对按 token 计费的代理来说,这是省钱的;对人来说,这是少翻十几个文件的。官方在 pylint、matplotlib、django 三个真实仓库上的案例研究表明,zg 最亮的场景是:证据跨文件/跨模块、且目标位置事先未知的调用链、数据流、架构类问题(比如「FontInfo 这个 NamedTuple 在数学文本渲染管线里怎么传播」)。如果问题本身就是一个精确标识符,rg 依然是最快的答案——zg 不取代它,而是补上它够不着的那半边。

二、五分钟上手:官方书架实验

拿两本公版小说当语料,最适合体会「语义搜索」和「关键词搜索」的区别:

# 需要 Node.js 22+
npm install -g @zvec/zvec-grep

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 query --human \
  "An unseen creature left a few marks. What did the detective infer?" \
  --limit 3

zg 会把《福尔摩斯回忆录》里相关段排在《爱丽丝》前面返回——注意查询里没有 “Sherlock”、没有 “footprint”,rg 在这里一个字都搜不出来。索引存在项目根的 .zvec-grep/ 目录下,之后自动增量刷新,不用手动维护。

命令挂了就加 --debug 重跑(直连和 server 模式都支持);zg status --mode direct --debug 能看到索引里每个文件的失败原因。

三、嵌入模型:本地是默认,不是妥协

zg 的立场是 local by default——文件、索引、模型全部留在本机,只有你明确授权时才会把数据发给远程嵌入服务。本机默认配置(~/.zvec-grep/config.json)长这样:

{ "version": 1, "defaults": { "embedding": "local/potion-code-16m-v2" } }

potion-code-16m-v2 是个极小的代码向模型,CPU 上跑得飞快,这也是 zg 敢默认本地的底气。需要更高召回质量时可以换:

  • llama.cpp / Transformers.js 本地模型——重一些,质量更好;
  • 远程嵌入模型(如 Qwen 系 text embedding)——质量上限最高,数据出本机需明确授权。

GPU 用户注意一个真实的坑:索引时的嵌入并发默认按「空闲显存 × 25% / 150MB」估算,上限 8。遇到 CUDA 报错、显存耗尽或原生崩溃,先把并发降到 1 重试:

export ZVEC_GREP_INDEX_EMBEDDING_CONCURRENCY=1   # PowerShell: $env:ZVEC_GREP_INDEX_EMBEDDING_CONCURRENCY="1"
zg --index --mode direct

也可以加 --device cpu 直接绕开 GPU。查询侧的推理不受这个并发参数影响。

四、接入 AI 代理(MCP)

一行命令把 zg 装进支持的代理(Codex、Claude Code、Qwen Code、Cursor、GitHub Copilot、VS Code、OpenCode 等):

zg install --target opencode --yes   # 换成你在用的代理名

装完后代理获得 zvec_grep_search 工具。以官方 OpenCode 演示为例,代理的实际调用长这样:

zvec_grep_search {
  "root": ".../zg-mystery",
  "query": "An unseen creature left a few marks. What did the detective infer?",
  "fts": ["marks", "unseen creature", "inferred", "detective"],
  "fuse": true
}

注意这个参数设计的巧思:query 走语义,fts 数组同时喂关键词路,fuse: true 融合——一次调用就把三种检索全用了。代理拿到的是带文件名和行号的证据(sherlock-holmes.txt:5479-5486 这种),下一步精确读文件就行,不需要把整个仓库扫一遍。

五、索引策略:不是每个目录都值得建索引

zg 建索引很快,但索引不是免费的(磁盘 + 首次嵌入耗时)。我的实践规则,供参考:

  1. 真实项目、问题类型是「语义/架构/跨文件」时才建——比如「这个项目的鉴权是怎么串起来的」;
  2. 精确文本、标识符、路径、正则查找,直接 rg,不要为一次 grep 建索引;
  3. 家目录、下载目录、临时目录不建——零散文件没有检索价值,白白吃磁盘;
  4. 建了索引的 git 仓库,往 .gitignore 加一行 .zvec-grep/,别让索引进版本库;
  5. 索引一旦存在就信任它的自动刷新,不要频繁重建或换模型(换了模型等于全部重嵌入)。

写在最后

参考:zvec-ai/zvec-grep(Apache 2.0)· 阿里云官方博客:From rg to zg · 路线图 Issue #128 · 架构图为本刊依据官方文档自绘。

zg 代表的方向我觉得值得所有工具作者抄作业:检索能力的升级,不该以改变使用习惯为代价。rg 的用户依然是 rg 的用户,只是多了一层语义;代理不是多了个要学的工具,而是少了一堆要翻的文件。「Know the words—or don’t. Just zg.」这句 slogan,起得很准。

❦ 终 ❦

← 回到首页全部归档 →