跳到主要内容

重排序才是核心:为什么检索系统的瓶颈从来不在索引

· 阅读需 12 分钟
Tian Pan
Software Engineer

构建 RAG 系统的团队几乎普遍都会遇到同样的瓶颈:他们花一周时间调整 HNSW 索引参数,添加乘积量化(product quantization),将 recall@100 从 0.81 提高到 0.87 —— 然后发现 LLM 的输出质量几乎没有任何改观。投入数月努力所基于的假设是:更好的索引等于更好的回答。事实并非如此。瓶颈从来不在索引上。

真正的卡点在于候选集与上下文窗口(context window)之间的重排序(ranking)步骤。你喂给 LLM 的内容决定了它的输出,而重排序的工作就是确保那些真正相关的文档,而不仅仅是语义上最相似的文档,能够进入上下文。这种区别比你调整的任何 HNSW 配置都更重要。

为什么嵌入模型会误导相关性

双编码器(Bi-encoder)嵌入模型独立地对查询和每个文档进行编码,然后通过余弦相似度(cosine similarity)评分。模型在编码文档时并不知道查询的内容 —— 它将每段文本编码为向量空间中的独立点,然后测量几何邻近度。对于主题相关的内容,这很有效。但只要相关性涉及到上下文,它就难免失效。

想象一个法律语料库,查询语句是“根据 UCC §2-709 的延迟付款处罚”。通过余弦相似度检索到的前几块内容可能包括:UCC 第 2 条的总体概述、关于合同法中付款条款的段落,以及关于救济限制的段落。它们在语义上都很接近。但没有一个能回答问题。正确的段落被埋在第 23 位 —— 它明确提到了 §2-709,但在嵌入器(embedder)将其映射到远离查询质心的上下文中。

这不是什么罕见的极端情况。在专业领域,这是常态。嵌入捕获的是主题邻近性;而相关性关乎意图、具体性和上下文。索引调优无法修复一个缺乏对查询实际需求感知的模型。

结构性差距:双编码器独立地对查询和文档评分,因此没有交互信号。交叉编码器(cross-encoder)模型将查询-文档对作为组合输入,并对两者运行全注意力机制(full attention)。它能看出一个文档回答了一个特定问题,即使该文档的主题指纹很普通。这就是让重排序强大的洞察力。

两阶段架构及其存在的理由

你不能直接在整个语料库上运行交叉编码器的原因是延迟。交叉编码器在查询时需要对每个候选文档进行一次完整的正向传播 —— 无法预先计算。在 40 QPS 下,如果交叉编码器为每个查询对 10,000 个文档评分,你的 p99 延迟会直接崩溃。在这种规模下,交叉编码器的开销会使 p99.9 超过 21 秒。

两阶段流水线解决了这个问题:

第一阶段 —— 候选生成(Candidate generation):运行快速的近似最近邻检索(使用 HNSW 的 ANN)或 BM25,在 5-30 毫秒内生成 100–500 个候选文档。这一阶段优化的是召回率(recall)—— 目标是不遗漏任何相关内容,即使代价是包含了一些不相关的文档。

第二阶段 —— 重排序(Reranking):仅对候选清单应用昂贵且精确的模型。交叉编码器处理 50–100 个文档会增加 100–200 毫秒,使大多数生产用例的总延迟保持在 300 毫秒以下。

关键的设计约束:第一阶段的工作是召回,而不是精确度(precision)。你不需要它非常擅长排序。你需要它确保真正相关的文档出现在前 500 名中。然后由第二阶段负责精确度工作。

这在实践中的意义是:停止用 NDCG 衡量第一阶段。请用 recall@k 来衡量。你需要的是“是否有相关文档出现在前 200 名中?”,并以此为目标进行优化。NDCG 会惩罚候选集内部的排序失败,但在你将其交给重排序器(reranker)时,这并不重要。

交叉编码器、ColBERT 和稀疏模型如何各司其职

并非所有重排序器的表现都一样。在它们之间做选择是延迟、吞吐量和准确性之间的权衡。

交叉编码器(例如 BGE Reranker、SBERT 交叉编码器、Cohere Rerank)联合编码查询-文档对。它们达到了最先进的准确率 —— 顶尖的交叉编码器在 MS MARCO 上的 MRR@10 超过了 0.40 —— 但每个查询的成本很高。它们无法预先计算文档表示,因此每个请求都需要从头开始对所有候选文档评分。这适用于质量比吞吐量更重要,且候选集限定在约 50–100 个文档的应用场景。

ColBERT(Contextualized Late Interaction,上下文延迟交互)采用了不同的方法:它离线预先计算文档的令牌级(token-level)嵌入,然后在查询时通过令牌交互的 MaxSim 操作进行评分,而不是进行完整的正向传播。这在 40 QPS 下产生了约 23 毫秒的 p50 延迟 —— 在质量相当的情况下,比交叉编码器快大约 10 倍。当你需要在更高吞吐量下获得接近交叉编码器的质量时,这是正确的选择。

学习型稀疏模型像 SPLADE 这样的工作方式与前两者都不同。它们产生的不是稠密向量,而是在词汇空间上的稀疏表示,识别哪些术语(terms)重要以及权重是多少。结果是:索引内存比稠密模型少 71%,查询时使用 CPU 兼容的倒排索引,并内置术语扩展功能,可以捕捉到原始查询漏掉的变体。SPLADE 并不取代重排序器,而是改变了第一阶段的架构:稀疏检索生成的候选集比 BM25 语义更丰富,但在大规模运行时比稠密 ANN 成本更低。

混合第一阶段 + 交叉编码器重排序器是目前性能的天花板。将 BM25 与稠密 ANN 检索结合(使用互惠排名融合 Reciprocal Rank Fusion 合并它们的排名列表),然后对合并后的前 50 名应用交叉编码器,在 BEIR 基准测试上比单一方法产生 12% 的 NDCG 提升,在 TREC 评估上比纯稠密检索产生 24–48% 的提升。

当你仅优化索引时会发生什么

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates