RAG 三元组评估
课程简介
上下文相关性、答案真实性、回答相关性三维度评估 RAG 质量。
🎬 本课程视频:Advanced RAG — 构建与评估高级 RAG 应用
RAG 三元组评估:系统化衡量 RAG 质量
一、为什么需要系统化的 RAG 评估?
RAG 系统的质量评估比传统软件评估更复杂。传统软件的输出是确定性的——输入相同,输出就相同。但 RAG 系统涉及检索和生成两个既有耦合又有不确定性的环节。一个小小的检索偏差可以导致生成的答案完全偏离事实。一个看似完美的回答可能只是模型在「背诵」自己的训练知识,而非真正基于检索到的文档。
系统化的评估体系能够帮助我们:
1. 定位问题环节:当输出质量不佳时,判断是检索环节的问题还是生成环节的问题
2. 量化优化效果:每次修改提示词、检索策略或文档库后,客观衡量效果是变好还是变差了
3. 建立质量标准:为生产环境设定质量门槛,低于阈值的回答进行人工审核或自动拦截
二、RAG 三元组评估框架
RAG 三元组(RAG Triad)是 TruLens 等工具推广的行业标准评估框架,从三个维度系统性地衡量 RAG 输出质量:
- 上下文相关性(Context Relevance):检索到的文档片段是否与用户问题相关
- 答案忠实性(Answer Faithfulness):LLM 的回答是否严格基于检索到的上下文
- 答案相关性(Answer Relevance):最终回答是否切实解决了用户的问题
2.1 三元组的层次关系
这三个维度不是平行的,而是有层次关系的:
用户问题
↓
检索阶段 → 上下文相关性(检索质量)
↓
生成阶段 → 答案忠实性(是否基于事实)
↓
交付阶段 → 答案相关性(是否解决问题)
上游的问题会传导到下游:上下文相关性差必然导致答案忠实性差,但上下文相关不保证答案忠实。
三、上下文相关性评估
3.1 定义与重要性
上下文相关性评估检索阶段的质量。问题是:检索系统返回的文档片段是否与用户查询紧密相关?如果返回了大量不相关的上下文,即使 LLM 的生成能力再好,也无法给出正确的回答。
3.2 评估方法
人工评估:让评估者阅读查询和检索结果,按照 1-5 分打分。
LLM 自动评估:使用专门的评估模型或评估提示词:
def evaluate_context_relevance(query, retrieved_contexts):
'''
使用 LLM 评估检索到的上下文与查询的相关性
'''
evaluation_prompt = f'''
你是一个 RAG 检索质量评估专家。请评估以下检索到的文档片段是否与用户查询相关。
用户查询:{query}
检索到的文档片段:
{retrieved_contexts}
请按以下维度评估(每项 1-5 分):
1. 直接相关性:文档片段是否直接回答了查询中的问题?
2. 信息充足度:文档片段是否提供了回答该问题所需的足够信息?
3. 冗余度:文档片段中有多少内容与查询无关?
最后给出总体评分(1-5)和说明。
'''
evaluation = evaluate_llm.generate(evaluation_prompt)
return parse_evaluation(evaluation)
3.3 关键问题
- 相关但无用:内容相关但过于宽泛,无法用于生成具体答案
- 部分相关:多个文档片段各自只与问题的一部分相关,需要拼接
- 假阳性:关键词匹配但语义不相关
四、答案忠实性评估
4.1 定义与重要性
答案忠实性是 RAG 评估中最核心的指标。它衡量的是:LLM 的每个陈述是否都能在检索到的上下文中找到事实依据。
忠实性差的典型表现就是幻觉——模型添加了上下文中不存在的信息。
4.2 评估方法
声明分解法(Claim Decomposition):
def evaluate_faithfulness(response, context):
'''
评估回答对上下文的忠实性
'''
# 1. 将回答分解为独立的声明(事实性陈述)
decomposition_prompt = f'''
将以下回答分解为独立的声明(每个声明是一个事实性陈述):
回答:{response}
返回 JSON 格式的声明列表。
'''
claims = extract_claims(decomposition_prompt, response)
# 2. 逐一验证每个声明
faithfulness_score = 0
supported_claims = []
unsupported_claims = []
for claim in claims:
verification_prompt = f'''
检查以下声明是否可以在给定的上下文中找到明确依据。
声明:{claim}
上下文:{context}
该声明是否完全基于上下文中的信息?
返回:SUPPORTED / PARTIALLY_SUPPORTED / NOT_SUPPORTED
并给出简短的说明。
'''
result = verify_claim(verification_prompt, claim, context)
if result == "SUPPORTED":
supported_claims.append(claim)
else:
unsupported_claims.append({
"claim": claim,
"status": result
})
# 3. 计算忠实性分数
faithfulness_score = len(supported_claims) / len(claims) if claims else 1.0
return {
"score": faithfulness_score,
"supported_claims": supported_claims,
"unsupported_claims": unsupported_claims
}
4.3 常见忠实性问题
- 直接添加无依据信息:回答中包含未在上下文中出现的数据或陈述
- 过度泛化:将上下文中的特定结论推广到不适当的范围
- 错误归因:将上下文中的陈述错误地归因到不同的实体
- 矛盾:回答中的信息与上下文中的信息直接冲突
4.4 对抗性评估
除了常规评估,还应该对忠实性进行对抗性测试:
输入:回答中包含上下文中没有的信息
预期:评估系统检测到幻觉
输入:回答用看似合理的推理掩盖无依据的结论
预期:评估系统穿透表面合理性,发现无依据陈述
五、答案相关性评估
5.1 定义与重要性
答案相关性从用户视角出发,衡量最终回答是否切实解决了用户的问题。一个回答可能完全忠实于上下文,但如果它回答的是另一个问题,或者只回答了问题的很小一部分,那么它就是相关度低的。
5.2 评估方法
用户意图匹配:
def evaluate_answer_relevance(query, response):
'''
评估回答是否解决了用户的问题
'''
prompt = f'''
用户提出了以下问题,AI 给出了一个回答。
请评估回答的相关性。
用户问题:{query}
AI 回答:{response}
评估维度:
1. 意图匹配(1-5分):回答是否针对用户真正的需求?
2. 完整性(1-5分):回答是否覆盖了问题中所有方面?
3. 可操作性(1-5分):用户是否可以直接使用这个回答?
4. 简洁性(1-5分):回答是否直接且有重点?
请给出总体评分和一针见血的改进建议。
'''
evaluation = evaluate_llm.generate(prompt)
return parse_evaluation(evaluation)
5.3 相关但不充分的陷阱
- 只回答了部分问题:多个子问题中只回答了一个
- 回答太笼统:回答正确但没有具体信息
- 回答了隐含问题但不是主要问题:用户问「怎么做」,回答「为什么重要」
六、自动化评估管道
6.1 评估集构建
要建立可靠的自动化评估,首先需要构建高质量的评估集:
eval_set = [
{
"id": "test_001",
"query": "2024年新能源汽车销量冠军是谁?",
"retrieved_context": "...",
"expected_response": "...",
"expected_context_relevance": 5,
"expected_faithfulness": 5,
"expected_answer_relevance": 5
},
# ... 100-500 个测试用例
]
评估集应覆盖:
- 简单事实型问题(40%)
- 多步推理型问题(30%)
- 比较分析型问题(20%)
- 边缘情况和恶意输入(10%)
6.2 自动回归测试
每次系统变更(修改提示词、更新文档库、切换检索策略)时自动运行评估:
def regression_test(reranker, llm_pipeline, eval_set):
results = []
for test_case in eval_set:
# 端到端执行
response = llm_pipeline(test_case["query"])
# 三元组评估
context_rel = evaluate_context_relevance(test_case["query"], response.retrieved_context)
faithfulness = evaluate_faithfulness(response.text, response.retrieved_context)
answer_rel = evaluate_answer_relevance(test_case["query"], response.text)
results.append({
"test_id": test_case["id"],
"context_relevance": context_rel,
"faithfulness": faithfulness,
"answer_relevance": answer_rel
})
# 汇总统计
avg_scores = {
"context_relevance": sum(r["context_relevance"] for r in results) / len(results),
"faithfulness": sum(r["faithfulness"] for r in results) / len(results),
"answer_relevance": sum(r["answer_relevance"] for r in results) / len(results)
}
return avg_scores, results
七、评估的最佳实践
- 建立基线:先运行一个初始版本的评估,记录当前的基线分数
- 保持评估集独立:评估集不应包含在训练集或用于调试的样例中
- 定期更新评估集:随着产品演进和用户反馈积累,持续扩充评估集
- 人工抽检:自动化评估虽然效率高,但应配合人工抽检确保评估质量
- 追踪趋势而非绝对值:更关注分数的变化趋势而非绝对数值
八、总结
RAG 三元组(上下文相关性、答案忠实性、答案相关性)从检索、生成、交付三个层级系统性地评估 RAG 系统的输出质量。上下文相关性衡量检索到的内容是否紧扣用户问题,答案忠实性验证回答是否基于检索上下文而非模型幻觉,答案相关性评估最终回答是否从用户视角解决了问题。建立自动化评估管道和高质量的评估集,是持续优化 RAG 系统的必要条件。
五、自动化评估的实现
5.1 使用 LLM 进行自动化评估
RAG 三元组评估可以用 LLM as Judge 的方式自动化:
def evaluate_rag(query, context, response):
scores = {}
# 评估上下文相关性
scores['context_relevance'] = llm_judge(
f"""判断以下上下文是否与查询相关:
查询:{query}
上下文:{context}
请给出 1-5 的评分并解释。"""
)
# 评估答案忠实性
scores['faithfulness'] = llm_judge(
f"""判断以下回答是否完全基于给定上下文:
上下文:{context}
回答:{response}
如果回答包含上下文未提及的信息,请指出。"""
)
# 评估答案相关性
scores['answer_relevance'] = llm_judge(
f"""判断以下回答是否解决了用户的问题:
问题:{query}
回答:{response}
请给出 1-5 的评分。"""
)
return scores
六、评估数据集构建
一个好的评估数据集应该包含:
- 典型问题:覆盖最常见的用户查询类型
- 困难问题:需要多步推理或精确数据
- 边缘情况:模糊问题、非法输入、空查询
- 对抗样本:误导性问题、含陷阱的问题
每种类型至少 20-50 个样本,总计 100-200 个测试用例。
七、评估运营化
评估不是一次性的活动,而是持续的过程:
- CI/CD 集成:每次代码变更自动运行评估
- 回归测试:防止已知问题在新版本中复现
- A/B 测试:对比不同策略的评估分数
- 监控看板:实时展示生产环境的评估指标
八、总结
RAG 三元组评估框架是构建可靠 RAG 系统的基石。
关键要点回顾:
- 上下文相关性确保 LLM 获得正确的信息
- 答案忠实性防止 LLM 产生幻觉
- 答案相关性确保回答了用户真正的问题
- 三元组之间存在平衡关系,需要联合优化
- 自动化评估和评估数据集是持续优化的基础
五、自动化评估的实现
5.1 使用 LLM 进行自动化评估
RAG 三元组评估可以用 LLM as Judge 的方式自动化:
def evaluate_rag(query, context, response):
scores = {}
# 评估上下文相关性
scores['context_relevance'] = llm_judge(
f"""判断以下上下文是否与查询相关:
查询:{query}
上下文:{context}
请给出 1-5 的评分并解释。"""
)
# 评估答案忠实性
scores['faithfulness'] = llm_judge(
f"""判断以下回答是否完全基于给定上下文:
上下文:{context}
回答:{response}
如果回答包含上下文未提及的信息,请指出。"""
)
# 评估答案相关性
scores['answer_relevance'] = llm_judge(
f"""判断以下回答是否解决了用户的问题:
问题:{query}
回答:{response}
请给出 1-5 的评分。"""
)
return scores
六、评估数据集构建
一个好的评估数据集应该包含:
- 典型问题:覆盖最常见的用户查询类型
- 困难问题:需要多步推理或精确数据
- 边缘情况:模糊问题、非法输入、空查询
- 对抗样本:误导性问题、含陷阱的问题
每种类型至少 20-50 个样本,总计 100-200 个测试用例。
七、评估运营化
评估不是一次性的活动,而是持续的过程:
- CI/CD 集成:每次代码变更自动运行评估
- 回归测试:防止已知问题在新版本中复现
- A/B 测试:对比不同策略的评估分数
- 监控看板:实时展示生产环境的评估指标
八、总结
RAG 三元组评估框架是构建可靠 RAG 系统的基石。
关键要点回顾:
- 上下文相关性确保 LLM 获得正确的信息
- 答案忠实性防止 LLM 产生幻觉
- 答案相关性确保回答了用户真正的问题
- 三元组之间存在平衡关系,需要联合优化
- 自动化评估和评估数据集是持续优化的基础
五、自动化评估的实现
5.1 使用 LLM 进行自动化评估
RAG 三元组评估可以用 LLM as Judge 的方式自动化:
def evaluate_rag(query, context, response):
scores = {}
# 评估上下文相关性
scores['context_relevance'] = llm_judge(
f"""判断以下上下文是否与查询相关:
查询:{query}
上下文:{context}
请给出 1-5 的评分并解释。"""
)
# 评估答案忠实性
scores['faithfulness'] = llm_judge(
f"""判断以下回答是否完全基于给定上下文:
上下文:{context}
回答:{response}
如果回答包含上下文未提及的信息,请指出。"""
)
# 评估答案相关性
scores['answer_relevance'] = llm_judge(
f"""判断以下回答是否解决了用户的问题:
问题:{query}
回答:{response}
请给出 1-5 的评分。"""
)
return scores
六、评估数据集构建
一个好的评估数据集应该包含:
- 典型问题:覆盖最常见的用户查询类型
- 困难问题:需要多步推理或精确数据
- 边缘情况:模糊问题、非法输入、空查询
- 对抗样本:误导性问题、含陷阱的问题
每种类型至少 20-50 个样本,总计 100-200 个测试用例。
七、评估运营化
评估不是一次性的活动,而是持续的过程:
- CI/CD 集成:每次代码变更自动运行评估
- 回归测试:防止已知问题在新版本中复现
- A/B 测试:对比不同策略的评估分数
- 监控看板:实时展示生产环境的评估指标
八、总结
RAG 三元组评估框架是构建可靠 RAG 系统的基石。
关键要点回顾:
- 上下文相关性确保 LLM 获得正确的信息
- 答案忠实性防止 LLM 产生幻觉
- 答案相关性确保回答了用户真正的问题
- 三元组之间存在平衡关系,需要联合优化
- 自动化评估和评估数据集是持续优化的基础
延伸阅读
- 📺 B 站播放列表:Advanced RAG — 构建与评估高级 RAG 应用
- 📚 更多学习资源,请访问 deeplearning.ai 官网