跳到主要内容

超越 RAG:混合搜索、智能体检索以及真正重要的数据库设计决策

· 阅读需 10 分钟
Tian Pan
Software Engineer

大多数团队将 RAG 上线并称之为检索策略。他们将文档分块、嵌入、存储向量,并在查询时运行最近邻搜索。这在演示中效果足够好。然而在生产环境中,用户开始报告系统找不到他们知道存在的文章、遗漏文档中字面意义上的错误代码,或者返回语义相似但事实错误的内容。

问题不在于 RAG。问题在于将检索视为一个一维问题,而它实际上一直都是多维的。

纯向量搜索在查找概念相似的内容方面表现出色。但它不擅长查找精确匹配项——例如产品 SKU、错误代码、版本号、人名或文件名。基于 BM25 的全文搜索则恰恰相反:它对精确术语很准确,但对同义词和释义则无能为力。对于真实用户依赖的生产系统来说,两者单独使用都不够。

本文将探讨那些真正能推动进展的检索架构决策:何时结合不同的搜索模式,智能体工作负载如何重塑检索系统设计,以及这对你选择和构建的数据库意味着什么。

纯向量搜索为何在边缘场景失效

密集检索背后的直觉引人入胜。将文档和查询嵌入到相同的高维空间中,语义相似的内容最终会在几何上彼此接近。这在概念级匹配方面效果非常出色。

但实际工作负载更为复杂。考虑以下情况:

  • 用户搜索 "TypeError: Cannot read properties of undefined (reading 'map')" —— 精确的错误字符串
  • 代码助手在包含 500 个文件的代码库中查找名为 processUserPayload 的函数
  • 法律研究工具查询特定的法规编号

基于嵌入的检索会近似这些结果。但它无法精确命中。召回率研究一致表明,BM25 在以关键词为主的查询中实现了约 72% 的召回率,而混合搜索则将其提升至 91%——在关键领域,25 个百分点的提升具有巨大的重要性。

这种失效模式足够微妙,以至于它通常不会在你的评估数据集中浮现,因为评估数据集往往是从检索成功的案例中构建的。你错过的那些案例被系统性地排除在基准测试之外。

混合搜索:结合 BM25 和密集向量

混合搜索并非新概念——它只是终于获得了合适的工具。其核心模式是:

  1. 通过稀疏检索系统(BM25 或 SPLADE)运行查询以获取关键词匹配结果
  2. 通过你的嵌入模型运行相同的查询以获取语义相似结果
  3. 使用倒数排序融合(Reciprocal Rank Fusion, RRF)或学习型排序器融合排名列表
  4. (可选)使用交叉编码器对合并后的列表进行重新排序
def reciprocal_rank_fusion(ranked_lists: list[list[str]], k: int = 60) -> list[str]:
scores: dict[str, float] = {}
for ranked in ranked_lists:
for rank, doc_id in enumerate(ranked):
scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank + 1)
return sorted(scores, key=scores.get, reverse=True)

RRF 是实用的默认选择。它简单、稳健,并且不需要训练数据:

在稀疏检索部分选择 BM25 还是 SPLADE 很重要。BM25 速度快且易于解释。SPLADE 学习稀疏表示,可以处理词汇不匹配的情况——例如当文档说“terminate your plan”(终止你的计划)时,用户却问“how do I cancel my subscription”(如何取消我的订阅)。对于文档和查询词汇差异较大的企业知识库,SPLADE 表现更优。而对于代码搜索或结构化数据这类精确术语很重要的场景,BM25 通常就足够了。

实际的决策树:

  • 以精确匹配为主的查询(错误代码、SKU、标识符):赋予 BM25 更高的权重
  • 概念级查询(操作方法、解释说明):赋予密集检索更高的权重
  • 大多数生产系统:采用混合方式,权重大致相等并结合 RRF 融合

智能体工作负载如何打破检索基础设施

传统 RAG 在每个用户回合中进行一次检索:用户发送消息,系统将其嵌入,获取 Top-K 分块,注入到上下文中,LLM 做出响应。每次交互只进行一次检索调用。

智能体系统打破了这一假设。一个处理大型代码库的编码智能体可能在一个“回合”中触发 50-100 次并行检索调用——包括对相关函数的语义搜索、针对特定语法的 grep 风格模式匹配、文件路径查找、依赖图遍历。检索不再是单线程流水线,而变成了高并发的工具调用工作负载。

这极大地改变了基础设施要求:

延迟特性转变:过去你可能只关心每次查询的 P50 延迟。现在你关心的是 100 次并行查询的 P99 延迟,因为你的智能体需要等待所有这些查询完成。一个 P50 延迟为 40 毫秒、P99 延迟为 500 毫秒的系统,对智能体来说远不如 P50 延迟为 60 毫秒、P99 延迟为 200 毫秒的系统。

查询多样性增加:智能体并行发出语义多样化的查询——它们不是重复运行同一个查询 N 次。一个能够在同一请求中处理语义搜索、全文搜索和元数据过滤的混合系统变得至关重要,而非可选项。

定价模型的重要性:对于人类交互节奏而言合理的按查询次数计费,在单个智能体回合触发 100 次查询时变得不可行。这正在推动向量数据库供应商转向存储加写入的定价模式,并提供廉价读取,这更符合智能体实际消费系统的方式。

Azure AI Search 的智能体检索报告称,通过并行运行子查询,延迟最高可降低 40%。Cursor 的编码助手通过结合语义搜索和基于 grep 的检索,在特定工作负载上实现了 25% 的性能提升——并投资于定制的嵌入模型,以进一步缩小领域差距。

随之而来的数据库设计决策

一旦你了解了工作负载——混合查询、高并发、可变查询类型——数据库架构的决策就变得更清晰了。

将对象存储作为主要存储现在变得可行。 S3 在 2020 年 12 月实现强一致性是一个悄然的转折点。你现在可以构建这样的系统:规范数据存储在对象存储中,计算节点是无状态的,NVMe SSD 仅用作缓存层。这在以前是不可能安全实现的。这意味着:你的向量存储可以独立扩展存储和计算,这在你拥有千亿向量但查询负载相对突发时非常重要。

你需要一个能够原生处理混合查询类型的检索系统。 一个只进行向量搜索但放弃全文搜索的系统,会迫使你维护两个独立的索引并自行合并结果。这虽然可行,但增加了操作复杂性。一个能在统一查询界面中处理这两种类型——并且能同时应用元数据过滤器的系统——将大大简化应用层。

对于质量敏感型应用来说,重排序是不可或缺的。 近似最近邻搜索以牺牲部分精度来换取速度。对于大多数用例来说,这是一个正确的权衡。但对于检索质量直接影响用户信任的应用——如法律、医疗、金融——在排名前 20 的结果(而非前 1000 名)上使用交叉编码器进行重排序,是值得增加延迟的。交叉编码器能够同时联合地看待查询和文档,而非独立看待,从而捕捉到双编码器可能遗漏的相关性。

2025 年的实用架构

以下是针对文档密集型应用的生产级检索栈的示例:

User query

├── Sparse retrieval (BM25/SPLADE)
│ └── Document index (inverted)

└── Dense retrieval (ANN search)
└── Vector index (HNSW or IVF)

└── RRF fusion

└── Metadata filter (date, source, access control)

└── Cross-encoder re-rank (top 20 → top 5)

LLM context injection

对于智能体应用,将检索层封装在一个工具接口中,智能体可以调用该接口并传入不同的参数:

@tool
def retrieve(
query: str,
mode: Literal["semantic", "keyword", "hybrid"] = "hybrid",
filters: dict = {},
top_k: int = 10,
) -> list[Document]:
"""Retrieve relevant documents. Use 'keyword' for exact matches,
'semantic' for concept-level search, 'hybrid' for unknown cases."""
...

让智能体明确控制检索模式,可以使其做出比默认采用一刀切的混合搜索更好的决策。一个搜索函数签名的编程智能体应该指定 mode="keyword"。一个回答概念性问题的智能体应该使用 mode="semantic"。能够推理检索策略的智能体将优于不能推理的智能体。

这对你的技术栈意味着什么

如果你今天正在构建一个新的检索系统:

  • 不要默认纯粹的向量搜索。 从一开始就为混合搜索做好预算。后期改造是痛苦的。
  • 将检索质量与端到端任务质量分开衡量。 检索的召回率和精确率是独立的指标。你需要知道是哪个层级出了问题。
  • 为智能体级别的并发性进行设计。 如果你正在构建任何智能体将调用的东西,你的检索层需要能够处理高并发查询负载并保持一致的 P99 延迟。
  • 将嵌入模型选择视为首要决策。 针对特定语料库,现成的模型表现不如领域专用模型。Cursor 的自定义嵌入模型带来了显著的提升。微调嵌入模型的成本通常低于团队预期。
  • 晚重排,早过滤。 在重排之前应用元数据过滤器以减少候选集。对通过过滤器的少量集合进行重排。搞错顺序的代价是高昂的。

将检索视为事后考虑的团队与将其视为核心工程问题的团队之间的差距正在扩大。随着智能体发出越来越多的检索调用,检索质量的影响会累积——每次调用的微小提升会在整个工作流中变成巨大的收益。值得你把它做好。


关键的架构洞察是,检索从来都不是一个单一的问题。关键词搜索和语义搜索解决了不同的子问题。智能体工作负载只是让赌注变得足够高,使得“足够好”和“设计正确”之间的差距变得不容忽视。

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