RAG 评估体系
提出问题
RAG(检索增强生成)是目前最广泛落地的 LLM 应用架构之一,但一个常见迷思是:上线后看用户反馈就够了,为什么要专门做评估?实际上,RAG 系统的质量痛点非常隐蔽——检索返回了 10 篇文档,LLM 只用了其中 1 篇,剩下 9 篇被忽略,但 LLM 自己编了一段"看起来合理"的回答。这种幻觉在日志里几乎无法被自动化检测,只能靠人工逐步排查。更棘手的是,检索质量下降和生成质量下降的症状可能相同(都是回答变差),但根因完全不同,修复方向也截然相反。因此,RAG 评估的核心价值在于:把检索和生成的质量拆开度量,让问题定位从"感觉不对"变成"具体哪项指标掉分了"。
真实场景:一个典型的 RAG 质量事故
某知识库问答系统上线后,用户反馈"回答越来越不准确"。运维团队的第一反应是"LLM 模型不行了",准备换模型。但实际排查后发现:检索召回率从 0.85 掉到了 0.62,原因是 Embedding 服务在上周灰度发布时换了版本,新版本的向量分布没对齐,导致相关文档排到了 Top-10 末尾。LLM 侧没有做任何修改,但检索到的信息变少了,LLM 被迫用更少的信息来回答,自然就开始编造。
如果当时有 RAG 评估体系,会看到 Context Recall 指标从 0.85 跌到 0.62,而 Faithfulness 可能反而还正常(因为 LLM 确实基于检索到的内容回答了,只是检索到的内容不够)。定位就直接指向检索层,而不是 LLM 层。
分析问题
检索层评估:命中率、精确率与上下文召回
检索层的核心指标衡量的是"系统有没有把正确答案找回来"。常见的评估维度包括:
- Context Precision(上下文精确率):检索结果中,真正有用的文档占所有检索结果的比例。高精确率意味着检索结果噪声少,LLM 不容易被无关信息干扰。
- Context Recall(上下文召回率):正确答案中有多少被检索结果覆盖了。高召回率意味着关键信息没有漏掉。
- Hit Rate(命中率):Top-K 结果中是否包含正确答案,典型的二元指标。
在实践中,高精确率 + 低召回率通常意味着检索策略过于保守(只返回最相关的 1-2 条),而低精确率 + 高召回率则意味着检索粒度太宽或 Embedding 区分度不够。两者需要根据业务场景平衡——问答类场景更看重精确率避免干扰,而摘要类场景更看重召回率确保信息完整。
检索指标对比
| 指标 | 计算公式 | 典型值 | 影响链 |
|---|---|---|---|
| Context Precision | 有用文档数 / 检索文档总数 | 0.7-0.9 | 低 → LLM 被噪声干扰,编造可能性↑ |
| Context Recall | 被覆盖的有用信息 / 全部有用信息 | 0.6-0.85 | 低 → LLM 信息不足,答案不完整 |
| MRR(Mean Reciprocal Rank) | 第一个正确答案的倒数排名均值 | 0.5-0.9 | 低 → 正确答案在末尾,Reranker 不行 |
| NDCG | 带位置权重的排序质量 | 0.6-0.9 | 综合排序质量,受 Reranker 影响 |
生成层评估:忠实度、相关性与答案完整性
生成层评估关注的是"LLM 有没有用好检索结果":
- Faithfulness(忠实度):答案是否基于检索到的文档,而不是模型凭空编造。这是 RAG 最关键的指标,也是 RAG 区别于纯 LLM 的核心价值。
- Answer Relevance(答案相关性):回答是否针对用户问题,而不是答非所问或泛泛而谈。
- Answer Correctness(答案正确性):答案与标准答案的匹配程度,需要 ground truth 支持。
其中忠实度的评估方法比较成熟:将答案拆解为原子声明(Claim),然后逐一验证每个声明是否能从检索到的文档中推导出来。如果某个声明没有任何文档支撑,则判定为幻觉。可以用 LLM-as-Judge 自动执行这个过程,也可以用人工标注做更精确的评估。
Faithfulness 的 Fine-grained 判定流程
输入:用户问题 Q + 检索文档集合 D + LLM 回答 A
↓
步骤 1:将 A 拆解为原子声明
A → {claim₁, claim₂, ..., claimₙ}
↓
步骤 2:对每个 claim_i,在 D 中检索证据
↓
步骤 3:LLM 判断 claim_i 是否可从 D 中推导
↓
├── 全部可推导 → Faithfulness = 1.0
├── 部分可推导 → Faithfulness = 可推导数 / 总数
└── 全部不可推导 → Faithfulness = 0.0踩坑记录:拆解粒度决定了 Faithfulness 分数的稳定性。按句子拆(粗粒度)时,一个句子包含 3 个事实,其中 1 个是幻觉,但整句判定为"可信"会漏掉问题。按短语拆(细粒度)时,评估结果敏感但成本高,且评判模型容易把"可推导"的边界判断错误。推荐的折中方案:按逗号/分号分隔的独立子句拆,每个子句包含一个完整的事实。
二阶段评估流程:从指标到行动
RAG 评估不能只看分数,要看分数变化后的根因排查。我整理了一个二阶段排查流程:
阶段一:指标监控(自动触发告警)
Context Recall 震荡 → 检索引擎/Embedding 问题
Faithfulness 震荡 → LLM 或 Prompt 问题
Answer Relevance 持续偏低 → Prompt 模板或 Reranker 排序问题
阶段二:根因分析(人工介入)
↓ Context Recall 低
├── 检查 Embedding 版本是否变更
├── 检查索引库是否新增了脏数据
└── 检查分块策略是否合理(块大小、重叠度)
↓ Faithfulness 低
├── 检查 LLM 的 system prompt 是否要求"只基于检索内容回答"
├── 检查检索到的上下文是否被截断(超 Token 限制)
└── 检查 Reranker 是否把无关文档排到了前面RAGAS 框架与 LLM-as-Judge
RAGAS 是目前最流行的开源 RAG 评估框架,它把上述指标系统化,核心思路是 端到端评估,无需人工标注。
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
from datasets import Dataset
# 构造评测数据:question + answer + contexts + ground_truth
data = {
"question": ["RAG 评估为什么要分开衡量检索和生成?"],
"answer": [
"因为检索质量下降和生成质量下降的症状可能相同,"
"但根因不同,分开衡量才能精确定位问题。"
],
"contexts": [[
"RAG 评估的核心价值在于把检索和生成的质量拆开度量。"
"检索质量下降和生成质量下降的症状可能相同(都是回答变差),"
"但根因完全不同,修复方向也截然相反。"
]],
"ground_truth": ["检索和生成的质量需要分开度量,便于定位问题根因。"]
}
dataset = Dataset.from_dict(data)
result = evaluate(dataset, metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
])
print(result)
# {'faithfulness': 0.95, 'answer_relevancy': 0.88, ...}RAGAS 的底层依赖 LLM-as-Judge,即用另一个 LLM 打分。这也意味着评估结果受评判模型的能力影响——如果评判模型本身也分不清忠实度的边界,评估结果就会失真。
LLM-as-Judge 的选型踩坑
实测不同评判模型对 Faithfulness 评分的影响(某企业内部知识库场景,100 条测试集):
| 评判模型 | Faithfulness 均值 | 人工一致率 | 单条评估耗时 |
|---|---|---|---|
| GPT-4o | 0.87 | 92% | 3.2s |
| GPT-4o-mini | 0.84 | 84% | 1.1s |
| Claude-3.5-Sonnet | 0.88 | 90% | 2.8s |
| 本地 7B 模型 | 0.78 | 65% | 8.5s |
8 年 Java 后端转型的面试官可能会问:"你们用 RAGAS 评估,结果可靠吗?" 回答要点:RAGAS 的 Faithfulness 分数是相对值,不是绝对值——同一个模型、同一个评测集,跑 A/B 版本看分数变化方向,比看绝对值更有意义。绝对值的意义取决于评判模型和人工标注的一致性。
组件级评估与评测集构建
除了 RAGAS 的端到端评估,组件级评估同样重要:
- Embedding 评估:对检索结果做 Recall@K / MRR 评估,看 Embedding 模型在领域数据上的检索质量。
- Reranker 评估:看 Reranker 是否能将正确答案排到更靠前的位置。
- LLM 生成评估:单独看 LLM 在给定上下文下的生成质量,排除检索的影响。
评测集的构建方法也有讲究:
| 方法 | 做法 | 适用场景 | 成本 | 覆盖率 |
|---|---|---|---|---|
| 人工标注 | 专家标注 question + ground_truth | 精确度要求高的场景 | 高 | 低 |
| 合成数据 | 用大模型生成 QA 对 | 冷启动、快速迭代 | 低 | 中 |
| 用户反馈回流 | 从日志中提取用户不满意的问答 | 生产环境持续监控 | 中 | 高 |
| 黄金文档 | 从已有文档按段落生成对应问题 | 知识库类 RAG 系统 | 低 | 中 |
评测集维护的常见坑
- 测试集与训练集同分布:如果用 LLM 生成用于训练的文档,又用同一批 LLM 生成测试 QA,评测结果会虚高。至少切换模型或 Prompt 模板来生成测试集。
- 测试集过时:知识库每周更新,但测试集还是三个月前的版本。新的高频问题没有被覆盖。
- 只有一个正确答案:很多问题可能有多个正确答案路径,测试集只覆盖了其中一条,导致 LLM 换了一种正确说法但被判定为错误。建议对开放式问题允许多个 ground truth。
生产环境持续评估的架构设计
RAG 评估不应该只在离线做,线上同样需要持续监控。推荐一种生产级架构:
用户请求 → API Gateway → RAG Pipeline → 响应
↓
监控 Agent(异步)
├── 周期性采样用户请求
├── 调用 LLM-as-Judge 打分
├── 写入指标存储(Prometheus/InfluxDB)
└── 指标阈值告警 → 值班群通知关键设计点:
- 采样率:全量评估成本太高,5% 采样 + 阈值告警触发时补全量聚合。
- 延迟容忍:评估是异步的,不阻塞线上响应。
- 指标存储:至少保留 7 天粒度,方便回溯版本发布前后的指标变化。
总结
RAG 评估的核心是分离检索质量与生成质量,否则根因定位就是瞎猜。RAGAS 提供了 Faithfulness/Context Precision/Context Recall 等成熟指标,配合 LLM-as-Judge 可以自动化端到端评估。但自动化评估不等于完美——评判模型的质量、评测集的覆盖度、指标阈值的设定,都需要根据业务场景调优。上线后建议用用户反馈做长尾兜底,因为再好的指标也无法覆盖所有用户预期。
最后给 Java 后端转型的同学一个面试建议:面试官问你 RAG 评估,不要只说 RAGAS 有哪些指标。要说清楚指标之间的关联——比如 Context Recall 下降会导致 Faithfulness 跟着下降(因为 LLM 信息不足),但反过来不一定成立。能讲清楚这个因果关系,说明你真正理解 RAG 的评估体系。