结合关键词、向量与重排序的工业级 RAG 检索方案
前言
在 RAG(检索增强生成)系统的落地过程中,开发者往往会发现单纯的向量检索(Dense Retrieval)并非万能。它在处理专有名词、缩写、特定型号(如 “iPhone 15 Pro”)或罕见词汇时,表现往往不如传统的关键词检索(Sparse Retrieval)。混合检索(Hybrid Search)通过融合两者的优势,已成为构建高性能 RAG 系统的标准配置。本文将深入探讨混合检索的原理、算法实现及优化策略。
检索技术的三驾马车
1. 关键词检索 (Sparse Retrieval / BM25)
- 原理:基于词频(TF)和逆文档频率(IDF)进行匹配。
- 优势:精确匹配能力强,对专有名词、编号极其敏感。
- 劣势:无法理解语义,受限于“词项重叠”(Vocabulary Overlap)。
2. 向量检索 (Dense Retrieval / Embedding)
- 原理:将文本映射到高维连续向量空间,计算余弦相似度。
- 优势:具备语义理解能力,能处理同义词和跨语言检索。
- 劣势:容易产生“语义漂移”,对长尾词和精确编号匹配较弱。
3. 稀疏向量检索 (Learned Sparse Retrieval / SPLADE)
- 原理:利用模型学习词项的重要性,生成具备语义扩展能力的稀疏向量。
- 优势:兼具关键词的精确性和向量的语义扩展性。
核心算法:结果融合 (Fusion)
混合检索的关键在于如何将来自不同检索器的结果列表合并。
1. RRF (Reciprocal Rank Fusion)
RRF 是一种无需归一化分数的排名融合算法,它只关注文档在各列表中的相对排名。
\[score(d) = \sum_{r \in R} \frac{1}{k + r(d)}\]- $r(d)$:文档 $d$ 在列表 $R$ 中的排名。
- $k$:平滑常数,通常取 60。
- 特点:极其鲁棒,不受不同检索器分数量级差异的影响。
2. 加权得分融合 (Weighted Score Fusion)
如果各检索器的分数已经过归一化(如都在 0-1 之间),可以使用加权求和。
\[FinalScore = \alpha \cdot Score_{dense} + (1 - \alpha) \cdot Score_{sparse}\]- $\alpha$:调节权重。在 Weaviate 等数据库中,$\alpha=1$ 为纯向量,$\alpha=0$ 为纯关键词。
工业级检索流水线:从召回到重排
一个成熟的检索系统通常分为两个阶段:
[用户查询] ──→ [查询改写/扩展]
│
┌─────────────┴─────────────┐
▼ ▼
[向量检索 (Top 100)] [BM25 检索 (Top 100)]
└─────────────┬─────────────┘
▼
[RRF 结果融合 (Top 50)]
│
▼
[重排序 (Re-ranking)] <-- 使用 Cross-Encoder (如 BGE-Reranker)
│
▼
[最终 Top 5 结果] ──→ [送入 LLM 生成]
技术实现:LangChain 混合检索与重排
以下代码展示了如何构建一个包含 BM25 + Vector + Cross-Encoder Re-ranker 的完整链路。
from langchain.retrievers import BM25Retriever, EnsembleRetriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain.retrievers.contextual_compression import ContextualCompressionRetriever
from langchain_community.document_compressors import BGERerank
# 1. 初始化基础检索器
doc_list = [
"LLM 应用的多租户架构主要分为 Silo, Bridge 和 Pool 三种模式。",
"混合检索结合了向量检索和关键词检索的优点。",
"RRF 算法常用于融合不同来源的检索结果。"
]
# 向量检索器
vectorstore = FAISS.from_texts(doc_list, OpenAIEmbeddings())
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# 关键词检索器
bm25_retriever = BM25Retriever.from_texts(doc_list)
bm25_retriever.k = 2
# 2. 融合检索器 (Ensemble)
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
# 3. 引入重排序 (Reranker)
# 使用 BGE-Reranker 提升精度
reranker = BGERerank(model="BAAI/bge-reranker-large", top_n=2)
compression_retriever = ContextualCompressionRetriever(
base_compressor=reranker,
base_retriever=ensemble_retriever
)
# 执行检索
query = "多租户架构有哪些模式?"
results = compression_retriever.get_relevant_documents(query)
进阶:查询增强技术
检索的质量不仅取决于数据库,还取决于你如何“问”问题。
1. HyDE (Hypothetical Document Embeddings)
- 原理:先让 LLM 根据问题生成一个“虚假的答案”,然后用这个虚假答案去向量数据库里检索。
- 优势:虚假答案与真实文档在向量空间中往往比原始问题更接近,能显著提升语义检索的召回率。
2. Multi-Query Retrieval (多查询检索)
- 原理:让 LLM 将用户的问题改写成 3-5 个意思相近但措辞不同的新问题,分别检索后取并集。
- 优势:克服了用户提问不专业或措辞单一的问题。
3. Self-Querying (自查询)
- 原理:让 LLM 从问题中提取出结构化的过滤条件。
-
例子:用户问“2023 年关于 AI 安全的论文有哪些?”,LLM 提取出
year=2023和topic='AI Safety',并将其转化为向量数据库的 Metadata Filter。
深度解析:为什么重排序 (Reranking) 如此重要?
Bi-Encoder (向量检索):将问题和文档分别编码,计算余弦相似度。速度极快,但无法捕捉问题与文档之间细微的交互。 Cross-Encoder (重排序):将问题和文档拼接在一起,同时输入模型。模型可以逐字逐句对比两者的相关性。精度极高,但计算量巨大。
最佳实践:
- 使用向量检索从百万级数据中快速召回 Top 100。
- 使用重排序模型对这 Top 100 进行精细打分,选出最终的 Top 5。 这种“粗排+精排”的架构是目前工业界 RAG 系统的天花板。
总结
混合检索不是简单的“1+1”,而是一套精密的工程体系。
- 基础层:BM25 + Vector。
- 融合层:RRF 算法。
- 精排层:Cross-Encoder 重排序。
- 增强层:HyDE 与多查询扩展。
通过这套组合拳,你可以构建出一个既懂语义、又能精准匹配专有名词的“超级大脑”。 “混合检索结合了 BM25 的精确匹配和向量检索的语义理解。”, “RRF 算法通过排名倒数求和来融合不同来源的检索结果。” ]
向量检索器
vectorstore = FAISS.from_texts(doc_list, OpenAIEmbeddings()) vector_retriever = vectorstore.as_retriever(search_kwargs={“k”: 5})
BM25 检索器
bm25_retriever = BM25Retriever.from_texts(doc_list) bm25_retriever.k = 5
2. 使用 EnsembleRetriever 进行 RRF 融合
ensemble_retriever = EnsembleRetriever( retrievers=[bm25_retriever, vector_retriever], weights=[0.4, 0.6] # 权重分配 )
3. 引入重排序 (Re-ranking) 提升精度
使用 BGE-Reranker 模型 (Cross-Encoder)
注意:在生产环境中,建议将 Reranker 部署为独立服务
reranker = BGERerank(model=”BAAI/bge-reranker-large”, top_n=3)
compression_retriever = ContextualCompressionRetriever( base_compressor=reranker, base_retriever=ensemble_retriever )
4. 执行检索
query = “什么是混合检索的优势?” docs = compression_retriever.get_relevant_documents(query)
for doc in docs: print(f”Score: {doc.metadata.get(‘relevance_score’, ‘N/A’)}”) print(f”Content: {doc.page_content}\n”) ```
性能优化与调优建议
-
权重调优 (Alpha Tuning):
- 对于技术文档/代码库:增加 BM25 权重(如 0.7),因为精确术语匹配至关重要。
- 对于客服/闲聊:增加向量检索权重(如 0.8),侧重语义理解。
-
查询改写 (Query Rewriting):
- 在检索前,利用 LLM 将用户模糊的提问改写为更适合检索的关键词组合。
-
多路召回的并发化:
- 向量检索和 BM25 检索应并行执行,以降低端到端延迟。
-
重排的成本控制:
- Cross-Encoder 计算开销巨大,仅对召回阶段的前 20-50 个文档进行重排,不要对全量文档重排。
总结
混合检索不再是“可选项”,而是生产级 RAG 系统的“标配”。通过 BM25 召回硬匹配 + 向量召回软语义 + Cross-Encoder 精准重排 的组合拳,可以显著提升 LLM 应用的回答准确率和用户信任度。
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:《 LLM应用开发——混合检索策略深度解析 》
本文链接:http://localhost:3015/ai/%E6%B7%B7%E5%90%88%E6%A3%80%E7%B4%A2%E7%AD%96%E7%95%A5.html
本文最后一次更新为 天前,文章中的某些内容可能已过时!
目录
- 前言
- 检索技术的三驾马车
- 1. 关键词检索 (Sparse Retrieval / BM25)
- 2. 向量检索 (Dense Retrieval / Embedding)
- 3. 稀疏向量检索 (Learned Sparse Retrieval / SPLADE)
- 核心算法:结果融合 (Fusion)
- 1. RRF (Reciprocal Rank Fusion)
- 2. 加权得分融合 (Weighted Score Fusion)
- 工业级检索流水线:从召回到重排
- 技术实现:LangChain 混合检索与重排
- 进阶:查询增强技术
- 1. HyDE (Hypothetical Document Embeddings)
- 2. Multi-Query Retrieval (多查询检索)
- 3. Self-Querying (自查询)
- 深度解析:为什么重排序 (Reranking) 如此重要?
- 总结
- 性能优化与调优建议
- 总结