总结混合检索 关键词 语义向量检索建两套索引一个关键词 稀疏检索BM25一个向量稠密检索多路召回怎么融合最简单的就是排名求和倒数排序融合计算两种索引召回准确率的排名然后把段落排名求和取排名最前的文本片段。---------详细介绍--------------------------------------先搞清RAG 的检索召回层在干嘛把 RAG 想象成一个开卷考试的学霸用户问一个问题考题他先去翻一堆参考书检索召回找到最相关的几段话然后把这些段落抄下来结合自己的理解拼成最终答案生成你问的“检索召回层”就是那个翻书找段落的环节。它不用生成任何新内容只管“找到可能用得上的资料”。为什么需要“混合检索”单一检索不够吗早期翻书只有一种方法看关键词。比如你搜“苹果手机”它就去找所有包含“苹果手机”这四个字的页面。这叫关键词检索像图书馆的卡片索引学名稀疏检索BM25 是代表作。但问题来了——用户问“水果里那种红红的、脆甜的果子”它一个字都没提“苹果”关键词检索就会傻眼什么都找不到。后来有了大模型能把句子变成一串数字向量意思相近的句子数字也挨得近。于是可以按语义找你说“红红的脆甜果子”它能找到“苹果”的段落。这叫语义检索也叫稠密检索。但语义检索也不是万能它可能把“苹果手机”和“苹果水果”搞混模糊性对一些特别精确、专有的名词比如产品型号 XJ-882反而容易漏掉不如直接搜字符串来得准。所以混合检索 关键词检索 语义检索。两者互补一个抓精确匹配一个抓意思相近召回的段落更全更准。实际工程中到底是怎么做的这就好比你要同时查两种目录一个是传统的书末“关键词索引”一个是新潮的“概念地图”。在工程上你需要搭建两个不同的“索引库”然后把两个结果巧妙地揉在一起。第一步建好两个“库”你得预先把所有参考书你的文档库处理成两种形态关键词索引库给 BM25 用把每段文本拆词建立“倒排索引”哪个词出现在了哪几个段落里。常用工具Elasticsearch最常用、OpenSearch、Lucene。它们自带强悍的 BM25 算法。你只需要把文本丢进去它内部就建好了。语义向量库给向量检索用用一个大模型比如 text-embedding-ada-002 或开源的 BGE把每个段落都算成一个向量比如 1024 维的一串小数。把这些向量存进一个专门的向量数据库。常用工具Milvus、Pinecone、Weaviate、Qdrant、FAISSFacebook 的库常被集成。所以你的一份文档会变成两份副本存在两个不同的库里。这叫双索引架构。第二步接到问题同时发问当用户问题来了你也得准备两路关键词查询直接把问题文本丢给 Elasticsearch让它用 BM25 去找。Elasticsearch 会返回最匹配的 N 个段落并给每个段落打个相关性分数比如 score5.2。语义查询用同一个 embedding 模型把用户问题也转成向量然后去向量数据库里搜最相似的 M 个段落。向量库也会返回每个段落一个相似度分数比如 0.89。这两路查询完全独立可以同时进行不会相互等待。这是工程上能快的关键。第三步把两个结果“揉”在一起这才是难点现在你手上有两份结果列表可能长这样关键词结果BM25 [段落A, 5.2 段落B, 4.1 段落D, 3.8 ...]语义结果向量 [段落C, 0.91 段落A, 0.88 段落B, 0.75 ...]你想把它们合成一个最终列表给大模型去读。怎么合直接用分数相加吗绝对不行因为分数的尺度不一样BM25 的分数可能是 1 到几十向量相似度是 0 到 1。直接加谁大谁说了算完全乱套。工程师们主要有两种成熟招数招数一排名融合RRF倒数排序融合——最流行、最省事完全不看具体分数只看排名。段落A在关键词路排第1在语义路排第2。段落C在语义路排第1在关键词路压根没进前10排第20。RRF 会给每个排名位置一个固定的分第1名得1/(601)第2名得1/(602)...60是个魔术常数。然后把同一段落在不同路上的分加起来按总分重新排。这样两边都靠前的段落会排在前面只在一边露头的也能有个说得过去的分数。招数二分数校准后加权求和——需要调参用一些数学方法比如把分数都映射到差不多的范围或用统计分布把两路分数变得可比然后按权重相加最终分 a * BM25分 b * 向量分。这要求你调权重a和b比较吃经验换一批文档可能又要重调。实际工程中RRF 因为零参数、效果好被大量使用。一个典型的实际架构图手绘版text用户问题 | ------------------- | | [关键词查询] [语义向量化] | | Elasticsearch 向量数据库 (BM25检索) (ANN近似检索) | | 结果集1 (带BM25分) 结果集2 (带相似度分) | | ---- 结果融合器 --- (例如RRF算法) | 最终 Top-K 段落 | 发给大模型生成有没有更省事的一站式方案有的。现在很多新式数据库看到了这个需求直接在一个系统里同时维护关键词索引和向量索引你只需要一次查询它内部就帮你把混合检索做了。比如Elasticsearch 8.x自带了向量字段一条查询可以同时写 BM25 条件和 kNN 向量搜索内部用线性加权或 RRF 融合。Weaviate、Pinecone等现代向量数据库大多都增加了 BM25 或混合搜索的支持。但即使如此理解上述分离的原理也至关重要因为调优时你还是得知道里面发生了什么。总结实际工程的三个核心双索引同时维护一个倒排索引和一个向量索引。多路并发查询时间时并行发出汇合结果。排名融合用类似 RRF 这样不看绝对分数的技巧公平地合并两个排名。这就是现在绝大多数 RAG 系统在做“混合检索”时的落地方式。它不神秘就是把两种找资料的方法结合起来用“排名”而不是“分数”来达成共识。希望这样讲你能抓住它的工程内核。如果还有想深挖的点随时聊
RAG优化的多路召回-混合检索
发布时间:2026/6/26 17:21:55
总结混合检索 关键词 语义向量检索建两套索引一个关键词 稀疏检索BM25一个向量稠密检索多路召回怎么融合最简单的就是排名求和倒数排序融合计算两种索引召回准确率的排名然后把段落排名求和取排名最前的文本片段。---------详细介绍--------------------------------------先搞清RAG 的检索召回层在干嘛把 RAG 想象成一个开卷考试的学霸用户问一个问题考题他先去翻一堆参考书检索召回找到最相关的几段话然后把这些段落抄下来结合自己的理解拼成最终答案生成你问的“检索召回层”就是那个翻书找段落的环节。它不用生成任何新内容只管“找到可能用得上的资料”。为什么需要“混合检索”单一检索不够吗早期翻书只有一种方法看关键词。比如你搜“苹果手机”它就去找所有包含“苹果手机”这四个字的页面。这叫关键词检索像图书馆的卡片索引学名稀疏检索BM25 是代表作。但问题来了——用户问“水果里那种红红的、脆甜的果子”它一个字都没提“苹果”关键词检索就会傻眼什么都找不到。后来有了大模型能把句子变成一串数字向量意思相近的句子数字也挨得近。于是可以按语义找你说“红红的脆甜果子”它能找到“苹果”的段落。这叫语义检索也叫稠密检索。但语义检索也不是万能它可能把“苹果手机”和“苹果水果”搞混模糊性对一些特别精确、专有的名词比如产品型号 XJ-882反而容易漏掉不如直接搜字符串来得准。所以混合检索 关键词检索 语义检索。两者互补一个抓精确匹配一个抓意思相近召回的段落更全更准。实际工程中到底是怎么做的这就好比你要同时查两种目录一个是传统的书末“关键词索引”一个是新潮的“概念地图”。在工程上你需要搭建两个不同的“索引库”然后把两个结果巧妙地揉在一起。第一步建好两个“库”你得预先把所有参考书你的文档库处理成两种形态关键词索引库给 BM25 用把每段文本拆词建立“倒排索引”哪个词出现在了哪几个段落里。常用工具Elasticsearch最常用、OpenSearch、Lucene。它们自带强悍的 BM25 算法。你只需要把文本丢进去它内部就建好了。语义向量库给向量检索用用一个大模型比如 text-embedding-ada-002 或开源的 BGE把每个段落都算成一个向量比如 1024 维的一串小数。把这些向量存进一个专门的向量数据库。常用工具Milvus、Pinecone、Weaviate、Qdrant、FAISSFacebook 的库常被集成。所以你的一份文档会变成两份副本存在两个不同的库里。这叫双索引架构。第二步接到问题同时发问当用户问题来了你也得准备两路关键词查询直接把问题文本丢给 Elasticsearch让它用 BM25 去找。Elasticsearch 会返回最匹配的 N 个段落并给每个段落打个相关性分数比如 score5.2。语义查询用同一个 embedding 模型把用户问题也转成向量然后去向量数据库里搜最相似的 M 个段落。向量库也会返回每个段落一个相似度分数比如 0.89。这两路查询完全独立可以同时进行不会相互等待。这是工程上能快的关键。第三步把两个结果“揉”在一起这才是难点现在你手上有两份结果列表可能长这样关键词结果BM25 [段落A, 5.2 段落B, 4.1 段落D, 3.8 ...]语义结果向量 [段落C, 0.91 段落A, 0.88 段落B, 0.75 ...]你想把它们合成一个最终列表给大模型去读。怎么合直接用分数相加吗绝对不行因为分数的尺度不一样BM25 的分数可能是 1 到几十向量相似度是 0 到 1。直接加谁大谁说了算完全乱套。工程师们主要有两种成熟招数招数一排名融合RRF倒数排序融合——最流行、最省事完全不看具体分数只看排名。段落A在关键词路排第1在语义路排第2。段落C在语义路排第1在关键词路压根没进前10排第20。RRF 会给每个排名位置一个固定的分第1名得1/(601)第2名得1/(602)...60是个魔术常数。然后把同一段落在不同路上的分加起来按总分重新排。这样两边都靠前的段落会排在前面只在一边露头的也能有个说得过去的分数。招数二分数校准后加权求和——需要调参用一些数学方法比如把分数都映射到差不多的范围或用统计分布把两路分数变得可比然后按权重相加最终分 a * BM25分 b * 向量分。这要求你调权重a和b比较吃经验换一批文档可能又要重调。实际工程中RRF 因为零参数、效果好被大量使用。一个典型的实际架构图手绘版text用户问题 | ------------------- | | [关键词查询] [语义向量化] | | Elasticsearch 向量数据库 (BM25检索) (ANN近似检索) | | 结果集1 (带BM25分) 结果集2 (带相似度分) | | ---- 结果融合器 --- (例如RRF算法) | 最终 Top-K 段落 | 发给大模型生成有没有更省事的一站式方案有的。现在很多新式数据库看到了这个需求直接在一个系统里同时维护关键词索引和向量索引你只需要一次查询它内部就帮你把混合检索做了。比如Elasticsearch 8.x自带了向量字段一条查询可以同时写 BM25 条件和 kNN 向量搜索内部用线性加权或 RRF 融合。Weaviate、Pinecone等现代向量数据库大多都增加了 BM25 或混合搜索的支持。但即使如此理解上述分离的原理也至关重要因为调优时你还是得知道里面发生了什么。总结实际工程的三个核心双索引同时维护一个倒排索引和一个向量索引。多路并发查询时间时并行发出汇合结果。排名融合用类似 RRF 这样不看绝对分数的技巧公平地合并两个排名。这就是现在绝大多数 RAG 系统在做“混合检索”时的落地方式。它不神秘就是把两种找资料的方法结合起来用“排名”而不是“分数”来达成共识。希望这样讲你能抓住它的工程内核。如果还有想深挖的点随时聊