RAG评估-用RAGAS量化你的知识库质量
RAG 系统有大量可调参数,每个参数都会影响最终效果:chunk size(文档切块大小)、overlap 大小(相邻块的重叠内容,防止信息在切割处丢失)、切分策略、top-k(每次检索返回最相关的前k个文档)、相似度阈值、embedding 模型、reranker(重排序器,对初次检索结果再次精排提升准确性)、Prompt、LLM 选择……这些参数的组合是指数级的,不可能全部手动试。
RAG 评估:用 RAGAS 量化你的知识库质量
RAG 系统有大量可调参数,每个参数都会影响最终效果:chunk size(文档切块大小)、overlap 大小(相邻块的重叠内容,防止信息在切割处丢失)、切分策略、top-k(每次检索返回最相关的前k个文档)、相似度阈值、embedding 模型、reranker(重排序器,对初次检索结果再次精排提升准确性)、Prompt、LLM 选择……这些参数的组合是指数级的,不可能全部手动试。
没有量化评估,RAG 优化就是在黑暗里摸索——改了几个月参数,却不确定哪次改动是真的有效,哪次只是感觉好了但其实没变化。RAGAS(Retrieval Augmented Generation Assessment)就是目前最常用的 RAG 自动化评估框架,能用数据驱动优化决策。
1.1 RAGAS 的四个核心指标
RAGAS 定义了四个核心指标,从不同维度衡量 RAG 系统的质量。
1.1.1 Faithfulness(忠实度)
衡量什么: 答案中的每一个陈述,是否都能在检索到的文档中找到依据。
分数范围: 0-1,越高越好。
怎么计算: RAGAS 把答案拆成若干个原子陈述,然后逐一判断每个陈述是否能被检索到的文档支持。支持的陈述数 / 总陈述数 = Faithfulness 分数。
举例:
用户问:"我们公司的年假政策是什么?"
检索到的文档说:"员工入职满一年后,每年有 10 天年假。"
LLM 回答:"根据公司政策,入职满一年后有 10 天年假。另外,高级员工还有额外 5 天。"
这个回答的 Faithfulness 分数会低,因为"高级员工额外 5 天"这个陈述在检索文档里找不到依据,属于 LLM "编造"的内容。
如果这个指标低,说明: 检索到的文档不足以支撑回答,LLM 在凭自己的知识或者"猜测"来填充答案。解决方向是提升检索质量,或者在 Prompt 里明确要求"只根据提供的文档回答,无法回答就说不知道"。
1.1.2 Answer Relevancy(答案相关性)
衡量什么: 答案是否真正回答了用户的问题。
分数范围: 0-1,越高越好。
怎么计算: RAGAS 用 LLM 从答案反推出可能的问题,然后看这些反推出的问题和原始问题有多相似。如果答案确实回答了问题,反推出的问题应该和原始问题接近。
举例:
用户问:"如何申请年假?"
LLM 回答:"公司的年假政策规定,满一年有 10 天年假,满三年有 15 天年假……"
这个回答 Faithfulness 可能很高(内容都来自文档),但 Answer Relevancy 低,因为用户问的是"如何申请"(流程),而不是"有多少天"(政策)。
如果这个指标低,说明: Prompt 设计有问题,LLM 没有抓住用户意图;或者检索到的文档有信息但方向不对,Prompt 没有引导 LLM 聚焦到用户真正关心的点。
1.1.3 Context Precision(上下文精确率)
衡量什么: 检索到的文档中,有多少是真正和回答这个问题相关的(信噪比)。
分数范围: 0-1,越高越好。
怎么计算: 检索到的文档里,判断每个文档是否对生成正确答案有贡献,有贡献的比例就是精确率。
举例:
检索到 3 个文档,top-k=3。其中文档 1 和文档 2 包含回答问题需要的信息,文档 3 是一个不相关的文档(碰巧包含了一些相同关键词)。Context Precision = 2/3 ≈ 0.67。
如果这个指标低,说明: 检索噪声大,系统召回了很多不相关的文档。可以考虑:提高相似度阈值、使用 reranker 过滤、缩小 top-k、优化 embedding 模型。
1.1.4 Context Recall(上下文召回率)
衡量什么: 回答这个问题所需要的信息,有多少被检索到了。
分数范围: 0-1,越高越好。
需要: 这个指标需要 ground_truth(标准答案),用来判断"需要什么信息"。
怎么计算: 把标准答案拆成若干陈述,判断每个陈述能否在检索到的文档中找到支持。找到支持的比例就是召回率。
如果这个指标低,说明: 知识库里有答案,但没有被检索到。可以考虑:增大 top-k、调整 chunk size(太大可能把关键信息稀释了)、换更好的 embedding 模型。
1.2 如何构建评估数据集
RAGAS 需要一批测试数据,格式是:
{
"question": "用户问题",
"answer": "RAG系统的回答",
"contexts": ["检索到的文档1", "检索到的文档2", ...],
"ground_truth": "标准答案(Context Recall需要)"
}
构建方式:
手工标注(最可靠): 从用户真实问题里抽取 50-100 个有代表性的问题,人工写标准答案,记录每次 RAG 系统的检索结果和回答。工作量大,但质量高,适合作为黄金测试集。
RAGAS 自动生成: RAGAS 提供了测试集生成工具,从你的文档自动生成问答对(以下为 RAGAS v0.2+ 的写法):
from ragas.testset import TestsetGenerator
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import DirectoryLoader
# 加载你的知识库文档
loader = DirectoryLoader("./docs", glob="**/*.txt")
documents = loader.load()
# 自动生成测试集(RAGAS v0.2+ API)
generator = TestsetGenerator.from_langchain(
generator_llm=ChatOpenAI(model="gpt-4o-mini"),
critic_llm=ChatOpenAI(model="gpt-4o-mini"),
embeddings=OpenAIEmbeddings()
)
testset = generator.generate_with_langchain_docs(
documents,
test_size=50
)
注意:RAGAS v0.1 使用
TestsetGenerator.with_openai()和evolutions参数,v0.2 之后 API 有较大变化,如遇旧版代码请参考官方文档对应版本。
1.3 完整评估代码
# evaluate_rag.py
# 以下代码适用于 RAGAS v0.2+
# v0.1 的 evaluate() 接口有所不同,请参考对应版本文档
import os
from datasets import Dataset
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall
)
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
os.environ["OPENAI_API_KEY"] = "sk-your-key"
# ——— 初始化RAG系统 ———
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings
)
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
return_source_documents=True
)
# ——— 准备评估数据集 ———
# 实际使用时,这里应该是你标注好的测试集
test_questions = [
"公司的年假政策是什么?",
"如何申请请假?",
"试用期是多少天?",
"加班费怎么计算?",
"员工福利有哪些?"
]
ground_truths = [
"入职满一年后每年10天年假,满三年15天,满五年20天。",
"需要提前三天在OA系统提交申请,经直属上级审批。",
"试用期为三个月,双方协商一致可以缩短。",
"工作日加班按1.5倍,休息日加班按2倍,法定节假日按3倍。",
"包括五险一金、补充医疗保险、年度体检、餐补、交通补贴。"
]
# ——— 运行RAG并收集结果 ———
eval_data = {
"question": [],
"answer": [],
"contexts": [],
"ground_truth": []
}
for question, ground_truth in zip(test_questions, ground_truths):
result = rag_chain.invoke({"query": question})
eval_data["question"].append(question)
eval_data["answer"].append(result["result"])
eval_data["contexts"].append([
doc.page_content for doc in result["source_documents"]
])
eval_data["ground_truth"].append(ground_truth)
print(f"已评估:{question}")
# ——— 转成Dataset格式 ———
dataset = Dataset.from_dict(eval_data)
# ——— 运行RAGAS评估 ———
result = evaluate(
dataset,
metrics=[
faithfulness,
answer_relevancy,
context_precision,
context_recall
],
llm=ChatOpenAI(model="gpt-4o-mini"),
embeddings=OpenAIEmbeddings()
)
# ——— 输出结果 ———
print("\n===== RAGAS评估结果 =====")
print(f"Faithfulness(忠实度): {result['faithfulness']:.3f}")
print(f"Answer Relevancy(答案相关性): {result['answer_relevancy']:.3f}")
print(f"Context Precision(上下文精确率): {result['context_precision']:.3f}")
print(f"Context Recall(上下文召回率): {result['context_recall']:.3f}")
# 保存详细结果
df = result.to_pandas()
df.to_csv("rag_evaluation_results.csv", index=False, encoding="utf-8")
print("\n详细结果已保存到 rag_evaluation_results.csv")
运行:
pip install ragas langchain langchain-openai langchain-community chromadb datasets
python evaluate_rag.py
输出示例:
===== RAGAS评估结果 =====
Faithfulness(忠实度): 0.823
Answer Relevancy(答案相关性): 0.756
Context Precision(上下文精确率): 0.667
Context Recall(上下文召回率): 0.714
1.4 评估结果怎么用
拿到分数之后,根据哪个指标低来确定优化方向:
Faithfulness 低(< 0.7)
LLM 在编造内容,没有忠实于检索到的文档。
排查方向:
- 检索到的文档是否真的包含回答问题的信息?如果没有,就是检索质量问题
- Prompt 里是否明确要求"只根据提供文档回答"?加上这个约束通常能提升 Faithfulness
- LLM 的 temperature 是否太高?降低 temperature 可以减少"创造性发挥"
Answer Relevancy 低(< 0.7)
答案没有回答用户的问题,方向跑偏了。
排查方向:
- 分析低分的具体案例,看 LLM 在回答什么(通常是检索到了相关主题但不同角度的文档)
- 考虑在检索前做问题改写,更精准地表达用户意图
- 调整 Prompt,明确要求"针对用户的具体问题直接回答"
Context Precision 低(< 0.6)
检索到了太多噪声文档。
排查方向:
- 提高相似度阈值,过滤掉低相关性的文档
- 引入 reranker(如 Cohere Rerank)对检索结果重排序
- 适当减小 top-k
Context Recall 低(< 0.6)
知识库里有答案但没检索到。
排查方向:
- 增大 top-k(检索更多候选文档)
- 检查 chunk size 是否合适,太小可能把完整知识点切碎了
- 考虑换更好的 embedding 模型(比如从 text-embedding-ada-002 升级到 text-embedding-3-large)
- 混合检索(向量检索 + BM25 关键词检索,BM25 是一种基于词频统计的传统文本匹配算法,与向量检索互补,能找到精确包含关键词的文档)通常能提升召回
1.5 LLM-as-Judge:RAGAS 内部的评估机制
RAGAS 计算这四个指标的方式,本质上是用一个 LLM(Judge LLM)来评估另一个 LLM 的输出。
以 Faithfulness 为例,RAGAS 的内部逻辑是:
这个方法有个前提:Judge LLM 要足够强。RAGAS 默认用 GPT-4,用 GPT-4o-mini 评估会便宜但可能准确性下降。
这也意味着:RAGAS 的评估结果本身是有噪声的,不是绝对精准的。但它的价值在于提供了一个一致、可重复的评估基准。同等条件下比较不同配置的分数,是有意义的。
1.6 持续评估,不是一次性的
RAG 系统会持续迭代:知识库更新、Prompt 调整、模型升级。每次改动都应该跑一遍评估,对比分数变化。
建议的持续评估流程:
- 维护一个黄金测试集(50-100 个问答对),放到版本控制里
- 每次改动后跑 RAGAS 评估,记录四个指标
- 对比前后指标变化,只有明确提升才合并改动
- 定期(比如每月)用新的用户问题更新测试集
RAGAS 评估是 RAG 优化的量化工具。有了这个工具,每次改动的效果都有数据支撑,而不是依赖主观判断。