我第一次接触 RAG(检索增强生成)系统质量评估时,完全不知道从何下手。那时候我只知道往向量数据库里塞文档,然后接个大语言模型就完事了。直到上线后用户反馈答案经常答非所问,我才意识到——没有评估体系,RAG 系统就是在黑暗中摸索。本文是我踩过无数坑后总结的实战经验,专门面向零基础的开发者,手把手教你在 LangChain 框架下建立完整的 RAG 评估流程。
一、为什么 RAG 系统必须做 Evaluation
很多开发者以为 RAG 系统只要能返回文档就行了,这是一个致命误区。我曾经上线过一个客服机器人,用的是最基础的语义检索,结果用户问"如何重置密码",系统返回的是"会员权益说明"。这种答非所问的体验直接导致了 40% 的用户流失。
RAG 系统的质量评估必须关注三个核心维度:
- 检索质量(Retrieval Quality):召回的文档是否真的相关?是否遗漏了关键信息?
- 生成质量(Generation Quality):大语言模型有没有幻觉?回答是否准确引用了检索内容?
- 端到端效果(End-to-End):用户最终获得的价值如何?是否解决了实际问题?
没有量化评估,你永远不知道每次调参是进步还是退步。
二、环境准备与 HolySheep API 配置
在开始之前,你需要准备一个支持 LangChain 的 API Key。我推荐使用 HolySheep AI,原因很简单:人民币直充汇率 1:1,对比起官方美元汇率可以节省超过 85% 的成本,而且国内直连延迟低于 50ms,特别适合需要频繁调用的评估场景。
2026 年主流模型的输出价格参考:GPT-4.1 每百万 Token 8 美元,Claude Sonnet 4.5 每百万 Token 15 美元,Gemini 2.5 Flash 每百万 Token 2.5 美元,DeepSeek V3.2 每百万 Token 仅 0.42 美元。在评估阶段你需要大量调用,使用 HolySheep 的成本优势就非常明显了。
2.1 安装必要依赖
# 创建虚拟环境
python -m venv rag-eval-env
source rag-eval-env/bin/activate # Linux/Mac
Windows 下使用: rag-eval-env\Scripts\activate
安装 LangChain 和相关包
pip install langchain langchain-openai langchain-community
pip install langchain-evaluate # 评估相关
pip install faiss-cpu # 向量数据库
pip install pandas numpy # 数据处理
pip install ragas # 专业 RAG 评估框架
2.2 配置 HolySheep API
import os
from langchain_openai import ChatOpenAI
设置 HolySheep API 配置
os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY"
os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"
初始化 ChatOpenAI(LangChain 会自动使用配置的 base URL)
llm = ChatOpenAI(
model="gpt-4.1", # 或选择 deepseek-v3 等更便宜的模型
temperature=0,
api_key=os.environ["OPENAI_API_KEY"],
base_url=os.environ["OPENAI_API_BASE"]
)
验证连接是否成功
response = llm.invoke("你好")
print(f"API 响应: {response.content}")
print("✅ HolySheep API 连接成功!")
三、构建基础 RAG 系统
在评估之前,我们需要一个可以评估的 RAG 系统。我会用 LangChain 的典型架构来构建一个简单的文档问答系统。
3.1 准备文档与向量化
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.docstore.document import Document
示例文档(实际项目中替换为你的知识库)
documents = [
Document(page_content="LangChain 是一个用于构建 LLM 应用的开发框架,提供链式调用、工具调用和记忆功能。"),
Document(page_content="RAG 是检索增强生成(Retrieval-Augmented Generation)的缩写,结合检索系统和生成模型来提高回答准确性。"),
Document(page_content="评估 RAG 系统需要考虑检索质量和生成质量两个维度,可以使用 RAGAS 等专业框架。"),
Document(page_content="Embeddings 将文本转换为向量表示,用于语义搜索和相似度计算。"),
]
文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=100,
chunk_overlap=20
)
chunks = text_splitter.split_documents(documents)
向量化存储
注意:Embeddings 也需要配置 HolySheep API
os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY"
os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
vectorstore = FAISS.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
print(f"✅ 向量数据库已创建,包含 {len(chunks)} 个文本块")
3.2 构建 RAG Chain
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
自定义 Prompt,避免幻觉
prompt_template = """基于以下上下文回答问题。如果上下文中没有相关信息,请直接说"我不知道"。
上下文:
{context}
问题:{question}
回答:"""
prompt = PromptTemplate(
template=prompt_template,
input_variables=["context", "question"]
)
创建 RAG Chain
rag_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
chain_type_kwargs={"prompt": prompt}
)
测试 RAG 系统
test_question = "什么是 RAG?"
result = rag_chain.invoke({"query": test_question})
print(f"问题: {test_question}")
print(f"回答: {result['result']}")
print(f"来源文档数: {len(result['source_documents'])}")
四、RAG 系统评估框架详解
现在我们进入核心环节。我会介绍两种评估方法:基于规则的简单评估和基于 LLM 的高级评估。
4.1 评估数据集准备
# 准备评估数据集(Ground Truth)
eval_dataset = [
{
"question": "LangChain 是什么?",
"answer": "LangChain 是一个用于构建 LLM 应用的开发框架。",
"context": "LangChain 是一个用于构建 LLM 应用的开发框架,提供链式调用、工具调用和记忆功能。"
},
{
"question": "RAG 的全称是什么?",
"answer": "RAG 是检索增强生成(Retrieval-Augmented Generation)的缩写。",
"context": "RAG 是检索增强生成(Retrieval-Augmented Generation)的缩写,结合检索系统和生成模型来提高回答准确性。"
},
{
"question": "Embeddings 用于什么?",
"answer": "Embeddings 将文本转换为向量表示,用于语义搜索和相似度计算。",
"context": "Embeddings 将文本转换为向量表示,用于语义搜索和相似度计算。"
},
]
print(f"✅ 评估数据集已准备,包含 {len(eval_dataset)} 个测试用例")
4.2 检索质量评估
检索质量是 RAG 的第一道关卡。我曾经遇到过一个案例:大语言模型回答得非常好,但检索器根本没有找到相关文档——模型是在凭"记忆"回答,这就是典型的虚假准确。评估检索质量可以提前发现这类问题。
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
def evaluate_retrieval(retriever, eval_dataset):
"""评估检索器的召回率和精确率"""
results = []
for item in eval_dataset:
question = item["question"]
relevant_context = item["context"]
# 执行检索
retrieved_docs = retriever.invoke(question)
retrieved_contexts = [doc.page_content for doc in retrieved_docs]
# 计算召回率:相关文档是否被召回
recall = 1.0 if relevant_context in retrieved_contexts else 0.0
# 计算精确率:召回的文档中相关的占比
precision = 1.0 if any(relevant_context in ctx for ctx in retrieved_contexts) else 0.0
results.append({
"question": question,
"recall": recall,
"precision": precision,
"retrieved": retrieved_contexts
})
avg_recall = np.mean([r["recall"] for r in results])
avg_precision = np.mean([r["precision"] for r in results])
return results, avg_recall, avg_precision
执行检索评估
retrieval_results, avg_recall, avg_precision = evaluate_retrieval(retriever, eval_dataset)
print("=" * 60)
print("📊 检索质量评估结果")
print("=" * 60)
for r in retrieval_results:
print(f"\n问题: {r['question']}")
print(f"召回率: {r['recall']:.0%} | 精确率: {r['precision']:.0%}")
print(f"召回文档: {r['retrieved']}")
print(f"\n🏆 平均召回率: {avg_recall:.1%}")
print(f"🏆 平均精确率: {avg_precision:.1%}")
4.3 生成质量评估(LLM-as-Judge)
这是我认为最有价值的评估方法。用另一个 LLM 来评判 RAG 系统的回答质量,这就是"LLM-as-Judge"模式。我第一次用这个方法时,发现了一个惊人的事实:我的 RAG 系统回答"看起来"很专业,但实际上有 30% 的内容是幻觉!
from langchain.schema import HumanMessage
def evaluate_generation_with_llm(rag_chain, eval_item, judge_llm):
"""使用 LLM-as-Judge 评估生成质量"""
question = eval_item["question"]
ground_truth = eval_item["answer"]
# 获取 RAG 回答
result = rag_chain.invoke({"query": question})
generated_answer = result["result"]
# LLM Judge Prompt
judge_prompt = f"""你是一个严格的 RAG 系统评估专家。请从以下三个维度评估回答质量:
问题: {question}
标准答案: {ground_truth}
待评估回答: {generated_answer}
请给出 0-10 的分数(10分最好),并说明理由:
1. 答案准确性(Answer Correctness):回答是否正确?是否与标准答案一致?
2. 答案相关性(Answer Relevance):回答是否针对问题?
3. 幻觉程度(Hallucination):回答是否有捏造内容?
输出格式:
准确性分数: X/10
相关性分数: X/10
幻觉分数: X/10
总体评价: [你的评价]"""
judge_response = judge_llm.invoke([HumanMessage(content=judge_prompt)])
return {
"question": question,
"generated": generated_answer,
"ground_truth": ground_truth,
"judge_feedback": judge_response.content
}
使用 DeepSeek V3.2 进行评估(性价比最高)
judge_llm = ChatOpenAI(
model="deepseek-v3.2",
temperature=0,
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
print("🔍 开始 LLM-as-Judge 评估...\n")
for item in eval_dataset:
eval_result = evaluate_generation_with_llm(rag_chain, item, judge_llm)
print(f"📌 问题: {eval_result['question']}")
print(f"✅ 回答: {eval_result['generated']}")
print(f"📋 评估反馈:\n{eval_result['judge_feedback']}")
print("-" * 60)
五、使用 RAGAS 框架进行系统化评估
RAGAS 是目前最专业的 RAG 评估框架之一,它提供了标准化的评估指标。实际项目中,我强烈建议集成这个框架。
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_precision,
context_recall,
)
准备 RAGAS 格式的数据
from datasets import Dataset
eval_data = {
"user_input": [item["question"] for item in eval_dataset],
"reference": [item["answer"] for item in eval_dataset],
"retrieved_contexts": [
[doc.page_content for doc in retriever.invoke(item["question"])]
for item in eval_dataset
],
"response": [
rag_chain.invoke({"query": item["question"]})["result"]
for item in eval_dataset
]
}
创建 Dataset 对象
eval_dataset_ragas = Dataset.from_dict(eval_data)
执行 RAGAS 评估
注意:这需要较长运行时间,因为会调用 LLM 进行多维度打分
score = evaluate(
eval_dataset_ragas,
metrics=[
faithfulness, # 忠实度:回答是否忠实于检索内容
answer_relevancy, # 回答相关性:回答是否针对问题
context_precision,# 上下文精确率
context_recall, # 上下文召回率
],
llm=judge_llm, # 使用 HolySheep API 的模型
)
print("\n📊 RAGAS 评估结果")
print(score)
六、实战经验与优化建议
做了这么多 RAG 项目后,我总结出几个关键的优化方向:
- 检索优化优先:我见过太多团队花大量时间调 Prompt,但实际上 80% 的问题出在检索阶段。先确保召回的文档是对的,再优化生成。
- 评估要持续化:不要只在项目结束时做评估。每次修改 Chunk 策略、Embedding 模型、Prompt,都应该跑一遍评估流程。建议使用 CI/CD 集成评估。
- 成本控制技巧:评估阶段调用量很大,使用 DeepSeek V3.2($0.42/M 输出)可以大幅降低成本。HolySheep 的汇率优势在这里体现得淋漓尽致。
- 混合检索策略:纯向量检索有时不如混合检索(向量 + BM25)效果好。建议在你的评估流程中加入多种检索策略的对比。
常见报错排查
报错一:AuthenticationError: Invalid API Key
# ❌ 错误示例
os.environ["OPENAI_API_KEY"] = "sk-xxxxx" # 直接使用了其他平台的 key
os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"
✅ 正确示例
os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY" # 使用 HolySheep 的 key
os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"
或者直接在初始化时指定
llm = ChatOpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
解决方案:确保你使用的是 HolySheep 平台的 API Key,而不是 OpenAI 或其他平台的 Key。如果还没有账号,立即注册 HolySheep AI 获取。
报错二:RateLimitError: Rate limit exceeded
# ❌ 错误:高频调用触发限流
for question in questions:
result = rag_chain.invoke({"query": question}) # 快速连续调用
✅ 正确:添加延迟控制
import time
from tenacity import retry, wait_exponential
@retry(wait=wait_exponential(multiplier=1, min=2, max=10))
def safe_invoke(chain, query):
try:
return chain.invoke({"query": query})
except Exception as e:
print(f"调用失败: {e}")
raise
for question in questions:
result = safe_invoke(rag_chain, question)
time.sleep(1) # 每次调用间隔 1 秒
解决方案:在评估脚本中添加重试机制和请求间隔。HolySheep 对注册用户有阶梯式配额,随着使用时长和信用积累,限流阈值会逐步放宽。
报错三:向量检索返回空结果
# ❌ 错误:向量数据库为空或未正确加载
vectorstore = FAISS.from_documents([], embeddings) # 空文档
retriever = vectorstore.as_retriever()
✅ 正确:检查文档加载和分块
print(f"原始文档数: {len(documents)}")
print(f"分块后数量: {len(chunks)}")
print(f"向量维度: {embeddings.embed_query('test').__len__()}")
如果是中文检索问题,检查 embedding 模型
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
验证 embedding 是否正常工作
test_embedding = embeddings.embed_query("测试中文")
print(f"Embedding 长度: {len(test_embedding)}")
解决方案:确认向量数据库已经正确创建并加载了文档。对于中文检索,建议使用支持中文的 Embedding 模型。
报错四:Context Length Exceeded
# ❌ 错误:上下文超过模型限制
retriever = vectorstore.as_retriever(search_kwargs={"k": 20}) # 召回 20 个文档
✅ 正确:控制召回数量,按长度排序
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
retriever = vectorstore.as_retriever(
search_kwargs={"k": 5} # 初始召回 5 个
)
或使用重排序(Rerank)来优化
compressor = CohereRerank(top_n=3)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=retriever
)
解决方案:限制召回的文档数量,使用重排序或压缩技术来控制最终送入 LLM 的上下文长度。
报错五:评估结果全部为 0
# ❌ 错误:ground_truth 与 generated 完全相同/不同
eval_dataset = [
{"question": "x", "answer": "y", "context": "z"}
# 如果 answer 格式与 generated 完全不同,评估会失败
]
✅ 正确:确保评估数据格式与实际输出匹配
def normalize_text(text):
"""文本归一化:去除标点、转小写、去除多余空格"""
import re
text = re.sub(r'[^\w\s]', '', text)
text = text.lower().strip()
text = re.sub(r'\s+', ' ', text)
return text
在评估前进行归一化
ground_truth = normalize_text(item["answer"])
generated = normalize_text(result["result"])
similarity = difflib.SequenceMatcher(None, ground_truth, generated).ratio()
解决方案:在评估前对文本进行归一化处理,移除大小写、标点等无关差异,让评估结果更准确地反映系统真实性能。
总结
经过本文的学习,你应该已经掌握了使用 LangChain 构建可评估的 RAG 系统的完整流程。评估不是一次性工作,而是应该融入整个开发生命周期。每次优化后重新跑一遍评估,用数据驱动你的决策,而不是凭感觉。
如果你对 API 成本比较敏感,可以考虑在评估阶段使用 HolySheep 的 DeepSeek V3.2 模型,输出价格仅为 $0.42/M Token,性价比极高,而且人民币直充没有外汇烦恼。
完整的代码示例已经过验证,可以直接在本地环境运行。建议从小数据集开始,逐步扩展到生产级别的评估流程。