集成检索介绍

它的优化对象是「检索召回的结果」,核心逻辑是对多路不同检索引擎的召回结果做融合重排,全程不修改用户的原始查询语句,和查询转换阶段"改写查询文本"的核心定位有本质区别。

1.3.1 集成检索器与混合检索策略
1.3.1.1 核心原理与优势

集成检索器的核心思想是多路召回、优势互补:接入多种不同检索逻辑的检索器,对同一个查询分别执行召回,再通过融合算法将多路结果合并排序,最终输出统一的文档列表,整体效果优于任意单一检索器。

单一检索算法都存在天然的能力边界:

  • 稀疏检索(如BM25关键词检索):擅长字面精确匹配,对专有名词、专业术语、数字、缩写的匹配度高,但无法理解语义、同义词、上下文关联;
  • 密集检索(如向量相似度检索):擅长语义模糊匹配,能理解同义词、句式变化、隐含语义,但对精确关键词、专有名词的匹配弱于字面检索。

将二者结合的混合检索(Hybrid Search) 是工业界生产级RAG的标准配置,能够同时覆盖字面匹配与语义匹配,大幅提升召回的准确率与全面性,也是Dify、Coze等主流AI应用平台的默认检索方案。

1.3.1.2 LangChain 内置实现:EnsembleRetriever

LangChain 官方封装了 EnsembleRetriever 集成检索器,原生支持多路检索器结果融合,默认基于RRF倒数排名融合算法做结果重排,可接入任意符合标准的Retriever实现。

1.3.1.2.1 核心构造参数
参数名 类型 说明
retrievers ListBaseRetriever 检索器列表,支持任意数量、任意类型的检索器组合
weights Listfloat 对应检索器的权重列表,长度与retrievers一致,权重越高对应检索器的结果优先级越高
1.3.1.2.2 基础实现示例(BM25+FAISS混合检索)

最经典的落地方案是「BM25关键词稀疏检索 + FAISS向量密集检索」的双路组合,实现完整的混合检索能力。

python 复制代码
import dotenv
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings

dotenv.load_dotenv()

# 1. 准备知识库文档
documents = [
    Document(page_content="笨笨是一只很喜欢睡觉的猫咪", metadata={"page": 1}),
    Document(page_content="我喜欢在夜晚听音乐,这让我感到放松。", metadata={"page": 2}),
    Document(page_content="猫咪在窗台上打盹,看起来非常可爱。", metadata={"page": 3}),
    Document(page_content="学习新技能是每个人都应该追求的目标。", metadata={"page": 4}),
]

# 2. 构建BM25关键词检索器(稀疏检索)
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 4

# 3. 构建FAISS向量检索器(密集检索)
faiss_db = FAISS.from_documents(
    documents, 
    embedding=OpenAIEmbeddings(model="text-embedding-3-small")
)
faiss_retriever = faiss_db.as_retriever(search_kwargs={"k": 4})

# 4. 初始化集成检索器,两路检索权重各占0.5
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, faiss_retriever],
    weights=[0.5, 0.5],
)

# 5. 执行混合检索
docs = ensemble_retriever.invoke("除了猫,你养了什么宠物呢?")
1.3.1.2.3 运行时动态配置

生产环境支持通过 configurable_fields 实现检索参数的动态调整,无需重启服务即可修改单路检索器的召回数量、匹配阈值等配置。

python 复制代码
# 为向量检索器配置可动态修改的搜索参数
faiss_retriever = faiss_db.as_retriever(search_kwargs={"k": 4}).configurable_fields(
    search_kwargs=ConfigurableField(
        id="search_kwargs_faiss",
        name="搜索参数",
        description="FAISS检索器的搜索参数配置",
    )
)

# 调用时传入配置,动态调整召回数量
config = {"configurable": {"search_kwargs_faiss": {"k": 1}}}
docs = ensemble_retriever.invoke("苹果", config=config)
1.3.1.3 融合算法逻辑

EnsembleRetriever 底层基于加权版RRF(倒数排名融合) 算法实现结果合并,核心执行逻辑:

  1. 并行调用所有检索器,分别获取各自的文档排名列表;
  2. 对每个文档,按其在各路检索器中的排名,结合对应检索器的权重,累计计算融合得分;
  3. 按总得分降序排列,去重后输出最终的融合结果。

与标准RRF算法相比,加权RRF支持人为调整不同检索通道的优先级:比如精确查询占比高的业务场景,可将BM25权重设为0.6、向量检索设为0.4,灵活适配业务偏好。

1.3.1.4 与RAG Fusion的边界区分

二者都使用了RRF融合算法,但所属阶段、解决的问题完全不同,是极易混淆的两个方案,核心区别如下:

方案 所属阶段 核心逻辑 差异来源 核心目标
集成检索器(混合检索) 检索阶段 同一个查询,多路不同检索引擎召回,结果融合 检索算法/引擎不同 兼顾字面匹配与语义匹配
RAG Fusion 查询转换+检索融合 多个改写查询,同一路检索器召回,结果融合 查询语句不同 提升召回的语义全面性

工业界最佳实践通常是二者叠加使用:先通过查询转换生成多个子查询,再对每个子查询执行混合检索,最后对所有结果做统一RRF融合,实现最大化的召回效果。

1.3.1.5 落地最佳实践
  1. 权重调优:默认两路各0.5是通用基线,需结合业务场景调优。事实类、精确查询多的场景调高BM25权重,语义类、咨询类查询多的场景调高高向量检索权重。
  2. 召回数量配置:单路检索器的召回数量建议略大于最终目标数量,保证融合后有足够的候选池做排序。例如最终返回4条结果,单路可各召回4~6条。
  3. 中文分词适配:原生BM25检索器默认按空格分词,不适合中文文本。生产环境需替换为Jieba等中文分词器,否则关键词检索效果会严重下降。
  4. 可扩展组合:不仅限于BM25+向量,还可接入图检索、SQL检索、知识库目录检索等多路通道,通过统一的RRF框架融合,适配复杂的多数据源RAG系统。
  5. 性能权衡:每增加一路检索器,检索耗时会相应增加,需在效果与性能之间做平衡。通用场景两路混合即可覆盖绝大多数需求,不建议堆砌超过三路检索器。
相关推荐
国科安芯1 小时前
FreeRTOS RISC-V 浮点上下文切换移植:在 IAR 工程中完整保存 FPU 寄存器
java·开发语言·单片机·嵌入式硬件·算法·系统架构·risc-v
小poop2 小时前
轮转数组:从暴力到最优,一题掌握算法复杂度分析
数据结构·算法·leetcode
樱桃读报僵尸2 小时前
说说 LLMRouter,Agent 执行过程中怎么动态的选择 LLM
算法
gis开发之家3 小时前
《Vue3 从入门到大神40篇》Vue3 源码详解(十):diff 算法全解析 —— 为什么 Vue3 比 Vue2 更快?
javascript·算法·typescript·前端框架·vue3·vue3源码
进击的丸子3 小时前
虹软人脸服务器SDK-C++语言Demo实操指南
后端·算法
兰令水3 小时前
hot100【acm版】【2026.7.25/26打卡-java版本】
java·算法·排序算法
音视频工程实战4 小时前
PromptQL 新手入门与实战指南
数据库·sql·算法
wabs6664 小时前
关于图论【卡码网104.建造最大岛屿的思考】
数据结构·算法·图论
玖玥拾5 小时前
LeetCode 27 移除元素
算法·leetcode