Ragas RAG 评估¶
为什么要学¶
构建 RAG(检索增强生成)系统容易,但如何知道它工作得好不好?手动评估耗时且不可扩展。Ragas 解决的核心问题是:
- 量化 RAG 质量:用数字衡量检索和生成的质量
- 自动化评估:无需人工逐条审核,LLM-as-Judge 自动打分
- 诊断定位:区分"检索差"还是"生成差",精确优化
- 持续监控:每次改动都能跑评估,防止回归
- 标准化指标:业界通用的 RAG 评估指标体系
无论你用什么框架构建 RAG,Ragas 都能帮你回答"这个 RAG 系统到底好不好用"。
核心概念¶
白话解释¶
把 RAG 评估想象成"考试阅卷": - Context Precision(上下文精确度):检索到的文档中,有多少是真正相关的? - Context Recall(上下文召回):回答所需的信息,检索到了多少? - Faithfulness(忠实度):回答是否忠于检索到的上下文?(不瞎编) - Answer Relevancy(回答相关性):回答和问题相关吗?
核心概念对照表¶
| 指标 | 评估什么 | 分数含义 | 优化方向 |
|---|---|---|---|
| Context Precision | 检索精度 | 相关文档占比 | 优化检索/重排序 |
| Context Recall | 检索召回 | 是否检索到所需信息 | 扩大检索范围 |
| Faithfulness | 生成忠实度 | 回答是否基于上下文 | 减少幻觉 |
| Answer Relevancy | 回答相关性 | 回答是否切题 | 优化prompt |
| Answer Correctness | 回答正确性 | 与参考答案对比 | 整体优化 |
| Context Entities Recall | 实体召回 | 关键实体是否被检索到 | 实体级检索优化 |
安装配置¶
安装¶
环境配置¶
# Ragas使用LLM进行评估,需要配置API
export OPENAI_API_KEY="sk-..."
# 或使用其他模型
export RAGAS_LLM_PROVIDER="openai" # openai/azure/bedrock
验证安装¶
from ragas.metrics import faithfulness, answer_relevancy
from ragas import evaluate
print("Ragas安装成功!")
print(f"可用指标: faithfulness, answer_relevancy, ...")
快速上手¶
准备评估数据¶
from datasets import Dataset
# RAG评估需要的数据格式
eval_data = {
"question": [
"什么是向量数据库?",
"RAG的优势是什么?"
],
"answer": [
"向量数据库是专门用于存储和查询高维向量的数据库系统,支持相似性搜索。",
"RAG通过检索外部知识来增强LLM的回答能力,减少幻觉。"
],
"contexts": [
["向量数据库是一种专门处理向量数据的数据库,支持高效的相似性搜索和最近邻查询。常见的向量数据库包括Pinecone、Weaviate、ChromaDB等。"],
["RAG(检索增强生成)将检索系统与LLM结合,通过检索相关文档来提供上下文,从而生成更准确的回答。主要优势包括:减少幻觉、知识可更新、可追溯来源。"]
],
"ground_truth": [
"向量数据库是专门设计用来存储、管理和查询高维向量数据的数据库系统。",
"RAG的主要优势包括减少LLM幻觉、可以更新知识而无需重新训练、回答可追溯来源。"
]
}
dataset = Dataset.from_dict(eval_data)
运行评估¶
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
# 一行代码完成评估
result = evaluate(
dataset=dataset,
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall,
]
)
print(result)
# {'faithfulness': 0.92, 'answer_relevancy': 0.88,
# 'context_precision': 0.85, 'context_recall': 0.90}
# 查看每条数据的详细分数
df = result.to_pandas()
print(df)
理解评估结果¶
# 分析结果
df = result.to_pandas()
# 找出低分的案例
low_faithfulness = df[df['faithfulness'] < 0.5]
print("忠实度低的案例(可能有幻觉):")
print(low_faithfulness[['question', 'answer']])
low_recall = df[df['context_recall'] < 0.5]
print("召回率低的案例(检索不够):")
print(low_recall[['question', 'contexts']])
进阶用法¶
1. 自动生成测试数据¶
from ragas.testset.generator import TestsetGenerator
from ragas.testset.evolutions import simple, reasoning, multi_context
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import DirectoryLoader
# 加载你的文档
loader = DirectoryLoader("./docs/", glob="**/*.md")
documents = loader.load()
# 配置生成器
generator_llm = ChatOpenAI(model="gpt-4o-mini")
critic_llm = ChatOpenAI(model="gpt-4o")
embeddings = OpenAIEmbeddings()
generator = TestsetGenerator.from_langchain(
generator_llm=generator_llm,
critic_llm=critic_llm,
embeddings=embeddings
)
# 自动生成测试集
testset = generator.generate_with_langchain_docs(
documents=documents,
test_size=20,
distributions={
simple: 0.5, # 简单问题
reasoning: 0.25, # 需要推理的问题
multi_context: 0.25 # 需要多文档的问题
}
)
# 转为Dataset
eval_dataset = testset.to_dataset()
print(eval_dataset)
2. 自定义评估指标¶
from ragas.metrics import Metric
from ragas.metrics.base import MetricWithLLM
from dataclasses import dataclass
@dataclass
class ConcisenessMetric(MetricWithLLM):
name: str = "conciseness"
async def _ascore(self, row, callbacks=None):
# 用LLM评估回答的简洁度
prompt = f"""评估以下回答的简洁度(0-1分):
问题: {row['question']}
回答: {row['answer']}
评分标准: 1=非常简洁,0=过于冗长
只返回一个数字。"""
result = await self.llm.agenerate_text(prompt)
return float(result.strip())
# 使用自定义指标
conciseness = ConcisenessMetric()
result = evaluate(dataset=dataset, metrics=[conciseness])
3. 使用本地模型评估¶
from langchain_community.llms import Ollama
from langchain_community.embeddings import OllamaEmbeddings
from ragas import evaluate
from ragas.metrics import faithfulness
# 使用本地Ollama模型作为评估LLM
from ragas.llms import LangchainLLMWrapper
from ragas.embeddings import LangchainEmbeddingsWrapper
local_llm = LangchainLLMWrapper(Ollama(model="llama3.2"))
local_embeddings = LangchainEmbeddingsWrapper(OllamaEmbeddings(model="nomic-embed-text"))
# 指定评估用的LLM
faithfulness_metric = faithfulness
faithfulness_metric.llm = local_llm
faithfulness_metric.embeddings = local_embeddings
result = evaluate(
dataset=dataset,
metrics=[faithfulness_metric]
)
4. 端到端 RAG Pipeline 评估¶
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy, context_precision
# 构建RAG Pipeline
def build_rag():
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(embedding_function=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
llm = ChatOpenAI(model="gpt-4o-mini")
return retriever, llm
# 收集评估数据
def collect_eval_data(questions, retriever, llm):
data = {"question": [], "answer": [], "contexts": []}
for q in questions:
# 检索
docs = retriever.get_relevant_documents(q)
contexts = [doc.page_content for doc in docs]
# 生成
answer = llm.invoke(f"基于以下上下文回答问题:\n上下文:{contexts}\n问题:{q}")
data["question"].append(q)
data["answer"].append(answer.content)
data["contexts"].append(contexts)
return Dataset.from_dict(data)
# 评估
questions = ["什么是向量数据库?", "如何优化RAG检索?"]
retriever, llm = build_rag()
eval_dataset = collect_eval_data(questions, retriever, llm)
result = evaluate(
dataset=eval_dataset,
metrics=[faithfulness, answer_relevancy, context_precision]
)
print(result)
5. CI/CD 集成¶
# test_rag_quality.py
import pytest
from ragas import evaluate
from ragas.metrics import faithfulness, context_recall
def test_rag_quality():
"""RAG质量门禁测试"""
dataset = load_test_dataset() # 你的测试数据
result = evaluate(
dataset=dataset,
metrics=[faithfulness, context_recall]
)
# 设置质量门槛
assert result['faithfulness'] > 0.8, \
f"忠实度{result['faithfulness']:.2f}低于阈值0.8"
assert result['context_recall'] > 0.7, \
f"召回率{result['context_recall']:.2f}低于阈值0.7"
6. 与 Langfuse 集成¶
from ragas.integrations.langfuse import RagasTrace
# 评估结果自动上报到Langfuse
result = evaluate(
dataset=dataset,
metrics=[faithfulness, answer_relevancy],
callbacks=[RagasTrace()] # 自动追踪到Langfuse
)
常见问题¶
Q1: 评估成本太高?¶
- 使用
gpt-4o-mini而非gpt-4o做评估 - 减少测试集大小(先评估 20-50 条)
- 使用本地模型评估(质量略低但免费)
- 对简单指标使用规则而非 LLM
Q2: 没有 ground_truth 怎么办?¶
不是所有指标都需要 ground_truth:
| 指标 | 需要ground_truth | 需要contexts |
|---|---|---|
| faithfulness | 不需要 | 需要 |
| answer_relevancy | 不需要 | 不需要 |
| context_precision | 需要 | 需要 |
| context_recall | 需要 | 需要 |
Q3: 评分不稳定怎么办?¶
- 多次评估取平均值
- 增大测试集
- 使用更强的模型做评估
- 检查评估 prompt 是否清晰
Q4: 如何解读低分?¶
faithfulness 低 → 模型在"编造"信息,优化:
- 加强检索相关性
- 在prompt中强调"只基于给定信息回答"
context_recall 低 → 检索遗漏了关键信息,优化:
- 增加检索数量(k值)
- 优化切块策略
- 改进embedding模型
answer_relevancy 低 → 回答偏题,优化:
- 改进prompt模板
- 减少无关上下文的干扰
参考资源¶
- Ragas 官方文档 - 完整文档
- Ragas GitHub - 源代码
- Ragas 指标详解 - 各指标原理
- RAG 评估最佳实践 - 实战指南
- 论文: RAGAS - 原始论文