跳到主要内容

生产级检索技术栈:为什么纯向量搜索会失败以及应对策略

· 阅读需 15 分钟
Tian Pan
Software Engineer

大多数 RAG 系统在部署时都配备了向量数据库、几千个 embeddings,并假设语义相似度已经足够接近正确性。事实并非如此。这种“语义相似”与“实际正确”之间的差距,正是 73% 的 RAG 系统在生产环境中失败的原因,而且几乎所有这些失败都发生在检索阶段 —— 甚至在 LLM 生成任何文字之前。

“对文档进行嵌入、使用余弦相似度查询、将 top-k 传递给 LLM”的 standard playbook 在演示中有效,是因为演示查询是经过设计的。生产环境的查询则不然。用户搜索的是产品 ID、发票号码、监管代码、拼错的竞争对手名称,以及单个 embedding 向量在几何上无法满足的多重约束问题。稠密向量搜索并没有错 —— 只是它并不完整。构建一个在生产环境中真正起作用的检索栈,需要理解其中的原因,并层层加入能够弥补这些缺陷的组件。

为什么稠密嵌入在生产环境中会失效

稠密嵌入(Dense embedding)将文档压缩成固定大小的向量。这种压缩在设计上就是有损的。对于语义相似性任务 —— 寻找关于相同话题的文档、改写、概念聚类 —— 这种压缩没问题。但对于精确查找任务 —— 寻找包含特定代码、专有名词或精确标识符的文档 —— 这种压缩会丢弃你实际需要的信息。

Google DeepMind 最近的一项研究将其公式化为一个几何约束:将查询映射到文档的分数矩阵的秩受限于嵌入维度。当语料库规模超过一定限度时,单向量模型根本无法划分文档空间来满足复杂的查询。在实践中,这意味着 512 维的模型在处理约 500,000 份文档时会可靠地失效,甚至大型的 4,096 维模型在 2.5 亿份文档时也会崩溃。这些并不是极端情况 —— 大多数生产级知识库都会触及这些限制。

一旦你开始留意,这些失败模式就是可以预见的:

  • 精确关键词查询:搜索 “Error 221” 会自信地返回关于 “Error 222” 的文档,因为这些 embeddings 在语义上是相邻的。
  • 罕见术语和标识符:产品 SKU、法律代码和词汇表之外的专有名词在稠密向量空间中表现不佳。
  • 组合约束:“蓝色越野跑鞋,10 码,100 美元以下”包含三个正交约束。单个向量会平均化搜索意图,而不是满足每个组成部分。
  • 特定领域词汇:在金融、医疗或工业领域,缩写词和专业术语的含义在通用 embeddings 中的编码并不一致。

检索返回了“足够接近”的文档。随后,LLM 根据这些文档生成一个听起来很自信的回答。最终,用户得到了一个语气极其笃定的错误答案。

2026 年重提 BM25 的理由

BM25 (Best Match 25) 是一种基于词频的排名算法,源自 20 世纪 90 年代。按照深度学习发展的逻辑,它现在理应被取代了。但它并没有,BEIR 基准测试解释了原因。

在对 18 个不同数据集的评估中,BM25 仍然是一种极具竞争力的零样本(zero-shot)方法。在论点检索任务中,BM25 的 nDCG@10 达到了 0.367,目前还没有测试过的神经模型能超过它。在没有针对特定领域进行微调的情况下,BM25 在 8–10 个数据集的分布外场景中表现优于稠密检索。它的索引大小仅为稠密编码的 10%,并且可以使用运维团队已经熟知的标准分片模式进行水平扩展。

BM25 擅长的正是稠密嵌入失效的地方:精确术语匹配、罕见 Token、专有名词和标识符。它通过逆文档频率(IDF)为罕见术语赋予更高的权重 —— 仅在少数文档中出现的术语比无处不在的术语更具诊断性。稠密模型往往会在嵌入压缩过程中冲淡这种信号。

像 SPLADE 这样的现代稀疏方法比 BM25 更进一步。SPLADE 使用 BERT 注意力机制来识别关键 Token 并执行学到的术语扩展 —— 在索引期间将“汽车”映射并激活“汽车”和“车辆”,同时不失稀疏检索的精确性。SPLADE++ 在推理时实现了仅针对文档的扩展,在降低延迟的同时保留了大部分质量提升。

实践总结:BM25 不是过时的备选方案。它是一个一流的检索组件,能捕捉到稠密嵌入系统性遗漏的信号。

混合检索:结合稠密与稀疏

检索性能的天花板不是由你选择哪种方法决定的 —— 而是由你如何结合它们决定的。稠密检索和稀疏检索能够检索到互补的文档集。稠密处理改写、同义词和语义变化;稀疏处理精确匹配、罕见术语和实体名称。并行运行它们并融合结果,在召回率基准测试中始终比单一方法高出 15–30%。

标准的融合方法是倒数排名融合 (RRF) 和线性得分插值 (Linear Score Interpolation)。

RRF 通过累加每个检索方法的倒数排名位置来组合结果:

score(d) = Σ 1 / (k + rank_method(d))

RRF 与得分无关 —— 它只使用排名位置,而不使用原始相似度得分。这消除了困扰得分插值的归一化问题:稠密余弦相似度和 BM25 得分处于不同的量级,简单的平均会产生无意义的结果。RRF 完全避开了这一点。正是出于这个原因,OpenSearch 在 2.19 版本中将 RRF 采用了默认的混合融合方式。权衡之处在于,你会丢失有关排名信号强度的信息。

线性插值 则直接使用得分:α × dense + (1 - α) × sparse。当 α 调整到 0.7 左右时,在标准 IR 基准测试中,它比纯 BM25 有 7–17% 的 MAP 和召回率提升。通过适当的校准,它可以优于 RRF,但它需要一个开发集进行调优,并且对分布偏移很敏感。

对于大多数生产系统,请从 RRF 开始。它不需要校准,在异构数据上能产生稳定的结果,并且在 Elasticsearch、OpenSearch 和 Weaviate 中原生可用。只有当你有一个带标签的评估集来调整 α,并且有一套在数据分布变化时重新调优的流程时,才切换到线性插值。

在最近的基准测试中,三路混合 —— 全文搜索、稠密向量和像 SPLADE 这样的稀疏学习嵌入 —— 始终优于两路融合方法。虽然实现复杂度确实增加了,但对于词汇多样性较高的语料库,召回率的提升也是实实在在的。

交叉编码器重排序:第二阶段

检索找到候选内容。重排序选出其中最好的。

架构差异至关重要。双编码器 (Bi-encoders) —— 向量数据库用于检索的工具 —— 独立地对查询和每个文档进行编码,然后计算相似度。这种方式速度很快,因为文档可以离线进行编码和索引。但在编码过程中,查询和文档从未发生交互:模型无法考虑查询中的特定术语与文档中特定短语之间的关联。

交叉编码器 (Cross-encoders) 在单次前向传播中同时处理查询和候选文档。其注意力机制可以评估查询术语与文档内容之间的精确关系。这种方式速度较慢 —— 你无法预先计算交叉编码器的评分 —— 但准确性显著提高:交叉编码器可以达到 95% 以上的精确率,而仅使用双编码器时仅为 70–80%。

标准的二阶段工作流如下:

  1. 运行混合检索(稠密 + 稀疏 + RRF)以获取 50–100 个候选结果
  2. 对候选结果运行交叉编码器重排序器,生成 5–20 个最终结果
  3. 将重排序后的结果传递给 LLM

重排序步骤通常会增加 30–60 ms 的延迟。最近的重排序器,如 GTE-reranker-modernbert-base(1.49 亿参数),在命中率基准测试上能与大得多的模型媲美,同时保持了足够的运行速度以支持交互式应用。生产系统的经验法则是:对于任何检索质量比原始吞吐量更重要的应用,交叉编码器重排序所带来的延迟开销都是值得的。只有当你要求总响应时间低于 100 ms 或每秒处理超过 1,000 次查询时,才考虑跳过它。

ColBERT 通过延迟交互 (late interaction) 在双编码器的速度和交叉编码器的准确性之间寻求平衡:查询和文档中的每个标记 (token) 都有自己的嵌入向量,评分时计算每个查询标记与所有文档标记之间的最大相似度。ColBERT 在保持大部分交叉编码器质量优势的同时,实现了 57.7 ms 的端到端总延迟 —— 当完整的交叉编码器重排序对于你的延迟预算来说太慢时,这是一个非常有用的选项。

高级检索:HyDE 与查询扩展

“查询-文档鸿沟”是一个常见问题,即用户提问的方式(“我该如何修复身份验证错误?”)与文档编写的方式(“身份验证失败恢复程序”)不同。标准检索寻找语义相似的文本,但词汇不匹配会降低召回率。

HyDE (假设性文档嵌入 / Hypothetical Document Embeddings) 通过反转方向来解决这个问题。检索系统不是直接对用户的问题进行嵌入,而是先要求 LLM 生成 3–5 篇能回答该问题的假设性文档。系统会对这些假设性文档进行嵌入并取平均值,生成的向量用于与实际语料库进行相似度搜索。由于假设性文档的语域与真实文档一致,词汇鸿沟会显著缩小。

HyDE 带来的提升非常显著 —— 在某些基准测试中,检索精确率提高了多达 42 个百分点,召回率提高了 45 个点。它在缺乏微调稠密检索条件的低监督领域特别有效。其代价是每次查询需要增加一次 LLM 调用(通过优化通常为 80–120 ms),并且对假设性生成提示词的质量较为敏感。

查询扩展 (Query expansion) 和重构以更低的成本实现类似的目的。将多部分问题分解为子查询、在检索前重写模糊的查询,以及用同义词扩展稀疏术语,都能在不增加假设性生成开销的情况下提高召回率。系统化查询重写框架在复杂的多跳查询中显示出 30–40% 的持续精确率提升。

衡量检索质量

检索问题未被察觉的最常见原因,是团队在衡量回答质量而非检索质量。LLM 会根据糟糕的检索上下文生成一个自信的回答。用户满意度指标和回答质量评分反映了检索失败,但它们无法帮你定位问题发生在工作流的哪个环节。

重要的检索特定指标:

  • Recall@k(召回率):相关文档出现在前 k 个检索结果中的比例是多少?这是评估你的检索系统是否能找到所需内容的主要指标。如果 Recall@10 低于 0.7,无论 LLM 模型多么优秀,它都无法给出好的答案。
  • Precision@k(精确率):在前 k 个结果中,有多少比例是真正相关的?当上下文长度有限,且你无法承担将无关内容传递给 LLM 的开销时,高精确率至关重要。
  • NDCG@k (归一化折损累计增益):一种关注排名的指标,会对出现在排名靠后的相关文档进行惩罚。当你需要对结果进行截断(例如只取前 k 个)时,请使用此指标,因为此时结果的顺序非常重要。
  • MRR (平均倒数排名):所有查询中第一个相关结果排名倒数的平均值。直接衡量正确文档是否出现在最顶部。

在生产环境中,应为检索流水线配置插桩,以记录查询、每个阶段检索到的候选文档,以及最终传递给 LLM 的文档。这样就可以针对标记好的测试集运行离线评估,并在分块策略、嵌入模型或检索配置发生变化时识别出性能退化。如果没有阶段级的监控,10% 的准确度下降往往会被归咎于 LLM,而无法追踪到实际上是由于降低了召回率的检索配置更改所导致的。

选择检索技术栈

合适的向量数据库和检索基础设施更多地取决于你的规模、现有技术栈和延迟要求,而不是基准测试分数。

Qdrant 是对延迟敏感的工作负载的首选。它采用 Rust 编写,在同类基准测试中实现了 6ms 的 p99 延迟,而 Elasticsearch 为 200ms。它的负载(payload)索引允许在不损失性能的情况下进行复杂的元数据过滤,当你需要在向量搜索之前按租户、日期范围或文档类型进行过滤时,这一点至关重要。

Weaviate 拥有最成熟的原生混合搜索实现。BM25F 对多个字段的词频进行加权,而 BlockMax WAND 使关键词搜索组件比简单实现快 10 倍。如果混合搜索是你架构的核心,并且你希望由一个系统同时处理两者,Weaviate 是自然的选择。

Elasticsearch 和 OpenSearch 如果你的团队已经在运营它们,那么它们是正确的选择。它们现在支持稠密向量搜索、基于 RRF 的混合融合以及集成重排序。其向量搜索性能“足够好” —— 虽然不是最快的,但可以接受 —— 并且你可以避免增加独立向量数据库的运维开销。

pgvector 与 PostgreSQL 配合,可以有效处理大多数文档量在 5000 万以下的生产级 RAG 系统。如果你已经在运行 Postgres,就可以避免增加全新的基础设施依赖。一个生产团队通过将专门的向量数据库切换为 PostgreSQL 加 pgvector,将检索成本从每月 6,000 美元降低到每月 700 美元,并且由于切换到了混合检索,准确率也得到了提高。

Pinecone 当你需要零运维开销并扩展到数十亿个向量时,选择它是合理的。托管服务完全消除了基础设施负担,但其成本溢价在规模适中时很难证明其合理性。

真正重要的基准测试数据是在你的实际查询分布上测得的召回率和延迟,而不是标准的信息检索测试集。在做出决定之前,请针对每个选项运行具有代表性的生产查询样本。

构建完整的流水线

一个处理上述失败模式的生产级检索流水线如下所示:

查询分析 —— 检测查询类型:精确查找、关键词搜索或语义搜索。重写模糊查询。将多部分问题分解为子查询。对于高价值查询,生成 HyDE 扩展。

并行检索 —— 并行运行稠密向量搜索(前 100 个候选结果)和稀疏 BM25 搜索(前 100 个候选结果)。如果你的领域具有显著的词汇多样性,请为稀疏组件使用像 SPLADE 这样的学习型稀疏模型。

融合 —— 使用 RRF 合并结果。如果你有带标签的开发集,请针对你的查询分布调整线性插值权重。

重排序 —— 将融合后的前 20 个候选结果通过交叉编码器(cross-encoder)重排序器。如果全量交叉编码器带来的额外延迟不可接受,请使用 ColBERT。

上下文组装 —— 附加文档元数据:来源、章节、日期和相关性得分。为需要的分块(chunks)包含父级上下文。这些字段对于回答质量以及用户在引用来源时的信任度起着关键支撑作用。

阶段级指标 —— 测量检索后的 recall@k、重排序后的 precision@k 以及生成后的忠实度(faithfulness)。记录足够的日志,以便将任何性能退化追溯到其产生的阶段。

那些在生产环境中成功运行 RAG 的团队并不是因为使用了更先进的 LLM —— 而是因为他们使用了更严谨的检索流水线。LLM 是一个生成系统,而不是检索系统。提供更好的上下文几乎总是比升级到更大的模型更有效。

References:Let's stay in touch and Follow me for more thoughts and updates