RAG 评估体系——怎么知道你的 RAG 系统好不好
没有评估指标,RAG 优化就是盲改。这套评估体系帮我把准确率从 70% 推到 92%。
为什么 RAG 评估难
传统软件评估简单
输入 → 输出 → 对比预期,准确率一目了然。
RAG 评估复杂
RAG 系统的输出受多因素影响:
- 检索质量(召回了什么文档)
- LLM 能力(怎么生成答案)
- Prompt 设计(怎么拼上下文)
- 文档质量(原始数据好不好)
评估不能只看”最终答案对不对”——还要看”中间环节哪里出问题”。
RAG 评估的三个层面
层面 1:检索质量
判断检索召回的文档是否相关。
指标:
- Recall@K:Top-K 召回了多少相关文档
- Precision@K:Top-K 召回了多少”假相关”文档
- MRR(Mean Reciprocal Rank):第一个相关文档的排名倒数
层面 2:答案质量
判断最终生成的答案是否正确。
指标:
- Answer Relevance:答案是否切题
- Faithfulness:答案是否忠于检索内容(不胡编)
- Correctness:答案是否事实正确
层面 3:用户体验
判断真实用户使用感受。
指标:
- 满意度(用户反馈)
- 响应时间(延迟)
- 采用率(用户是否真的用)
评估数据集准备
1. 准备测试集
最重要的步骤——没有测试集,所有评估都是”感觉”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| test_questions = [ { "question": "公司的年假政策是什么?", "expected_answer": "员工每年享有 7 天年假...", "expected_doc_ids": ["policy_001", "policy_002"], "difficulty": "easy" }, { "question": "如何在系统中重置密码?", "expected_answer": "登录页面点击'忘记密码'...", "expected_doc_ids": ["faq_005"], "difficulty": "medium" }, ]
|
测试集要包含:
- 简单问题(直接答案)
- 中等问题(需要推理)
- 难题(检索不到)
- 刁钻问题(超出知识库范围)
2. 测试集来源
| 来源 |
优点 |
缺点 |
| 真实用户问题 |
真实场景 |
需要积累 |
| 人工标注 |
质量高 |
费时费力 |
| LLM 生成 |
快 |
质量参差 |
| 公开数据集 |
标准 |
不一定适合 |
建议:真实问题为主 + LLM 补充 + 人工 review。
评估指标详解
1. 检索质量指标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| def recall_at_k(retrieved_ids, expected_ids, k=10): """Top-K 召回率""" retrieved_top_k = set(retrieved_ids[:k]) expected = set(expected_ids) if not expected: return 0 return len(retrieved_top_k & expected) / len(expected)
def precision_at_k(retrieved_ids, expected_ids, k=10): """Top-K 准确率""" retrieved_top_k = set(retrieved_ids[:k]) if not retrieved_top_k: return 0 expected = set(expected_ids) return len(retrieved_top_k & expected) / len(retrieved_top_k)
def mrr(retrieved_ids, expected_ids): """第一个相关文档的排名倒数""" for i, doc_id in enumerate(retrieved_ids): if doc_id in expected_ids: return 1 / (i + 1) return 0
|
2. 答案质量指标(用 LLM 评估)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| EVAL_PROMPT = """ 你是评估员,判断 AI 回答的质量。
问题: {question} AI 回答: {answer} 标准答案: {expected}
从三个维度评分(1-5):
1. Answer Relevance(答案相关性): 1: 完全答非所问 5: 完美回答问题
2. Faithfulness(忠实度): 1: AI 编造了内容 5: 完全基于检索内容
3. Correctness(正确性): 1: 答案错误 5: 与标准答案一致
输出 JSON:{{"relevance": 5, "faithfulness": 4, "correctness": 5, "reason": "..."}} """
def evaluate_with_llm(question, answer, expected, llm): prompt = EVAL_PROMPT.format( question=question, answer=answer, expected=expected ) response = llm(prompt) return json.loads(response)
|
3. 综合评分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| def rag_evaluate(test_set, rag_system, llm): results = [] for item in test_set: retrieved = rag_system.retrieve(item["question"]) answer = rag_system.generate(item["question"], retrieved) recall = recall_at_k(retrieved, item["expected_doc_ids"]) scores = evaluate_with_llm(item["question"], answer, item["expected_answer"], llm) results.append({ "recall": recall, "relevance": scores["relevance"], "faithfulness": scores["faithfulness"], "correctness": scores["correctness"] }) avg = { "recall": mean([r["recall"] for r in results]), "relevance": mean([r["relevance"] for r in results]), "faithfulness": mean([r["faithfulness"] for r in results]), "correctness": mean([r["correctness"] for r in results]) } return avg
|
RAGAS 框架(推荐)
RAGAS 是专门评估 RAG 系统的开源框架——免去自己写评估代码。
安装
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| from ragas import evaluate from ragas.metrics import ( context_relevancy, faithfulness, answer_relevancy, answer_correctness )
data = { "question": [...], "contexts": [...], "answer": [...], "ground_truth": [...] }
result = evaluate(data, metrics=[ context_relevancy, faithfulness, answer_relevancy, answer_correctness ])
print(result)
|
输出:
1 2 3 4
| context_relevancy: 0.85 faithfulness: 0.92 answer_relevancy: 0.88 answer_correctness: 0.79
|
一目了然——哪个环节出问题、问题多大。
我的 RAG 评估体系
我用了 6 个月时间搭建的体系——
工具栈
| 工具 |
用途 |
| RAGAS |
自动评估指标 |
| LangSmith |
调用追踪 |
| Phoenix(arize) |
调试可视化 |
| 自建 dashboard |
趋势监控 |
评估流程
日常(每次发版):
1 2 3 4 5 6 7 8
| python eval/run_eval.py --test tests/v2.json
python eval/compare.py current.json baseline.json
python eval/failure_analysis.py
|
每周:
评估看板
我搭了一个 Grafana 看板,监控:
- 整体 Recall / Precision
- 按类别拆分(技术问题 / 账单问题 / …)
- 按难度拆分(简单 / 中等 / 难)
- LLM 调用 Token 成本
- 响应延迟 P50 / P99
任何一项恶化,立即报警。
几个核心经验
1. 测试集要”够刁”
简单问题谁都能做对——测试集要包含真正难的问题:
- 多跳推理(“X 和 Y 的关系是什么?”)
- 跨文档(“对比 A 和 B 的差异”)
- 边界情况(“文档里没说怎么办”)
2. 评估指标要分层
不要只看一个数字——
1 2 3 4 5 6
| 总平均: 0.85 ← 这个数字没用 ├── 检索质量: 0.92 ← OK ├── 答案质量: 0.78 ← 这里有问题! │ ├── 简单问题: 0.95 │ ├── 中等问题: 0.80 │ └── 难题: 0.45 ← 难题特别差
|
分层才能定位问题。
3. 失败案例比成功案例重要
10 个失败案例 > 100 个成功案例——失败案例告诉你哪里要改。
1 2 3 4
| for result in eval_results: if result["correctness"] < 3: save_to_failure_db(result)
|
每周 review 失败 case,找到共性,批量优化。
4. 防止”过拟合到测试集”
测试集也不能一成不变——
- 季度更新一次(加新问题)
- 加”对抗样本”(故意刁难)
- 留 20% 测试集永远不参与训练/优化
5. 用户反馈是黄金数据
真实用户反馈 > 任何评估指标——
1 2 3 4 5
| for conversation in user_conversations: if conversation.user_feedback: add_to_test_set(conversation)
|
3 个月后,测试集会非常接近真实场景。
实战优化案例
我用评估体系,把一个 RAG 系统从 70% 推到 92%:
阶段 1:Baseline 评估
1 2 3
| Recall@10: 0.65 Faithfulness: 0.85 Correctness: 0.70
|
阶段 2:定位问题
分析失败 case 发现:
- 检索召回率低(Recall 0.65)
- 答案冗长、爱”扩展”(Faithfulness 高但 Correctness 低)
阶段 3:针对性优化
| 优化 |
提升 |
| Embedding 模型升级(BGE-large) |
Recall +15% |
| Hybrid 检索(BM25 + 向量) |
Recall +8% |
| Query 改写 |
Recall +5% |
| 限制 LLM 输出长度 |
Correctness +7% |
| 强化 Prompt(要求简洁) |
Correctness +5% |
阶段 4:重新评估
1 2 3
| Recall@10: 0.93 Faithfulness: 0.91 Correctness: 0.92
|
准确率从 70% → 92%——所有优化都基于评估数据。
写在最后
RAG 评估不是”做一次就完”——是持续迭代。
我的建议:
- 第一周:搭评估体系(RAGAS + 自建)
- 第二周:准备测试集(200+ 条)
- 第三周:跑 baseline
- 之后:每次优化前先评估,优化后再评估
没有评估的 RAG 优化,都是在”赌”。
RAG 工程的本质,是”用数据驱动优化”——评估体系就是数据来源。