简介:面向AI应用开发者与研究者的RAG评估方法详解源码包,聚焦检索增强生成系统的准确率、忠实度、召回率等核心指标,系统梳理人工评估与自动评估两条技术路径。人工评估依赖专家对生成内容的主观判断,自动评估则借助LangSmith、Langfuse和RAGAS等主流工具与框架,形成客观、可复现的评估结果。压缩包共3个文件,包含inscode代码片段、html说明文档与gitignore配置,整体仅5KB,轻量精炼,便于快速查看核心实现。已有178人学习,适合正在搭建RAG评估流程或需要优化检索效果的技术人员。通过源码可了解评估指标的具体计算逻辑、评估流程设计思路,以及针对召回率的实用优化建议,帮助读者构建更可靠、可量化的RAG质量保障体系,从而提升生成内容在实际应用中的准确性与可信度。 我帮不少团队Review过RAG项目,发现一个很普遍的现象:大家都在卷知识库怎么切块、embedding换什么模型、用哪个向量库,但被问到“你的RAG效果到底怎么样”时,往往只能指着两三个手工挑出来的漂亮回答截图。这不是评价,这是幸存者偏差。RAG评估方法这件事,短时间看不出价值,但一旦进入调优阶段,没有一套量化指标,你连问题出在检索还是生成都说不清楚。这篇文章我就把RAG评估的方法体系完整拆一遍,从指标体系到RAGAS框架的评估源码,再到实际测试中踩过的坑,一次性讲清楚。适合正在调知识库问答系统的工程师,也适合需要验证RAG业务效果的产品和技术负责人。
1. 为什么说没有评估的RAG只能算Demo
1.1 RAG链路太长,问题到底出在哪一环
RAG系统从来不是一个“单个模型”问题。从文档加载、解析、切分、向量化、检索再到LLM生成,整条链路随便哪一环出现偏差,用户看到的就是答案不对、答非所问或者一本正经胡说八道。
举例来说,文档切分太粗,切出来的片段包含大量无关内容,向量检索召回的前几个片段可能和问题一点关系都没有;切分太细,语义被切断,检索又召回不完整的关键证据。这类问题不通过量化评估,光靠打开控制台看一两条日志根本定位不了。
最典型的场景是这样的:你问知识库“设备保修期内能不能免费换电池”,系统回答“在保修期内可以申请换货服务”。用户觉得这答案勉强能用,但你无法判断它到底是从哪段上下文推理出来的、检索出来的相关片段排在第几名、答案中有多少内容其实没有找到上下文支撑。没有评估体系,这些问题只能靠猜。
1.2 评估的本质是给每个环节装上仪表盘
我觉得评估的核心价值不是“打分”,而是给系统装上一套可观测的仪表盘。RAG评估天然要拆成两条线:
- 检索线:东西到底检没检到?排在第几位?相关片段有没有出现在top-k结果里?
- 生成线:检到了之后有没有用上?答案有没有忠实于检索到的上下文?答得对不对?
这两条线对应的指标完全不同。如果检索线表现差,你该去优化切分策略、embedding模型、重排模型;如果生成线表现差,你该去改prompt、换LLM、调生成参数。没有分层评估,优化动作就是盲目的。
很多人一开始会拿“准确率”来衡量RAG,但RAG和传统分类任务有本质区别——它没有严格的类别标签,答案是开放生成的,还涉及上下文引用是否正确。所以必须使用一套面向检索和生成特性的指标体系。后续所有源码演示,我都会围绕这个分层思路展开。
2. 先把指标讲透:检索质量与生成质量分开看
2.1 检索侧核心指标:Hit Rate、MRR、NDCG
检索侧指标衡量的是“知识库召回能力”。构建评估集时,每个样本需要包含问题、期望召回的知识片段(或文档ID)、实际检索结果。然后算三个最常用的指标。
Hit Rate(命中率)是最直观的指标:在top-k检索结果中,只要有任意一个片段覆盖了正确答案的要点,就算命中。计算方式就是命中问题数除以总问题数。它适合回答“系统的召回能力是不是基本合格”这个问题。
MRR(平均倒数排名)比Hit Rate更进一步,它关心正确答案在结果列表中的排序位置。公式是:对每个问题,找到第一个正确结果的排名rank_i,取倒数得到1/rank_i,再对所有问题取平均。MRR@10的值如果是0.7,说明正确信息平均出现在第一个或第二个位置,基本能保证提示词中塞进有效上下文。
NDCG(归一化折损累计增益)是信息检索领域的经典指标,能处理“相关性有分级”的场景。它先把相关性分数按排序位置折损累加得到DCG,再除以理想排序下的IDCG,归一化到0~1。检索结果里如果第一个就是最相关的片段,NDCG就是1。它比MRR更细腻,适合在优化重排模型时使用。
这三个指标高度依赖top-k的设定。k设得越大,Hit Rate当然越高,但塞给LLM的噪声也越多。实际项目里我通常用Hit Rate@5作为初筛,用MRR@10和NDCG@10来观察排序质量。
2.2 生成侧核心指标:Faithfulness、Answer Relevancy、Context Relevancy
检索没问题不代表生成没问题。生成侧指标回答的是三个更关键的问题:
Context Relevancy(上下文相关性)衡量检索回来的contexts里有多少信息真正和问题相关。RAGAS中它是这样算的:让LLM从上下文中提取和问题相关的句子,再用“提取句子数/上下文句子总数”得到比值。如果这个分数低,说明检索回来的上下文里塞了一大堆无关内容,即使最后答案对了,也是模型硬凑的。
Faithfulness(忠实度)是我最看重的指标之一。它衡量生成答案中的陈述是否能被给定上下文所支撑。计算逻辑是:把答案拆成若干条独立陈述,逐条判断是否可以从上下文中推断出,最后算“被支撑的陈述数/总陈述数”。如果这个分数低,意味着模型在没有依据的情况下发挥,幻觉风险极高。
Answer Relevancy(答案相关性)衡量答案是否对上了用户的问题,避免答非所问。RAGAS的实现思路是反向验证:让LLM根据答案反推生成若干个子问题,再计算这些子问题与原问题的语义相似度。这个指标能拦住那种“生成内容很流畅但根本不是用户想问的”情况。
这三个指标各有盲区。Faithfulness不判断答案是否正确,它只看答案是不是基于上下文;Answer Relevancy不看事实正误,只看相关不相关。所以实际评估时不能只抽一个指标,必须组合使用。
2.3 端到端与可溯源指标
除了检索侧和生成侧,还有一类端到端指标直接把系统输出和标准答案做对比。
Answer Correctness(答案正确性)需要人工标注ground truth。RAGAS会综合两方面:事实正确性(提取答案和参考答案中的关键信息进行比对)和语义相似度(向量化后计算相似度得分)。它同时衡量“说了对的东西”和“说得像不像”。
引用准确率(Citation Accuracy)是进阶指标,特别适合法律、医疗、金融这类要求答案可溯源的场景。它检查答案中标注的引用片段是否真的支撑了对应句子。这在RAGAS标准工具里没有直接内置,通常需要自己写规则或者用LLM判断,但价值很大——用户看到答案时能直接跳转到来源文档,信任感完全不一样。
3. 用RAGAS跑通一次完整评估(附源码)
3.1 环境安装与数据准备
RAGAS是目前最主流的开源RAG评估框架,它内置了上述绝大多数指标,也支持生成合成测试集。我用它做评估已经有很长时间,稳定性和指标覆盖面都够用。
安装依赖只需要三件事:
pip install ragas langchain-openai langchain-community datasets pandasRAGAS底层需要调用LLM作为评判者(judge),我的示例使用OpenAI接口。如果你在使用其他兼容模型,把模型名和base_url替换掉即可,但要注意不同模型当judge,分数会有系统偏差,这一点后面专门讲。
准备评估数据时,每条样本需要四个字段:
- question:用户提问
- answer:你的RAG系统生成的最终答案
- contexts:检索系统召回并传给LLM的上下文片段列表
- ground_truth:标准答案(用于计算Answer Correctness)
如果手头没有标注数据,RAGAS的TestsetGenerator能基于你的知识库文档自动合成问答对,这是搭建初始评估集最快的方式。
3.2 合成测试集的生成
合成测试集的价值在于:你可以拿几百篇真实文档,让框架按不同演进类型生成难度不等的问题。RAGAS提供了三种演进类型:
- simple:基于单个上下文块的简单问题
- reasoning:需要多步推断的问题
- multi_context:需要融合多个上下文块的综合问题
生成时给这三种类型分配比例,能模拟真实用户复杂多样的提问方式。示例代码如下:
from ragas.testset.generator import TestsetGenerator from ragas.testset.evolutions import simple, reasoning, multi_context from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_community.document_loaders import TextLoader # 加载知识库文档,这里以本地文本文件为例 loader = TextLoader("kb_docs/knowledge_base.txt") documents = loader.load() # 初始化评估用的LLM和Embedding generator_llm = ChatOpenAI(model="gpt-4o", temperature=0) critic_llm = ChatOpenAI(model="gpt-4o", temperature=0) embeddings = OpenAIEmbeddings(model="text-embedding-3-small") # 生成测试集 generator = TestsetGenerator.from_langchain( generator_llm, critic_llm, embeddings ) testset = generator.generate_with_langchain_docs( documents, test_size=50, distributions={ simple: 0.4, reasoning: 0.3, multi_context: 0.3 }, ) testset_df = testset.to_pandas() testset_df.to_csv("rag_testset.csv", index=False) print(testset_df.head())生成出来的测试集包含question、contexts、ground_truth等字段,不需要再标注。但我强烈建议人工抽查20%的生成样本,剔除那些语义不通或者答案本身就有问题的题目。合成数据只能帮你起步,真实业务的高质量测试集还是得靠持续积累。
3.3 执行评估并解读结果
有了测试集之后,跑评估的代码非常简洁。构造Dataset对象,把列填进去,然后调用evaluate。
from datasets import Dataset from ragas import evaluate from ragas.metrics import ( faithfulness, answer_relevancy, context_relevancy, context_recall, answer_correctness, ) # 这里假设你已经通过自己的RAG链路生成了answer和contexts eval_data = { "question": ["什么是RAG评估的忠实度?"], "answer": ["忠实度衡量生成答案中的陈述是否被检索上下文所支撑。"], "contexts": [["RAG评估中,Faithfulness(忠实度)衡量答案中包含的陈述是否可以从给定上下文中推断出来。"]], "ground_truth": ["忠实度指代答案内容与检索上下文的支撑一致性。"], } dataset = Dataset.from_dict(eval_data) metrics = [ faithfulness, answer_relevancy, context_relevancy, context_recall, answer_correctness, ] result = evaluate(dataset, metrics=metrics) result.to_pandas().to_csv("eval_results.csv", index=False) print(result)这里补充说明一下context_recall:它的作用是检查ground truth中的关键信息是否出现在了检索到的上下文中,属于检索侧的“召回率”变体。我自己一般会固定使用 faithfulness + answer_relevancy + context_relevancy + context_recall这一组基线指标,再根据具体业务加answer_correctness。
跑完之后不要只看总分。RAGAS的evaluate结果会一行一条样本地展示每个指标得分,重点是去看分数低的样本集中在什么类型上。比如faithfulness普遍低,说明生成环节脱离上下文,优先改prompt或换生成模型;context_relevancy低,说明检索结果噪声大,优先优化切分和重排。
4. 实测中最容易踩的四个坑
4.1 用LLM当评判者的随机性问题
RAGAS这类框架里的指标几乎全靠LLM打分,这就会带来两个问题:一是随机性,二是系统性偏差。实测中同一份数据、同一个模型,temperature设成0时结果也会有小幅波动,设成0.7时分数能差出好几个点。
我的处理方式是:把所有judge角色的temperature固定为0,每次跑完评估保留原始输出文件,做对比时用同一份测试集、同一组参数。不要让LLM的随机波动掩盖真实的优化效果。还要注意,换一个judge模型(比如从GPT-4o换成开源模型),绝对分数会发生整体偏移,所以团队内部要固定judge模型,不要换来换去。
4.2 测试集规模过小的统计陷阱
很多demo项目拿10条、20条数据跑评估,然后拿这个分数去汇报。这在统计上是站不住脚的:faithfulness这类指标每一条的波动都很大,20条样本的95%置信区间可能横跨正负10个百分点以上。
建议评估集至少30到50条,作为回归测试集至少要100条以上。合成生成的数据可以先垫底,但真实用户问题要定期补充进来。一个好的评估集应该持续维护,每次线上发现badcase就把它加入回归集,让评估集和真实分布对齐。
4.3 top-k与Rerank对指标影响非常大
top-k参数会显著影响检索侧指标。把top-k从3改成5,Hit Rate可能从0.6跳到0.8,但生成质量可能反而下降,因为上下文里塞了更多噪声。做对比实验时,除了你想验证的那个变量,其它参数全部要固定。
另外,单独评估Rerank模型时,Hit Rate几乎不会变,因为Rerank只是重新排序,并没有改变候选集合;它提升的是MRR、NDCG这类体现排位的指标,以及最终生成时的上下文质量。很多人在这一步搞混,觉得“加了Rerank为什么召回率没变”,这不是模型没效果,而是你用了错误的观察指标。
4.4 指标全部高分但用户不满意的落差
最让人疑惑的情况是:评估报告上所有指标都在0.8以上,真实用户却觉得答案没用。问题几乎总是出在评估集和真实查询分布不一致上面。你的测试集都是单跳、事实型问题,而真实用户提问往往是模糊的、多跳的、存在隐含约束的。合成生成的测试集更是容易出现“出题容易”的倾向。
对应办法是构建多维度的测试集:包含简单问题、多跳问题、否定问题、跨文档综合问题、甚至没有标准答案的问题类别,并按真实业务比例混合。评估分数只有在你认真维护数据集的前提下才有意义。
5. 落地到真实项目时,我的指标选择建议
5.1 按场景选指标
不同业务形态对RAG的诉求差异很大,指标组合也应该跟着场景走。我通常会给出这样一张选择表:
| 业务场景 | 检索侧推荐指标 | 生成侧推荐指标 | 选型理由 |
|---|---|---|---|
| 企业知识库问答 | Hit Rate@5 | Faithfulness + Answer Relevancy | 对答案依据要求高,优先防幻觉 |
| 复杂多跳问答 | MRR@10 + NDCG@10 | Context Relevancy + Answer Correctness | 排序质量和多片段融合是关键 |
| 客服FAQ | Hit Rate@3 | Answer Correctness | 问题模式固定,正确答案判定明确 |
| 法律/医疗可溯源 | Hit Rate@5 + Citation Accuracy | Faithfulness | 必须能指出答案出处,引用准确率大于一切 |
| 内容摘要/辅助写作 | NDCG@10 | Answer Relevancy + Faithfulness | 检索结果参考顺序和相关性更重要 |
这里面Citation Accuracy在RAGAS默认指标里没有一键封装,我在项目中是自己写了个LLM判断器:把答案里的每个陈述和对应引用片段拼接起来,让LLM判断引用是否真的支撑该陈述,再用支撑数量除以总陈述数得到准确率。这个自定义指标非常值得做。
5.2 建议的最小评估闭环
我实践下来,一个可落地的RAG评估闭环必须包含四件事:
- 测试集管理:把合成数据、人工标注数据、线上badcase兜进同一个数据集,每条样本打标签标明难度和类型。
- 定时评估机制:通过CI/CD在每次检索流程配置变更后自动跑一遍全量评估,输出指标趋势,而不是隔几周手动跑一次。
- 单条样本钻取:评估结果必须暴露到单条粒度,点击一条样本就能看到它的question、contexts、answer、ground_truth以及每个分数,这样才能定位问题来源。
- badcase回流:把线上不满足用户预期的case持续补充进测试集,让评估集和真实世界越走越近。
最后分享一点个人体会:指标不是用来摆设的,它要服务你下一次改动决策。我每次改完chunk size或者prompt,只看两个数,同一个评估集上的faithfulness和context_relevancy变化方向。这两个数如果能稳中向上,说明改动方向是对的。至于绝对数字,它只告诉你系统当前的下限,不会告诉你最优解在哪里。做RAG评估最难的不是会跑代码,而是愿意花时间把测试集养起来,然后眼睁睁看着badcase逼你去修那些之前一直想忽视的链路问题。
本文还有配套的精品资源,点击获取