检索与知识系统AI 编程

RAG 向量检索的核心抉择:什么时候最简单的方案就够用

RAG 向量检索的核心抉择:什么时候最简单的方案就够用

RAG(检索增强生成)现在是 AI 应用层最火的技术范式之一。ChatGPT 的联网搜索、Perplexity、各种企业知识库问答,底层都有一个共同的动作:把用户的问题转成向量,然后在一大堆文档向量里找出最相关的那几条,塞给大模型生成回答。

这一步叫向量检索。它其实不是 AI 时代的新问题。搜索引擎领域已经围绕这个题目做了几十年的探索,只不过当年搜的是网页,现在搜的是文档片段(passage),底层数学完全一样。其中最关键的技术挑战,就是近似最近邻搜索(Approximate Nearest Neighbor,ANN)。

几十年的积累,被一篇论文撞了一下

过去几十年,ANN 领域积累了树结构、哈希编码、乘积量化、图导航这些精巧方法。每一代都在前一代的瓶颈上做出突破,驱动这些突破的是互联网规模的检索场景:百亿级网页,查询词覆盖人类能想到的一切话题,数据分布极其分散。在这种场景下,单一的分治策略确实不够用,所以才需要一套比一套复杂的补偿机制。

但 RAG 的文本语料有一个被低估的差异。

互联网检索面对的是任意网页、任意查询。RAG 面对的是特定领域的文档集合:客服知识库、产品手册、内部文档。即使是通用 RAG(比如基于维基百科的问答),文本嵌入空间也有一个互联网网页不具备的几何特征。2026 年一篇名为 The Geometry of Consolidation 的论文把这个特征严格化了:来自对比式文本编码器的嵌入向量,方差集中在极少数有效维度上。同一个语义簇里的不同表述(比如”怎么退货”和”退款流程”),在向量空间里挤得非常紧。

论文做了一个实验。在特定指标和前提下,把聚类 centroid 和 PQ、HNSW 等主流 ANN 方法放在一起比较。结果:在大多数真实语料上,centroid 压在了上面。centroid 本身不是一个新方法,它就是取平均。当然,这个结论有它的限定条件,后面会专门讲。

这篇论文提供了理解这个结果的钥匙:什么时候”切和补”的逻辑是必须的,什么时候可以直接砍掉冗余而不需要补偿。

向量检索为什么需要”近似”

先理解具体的数字。一个典型的企业 RAG 系统,文档库可能有几十万到几百万条 passge。每条 passge 由一个文本编码模型转成一个向量,维度通常在 768 到 4096 之间。每次用户问一个问题,系统需要在零点几秒内从这一百万个向量里找到余弦相似度最高的那几条。

暴力做法是算一百万个 cos 然后排序。一台机器做这件事需要几十到几百毫秒,多用户并发下直接崩掉。所以必须做近似:不保证一定找到绝对最近的那条,但保证以很高概率在极短时间内找到很接近的那几条。用精度换速度。

这就是 ANN。你今天用的 FAISS、Milvus、Pinecone、Weaviate,底层全都靠某种 ANN 方法在跑。大多数开发者调用这些库的时候并不关心里面是什么,传进去向量,拿回来结果,够了。但当你需要做技术选型,内存够不够,延迟能不能压到 10ms,召回率掉多少可以接受,黑箱就不够用了。

分治:所有 ANN 方法共享的一条直觉

这么多 ANN 方法,拉开看有一条贯穿的底层直觉:不要搜整个空间,把它切开,只搜和查询相关的那些碎片。这是分治。

分治带来一个坑。切出来的碎片是离散的,但查询是连续的。一个碎片和相邻碎片之间有一条边界线,查询向量可能刚好落在这条线上。如果你只搜查询所在的那个碎片,就会漏掉旁边碎片里的候选。那边可能放着真正最相似的那条。切割制造了搜索盲区。

分治的坑:查询落在分区边界上,漏掉了相邻分区里更近的候选

所以,每一种 ANN 方法的本质差异,不是谁的数学更漂亮,而是两件事:第一,用什么规则去切。第二,切完之后怎么补回被遗漏的边界信息。

四种传统思路:切法不同,补法不同

下面四种方法,各看它们”怎么切”和”怎么补”的直觉就可以了。

树方法:在空间坐标上切。 最早的思路,比如 k-d tree。每一步选一个维度,画一条线把空间分成两半,递归下去。查询时沿着树往下走,找到叶子后做”回溯”:回头检查旁边的分区里有没有更近的点。这个回溯就是它的补偿机制。

问题出在维度。当向量维度超过几十,“画一条线分开空间”这件事在数学上就不成立,因为高维空间里所有点都差不多远,没有哪一维能真正把数据切开。回溯需要检查的节点数爆炸,退化到和最笨的暴力搜索一样慢。树方法在低维很强,但在今天几百上千维的文本向量上基本不能用。

哈希方法:用概率编解码。 换个思路:不切坐标空间了,把向量投到一个编码空间里。拿一堆随机超平面,看向量落在平面的哪一侧,打一串 0/1 的二进制码。两个向量语义越近,这串码的差异越小。查询时找到查询向量的码,在同一个码的桶里找候选。

补边界的方式是”多张表”:用不同的随机超平面组合建多张独立的哈希表。一个查询的真正最近邻可能在哪张表里落到了不同的桶?没关系,它大概率在至少一张表里和你落在同一个桶。多张表等于多次机会,概率保证不丢。

这个叫局部敏感哈希(Locality-Sensitive Hashing,LSH)。它的强大在于有严格的理论保底:给定参数,你能算出需要多少张表才能保证某个召回率。代价是内存:表越多,存的东西越多。

量化方法:压缩向量本身。 再换一个角度。前两种方法都在切”空间”,能不能切”向量”?把每个 1024 维的向量切成若干段,每段几十维。对每段单独做聚类,用聚类中心的编号替代原始浮点数。这样一个向量就变成了几个短整数,存储从几千字节降到几十字节。

查询时先用压缩后的近似距离做粗筛,拉出一批候选,再对候选直接算精确 cos 做精排。粗筛补回量化损失的信息,精排保证边界附近不丢。这叫乘积量化(Product Quantization,PQ),是 FAISS 的默认压缩方案,撑起了十亿级检索的基本框架。

PQ 的核心前提是:每个向量还留在索引里,只是存的更省。

图方法:让切割和补偿变成同一件事。 这不切空间也不切向量了。建一个多层图,上层节点少,负责大步跳跃;下层节点密,负责精细定位。查询时从顶层随机出发,逐层贪心往下走,最终收敛到最近邻。

这个叫分层可导航小世界图(Hierarchical Navigable Small World,HNSW),是目前大多数 benchmark 上综合表现最好的方法。它的妙处在于:图的层级结构同时充当了切割和补偿。你在某一层走偏了,下层有更多连接帮你重新定位。没有显式的”先切后补”,导航本身一体两面。

代价是内存。每个节点要存好多条边,图比原始向量还占空间。工程上通常和 PQ 搭配使用:图负责导航,压缩向量负责最终距离计算。

聚类:什么时候”不补”就够了

前面四种方法,不管切法多聪明,都在花力气补偿切割丢失的边界信息。聚类方法的逻辑截然相反:不补。

先把所有向量按语义聚成若干簇,每簇只保留一个中心点(centroid)。查询时直接算查询到所有中心点的距离,命中 top-k 个簇,把对应簇的原始文本拉出来。中间没有精排,没有补偿步骤。

直觉上这显然不行。边界附近的查询怎么办?一个簇内部的点散开了怎么办?这些正是前四种方法花了几十年去解决的问题。

而那篇 consolidation 论文的发现是:在 RAG 的真实文本语料上,这些问题大多数时候不构成问题。

原因在嵌入空间的几何结构。现代的文本编码模型在训练时被反复要求把同义表述拉近、异义推远。同一个意思的几十种说法,不管措辞怎么变,它们的向量都会挤在球面上的一小块区域里。这个区域在直觉上就能用一个中心点来概括。centroid 站在正中间,就像一个球形帐篷的顶点,能盖住底下所有的点。查询不管落在区域的哪个位置,找到的最近中心点大概率就是正确的那个。

反过来,互联网规模的通用检索面对的是高度多样化的数据:一篇文章讲量子力学,另一篇讲菜谱,第三篇讲体育。这些内容的嵌入向量散布在各个方向,一个中心点覆盖不住,所以才需要 PQ 的压缩、HNSW 的图导航这些补偿机制。

论文的贡献不在于发明了 centroid,centroid 比所有方法都老。它的贡献是把”什么时候不补就够用”这个判断从模糊的直觉变成了可以提前计算的几何判据:拿到一个语料,算一下簇的有效维度和簇内平均距离。如果落在 tight regime,聚类就够了。如果落在 spread regime,才需要上更复杂的补偿方案。

这篇论文的边界在哪里。 上面说的”centroid 表现更好”是在一个很具体的设定下成立的。论文用的核心指标不是一个业界通用的检索质量指标,而是一个在定义上就更偏向按簇组织的方法的评测方式。另外,这个指标上的优势也没有稳定地转化为下游任务的实际提升。论文自己没有比较 latency,centroid 索引也未被任何主流向量数据库原生支持。所以这篇论文颠覆的不是搜索引擎几十年的积累。它最有用的部分是一个决策启发:对于文本 RAG 这种数据分布偏紧的场景,在 index bytes 有限的前提下,聚类 centroid 是一个被低估的选项。动手选方案之前先看看自己数据的几何属性,但它没有说你可以扔掉所有其他方法。

怎么选:从四个问题出发

实际的工程选择,可以从四个问题出发。不需要记住所有方法的实现。

第一,你的数据规模多大,内存预算多少。百万级以下、内存宽裕,HNSW 加精确向量是省心的默认选择。十亿级以上、内存紧张,走 PQ 或者 HNSW 加 PQ 的混合方案。

第二,你对召回率的要求有多刚性。99% 以上需要 HNSW 级别的精度。90% 通常就够了的话,PQ 或 LSH 都可以考虑,换来更大的压缩比。

第三,你的数据有多少真正的有效维度。如果做的是文本 RAG,你的嵌入向量名义上 1024 维,实际有效维度常常只有十几到几十。这是 embedding 领域已经反复验证过的规律。有效维度越低,数据越”挤”,你就可以越激进地砍。拿到一个新语料,先算一下 d_eff 和簇内平均距离。如果落在 tight regime,centroid 聚合可能就够了,不需要上 HNSW。

第四,你只是调 SDK 的开发者,还是需要做深度定制。绝大多数场景下,FAISS 的默认 HNSW 或者 PQ 索引已经足够好。理解这些方法的直觉价值在于:看到 FAISS index 类型选择界面时,脑子里有一张地图,知道每种选项在”切”和”补”的哪个位置,你的数据和需求更靠近哪一端。

那篇 consolidation 论文最有用的信息是这个:在很多你原本打算花大力气去搭建复杂 ANN 管道的场景里,条件满足,那些投入可能白花了。先算几何,再选方案。

鸭哥每日手记

日更的深度AI新闻和分析