RAG 系统评估指标实战:Faithfulness 与 Relevancy 详解 RAG 系统评估指标实战Faithfulness 与 Relevancy 详解WEB项目地址演示地址安卓APP下载地址演示地址你调了一周的 prompt改了三版分块策略换了两个 embedding 模型。用户问效果怎么样你只能回一句感觉比之前好了一点。这种感觉我太熟悉了。其实评估 RAG 没那么玄乎。这篇教程不讲论文里的复杂公式直接给你两把尺子——Faithfulness忠实度和 Relevancy相关性教你怎么量、怎么算、怎么用。跟住我们从零开始。一、评估核心概念先搞懂这两个指标到底在量什么用大白话解释别被英文术语吓住。Faithfulness忠实度看模型回答的内容是不是有据可查。你给 RAG 系统喂了一段参考材料它回答的内容能不能在材料里找到依据如果材料里只说了张三今天去了公司模型回答张三今天去了公司并吃了午饭那吃了午饭就是凭空捏造的——Faithfulness 要扣分。可以把它理解成事实核查员的角色。Relevancy相关性看检索回来的内容是不是答非所问。用户问李四的工资是多少系统从知识库里捞回来一堆王五的考勤记录相关吗不相关。Relevancy 要扣分。可以把它理解成图书管理员的角色——用户要借《三国演义》你搬来一摞《西游记》事情没办对。两者关系Relevancy 管找没找对Faithfulness 管说没说错。一个负责检索质量一个负责生成质量。两个都高系统才靠谱。二、本地评估环境搭建与依赖安装动手之前确认你的机器能跑起来。2.1 硬件要求评估比训练轻量得多。不需要 GPU纯 CPU 就能跑。内存有个 8GB 就够。如果你要用的评估模型是本地部署的比如用 Qwen 做评判那可能需要 6-8GB 显存。但新手阶段我强烈建议先用 API下面会说明。2.2 安装依赖新建一个目录安装必要的包mkdirrag-evalcdrag-eval pipinstallragas pandas python-dotenv openai解释一下这几个包ragas专门做 RAG 评估的框架Faithfulness 和 Relevancy 的计算函数已经封装好了pandas用来处理评估数据集python-dotenv管理 API Key 环境变量openaiRagas 默认用 OpenAI 模型做评判也可以用本地模型替换后面会讲2.3 选择评判模型Ragas 计算 Faithfulness 和 Relevancy 的方式是用一个裁判大模型来打分。这个裁判可以是OpenAI APIGPT-4o 或 GPT-4o-mini—— 省事效果稳定本地部署的开源模型Qwen、DeepSeek—— 数据不外传但要自己搭环境新手先用 OpenAI API 跑通流程# 创建 .env 文件echoOPENAI_API_KEY你的key.env如果不想用 OpenAI后面我会给替代方案。三、Faithfulness 指标计算代码实现动手写代码。先准备一份最简单的测试数据。Ragas 评估需要四样东西question用户的问题answerRAG 系统给出的回答contexts检索回来的参考材料列表形式可以有多个片段ground_truth可选标准答案有些指标需要3.1 输入数据结构示例fromdatasetsimportDataset data{question:[张三2023年的销售额是多少],answer:[根据数据张三2023年销售额为 128.5 万元。],contexts:[[张三2023年销售业绩全年销售额 128.5 万元达成率 107%。,2023年度销售排名张三位列第3名。]]}datasetDataset.from_dict(data)3.2 调用 Ragas 计算 Faithfulnessfromragasimportevaluatefromragas.metricsimportfaithfulness resultevaluate(datasetdataset,metrics[faithfulness],)print(result)输出大概是这样的{faithfulness: 0.95}分数范围 0 到 1。越接近 1说明回答越忠实于参考材料。3.3 Faithfulness 的扣分逻辑你可能好奇 0.95 是怎么算出来的。Ragas 内部做的是拆解 核对把 answer 拆成若干个陈述句claims逐一检查每个陈述句是否能在 contexts 里找到依据有依据的陈述比例就是 Faithfulness 得分比如这个回答“张三销售额为 128.5 万元达成率为 107%排名第3。”拆成三句“张三销售额为 128.5 万元” → ✅ 材料里有“达成率为 107%” → ✅ 材料里有“排名第3” → ✅ 材料里有3 分全得Faithfulness 1.0。但如果回答多了材料里没有的信息“张三销售额为 128.5 万元他是今年唯一超额的销售。”材料里根本没提唯一超额。两个 claims 里有一个没依据Faithfulness 0.5。3.4 不用 Ragas 手写一个简化版如果你想更深入理解原理或者不想引入 Ragas 这个依赖可以自己实现一个简化的 Faithfulness 评估importopenaidefsimple_faithfulness(question,answer,contexts):promptf 你是一个事实核查员。请判断以下回答中的每一句话是否能在给定的参考材料中找到依据。 参考材料{contexts}回答{answer}请输出格式 总句数X 有依据句数Y 得分Y/X responseopenai.ChatCompletion.create(modelgpt-4o-mini,messages[{role:user,content:prompt}])# 解析响应里的得分returnparse_score(response)但说实话Ragas 已经帮你把细节处理好了直接用更省事。四、Relevancy 指标量化方法与调用Relevancy 叫相关性但 Ragas 里它实际上叫Context Relevancy——专门评估检索回来的内容跟问题的相关程度。4.1 计算 Relevancy用法跟 Faithfulness 几乎一样fromragas.metricsimportcontext_relevancy resultevaluate(datasetdataset,metrics[context_relevancy],)print(result)# {context_relevancy: 0.88}4.2 Relevancy 的扣分逻辑Ragas 计算 Context Relevancy 的方式是把 contexts 里的每句话拆出来用大模型判断这句话对回答问题有没有帮助有帮助的比例 Relevancy 得分比如用户问“张三的销售额是多少”检索回来的 contexts 长这样张三2023年销售额为128.5万元。 # 这句话有用 张三入职日期为2020年3月。 # 这句话没用 公司2023年总营收为5.2亿元。 # 这句话也没用太宏观3 句话里只有 1 句有用Relevancy ≈ 0.33。关键区别Relevancy 不关心回答对不对只关心检索回来的材料里有用信息占多少。如果捞回来一堆废话但最后答对了Relevancy 分也不会高。4.3 Faithfulness Relevancy 一起跑实际评估时通常两个指标一起算fromragas.metricsimportfaithfulness,context_relevancy resultevaluate(datasetdataset,metrics[faithfulness,context_relevancy],)print(fFaithfulness:{result[faithfulness]:.2f})print(fContext Relevancy:{result[context_relevancy]:.2f})五、构建最小化测试数据集验证流程别急着把全部数据都扔进去。先造一个最小可验证集——包含 5 到 10 条典型问答就够了。5.1 构造三个典型样本样本1应该全高分 Q: 张三的销售额是多少 A: 张三2023年销售额为128.5万元。 C: [张三2023年销售额为128.5万元达成率107%] 预期Faithfulness高Relevancy高 样本2检索相关但回答偏离 Q: 张三的销售额是多少 A: 张三2023年销售额为128.5万元他是公司最优秀的员工。 C: [张三2023年销售额为128.5万元达成率107%] 预期Faithfulness低最优秀员工没依据Relevancy高 样本3检索不相关 Q: 张三的销售额是多少 A: 根据数据张三2023年销售额为128.5万元。 C: [公司2023年总营收5.2亿元, 李四销售额为95万元] 预期Faithfulness低材料里没张三的数据Relevancy低5.2 跑验证fromdatasetsimportDataset test_data{question:[张三的销售额是多少,张三的销售额是多少,张三的销售额是多少,],answer:[张三2023年销售额为128.5万元。,张三2023年销售额为128.5万元他是公司最优秀的员工。,根据数据张三2023年销售额为128.5万元。,],contexts:[[张三2023年销售额为128.5万元达成率107%],[张三2023年销售额为128.5万元达成率107%],[公司2023年总营收5.2亿元,李四销售额为95万元],]}datasetDataset.from_dict(test_data)resultevaluate(dataset,metrics[faithfulness,context_relevancy])print(result)5.3 看一眼输出验证你的预期跑完之后对照前面列的预期样本1两项都应该接近 1.0样本2Faithfulness 偏低Relevancy 偏高样本3两项都偏低如果不吻合检查你的数据格式——最常见的问题是 contexts 传成了字符串而不是列表。六、解读评估报告与分数含义分析拿到分数之后怎么看先说结论没有绝对的好分数只有相对的改进趋势。6.1 分数区间参考基于 Ragas 官方文档和社区实践的经验值分数范围Faithfulness 含义Relevancy 含义0.9 - 1.0回答基本没有捏造检索内容几乎句句有用0.7 - 0.9少量细节有偏差大部分检索内容有用混了少量噪声0.5 - 0.7回答里有不少材料外信息约一半检索内容跟问题无关 0.5严重幻觉不能信任检索系统基本失效6.2 常见组合分析高 Faithfulness 高 Relevancy理想状态系统运行良好。继续保持。高 Faithfulness 低 Relevancy检索捞回来一堆不相关的东西但生成模型很老实只在有限的材料里作答没瞎编。这种情况问题出在检索端——分块策略、embedding 模型、混合检索都可能需要调。低 Faithfulness 高 Relevancy检索找对了材料但生成模型不听话自己加了料。这种情况是生成端的 prompt 约束不够或者模型本身太发散。低 Faithfulness 低 Relevancy两头都出问题了。先别急着优化先检查数据流程——是不是文档压根没解析对是不是 embedding 模型选错了语言七、低分场景下的常见报错排查指南7.1 “Faithfulness 忽高忽低不稳定”可能原因评估用的裁判模型不稳定尤其是用 GPT-3.5 时。解决方案换成 GPT-4o-mini稳定性比 3.5 好很多增加评估样本数量至少 50 条以上取平均固定 temperature07.2 “Relevancy 永远上不了 0.8”可能原因你的检索系统确实不行。但也可能——你的 contexts 长度太长里面必然混了大量不直接相关的内容。排查方法把一条 contexts 手动切成小块看有没有哪一块跟问题直接相关。如果所有块都擦边说明检索没找准。如果有一块明确相关但被很多无关内容包围考虑用更精细的分块或重排序。7.3 “Ragas 报错OPENAI_API_KEY not set”忘了设环境变量。exportOPENAI_API_KEY你的key或者在代码里直接设置不推荐但调试时应急importos os.environ[OPENAI_API_KEY]你的key7.4 “评估跑得特别慢”如果测试集有几百条每一条都要调用大模型打分确实慢。加速方案用gpt-4o-mini替代gpt-4o速度翻倍便宜得多把数据集分批并行评估用 HuggingFace 的本地模型替代 API后面会讲7.5 “我想用本地模型替代 OpenAI”完全可行。Ragas 支持自定义 LLMfromragas.llmsimportllm_factory# 用本地部署的 Qwencustom_llmllm_factory(modelqwen2.5:7b,# 你本地部署的模型名base_urlhttp://localhost:11434/api/generate,# Ollama 地址)resultevaluate(datasetdataset,metrics[faithfulness,context_relevancy],llmcustom_llm)注意本地模型的质量会影响评估的准确性。建议先用 GPT-4o 跑一批基准数据再用本地模型对比——如果分数趋势一致说明可以用。八、提升忠实度与相关性的优化技巧分数看完了知道低了怎么改给几个立竿见影的操作。8.1 提升 Faithfulness忠实度的招数招数一在 prompt 里明确告诉模型不要瞎编prompt 你是一个严谨的助手。请只根据以下参考资料回答问题。 如果参考资料中没有答案请直接说参考资料中没有相关信息。 绝对不要编造任何信息。 这招治标但确实管用。实测 Faithfulness 能提升 5-10 个点。招数二限制回答长度越长的回答越容易产生幻觉。把答案控制在 3-5 句话以内Faithfulness 会自然上升。招数三如果用了温度参数调到 0.2 以下温度越高模型越有创意创造力的另一面就是编造。8.2 提升 Relevancy相关性的招数Relevancy 低本质是检索没做好。排查顺序第一步检查分块策略块是不是太长了超过 512 token 的长块里必然混入不相关内容块是不是没有语义完整性句子被拦腰切断第二步换 embedding 模型中文场景用 BGE 或 M3E别用英文模型硬撑混用模型对比一下效果常见的嵌入模型在本地的表现差异可能很明显第三步加一层重排序Rerank先向量检索召回 Top 20用 cross-encoder 模型重排取 Top 5加了 rerank 之后Relevancy 一般能涨 0.1-0.15。九、自动化评估脚本封装与复用每次都写重复代码太烦了。封装成一个脚本以后一键跑。9.1 完整脚本# eval_rag.pyimportosfromdatasetsimportDatasetfromragasimportevaluatefromragas.metricsimportfaithfulness,context_relevancyfromdotenvimportload_dotenv load_dotenv()classRAGEvaluator:def__init__(self,dataset_pathNone):self.dataset_pathdataset_path self.resultsNonedefload_data(self,questions,answers,contexts):加载评估数据data{question:questions,answer:answers,contexts:contexts,}self.datasetDataset.from_dict(data)returnselfdefrun(self):执行评估self.resultsevaluate(datasetself.dataset,metrics[faithfulness,context_relevancy],)returnself.resultsdefreport(self):打印报告ifself.resultsisNone:print(请先运行 run())returnprint(*50)print(RAG 评估报告)print(*50)print(f样本数量{len(self.dataset)})print(fFaithfulness{self.results[faithfulness]:.4f})print(fContext Relevancy{self.results[context_relevancy]:.4f})print(*50)# 使用示例if__name____main__:evaluatorRAGEvaluator()# 从 CSV 或数据库读取数据questions[张三的销售额是多少,...]answers[张三2023年销售额为128.5万元。,...]contexts[[...],...]evaluator.load_data(questions,answers,contexts)evaluator.run()evaluator.report()9.2 批量对比不同版本评估的真正用途是对比。改了一个参数之后跑一遍评估看分数有没有变化。# 版本 A原始版本eval_v1RAGEvaluator().load_data(...).run()# 改了一个参数比如分块大小从 512 改成 256eval_v2RAGEvaluator().load_data(...).run()print(fV1 Faithfulness:{eval_v1[faithfulness]:.3f})print(fV2 Faithfulness:{eval_v2[faithfulness]:.3f})print(f变化{eval_v2[faithfulness]-eval_v1[faithfulness]:.3f})十、从单点评估到持续监控的进阶路径跑一次评估只是起点。要让评估真正起作用需要把它变成日常流程的一部分。10.1 建立评估基线在你开始任何优化之前先跑一次完整的评估把分数记录下来。这就是基线。基线的作用是以后任何改动都要跟基线对比。分数涨了说明改动有效跌了说明方向不对。10.2 构建标准评估集准备一套固定的测试数据集100-200 条覆盖系统要处理的各种场景简单事实查询30%多步推理查询30%数值计算查询20%否定或边界查询20%这套数据不要变。每次评估都用同一套才能公平对比。10.3 持续集成CI接入如果你在团队里开发 RAG 系统可以把评估脚本接入 CI 流程每次 PR 提交自动跑一遍评估如果 Faithfulness 或 Relevancy 下降超过阈值PR 标记为需要审查10.4 数据飞轮从生产环境里采样真实用户的问题和反馈定期补充到评估集中。三个月后你会发现评估集越来越像真实流量评估结果也越来越有参考价值。快速上手指南如果你现在就想动手照着这几步走# 1. 安装pipinstallragas pandas python-dotenv openai# 2. 准备数据复制下面代码from datasetsimportDataset data{question:[张三的销售额是多少],answer:[张三2023年销售额为128.5万元。],contexts:[[张三2023年销售额为128.5万元达成率107%]]}datasetDataset.from_dict(data)# 3. 跑评估from ragasimportevaluate from ragas.metricsimportfaithfulness, context_relevancy resultevaluate(dataset,metrics[faithfulness, context_relevancy])print(result)搞定。从安装到出分数不超过 5 分钟。评估不是玄学是工程。把这两把尺子用起来以后再有人问效果怎么样你可以直接甩分数了。