搭完一个 RAG,最危险的判断是"看起来回答得挺对"。一旦把它当结论上线,出问题的永远是那几个没测到的 case:检索召回漏了关键条款、生成时把模型自己的知识混进答案、回答跑题却自洽。RAG 和普通 LLM 应用不同,它是一条管道(检索 → 生成),坏在哪一段必须分开测,否则你连该调 chunk size 还是改 prompt 都不知道。这篇 SOP 走一遍用 Ragas、TruLens、DeepEval 三个主流框架量化 RAG 质量的全流程:先拆出三层质量维度,再准备评估集,然后逐层给可复制代码,最后附踩坑和 FAQ。和本站《用 Dify 搭企业知识库 RAG 实操 SOP》不同,那篇讲怎么"搭",这篇讲怎么"评"——评估是搭建之后、上线之前不可跳过的一环。
一、三层质量:先把"好坏"拆成可测的维度
RAG 的好坏不是一个分数,是三个维度的组合,分别对应管道的不同环节:
| 维度 | 测什么 | 对应管道环节 | 主流指标 |
|---|---|---|---|
| 检索质量 | 召回的上下文是否相关、是否全 | 检索器 / 向量库 | context precision、context recall |
| 生成忠实度 | 答案是否都来自检索到的上下文、有没有幻觉 | 生成器 prompt / LLM | faithfulness(TruLens 叫 groundedness) |
| 答案相关性 | 答案是否回应了问题、对不对 | 生成器 | answer relevancy、answer correctness |
记住一句话:检索质量决定上限,生成忠实度决定下限,答案相关性决定用户体验。 三层得分都高,RAG 才算稳。只看其中一个会误判——比如 faithfulness 满分但 context recall 是 0(该召回的没召回),说明模型在"对着残缺上下文一本正经地编",下限有了但答非所问。
三个框架的指标名对照(语义一一对应,字段名不同):
| 维度 | Ragas | DeepEval | TruLens |
|---|---|---|---|
| 检索相关性 | context_precision | ContextualPrecisionMetric | Context Relevance |
| 检索召回 | context_recall | ContextualRecallMetric | 归入 Context Relevance |
| 生成忠实度 | faithfulness | FaithfulnessMetric | Groundedness |
| 答案相关性 | answer_relevancy | AnswerRelevancyMetric | Answer Relevance |
| 答案正确性 | answer_correctness | AnswerCorrectnessMetric | 需自定义 feedback |
二、准备评估集:没有 ground_truth 就只能评一半
这是最容易被跳过的一步,也是踩坑最多的地方。评估质量的上限由评估集决定,不是由框架决定。一个最小的评估样本长这样:
eval_samples = [
{
"question": "公司年假按多少天计算?", # 用户问题
"ground_truth": "工龄满1年10天,满10年15天。", # 人工标注的标准答案
"contexts": ["...检索到的片段1...", "...片段2..."], # 实际召回的上下文
"answer": "根据规定,年假为10天。", # RAG 系统实际给出的答案
},
# 建议 50-100 条,覆盖事实型 / 对比型 / 多跳推理 / 拒答型问题
]四个字段决定了你能算哪些指标:
- 有
question+answer+contexts:能算 faithfulness、answer_relevancy、context_precision。 - 再加
ground_truth:才能算 context_recall、answer_correctness。
这意味着:如果不标注 ground_truth,你永远测不到"检索是否漏召回"和"答案是否正确"——而这恰恰是 RAG 最容易翻车的地方。很多团队图省事只喂 question/answer/contexts,跑出来的 faithfulness 和 answer_relevancy 都挺高,就以为 RAG 没问题,上线后用户一问就发现检索漏了关键文档。评估集宁可小而精(50 条人工标注),不要大而糙(1000 条自动生成无标注)。
三、检索质量:context precision / recall 怎么读
检索是 RAG 的地基。检索质量分两个方向:召回了多少该召的(recall),召回来的排得对不对(precision)。
context_precision(Ragas)/ ContextualPrecisionMetric(DeepEval):衡量相关片段是否排在前面。理想情况是相关 chunk 排在 top-1、top-2;如果相关 chunk 排在第 8 位,precision 就低。它需要 ground_truth 来判断哪些片段算"相关"。
context_recall:衡量标准答案里的信息是否都被检索到了。把 ground_truth 拆成一句句声明,逐句检查它们能否在 contexts 里找到对应。recall 低,说明检索漏了。
下面是 Ragas 一次性算全部核心指标的代码:
# pip install ragas langchain-openai
from ragas import evaluate
from ragas.metrics import (
context_precision, context_recall,
faithfulness, answer_relevancy,
)
from datasets import Dataset
dataset = Dataset.from_list(eval_samples) # 上一节那份
result = evaluate(
dataset,
metrics=[context_precision, context_recall, faithfulness, answer_relevancy],
)
print(result) # 各指标平均分
print(result.to_pandas()) # 逐条样本的得分,找 bad case读分时别只看平均分。context_precision 平均 0.85 看着不错,但翻 to_pandas() 找出得分低于 0.5 的样本,那才是真正要优化的检索 case——往往是某个专有名词没被 embedding 命中,需要换 embedding 模型或加关键词检索补召回。
四、生成忠实度:faithfulness 怎么测
忠实度衡量"答案有没有幻觉"。Ragas 的 faithfulness 做法是:先把答案拆成一句句可验证的声明(claim),再逐句检查每条声明能否被检索到的上下文支持。全部支持得 1,有一条不被支持就扣分。它不需要 ground_truth——这正是它最有用的地方:即使没有标准答案,也能测出"答案是不是在上下文基础上编的"。
TruLens 把同一个维度叫 groundedness(接地度),是它"RAG triad"三件套之一:
# pip install trulens trulens-provider-openai
from trulens.core import Tru
from trulens.core import Feedback
from trulens.providers.openai import OpenAI
provider = OpenAI() # 评估器 LLM
groundedness = Feedback(provider.groundedness_measure) # 答案是否被上下文支持
context_rel = Feedback(provider.qs_relevance) # 上下文是否与问题相关
answer_rel = Feedback(provider.qs_relevance) # 答案是否切题(换输入端)
# 用 .on(...).on_output() 把 feedback 绑到 app 的输入/输出/检索上下文,
# 给你的 RAG app 包一层 Tru 记录,跑评估集即自动算三件套
tru = Tru()
tru.run(app=your_rag_app)如果暂时不想引入框架,最小可用的是一个手动 LLM-as-judge 的 prompt 模板,专门评忠实度,逻辑和 Ragas faithfulness 内部一致:
你是一个严格的 RAG 评估器。下面给出一组检索到的上下文(CONTEXT)和系统生成的答案(ANSWER)。
请把 ANSWER 拆成一条条可验证的事实声明,再逐条判断它能否被 CONTEXT 支持。
规则:
1. 只能依据 CONTEXT 判定,不得使用自身知识。
2. 每条声明输出 supported / not_supported / unverifiable。
3. 存在 not_supported 的声明,说明模型在编造,faithfulness 低。
4. 最终给出 faithfulness = supported 声明数 / 总声明数(0-1 分)。
CONTEXT: {retrieved_contexts}
ANSWER: {answer}faithfulness 低通常不是检索的锅,是生成环节出了问题:要么 system prompt 没限制"只能基于上下文回答",模型把自身知识混进来了;要么塞了太多无关上下文,模型被噪声带跑开始编。修法是回去收紧生成 prompt,而不是调检索。
五、答案相关性:answer relevancy / correctness
answer_relevancy:衡量答案是否切题。做法是反向从答案生成几个"可能的问题",再算这些问题和原问题的相似度。答案跑题(问 A 答 B)得分就低。不需要 ground_truth。
answer_correctness:把答案和 ground_truth 逐条比对,需要标注的标准答案。这是最严格的指标,能抓出"答得流畅但数字错了"的 case。
DeepEval 用法(和 Ragas 思路一致,字段名不同):
# pip install deepeval
from deepeval import evaluate
from deepeval.metrics import (
FaithfulnessMetric, AnswerRelevancyMetric,
ContextualPrecisionMetric, ContextualRecallMetric,
)
from deepeval.test_case import LLMTestCase
case = LLMTestCase(
input="公司年假按多少天计算?", # = question
actual_output="根据规定,年假为10天。", # = answer
retrieval_context=["...片段1...", "...片段2..."], # = contexts
expected_output="工龄满1年10天,满10年15天。", # = ground_truth(可选)
)
metrics = [
FaithfulnessMetric(),
AnswerRelevancyMetric(),
ContextualPrecisionMetric(),
ContextualRecallMetric(),
]
evaluate([case], metrics) # 生成报告,bad case 会标出失败原因DeepEval 的字段映射记一下:input=问题、actual_output=答案、retrieval_context=上下文、expected_output=标准答案。和 Ragas 字段名不同,但语义一一对应,迁移时照着这张表换字段即可。
六、踩坑记录
坑一:不标 ground_truth 还想算 context_recall。 context_recall 和 answer_correctness 都依赖标准答案,没标注只能评 faithfulness、answer_relevancy、context_precision 的部分。评估集宁少勿假,先标 50 条真样本。
坑二:用同一个 LLM 既当生成器又当评估器。 self-rewarding bias——模型评自己出的答案会系统性打高分。评估器 LLM 最好换一个更强或不同厂商的模型(生成用 GPT-4o-mini,评估用 GPT-4o 或 Claude)。
坑三:评估样本太少就下结论。 10 条样本跑出平均分 0.9 没有统计意义,一两条 bad case 就能把均值拉偏。至少 50 条,且要覆盖事实型、对比型、多跳推理、拒答型等不同问法。
坑四:只看平均分不看 bad case。 平均 0.85 可能掩盖了 3 条 0 分的高危 case。一定导出逐条结果,按分数升序排,重点看最差的 10%——那些才是上线后会咬人的。
坑五:context_recall 高但 faithfulness 低,去调检索。 方向错了。检索已经召回了正确文档(recall 高),是生成时没用上或跑偏了(faithfulness 低)。该收紧生成 prompt,不是改 chunk。
坑六:用英文 judge 模型评中文答案。 评估器对中文答案的 claim 拆解和判定系统性偏差,faithfulness 偏低、answer_relevancy 噪声大。中文场景评估器优先选支持中文强的模型或专门调过中文的,别图省事套默认英文配置。
FAQ
Q1:Ragas、TruLens、DeepEval 三个怎么选?
场景优先级不同:Ragas 指标最全、文档最厚,适合做离线批量评估和回归测试;TruLens 强在"RAG triad"三件套和实时 dashboard,适合给线上 app 做持续监控;DeepEval 接口最像 pytest,能直接 assert_test、在 CI 跑测试,适合工程化集成进流水线。一句话:离线评估选 Ragas,持续监控选 TruLens,CI 集成选 DeepEval。
Q2:评估一定要标注 ground_truth 吗?没有标注能评什么? 不标也能评,但只能评一半。没 ground_truth 时仍能算 faithfulness、answer_relevancy、context_precision,测的是"有没有幻觉、答没答跑题、相关片段排没排前"。但测不了 context_recall(是否漏召回)和 answer_correctness(答得对不对)。这两项恰恰是 RAG 翻车重灾区,强烈建议至少标 50 条。
Q3:评估器 LLM 用哪个?能用本地模型吗? 三个框架都支持换评估器 LLM:Ragas 通过 LangChain 封装接入任意 LLM;TruLens 有 provider 抽象;DeepEval 同理。能用本地模型,但注意评估器要足够强——拿 7B 小模型当 judge 评 70B 模型的答案,判不准。成本敏感时用本地或便宜模型做粗筛,拿不准的 bad case 再用强模型复核。
Q4:每次评估花多少 API 费?怎么省? Ragas 跑 100 条样本 × 4 指标,用 GPT-4o 大约在几美元量级,主要花在 faithfulness 的 claim 拆解和逐条验证上。省钱三招:先小样本(20 条)跑通调参再全量;用更便宜的评估模型(GPT-4o-mini)先筛 bad case;只对低分样本用强模型复核。Ragas / DeepEval 都支持缓存评估结果避免重复算。
Q5:线上 RAG 怎么持续监控,不只上线前评一次? 上线前评一次只能证明"那一刻行",文档和问法都在变。持续监控用 TruLens:给线上 app 包一层记录,每次真实问答自动算 triad 三件套写进 dashboard,分数掉下来自动告警。Ragas / DeepEval 更适合做成定时回归任务——文档更新后自动重跑评估集,对比分数是否退化。
参考来源