引言

“我的RAG系统效果怎么样?“这是每个RAG开发者都会问的问题。但回答这个问题并不简单——RAG系统包含检索和生成两个环节,每个环节都有多个质量维度。

2026年,RAG评估已经形成了一套比较完整的指标体系。从检索的准确率和召回率,到生成的忠实度和相关性,再到端到端的用户满意度。本文将系统介绍这些指标。

一、RAG评估框架

1.1 评估维度

RAG系统
├── 检索质量
│   ├── 准确率(Precision)
│   ├── 召回率(Recall)
│   ├── 排序质量(NDCG/MRR)
│   └── 多样性(Diversity)
├── 生成质量
│   ├── 忠实度(Faithfulness)
│   ├── 答案相关性(Answer Relevance)
│   ├── 完整性(Completeness)
│   └── 正确性(Correctness)
└── 端到端质量
    ├── 用户满意度
    ├── 响应延迟
    └── 成本效率

1.2 评估方法

  • 人工评估:最准确但成本高
  • 自动评估:使用LLM或规则自动评估
  • 基准测试:在标准数据集上测试
  • A/B测试:线上对比不同版本

二、检索质量指标

2.1 准确率与召回率

class RetrievalMetrics:
    def precision_at_k(self, retrieved, relevant, k):
        """Top-K准确率"""
        retrieved_k = retrieved[:k]
        relevant_set = set(relevant)
        retrieved_set = set(retrieved_k)
        return len(relevant_set & relevant_set) / k
    
    def recall_at_k(self, retrieved, relevant, k):
        """Top-K召回率"""
        retrieved_k = retrieved[:k]
        relevant_set = set(relevant)
        retrieved_set = set(retrieved_k)
        return len(retrieved_set & relevant_set) / len(relevant_set)
    
    def average_precision(self, retrieved, relevant):
        """平均准确率"""
        relevant_set = set(relevant)
        precisions = []
        num_relevant = 0
        
        for i, doc in enumerate(retrieved):
            if doc in relevant_set:
                num_relevant += 1
                precisions.append(num_relevant / (i + 1))
        
        if not precisions:
            return 0.0
        return np.mean(precisions)
    
    def mean_average_precision(self, queries_results):
        """MAP"""
        return np.mean([self.average_precision(r["retrieved"], r["relevant"]) 
                       for r in queries_results])

2.2 排序质量

    def ndcg_at_k(self, retrieved, relevance_scores, k):
        """NDCG@K"""
        # DCG
        dcg = sum(
            (2 ** relevance_scores.get(doc, 0) - 1) / np.log2(i + 2)
            for i, doc in enumerate(retrieved[:k])
        )
        
        # IDCG(理想排序的DCG)
        ideal_order = sorted(relevance_scores.values(), reverse=True)[:k]
        idcg = sum(
            (2 ** score - 1) / np.log2(i + 2)
            for i, score in enumerate(ideal_order)
        )
        
        return dcg / idcg if idcg > 0 else 0
    
    def mrr(self, queries_results):
        """平均倒数排名"""
        reciprocal_ranks = []
        for result in queries_results:
            for i, doc in enumerate(result["retrieved"]):
                if doc in result["relevant"]:
                    reciprocal_ranks.append(1 / (i + 1))
                    break
            else:
                reciprocal_ranks.append(0)
        return np.mean(reciprocal_ranks)

2.3 上下文相关性

class ContextRelevanceMetric:
    async def measure(self, question, retrieved_context):
        """评估检索到的上下文与问题的相关性"""
        prompt = f"""
        问题: {question}
        
        检索到的上下文:
        {self.format_context(retrieved_context)}
        
        请评估上下文与问题的相关性:
        1. 有多少段落直接相关?
        2. 有多少段落间接相关?
        3. 有多少段落完全不相关?
        4. 相关性评分(0-1)
        """
        result = await self.llm.call(prompt)
        return result["relevance_score"]

三、生成质量指标

3.1 忠实度(Faithfulness)

答案是否忠实于检索到的上下文,不产生幻觉:

class FaithfulnessMetric:
    async def measure(self, answer, context):
        """评估答案对上下文的忠实度"""
        # 1. 将答案分解为陈述
        statements = await self.extract_statements(answer)
        
        # 2. 逐一验证每个陈述是否被上下文支持
        supported = 0
        unsupported = []
        
        for stmt in statements:
            is_supported = await self.check_support(stmt, context)
            if is_supported:
                supported += 1
            else:
                unsupported.append(stmt)
        
        faithfulness = supported / len(statements) if statements else 0
        
        return {
            "faithfulness": faithfulness,
            "supported_statements": supported,
            "unsupported_statements": unsupported
        }
    
    async def check_support(self, statement, context):
        """检查陈述是否被上下文支持"""
        prompt = f"""
        陈述: {statement}
        上下文: {context}
        
        这个陈述是否可以从上下文中推导出来?(是/否)
        """
        result = await self.llm.call(prompt)
        return "是" in result

3.2 答案相关性

答案是否直接回答了用户的问题:

class AnswerRelevanceMetric:
    async def measure(self, question, answer):
        """评估答案与问题的相关性"""
        # 方法1: 从答案反向生成问题,比较与原始问题的相似度
        prompt = f"""
        基于以下答案,生成3个可能的问题:
        
        答案: {answer}
        """
        generated_questions = await self.llm.call(prompt)
        
        # 计算生成的问题与原始问题的相似度
        similarities = []
        for gen_q in generated_questions:
            sim = await self.compute_similarity(question, gen_q)
            similarities.append(sim)
        
        return np.mean(similarities)

3.3 完整性

答案是否覆盖了问题的所有方面:

class CompletenessMetric:
    async def measure(self, question, answer, context):
        """评估答案的完整性"""
        # 1. 从问题中提取需要回答的要点
        points = await self.extract_key_points(question)
        
        # 2. 检查每个要点是否在答案中被覆盖
        covered = 0
        uncovered = []
        
        for point in points:
            is_covered = await self.check_coverage(point, answer)
            if is_covered:
                covered += 1
            else:
                uncovered.append(point)
        
        return {
            "completeness": covered / len(points) if points else 1.0,
            "covered_points": covered,
            "uncovered_points": uncovered
        }

四、RAGAS框架

RAGAS(RAG Assessment)是2026年最流行的RAG评估框架:

class RAGAS:
    """RAGAS评估框架"""
    
    async def evaluate(self, question, answer, context, ground_truth=None):
        """RAGAS综合评估"""
        results = {}
        
        # 1. 上下文精确率(Context Precision)
        results["context_precision"] = await self.context_precision(question, context)
        
        # 2. 上下文召回率(Context Recall)
        if ground_truth:
            results["context_recall"] = await self.context_recall(ground_truth, context)
        
        # 3. 忠实度(Faithfulness)
        results["faithfulness"] = await self.faithfulness(answer, context)
        
        # 4. 答案相关性(Answer Relevancy)
        results["answer_relevancy"] = await self.answer_relevancy(question, answer)
        
        # 5. 综合得分
        results["ragas_score"] = np.mean([
            results["context_precision"],
            results.get("context_recall", 1.0),
            results["faithfulness"],
            results["answer_relevancy"]
        ])
        
        return results

五、端到端评估

5.1 人工评估

class HumanEvaluation:
    async def evaluate(self, test_cases, evaluators):
        """人工评估"""
        results = []
        
        for case in test_cases:
            # 生成RAG回答
            rag_answer = await self.rag_system.query(case.question)
            
            # 多个评估员评分
            scores = []
            for evaluator in evaluators:
                score = await evaluator.evaluate(
                    question=case.question,
                    answer=rag_answer,
                    reference=case.expected_answer,
                    criteria=["accuracy", "completeness", "relevance", "fluency"]
                )
                scores.append(score)
            
            # 计算平均分和一致性
            avg_scores = self.average_scores(scores)
            agreement = self.compute_inter_annotator_agreement(scores)
            
            results.append({
                "question": case.question,
                "answer": rag_answer,
                "scores": avg_scores,
                "agreement": agreement
            })
        
        return results

5.2 LLM-as-Judge

class LLMJudge:
    async def judge(self, question, answer, reference=None):
        """使用LLM作为评判"""
        prompt = f"""
        问题: {question}
        答案: {answer}
        {"参考答案: " + reference if reference else ""}
        
        请从以下维度评分(1-5分):
        1. 准确性: 答案是否事实正确
        2. 完整性: 答案是否覆盖所有要点
        3. 相关性: 答案是否直接回答问题
        4. 流畅性: 答案是否表达清晰
        5. 有用性: 答案对用户是否有用
        
        输出JSON格式,包含每个维度的分数和总评。
        """
        result = await self.llm.call(prompt)
        return result

5.3 在线评估

class OnlineEvaluation:
    async def collect_feedback(self, query_id, user_feedback):
        """收集用户反馈"""
        # 用户可以点赞/点踩/评分
        await self.feedback_store.save({
            "query_id": query_id,
            "feedback": user_feedback,
            "timestamp": time.time()
        })
    
    async def analyze_metrics(self, time_window=7*24*3600):
        """分析在线指标"""
        feedback = await self.feedback_store.get_recent(time_window)
        
        return {
            "satisfaction_rate": self.compute_satisfaction(feedback),
            "thumbs_up_rate": self.compute_thumbs_up_rate(feedback),
            "follow_up_rate": self.compute_follow_up_rate(feedback),  # 用户追问比例
            "copy_rate": self.compute_copy_rate(feedback),  # 用户复制答案的比例
            "regeneration_rate": self.compute_regeneration_rate(feedback)  # 用户重新生成的比例
        }

六、基准数据集

6.1 常用基准

数据集类型特点
Natural Questions开放域问答真实用户问题
MS MARCO段落检索大规模检索基准
HotpotQA多跳推理需要多步推理
TriviaQA问答事实型问答
KILT多任务多种知识密集型任务

6.2 自定义评估集

class CustomEvalSetBuilder:
    async def build_from_production(self, production_logs, num_samples=100):
        """从生产日志构建评估集"""
        # 1. 采样真实用户问题
        samples = self.sample_queries(production_logs, num_samples)
        
        # 2. 为每个问题标注标准答案
        for sample in samples:
            sample.ground_truth = await self.generate_ground_truth(sample)
            sample.relevant_docs = await self.identify_relevant_docs(sample)
        
        # 3. 质量审核
        reviewed = await self.human_review(samples)
        
        return reviewed

七、持续评估

class ContinuousEvaluation:
    async def run_continuous_eval(self):
        """持续评估循环"""
        while True:
            # 1. 在评估集上运行
            results = await self.eval_suite.run(self.rag_system)
            
            # 2. 与基线比较
            comparison = self.compare_with_baseline(results)
            
            # 3. 检测退化
            if self.has_degradation(comparison):
                await self.alert_degradation(comparison)
            
            # 4. 更新仪表盘
            await self.update_dashboard(results)
            
            await asyncio.sleep(self.eval_interval)

结语

评估是RAG系统持续改进的基础。没有度量就没有优化。2026年的RAG评估已经形成了多维度、多方法的评估体系——从检索到生成、从自动到人工、从离线到在线。

选择评估指标时,记住:没有单一指标能全面衡量RAG质量。需要根据应用场景选择合适的指标组合。事实型问答关注准确性和忠实度,研究型问答关注完整性和相关性,对话型问答关注连贯性和有用性。

最终,最好的评估指标是用户满意度。所有技术指标都是用户满意度的代理。定期收集用户反馈,让用户告诉你系统是否真的在变好,这才是评估的终极目的。

加入讨论

这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。

碳基与硅基的智慧碰撞,认知差异创造无限可能。