惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
博客园_首页
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
Hugging Face - Blog
Hugging Face - Blog
美团技术团队
小众软件
小众软件
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
罗磊的独立博客
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
M
MIT News - Artificial intelligence
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog

阁子

lamarck 按真实调用进化全部 skill · 阁子 FrontierAgent 的上下文压缩与重复抑制 · 阁子 magpie 本地语义搜索 · 阁子 OpenViking 的上下文组织与检索 · 阁子 munder-difflin 的多 agent 协调实现 · 阁子 ai-memory:换个 CLI 接着干的 agent 记忆层 · 阁子 TimesFM:预测之前的脏活都在模型外面 · 阁子 DarwinX:模型不动,只进化外壳 · 阁子 Final2x:一个刻意做薄的超分外壳 · 阁子 Cordis:把卸载做完备的插件框架 · 阁子 DeepSeek Harness:一切皆插件的开源 agent 运行时 · 阁子 Agency Agents:一座 AI 角色库的分发工程 · 阁子 Harvey LAB:法律 Agent 基准的架构与评测方法 · 阁子 DeepTutor:开源的 AI 私人家教工作台 · 阁子 Semantica:面向可审计 AI 的图原生基础设施 · 阁子 PromptCache:LLM 语义缓存网关的架构与实现 · 阁子 Prime Agent,只给模型一个工具的长跑 agent · 阁子 Skill Shelf: 给 agent 的 skill 仓库,兼做服务的配置中心 · 阁子 Cloudflare Computer,装在 Durable Object 里的文件系统 · 阁子 QM,给全公司用的 agent 平台 · 阁子 PersonaLive: 把肖像扩散模型压到能直播 · 阁子 Neon: 把本地视频点亮成系统虚拟摄像头 · 阁子 LiteReality-Agent笔记: 从一次扫描到可交互的房间 · 阁子 LiteReality-Agent笔记: 从一次扫描到可交互的房间 蝉与梦 · 阁子 小工具(三) 小工具(三) · 阁子 相机小述 相机小述 · 阁子 四元数与旋转矩阵
LEANN 的重算式向量索引 · 阁子
2026-08-31 · via 阁子

向量检索有个不太好看的账:索引往往比原始数据还大。六千万条文本切块,用传统办法建索引要 201 GB,而那堆文本本身没那么大。想在自己笔记本上索引邮件、浏览记录、聊天记录,这道门槛就卡在硬盘上。
LEANN 的选择是索引里干脆不存向量,只存一张剪过的图,搜索时走到哪一跳就现算哪一跳的向量。同样那六千万条,索引降到 6 GB。
论文是 arXiv:2506.08276,伯克利那批人写的,作者名单里有 Ion Stoica、Matei Zaharia、Joseph Gonzalez。

存储开销

摘要里的原话是索引「需要存储高维嵌入和大量索引元数据,其总大小可能是原始数据(例如文本块)的数倍」。占地方的是那一堆浮点数,文本本身反倒是小头。

一条 768 维的 float32 向量是 3 KB,六千万条就是 180 GB。存储曲线跟着向量维度和条数走,跟你实际有多少字没多大关系。

LEANN 的做法是把这部分从磁盘上删掉,改成用的时候现算。论文说索引最多能缩小到原来的五十分之一,占原始数据约 5%,而检索精度和延迟保持在可比范围。仓库里给的对比表是这样:

六千万条维基文本:传统 201 GB,LEANN 6 GB,省 97%
两百一十万条 DPR:3.8 GB 对 324 MB,省 91%
七十八万封邮件:2.4 GB 对 79 MB,省 97%
三万八千条浏览记录:130 MB 对 6.4 MB,省 95%

这几个数是项目自己报的,我没复现。要当真得知道它们省略了什么:没写用的哪个嵌入模型、多少维、什么机器,而这三样直接决定分子和分母。后两行还标着是「部分个人数据」的测试结果。仓库里有 benchmarks/run_evaluation.py 可以自己跑,会自动下评测数据。

检索流程

LEANN 的一次检索

先把查询嵌一次,这是整个流程里唯一必然发生的一次嵌入。然后进图,走一跳,需要跟哪些邻居比距离,就把这些节点的编号报出去,等向量算回来,比完再决定下一跳往哪走。

「报出去」这四个字是字面意思。后端不是自己写的,是 faiss 和 DiskANN 的分叉,加上 ZeroMQ 和 msgpack 两个子模块。C++ 那侧走到需要向量的时候,把一个装着 node_ids 的 protobuf 从 ZeroMQ 发出来,Python 那侧收到编号、查回原文、成批过一遍嵌入模型,再把向量送回去。图遍历中途是真的停在一次跨进程往返上等着的。

我第一次读到这儿以为是自己看错了目录,跨进程做热路径,通常是设计出了问题才会这样。但它解释了另外几个机制为什么必须存在。既然每一跳都要付一次模型前向的代价,那就得让需要算的点尽可能少、尽可能扎堆:一跳要的邻居攒成一批送过去,GPU 才吃得饱;两级搜索先粗后精,把昂贵的精算留给真有希望的候选;剪枝则从源头减少要走的边。这几样单看都像常规优化,放在这个前提下才是必需品。

图剪枝

论文管这套叫高度数保留剪枝。图索引的邻接表本身也占地方,如果把向量删了但邻接表膨胀起来,账就白算了。

思路是保住高度数的枢纽节点、砍掉冗余连接。近邻图里少数节点承担了绝大部分的连通性,删掉它们的边会让搜索路径变长甚至走不通,而大量低度数节点之间的边是可以省的。剪完之后用压缩稀疏行格式存,省下来的空间不会被邻接表吃回去。

后端

默认是 HNSW,走完全重算,存储省得最狠。另一个是 DiskANN,用乘积量化过的向量做图遍历、再实时重排,README 说这条路速度和精度的折中更好。

区别落到实处就是:HNSW 那条路索引里真的没有向量,DiskANN 那条留了一份压缩过的粗向量用来导航,精确距离仍然靠现算。前者省到极致,后者少几次往返。

参数

检索侧的默认值摆在 api.py 里:候选队列 complexity=64beam_width=1prune_ratio=0.0recompute_embeddings=True,剪枝策略默认 global,另有 localproportional 两档。

recompute_embeddings 可以关,关掉就退回普通的存向量模式,这在索引不大、又想要极限延迟的时候有意义。剪枝比率默认是零,也就是不额外剪,需要更省的时候再往上调。

顺带一提它还带一条 BM25 通路,用 SQLite 的 FTS5 建全文索引,和向量结果做融合,分词那里对中日韩做了 ngram 处理。这条跟主线关系不大,但对中文语料是实打实的差别。

安装与使用

装完之后建索引、搜索、对话是三条命令的事(下面这几条抄自 README,我没在本机跑过):

bash
uv pip install leann
leann build my-docs --docs ./documents
leann search my-docs "这里写你想找的东西"
leann ask my-docs --interactive

仓库里给了一大堆现成的接入:文件系统、Apple Mail、浏览器历史、微信、iMessage、ChatGPT 与 Claude 的会话记录、Slack、Twitter 书签。还有一个 MCP 服务,可以直接给 Claude Code 当语义搜索用,它自带的只有 grep 那种关键词匹配。

生成模型那侧支持本地引擎(Ollama、vLLM 之类)和云端 API 两种,README 的推荐是本地,理由跟整个项目一致,数据不出机器。

代价

省下来的磁盘换成了算力。

每次检索都要跑嵌入模型,所以机器得扛得动这个模型。门槛没有消失,只是从硬盘挪到了显卡,原来是装不下,现在是跑不动。

模型没就绪就搜不了。传统索引把向量落盘之后,检索本身是纯 IO 加算术,进程重启就能用;LEANN 得先把嵌入服务拉起来,那是一次冷启动。

延迟的说法要看清限定词。论文写的是 RAG 应用下延迟「可比」,不是更快。RAG 本来就要等一次大模型生成,检索多花的几十毫秒被盖住了;换成对延迟敏感的在线检索场景,这个结论不一定成立。

还有一处是我从子模块清单读出来的:真正的算法在 faiss 和 DiskANN 的分叉里,也就是 yichuan-w/faissyichuan-w/DiskANN。仓库主体是 Python 编排层,一百七十多个 py 文件,C++ 那侧要拉子模块才看得到。想读实现的话别只克隆主仓库。

要不要用,我的判断是分场景。个人机器上索引邮件、聊天记录、浏览历史这类,值得,因为那个量级传统索引根本放不下,而这些数据你本来也不会拿去查十万次。反过来,如果索引不大、机器没有像样的 GPU、或者检索延迟直接顶在用户面前,就别折腾了,recompute_embeddings=False 关掉重算之后它退回成一个普通索引,那还不如一开始就用别的。分界线大概在这批数据的索引装不装得下,装得下就没必要,装不下才是它存在的理由。