首页 > 教程攻略 > ai资讯 >【大模型RAG优化】RAG召回环节评估实践

【大模型RAG优化】RAG召回环节评估实践

来源:互联网 时间:2026-07-29 15:49:30

对于大模型RAG来说,召回环节能不能把包含答案的文本块捞回来,直接决定了最终LLM的回答质量——这个道理其实不难理解。文本切块策略、向量化模型、召回算法……每一个环节都在影响着召回效果。所以,构建一套召回评估流程,然后持续迭代优化,是搭建RAG系统绕不过去的必要步骤。

【大模型RAG优化】RAG召回环节评估实践

要评估召回效果,需要准备好测试数据——形式就是“问题”和“包含答案的文本块”这样的二元组。常用的评估指标有两个:

命中率(Hit Rate)

平均倒数排名(MRR)

命中率很直观,衡量的是包含答案的文本块是否出现在召回列表中。只看有没有,不看它在列表里的位置——命中了就是1,没命中就是0。

而平均倒数排名则更精细一些:每次召回,把包含答案的文本块在列表里的位置取倒数,然后对所有问题求平均。公式是:
MRR = (1/N) * Σ (1 / rank_i),其中 rank_i 表示第 i 个问题对应的答案文本块在召回列表中的排名。

在实际项目中,通常没有现成的“问题-答案块”测试集,所以需要自己构建。LlamaIndex 提供了一个很方便的接口 generate_question_context_pairs,它会调用 LLM,根据切分好的文本块生成对应的问题。LLM 默认使用的提示词大致是这样的:
把文本块作为上下文,要求模型扮演老师,针对这段内容出若干道测验题,并且试题要覆盖整段信息的多样性。

Context information is below.
---------------------
{context_str}
---------------------
Given the context information and not prior knowledge.
generate only questions based on the below query.
You are a Teacher/ Professor. Your task is to setup 
{num_questions_per_chunk} questions for an upcoming 
quiz/examination. The questions should be diverse in nature 
across the document. Restrict the questions to the 
context information provided.

除此之外,LlamaIndex 还提供了 RetrieverEvaluator 接口——你只需要传入测试数据集、向量数据库和向量化模型,它就能自动跑出命中率和 MRR 这两个指标。下面是一段完整的示例代码,展示了从构建向量数据库、生成测试数据到评估的全流程:

from llama_index.evaluation import generate_question_context_pairs
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext, OpenAIEmbedding
from llama_index.node_parser import SentenceSplitter
from llama_index.llms import OpenAI
import os
from llama_index.evaluation import RetrieverEvaluator
import pandas as pd

os.environ["OPENAI_API_BASE"] = "xxx"
os.environ["OPENAI_API_KEY"] = "xxx"

llm = OpenAI(model="gpt-35-turbo")

# 文本加载与切块,data文件夹中存放txt文件
documents = SimpleDirectoryReader("./data/").load_data()
node_parser = SentenceSplitter(chunk_size=512)
nodes = node_parser.get_nodes_from_documents(documents)

# 设置文本块id
for idx, node in enumerate(nodes):
    node.id_ = f"node_{idx}"

# 构建向量数据库
embed_model = OpenAIEmbedding()
service_context = ServiceContext.from_defaults(embed_model=embed_model)
vector_index = VectorStoreIndex(nodes, service_context=service_context)
retriever = vector_index.as_retriever(similarity_top_k=2)

# 根据原始文本块生成问题
qa_dataset = generate_question_context_pairs(
    nodes, llm=llm, num_questions_per_chunk=2
)

# 定义评估器
retriever_evaluator = RetrieverEvaluator.from_metric_names(
    ["mrr", "hit_rate"], retriever=retriever
)

# 在所有生成的问题上评估召回效果
eval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)
result = []
for eval_result in eval_results:
    metric_dict = eval_result.metric_vals_dict
    result.append(metric_dict)

result_df = pd.DataFrame(result)
hit_rate = result_df["hit_rate"].mean()
mrr = result_df["mrr"].mean()
print("hit_rate:", hit_rate)
print("mrr:", mrr)

有了这套流程,就能定量地知道当前召回环节的瓶颈在哪里——是切块太粗导致信息混杂,还是向量模型不够精准,或者召回策略的 top_k 设置不合理。然后针对性地调整,再跑一遍评估,直到指标达到预期。这才是构建可靠 RAG 系统的正确姿势。