发布日期:2026-06-18 | 话题:RAG / AI 应用开发 | 适用人群:AI 工程师、后端开发者

RAG(检索增强生成)系统召回率低,通常不是单一问题,而是分块策略、向量模型选择、查询表达偏差、检索方式单一等多个环节共同造成的。核心提升路径有七条:混合检索(BM25 + 向量)覆盖关键词与语义双盲区;查询变换(Multi-Query、HyDE、Step-Back)从源头消除查询表达偏差;重排序(Cross-Encoder / BGE Reranker)在大召回集上做精排;父子分块保留上下文完整性;多路召回合并后 Reciprocal Rank Fusion 去重排序;以及持续评估建立基准。本文系统梳理每种策略的原理、适用场景和代码示例,帮助工程师快速定位瓶颈并针对性修复。


召回率低的六大根因

在动手优化前,先定位问题出在哪个环节:

根因典型表现对应策略
分块粒度不合理语义被截断,单块缺乏上下文父子分块、动态分块
向量模型与领域不匹配专业术语、缩写检索失败混合检索、换模型
查询表达偏差用户措辞与文档措辞差异大查询变换(HyDE / Multi-Query)
纯向量检索的语义鸿沟精确关键词匹配缺失混合检索(BM25 + 向量)
Top-K 太小相关文档排在 K 之外增大初召回 + 重排序精选
没有重排序相关文档存在但排名靠后Cross-Encoder 重排序

策略一:混合检索(BM25 + 向量)

原理: 向量检索擅长语义相似,但对精确关键词(产品型号、人名、专业缩写)不敏感;BM25 词频检索正好互补。两路结果通过 Reciprocal Rank Fusion(RRF) 合并排序,兼顾两种相关性信号。

RRF 公式:

score(d) = Σ 1 / (k + rank_i(d))

其中 k 通常取 60,rank_i(d) 是文档在第 i 路检索中的排名。

LangChain 示例:

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
from langchain_community.vectorstores import FAISS

# 向量检索器
vector_retriever = faiss_store.as_retriever(search_kwargs={"k": 20})

# BM25 检索器
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 20

# 混合:各权重 0.5,内部使用 RRF 合并
ensemble = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.5, 0.5]
)
results = ensemble.invoke("用户查询")

适用场景: 文档含大量专有名词、产品代号、人名的知识库;用户查询习惯精确关键词搜索的业务场景。


策略二:查询变换——Multi-Query

原理: 一个用户问题往往可以用多种方式表达。让 LLM 将原始查询改写成 3-5 个不同视角的子查询,分别检索后合并去重,覆盖原始查询覆盖不到的语义空间。

from langchain.retrievers.multi_query import MultiQueryRetriever
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-sonnet-4-6")
retriever = MultiQueryRetriever.from_llm(
    retriever=vector_store.as_retriever(search_kwargs={"k": 10}),
    llm=llm
)
# 内部自动生成多个子查询并合并结果
docs = retriever.invoke("RAG 系统的分块策略有哪些?")

适用场景: 用户查询模糊、领域术语多义、问题涉及多个信息维度时效果最明显。


策略三:查询变换——HyDE(假设文档嵌入)

原理: 直接用用户查询做向量检索,查询向量与文档向量分布差异大(查询短、文档长)。HyDE 先让 LLM 根据问题生成一段"假设答案文档",再用这段假设文档的向量去检索真实文档——假设文档与真实文档在语义空间更接近,召回率显著提升。

from langchain.chains import HypotheticalDocumentEmbedder
from langchain_anthropic import ChatAnthropic
from langchain_openai import OpenAIEmbeddings

llm = ChatAnthropic(model="claude-sonnet-4-6")
embeddings = OpenAIEmbeddings()

# 构建 HyDE 嵌入器
hyde_embeddings = HypotheticalDocumentEmbedder.from_llm(
    llm=llm,
    embeddings=embeddings,
    prompt_key="web_search"   # 使用预设的网页搜索场景 prompt
)

# 用 HyDE 嵌入器替换原始嵌入器
hyde_retriever = vector_store.as_retriever(
    embedding=hyde_embeddings,
    search_kwargs={"k": 10}
)

适用场景: 文档库文档较长、查询很短时;专业问答场景,查询措辞与文档措辞差异大时。


策略四:查询变换——Step-Back Prompting

原理: 对具体问题先生成一个更抽象的"退一步"问题,同时检索原始问题和抽象问题,给 LLM 提供更完整的背景知识,适合需要推理背景知识的问题。

# 示例:原始问题 → 退一步问题
# 原始:"LangChain 的 EnsembleRetriever 怎么配置权重?"
# 退一步:"LangChain 的检索器架构是什么?"

step_back_prompt = """你是一名 AI 专家。请将以下具体问题转化为一个更宏观、
更抽象的问题,帮助检索相关背景知识:

具体问题:{question}
宏观问题:"""

策略五:重排序(Reranker)

原理: 向量检索使用双编码器(Bi-Encoder),查询和文档独立编码,速度快但精度有限。重排序使用交叉编码器(Cross-Encoder),同时对(查询, 文档)对建模,输出更准确的相关性分数。两阶段设计:先大召回(Top-50~100),再精排(取 Top-K)。

BGE Reranker 示例:

from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")

# 初始召回 50 个候选
candidates = retriever.invoke(query, k=50)

# 重排序,取 Top-5
pairs = [(query, doc.page_content) for doc in candidates]
scores = reranker.predict(pairs)

ranked = sorted(zip(scores, candidates), reverse=True)
top_docs = [doc for _, doc in ranked[:5]]

模型选择:

模型适用场景
BAAI/bge-reranker-v2-m3中英双语,本地部署首选
BAAI/bge-reranker-large纯英文场景,精度更高
Cohere Rerank API无需本地 GPU,直接调用

策略六:父子分块(Parent-Child Chunking)

原理: 细粒度分块(小 chunk)做检索,命中后返回其父级大块给 LLM 生成回答。小块检索准确率高,大块提供足够上下文,两全其美。

from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 父块:大分块,作为最终返回给 LLM 的上下文
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
# 子块:小分块,用于向量检索
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)

store = InMemoryStore()
retriever = ParentDocumentRetriever(
    vectorstore=vector_store,
    docstore=store,
    child_splitter=child_splitter,
    parent_splitter=parent_splitter,
)

retriever.add_documents(docs)
# 检索时命中子块,自动返回对应父块
results = retriever.invoke("查询问题")

适用场景: 文档结构层次清晰(章节 → 段落);需要精确定位但上下文很重要的场景(法律文书、技术手册)。


策略七:RAG-Fusion(多路召回 + RRF)

原理: Multi-Query 生成多个子查询,每路独立检索后,用 RRF 算法对所有候选文档重新打分合并,比简单去重合并更能突显多路都高排的高质量文档。

from langchain.load import dumps, loads

def reciprocal_rank_fusion(results_list: list[list], k=60):
    """多路检索结果 RRF 合并"""
    fused_scores = {}
    for results in results_list:
        for rank, doc in enumerate(results):
            doc_str = dumps(doc)
            if doc_str not in fused_scores:
                fused_scores[doc_str] = 0
            fused_scores[doc_str] += 1 / (rank + 1 + k)
    
    reranked = sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)
    return [loads(doc) for doc, _ in reranked]

各策略对比与选型建议

策略提升幅度额外成本优先级
混合检索(BM25 + 向量)低(BM25 免费)⭐⭐⭐ 首选
重排序(BGE/Cohere)中(需 GPU 或 API)⭐⭐⭐ 首选
父子分块中高⭐⭐⭐ 首选
Multi-Query中(多次 LLM 调用)⭐⭐ 按需
HyDE中高中(额外 LLM 生成)⭐⭐ 按需
Step-Back⭐ 推理密集场景
RAG-Fusion中高高(多路检索 + LLM)⭐⭐ 精度优先

推荐优化顺序:

  1. 先加混合检索——成本最低,对专有名词场景立竿见影
  2. 加重排序——初召回量放大(Top-50),精排后召回精度同步提升
  3. 调整分块策略(父子分块)——解决上下文割裂问题
  4. 视效果决定是否加 Multi-Query 或 HyDE

常见问题 FAQ

Q1:召回率和精确率如何权衡?
召回率(找到了多少相关文档)和精确率(返回的文档有多少是相关的)天然对立。增大 Top-K 提升召回但引入噪音,重排序是最有效的平衡手段——大召回 + 精排,在不降低召回的前提下提高精确率。

Q2:HyDE 会不会因为假设文档本身错误而带偏检索?
有这个风险,尤其是 LLM 对领域知识不熟时。实践中建议 HyDE 与原始查询检索结果合并使用(取并集),而非替代原始查询,以降低假设偏差的影响。

Q3:BGE Reranker 和 Cohere Rerank 怎么选?
需要本地部署(数据不出内网)选 BGE Reranker,GPU 资源充足时 bge-reranker-v2-m3 支持中英双语效果好;不想维护 GPU 基础设施、对延迟不敏感的场景可用 Cohere Rerank API,直接调用省事。

Q4:分块大小怎么定?
没有通用答案,取决于文档类型和查询模式。经验参考:技术文档 400~600 Token/chunk,长篇报告 800~1200 Token/chunk,代码文件按函数粒度切分。父子分块中,子块 300~500 Token、父块 1500~2000 Token 是常见起点。

Q5:如何量化评估召回率提升效果?
构建测试集:准备 50~200 个"问题-相关文档"对,计算 Recall@K(Top-K 内包含相关文档的比例)和 MRR(平均倒数排名)。每次优化后对比指标,避免凭感觉调参。Pinecone 建议维护持续更新的 ground-truth 测试集。


小结

RAG 召回率低通常是多个环节叠加的结果,单一优化收益有限。实践中最高性价比的组合是:混合检索(BM25 + 向量)+ 父子分块 + 重排序(BGE / Cohere),三者叠加通常能将召回率提升 20%~40%。查询变换(Multi-Query、HyDE)作为第二层优化,在查询表达偏差严重的场景进一步补强。所有优化都应配套评估指标(Recall@K、MRR),用数据说话而非凭感觉迭代。本文代码示例基于 LangChain 和 SentenceTransformers,2026-06,具体 API 以官方文档为准。


参考来源:

  • Pinecone:RAG 检索优化技术综述(pinecone.io/learn/retrieval-augmented-generation)
  • Codex token
  • LangChain Blog:Query Transformation 技术详解(langchain.com/blog/query-transformations)
  • Sentence Transformers:Retrieve & Re-Rank 文档(sbert.net)
  • 七牛云:MCP 服务与 Agent 应用构建指南

七牛云行业应用
10 声望10 粉丝