找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5303

积分

0

好友

719

主题
发表于 昨天 21:10 | 查看: 4| 回复: 0

👔面试官:你的 RAG 系统用的什么检索方式?

🙋‍♂️我:用的向量检索,把用户问题转成向量去向量库里找相似度最高的,效果挺好的。

👔面试官:那用户搜「RTX 4090 显卡功耗」,你知识库里就写着「RTX 4090」,向量检索召不回来怎么办?

🙋‍♂️我:那我可以把 top-K 调大一点,或者换个更好的 Embedding 模型,总能找到的。

👔面试官:调大 top-K 召回一堆无关内容有什么用?你有没有想过问题的根源在于向量检索本身对精确词就不敏感?多路召回了解过吗?

看来只靠单路检索是远远不够的,让我来聊聊多路召回的思路。

💡 简要回答

多路召回就是同时用多种不同的检索方式去捞候选内容,然后合并排序,而不是只靠单一的向量检索。我理解核心出发点是向量检索和关键词检索各有盲区,向量检索擅长语义相似,但对精确词语比如产品型号、缩写、数字效果比较差;BM25 关键词检索正好相反,精确匹配强,但不理解语义。我在项目里常用的组合是向量检索加 BM25 混合检索,再加上多 Query 扩展,也就是把用户问题改写成多个版本分别检索。多路的结果用 RRF 算法融合,最后送进 Rerank 精排。

📝 详细解析

什么是多路召回?

多路召回,顾名思义,就是同时用多种不同的检索方式去捞候选内容,最后再把各路结果合并、排序,交给 LLM 生成答案。

和它对应的是「单路召回」,也就是只用一种检索方式,最典型的就是只用向量检索:用户问题转成向量,去向量库里找相似度最高的 Top-K 个 chunk,然后直接喂给 LLM。这套流程在很多场景下能跑起来,但有明显的天花板。你可能会问,既然向量检索有语义理解能力,为什么还不够用?原因很简单——没有任何一种检索方式是全能的,向量检索有它的盲区,BM25 也有它的盲区,把它们组合起来互相补盲区,总召回质量才会比单路高。

多路召回与单路召回对比:左侧单路召回存在天花板,右侧多路召回通过向量检索+BM25+融合排序+Rerank实现全面覆盖

常见的组合是三路:

三路召回详解:用户问题经由向量检索、BM25关键词检索、多Query扩展三条路径并行处理,结果合并去重后经RRF融合及Rerank精排,最终输入LLM生成答案

第一路是向量检索,负责语义层面的覆盖,处理同义词、近义词、不同表达方式,「退货」和「申请售后」在向量空间里是邻居,能互相命中。第二路是BM25 关键词检索,负责精确词匹配,专门处理产品型号、专有名词、数字这类向量检索搞不定的场景。第三路是多 Query 扩展,把用户问题改写成多个不同角度的版本,覆盖更多表述差异,相当于撒了一张更宽的网。

三路各自召回一批候选,再用 RRF 算法把排名融合成一个统一的结果列表,最后送进 Rerank 精排,才把最终上下文交给 LLM。

为什么单路召回不够用?

理解了多路召回是什么之后,自然会追问:单路到底差在哪?为什么非要搞这么复杂?

单纯依赖向量检索是大多数 RAG 系统早期的做法,但它有一个明显的短板:对精确词语的召回效果差

为什么单路召回不够用:向量检索易混淆精确词语,BM25无法处理同义词,多路召回让二者盲区互补,实现全面覆盖

比如用户问「M4 Pro 芯片的性能参数」,这里的「M4 Pro」是一个专有名词,向量模型可能把它和「苹果最新处理器」的向量拉得很近,但如果知识库里这个词本来就是「M4 Pro」,向量检索不如直接关键词匹配来得准。很多人以为换个更好的 Embedding 模型就能解决,其实不行——这是向量检索「只看语义、不看字面」的固有局限,不管用哪个模型都存在这个问题。

反过来,关键词检索(BM25)对同义词和不同表达方式无能为力。用户问「怎么退货」,文档里写的是「申请售后」,词没重叠,BM25 完全召回不到。

两种检索方式的盲区恰好互补,这就是「多路召回」的出发点。理解了这个互补关系,后面每一路的作用就非常清晰了。

第一路:向量检索(Dense Retrieval)

向量检索是多路召回的基础一路。核心做法是:把文档和用户问题都用 Embedding 模型转成向量,然后用余弦相似度在向量库里找最近的 top-K 个 chunk。

向量检索核心流程:Embedding将文档转为向量存入向量数据库,查询时通过余弦相似度找最相近的top-K结果;优势是擅长语义匹配,短板是精确词召回差

它擅长语义匹配,同义词、不同表达方式都能覆盖,但对精确词语(产品型号、缩写)效果不佳——而这恰好是第二路 BM25 的强项。

第二路:BM25 关键词检索(Sparse Retrieval)

理解了向量检索搞不定精确词语这个问题,BM25 的加入就顺理成章了。BM25 是 TF-IDF 的改进版本,根据词频和文档频率给每个词打分,找出包含查询词最多、且这些词在整个语料里不太常见(也就是区分度高)的文档。它的核心逻辑是:一个词在这篇文档里出现多(词频高),但在整个知识库里出现少(区分度高),说明这个词对这篇文档很具代表性,权重就高。本质上是在问:「这个词有没有『代表』这篇文档?」

BM25关键词检索:根据TF和IDF计算词权重,通过Jieba分词建立倒排索引实现精确匹配;核心优势是精确词语召回极佳,短板是无法理解同义词和语义,与向量检索互补

中文场景下用 BM25 需要先做分词(比如用 jieba 切词),再对分词后的词列表建索引和检索。实现上就是对每个 chunk 先切词建索引,查询时同样切词后计算 BM25 分数排序。纯文本匹配,速度极快,对精确词语、数字、专有名词的召回效果非常好。

前两路解决了「语义匹配」和「精确词匹配」的问题,但还有一个场景它们都覆盖不到——用户提问的角度和文档表述的角度压根不一样,不是同义词的问题,而是整个视角的差异。这就需要第三路出场了。

第三路:多 Query 扩展召回

为什么还需要第三路?因为用户提问的角度和知识库里文档的表述角度不一致,这不是同义词能解决的。比如用户问「产品多久能送到」,文档里写的是「配送时效说明」,两句话角度完全不同,向量相似度可能不高,BM25 也匹配不到关键词。

多Query扩展召回:通过LLM将原始问题改写为多个版本,并行检索后合并去重,解决用户提问角度与文档表述不一致的问题,召回覆盖率可提升10%~20%

多 Query 扩展的做法是:用 LLM 把用户的原始问题改写成 3~5 个不同角度的版本,分别去检索,然后把所有结果合并去重。这样只要有一个改写版本和文档的表述对上了,就能把正确的内容召回来,就像拦截网越宽,捕到鱼的概率越高。

实现上,先调 LLM 生成多个问题变体,每个变体分别跑向量检索,最后把所有结果汇总并去重(同一个 chunk 被多个变体召回时只保留一份)。代价是多了几次 LLM 调用,但在用户提问风格多变的场景下,召回覆盖率能提升 10%~20%。

结果融合:RRF 算法

三路召回各自拿回了一批候选,接下来的问题就是:怎么把三路结果合成一份?每一路都有自己的排序结果,分数单位不一样(向量检索是余弦相似度,BM25 是 TF-IDF 分数),没法直接加权平均。你可能会想,能不能归一化之后再加权?理论上可以,但实际上各路分数的分布差异很大,归一化效果不稳定,工程上也更复杂。

RRF(Reciprocal Rank Fusion,倒数排名融合)是目前最常用的融合方法,它只用排名而不用原始分数,巧妙地绕开了分数不可比的问题:

RRF公式: RRF_score(d) = Σ(1/(k + rank_r(d))),其中k为平滑参数,r遍历各路检索排序

$$RRF\_score(d) = \sum_{r \in R} \frac{1}{k + rank\_r(d)}$$

其中 $k$ 是平滑参数(通常取 60),$rank\_r(d)$ 是文档 $d$ 在某一路结果里的排名。

RRF 的直觉很好理解:不管各路分数怎么算(因为向量相似度和 BM25 分数本来就没有可比性),只看排名。一个文档在多路检索里都排名靠前,它的 RRF 综合分就高,就像多位评委都给高分的选手,最后的综合排名就高。这个方法不需要训练、计算量极小,工程落地成本很低。

值得注意的是,RRF 本质上还是粗排,适合在 Rerank 之前做候选集合并。如果对最终召回精度要求很高,还是要在 RRF 融合之后接一个 Cross-Encoder 结构的精排模型(比如 bge-reranker-v2-m3)做深度打分,把真正相关的内容筛到最前。

实战建议

不是每个场景都需要三路全上,按业务特点来选:

知识库里有大量专有名词、产品型号、数字的场景(比如电商、IT 文档),向量 + BM25 双路是标配,收益很明显。

用户提问方式多变、和文档表述差异大的场景(比如客服问答),加上多 Query 扩展,召回覆盖率能提升 10%~20%。

对召回质量要求极高的场景,三路全上,最后接 Rerank,把融合结果精排一遍再给 LLM,把质量做到天花板。

把三种召回方式的特点对比一下,方便选型:

召回方式 擅长 短板 适合场景
向量检索 语义相似、同义词、不同表达 精确词语、数字、专有名词 通用语义检索
BM25 关键词 精确词匹配、专有名词 同义词、语义相关但词不重叠 有大量精确词语的知识库
多 Query 扩展 覆盖不同表述角度 增加 LLM 调用开销 用户提问风格多变的场景

🎯 面试总结

回到开头的场景:用户搜「RTX 4090 显卡功耗」,向量检索召不回来,调大 top-K 或者换模型都不是治本之策。问题的根源是向量检索对精确词天然不敏感,这不是模型能力的问题,而是检索方式本身的局限。多路召回的思路很简单:既然没有任何一种检索方式是全能的,那就同时走多条路——向量检索管语义,BM25 管精确词,多 Query 扩展管表述差异,三路结果用 RRF 融合,互为补充,覆盖面远比单路广。面试时把「为什么单路不够」和「多路怎么组合、怎么融合」这两条线讲清楚,就到位了。




上一篇:AI时代全栈开发困境:前端写后端接口,为什么后端同学让我补架构课
下一篇:Function Calling 和 MCP 场景选型:不止看规模,这五步决策更实用
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-5-22 02:46 , Processed in 0.666729 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表