构建一个RAG系统不难但构建一个可以持续改进的RAG系统很难。大多数团队的困境是系统上线后你如何知道它真的好用修改了某个参数是变好了还是变差了没有评估体系就没有持续优化的基础。本文系统介绍RAG评估的核心框架、关键指标与工程实践。为什么RAG评估如此重要一个真实的场景某公司用LlamaIndex搭建了内部知识库问答系统初期效果感觉还不错。三个月后有人反馈很多问题回答错误。开发团队排查后发现- 检索召回率低相关文档没被找到- 部分文档在分块时被切割关键信息丢失- 模型有时忽略了检索结果用自身知识回答但最关键的问题是他们不知道这些问题从什么时候开始出现的也不知道哪个问题最严重。没有评估就没有数据驱动的改进。## RAG评估的三个维度评估一个RAG系统需要从三个层面入手### 维度1检索质量Retrieval Quality检索模块是RAG的眼睛如果找不到相关文档后面什么都是空谈。关键指标-召回率RecallK对于一个查询相关文档中有多少比例出现在Top-K结果中-精确率PrecisionKTop-K结果中有多少比例是真正相关的-MRRMean Reciprocal Rank第一个相关文档出现的位置排名的倒数均值-NDCGNormalized Discounted Cumulative Gain考虑了相关性层次的综合排序指标pythondef recall_at_k(retrieved_ids: list, relevant_ids: set, k: int) - float: 计算RecallK top_k set(retrieved_ids[:k]) if not relevant_ids: return 0.0 return len(top_k relevant_ids) / len(relevant_ids)def precision_at_k(retrieved_ids: list, relevant_ids: set, k: int) - float: 计算PrecisionK top_k retrieved_ids[:k] if not top_k: return 0.0 relevant_in_top_k sum(1 for doc_id in top_k if doc_id in relevant_ids) return relevant_in_top_k / kdef mrr(retrieved_ids_list: list[list], relevant_ids_list: list[set]) - float: 计算Mean Reciprocal Rank rr_scores [] for retrieved, relevant in zip(retrieved_ids_list, relevant_ids_list): for rank, doc_id in enumerate(retrieved, 1): if doc_id in relevant: rr_scores.append(1.0 / rank) break else: rr_scores.append(0.0) return sum(rr_scores) / len(rr_scores) if rr_scores else 0.0### 维度2生成质量Generation Quality即使检索完美生成模块也可能产生问题忽略检索结果、幻觉、答非所问。关键指标****忠实度Faithfulness答案是否基于检索到的上下文是否有凭空捏造答案相关性Answer Relevance答案是否回答了用户的问题上下文利用率Context Utilization提供的上下文有多少被有效利用python# 使用RAGAS框架评估生成质量from ragas import evaluatefrom ragas.metrics import faithfulness, answer_relevancy, context_precision, context_recallfrom datasets import Dataset# 准备评估数据集eval_data { question: [什么是RAG, 如何优化检索效果], answer: [RAG是检索增强生成..., 可以通过调整chunk size...], contexts: [ [检索增强生成RAG是一种..., RAG系统由检索器和生成器组成...], [优化RAG检索效果的方法包括..., chunk size是影响检索质量的关键...], ], ground_truth: [RAG即Retrieval-Augmented Generation..., 优化检索效果可以从...],}dataset Dataset.from_dict(eval_data)results evaluate( dataset, metrics[ faithfulness, # 忠实度 answer_relevancy, # 答案相关性 context_precision, # 上下文精确率 context_recall, # 上下文召回率 ])print(results)### 维度3端到端质量End-to-End Quality最终用户关心的是系统能不能回答好我的问题需要端到端的综合评估。关键指标- 正确率Accuracy与标准答案对比- 用户满意度User Satisfaction真实用户的主观评分- 任务完成率Task Completion Rate需要多轮对话才能完成任务的比例## 构建评估数据集评估的质量直接依赖评估数据集的质量。有三种构建方式### 方式1人工构建Golden Dataset最可靠但最贵。由领域专家根据实际文档库人工构建问题-答案对python# 评估数据集格式golden_dataset [ { id: q001, question: 公司的退款政策是什么, ground_truth_answer: 根据退款政策用户在购买后7天内可申请全额退款..., relevant_doc_ids: [policy_doc_v3_p12, policy_doc_v3_p13], difficulty: simple, # simple/medium/hard category: policy, }, ...]### 方式2AI辅助生成Synthetic Dataset用LLM从文档库自动生成问题人工抽样验证pythonfrom langchain_openai import ChatOpenAIfrom langchain.prompts import PromptTemplatedef generate_qa_from_chunk(chunk: str, llm: ChatOpenAI, n_questions: int 3) - list[dict]: 从文档块生成QA对 prompt PromptTemplate.from_template( 基于以下文档内容生成{n}个有价值的问题和对应的标准答案。 要求问题应该基于文档内容可以回答但不要直接复制原文。 文档内容 {content} 以JSON格式输出格式如下 [ {{question: 问题1, answer: 答案1}}, ... ] ) response llm.invoke(prompt.format(contentchunk, nn_questions)) import json return json.loads(response.content)# 批量生成qa_dataset []for chunk in document_chunks: qa_pairs generate_qa_from_chunk(chunk, llm) qa_dataset.extend(qa_pairs)### 方式3生产日志挖掘从真实用户查询日志中挖掘高价值评估样本pythondef mine_eval_cases_from_logs(user_logs: list[dict]) - list[dict]: 从用户日志挖掘评估案例 eval_cases [] for log in user_logs: # 筛选有用户反馈的查询点赞/踩 if log.get(feedback) in [thumbs_up, thumbs_down]: eval_cases.append({ question: log[query], system_answer: log[answer], user_feedback: log[feedback], contexts_used: log[retrieved_contexts], timestamp: log[timestamp], }) # 重点关注负反馈案例 negative_cases [c for c in eval_cases if c[user_feedback] thumbs_down] return negative_cases## 自动化评估Pipeline建立自动化评估流程让每次改动都能快速看到数字反馈pythonimport jsonfrom datetime import datetimefrom typing import Callableclass RAGEvaluator: def __init__(self, rag_system, eval_dataset: list[dict], llm_judgeNone): self.rag rag_system self.dataset eval_dataset self.llm_judge llm_judge or ChatOpenAI(modelgpt-4o-mini) def evaluate_faithfulness(self, question: str, answer: str, contexts: list[str]) - float: 用LLM评估答案对上下文的忠实度 prompt f 评估以下答案是否完全基于提供的上下文忠实度评分。 问题{question} 上下文{chr(10).join(contexts)} 答案{answer} 评分标准0-1 1.0答案完全基于上下文无任何捏造 0.5答案主要基于上下文有轻微延伸 0.0答案包含上下文中没有的信息或与上下文矛盾 只输出一个0到1之间的小数 score float(self.llm_judge.invoke(prompt).content.strip()) return max(0.0, min(1.0, score)) def run_full_evaluation(self, experiment_name: str None) - dict: 运行完整评估 results [] for item in self.dataset: question item[question] expected item.get(ground_truth_answer, ) # 运行RAG系统 rag_result self.rag.query(question) answer rag_result[answer] contexts rag_result[contexts] # 计算各项指标 faithfulness_score self.evaluate_faithfulness(question, answer, contexts) results.append({ question: question, answer: answer, faithfulness: faithfulness_score, contexts_count: len(contexts), }) # 汇总 avg_faithfulness sum(r[faithfulness] for r in results) / len(results) summary { experiment: experiment_name or datetime.now().isoformat(), total_questions: len(results), avg_faithfulness: avg_faithfulness, timestamp: datetime.now().isoformat(), } print(f评估完成:) print(f 忠实度: {avg_faithfulness:.3f}) return {summary: summary, details: results}## 常见问题的诊断与修复有了评估体系你就能系统诊断问题**问题Recall5低0.7**→ 检索策略有问题→ 排查Embedding模型是否适合领域、chunk size是否合理、是否需要混合检索BM25向量问题Faithfulness低0.8→ 生成模型不忠实上下文→ 排查系统提示是否强调基于上下文回答、上下文是否太长导致模型忽略、是否需要更换模型问题Answer Relevancy低0.7→ 答案没有回答用户的问题→ 排查检索到的文档是否真正相关、生成模型是否理解了问题意图问题端到端准确率低但各子指标高→ 组合问题通常是上下文拼接逻辑或最终生成的问题## 建立持续评估文化最后技术层面的评估体系只是基础。更重要的是建立团队的评估文化1.每次重要修改前后都运行评估对比数字不凭直觉判断好坏2.定期每周/每月回顾评估趋势及时发现回退3.收集真实用户反馈作为评估数据集的持续补充4.设立基准Baseline记录每个重要版本的评估结果评估是RAG工程化的核心基础设施。没有评估就像在黑暗中摸索有了评估才能把RAG从感觉还行提升到数据证明可靠。