游乐游手机版
首页/AI热点日报/热点详情

RAG检索召回不准确?三种实战提升方法

类型:热点整理2026-06-26
前言 在《RAG实战篇:构建一个最小可行性的Rag系统》一文中,已经介绍了Rag系统的实现框架,以及如何搭建一个最基本的Naive Rag。 前四篇文章分别探讨了索引(Indexing)、查询转换(Query Translation)、路由(Routing)和查询构建(Query Construct

前言

RAG实战篇:检索召回结果不准确?试试这三种实用方法

在《RAG实战篇:构建一个最小可行性的Rag系统》一文中,已经介绍了Rag系统的实现框架,以及如何搭建一个最基本的Naive Rag。

前四篇文章分别探讨了索引(Indexing)、查询转换(Query Translation)、路由(Routing)和查询构建(Query Construction)环节的优化方案。

现在轮到检索召回(Retrieval)这个环节了。这篇文章将重点介绍如何优化RAG系统的召回结果,从而提升LLM大模型回答的准确度。

检索召回的过程大致是这样的:用户的问题被输入到嵌入模型中进行向量化,然后在向量数据库中搜索语义相似的知识文本或历史对话记录,最后返回结果。

但在Naive Rag中,系统会把所有检索到的块一股脑全扔给LLM生成回答,这样很容易出现中间内容丢失、噪声占比过高、上下文长度限制等问题。

接下来,结合源代码,详细拆解三种优化召回准确率的实用方案——Reranking(重排序)、Refinement(压缩)和Corrective Rag(纠正性Rag)。

具体的源代码地址可以在文末获取。

1. Rerank(重排序)

重排序,说白了就是给检索回来的结果重新排个队,把更相关、更靠谱的内容提到前面,从而提升检索质量。

重排序主要有两种类型:基于统计打分的重排序和基于深度学习的重排序。

基于统计的重排序,通常是汇总多个来源的候选结果列表,用多路召回的加权得分或倒数排名融合(RRF)算法来重新算分。这种方法计算简单,成本低效率高,广泛应用于对延迟敏感的传统检索系统,比如内部知识库检索、电商智能客服检索等。

在之前《RAG实战篇:优化查询转换的五种高级方法,让大模型真正理解用户意图》一文中提到的RAG Fusion中的reciprocal_rank_fusion,就是一种基于统计打分的重排序。再来回顾一下代码:

def reciprocal_rank_fusion(results: list[list], k=60):
    """ Reciprocal_rank_fusion that takes multiple lists of ranked documents 
    and an optional parameter k used in the RRF formula """
    # Initialize a dictionary to hold fused scores for each unique document
    fused_scores = {}
    # Iterate through each list of ranked documents
    for docs in results:
        # Iterate through each document in the list, with its rank (position in the list)
        for rank, doc in enumerate(docs):
            # Convert the document to a string format to use as a key (assumes documents can be serialized to JSON)
            doc_str = dumps(doc)
            # If the document is not yet in the fused_scores dictionary, add it with an initial score of 0
            if doc_str not in fused_scores:
                fused_scores[doc_str] = 0
            # Retrieve the current score of the document, if any
            previous_score = fused_scores[doc_str]
            # Update the score of the document using the RRF formula: 1 / (rank + k)
            fused_scores[doc_str] += 1 / (rank + k)
    # Sort the documents based on their fused scores in descending order to get the final reranked results
    reranked_results = [
        (loads(doc), score)
        for doc, score in sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)
    ]
    # Return the reranked results as a list of tuples, each containing the document and its fused score
    return reranked_results

另一种是基于深度学习模型的重排序,也就是常说的Cross-encoder Reranker。这类模型经过专门训练,能够更好地分析问题和文档之间的相关性。它给问题与文档之间的语义相似度打分,打分只取决于文本内容,不依赖文档在召回结果中的位置。优点是检索准确度更高,但成本也更高,响应更慢,适合对检索精度要求极高的场景,比如医疗问诊。

Cohere就是一个很优秀的开源工具,支持多种重排序策略,使用起来也很简单:

from langchain_community.llms import Cohere
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CohereRerank
from langchain.retrievers.document_compressors import CohereRerank

retriever = vectorstore.as_retriever(search_kwargs={"k": 10})

# Re-rank
compressor = CohereRerank()
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor, base_retriever=retriever
)

compressed_docs = compression_retriever.get_relevant_documents(question)

2. Refinement(压缩)

压缩的思路更直接:检索到的内容块,别直接喂给大模型,先删掉无关的内容,突出重要的上下文,这样能减少整体提示长度,降低冗余信息对大模型的干扰。

LangChain里有一个基础的上下文压缩检索器——ContextualCompressionRetriever,可以轻松实现这个功能:

from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
from langchain_openai import OpenAI

llm = OpenAI(temperature=0)
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor, base_retriever=retriever
)

compressed_docs = compression_retriever.invoke(
    "What did the president say about Ketanji Jackson Brown"
)

还有一种更简单但更强大的压缩器——LLMChainFilter,它用LLM链来决定过滤掉哪些文档,返回哪些文档,不修改文档内容:

from langchain.retrievers.document_compressors import LLMChainFilter

_filter = LLMChainFilter.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
    base_compressor=_filter, base_retriever=retriever
)

compressed_docs = compression_retriever.invoke(
    "What did the president say about Ketanji Jackson Brown"
)
pretty_print_docs(compressed_docs)

3. Corrective Rag(纠错性Rag)

Corrective-RAG(CRAG)是一种更聪明的RAG策略:它引入了“自我反思/自我评分”机制。具体来说,采用轻量级的“检索评估器”为每个检索到的文档返回一个置信度分数,然后根据这个分数决定触发哪种检索操作。

评估器可以根据置信度分数把文档标记到三个桶里:正确模糊不正确

  • 如果所有文档的置信度都低于阈值,说明检索“不正确”,这时会触发新的知识来源(比如网络搜索)来弥补。
  • 如果至少有一个文档的置信度高于阈值,说明检索“正确”,这时会对文档进行知识细化——把文档分割成“知识条”,根据相关性对每个条目打分,最相关的重新组合成内部知识。

所以,Corrective Rag的核心在于“检索评估器”的设计。下面是一个实现示例:

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI

# Data model
class GradeDocuments(BaseModel):
    """Binary score for relevance check on retrieved documents."""
    binary_score: str = Field(
        description="Documents are relevant to the question, 'yes' or 'no'"
    )

# LLM with function call
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
structured_llm_grader = llm.with_structured_output(GradeDocuments)

# Prompt
system = """You are a grader assessing relevance of a retrieved document to a user question. \n
If the document contains keyword(s) or semantic meaning related to the question, grade it as relevant. \n
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question."""

grade_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        ("human", "Retrieved document: \n\n {document} \n\n User question: {question}"),
    ]
)

retrieval_grader = grade_prompt | structured_llm_grader
question = "agent memory"
docs = retriever.get_relevant_documents(question)
doc_txt = docs[1].page_content
print(retrieval_grader.invoke({"question": question, "document": doc_txt}))

当然,Corrective Rag也有它的局限性:严重依赖检索评估器的质量,而且容易受到网络搜索引入的偏见影响。所以,微调检索评估器往往是不可避免的。

总结

这篇文章详细介绍了优化Retrieval(检索召回)的三种实用方法:Rerank(重排序)、Refinement(压缩)、Corrective Rag(纠错性Rag)。

检索召回之后,下一步就是最终的内容生成了。即使用了上面这些优化方案,生成环节仍然可能遇到格式错误、内容不完整、整治不正确等问题。下一篇文章,将继续讨论如何优化生成环节,给整个RAG流程画上一个完美的句号。

来源:https://www.53ai.com/news/RAG/2024101145798.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。