Ragas 大模型评测框架深度调研指南

Ragas 大模型评测框架深度调研指南

目录


一、Ragas 是什么

Ragas (Retrieval-Augmented Generation Assessment)是一个专门用于评估 RAG(检索增强生成)系统 性能的 Python 开源框架。

1.1 核心价值

价值点 说明
评估驱动开发 将评估融入开发流程,而非事后补充
自动化测试 自动测试 RAG 系统的各个组件
多模型支持 支持本地和云端大模型作为评估器
可量化指标 提供数值化的性能评估指标
易于集成 与 LangChain、LlamaIndex 等框架无缝对接

1.2 适用场景

复制代码
┌─────────────────────────────────────────────────────────┐
│                     Ragas 适用场景                       │
├─────────────────────────────────────────────────────────┤
│  ✓ 知识库问答系统评估                                    │
│  ✓ 企业级 RAG 应用性能监控                              │
│  ✓ 不同检索策略对比分析                                  │
│  ✓ LLM 幻觉检测                                          │
│  ✓ CI/CD 自动化测试                                      │
└─────────────────────────────────────────────────────────┘

二、核心评估指标

2.1 指标体系概览

scss 复制代码
                    Ragas 评估指标体系
                           │
        ┌──────────────────┼──────────────────┐
        │                                      │
    检索质量指标                           生成质量指标
        │                                      │
        ├─ Context Precision                  ├─ Faithfulness
        │  (上下文精确度)                      │  (忠实度)
        │                                      │
        ├─ Context Recall                     ├─ Answer Relevancy
        │  (上下文召回率)                      │  (答案相关性)
        │                                      │
        └─ Context Entity Recall              └─ Factual Correctness
           (上下文实体召回)                      (事实正确性)

2.2 检索质量指标

Context Precision(上下文精确度)

定义:衡量检索到的上下文与问题的相关性

diff 复制代码
评分标准:
- 高分:检索到的文档都高度相关,没有噪音
- 中分:部分相关,存在一些不相关内容
- 低分:检索结果包含大量不相关内容

应用场景

  • 评估向量数据库检索效果
  • 对比不同 embedding 模型
  • 优化 chunk size 和 overlap 参数
Context Recall(上下文召回率)

定义:衡量检索信息的完整性,是否覆盖回答所需的所有关键信息

diff 复制代码
评分标准:
- 高分:检索到的信息足够回答问题
- 中分:部分信息缺失,但可勉强回答
- 低分:关键信息缺失,无法准确回答
Context Entity Recall(上下文实体召回)

定义:专门评估实体(如人名、地名、时间等)的召回情况

2.3 生成质量指标

Faithfulness(忠实度)

定义:衡量答案是否基于检索到的上下文,检测幻觉问题

python 复制代码
# 评估问题示例
"答案中的所有声明是否都能在检索到的上下文中找到依据?"

评分维度:
- 事实一致性
- 无额外编造信息
- 逻辑推理正确性
Answer Relevancy(答案相关性)

定义:衡量答案与问题的相关程度

python 复制代码
# 评估方法
1. 将答案转换为反向问题
2. 计算反向问题与原问题的相似度
3. 评分范围:0-1,越高越好
Factual Correctness(事实正确性)

定义:衡量答案的事实准确性,通常需要参考标准答案

2.4 指标选择建议

评估目标 推荐指标组合
检索系统优化 Context Precision + Context Recall
幻觉检测 Faithfulness
用户体验评估 Answer Relevancy + Faithfulness
完整评估 全部指标

三、安装与配置

3.1 基础安装

bash 复制代码
# 标准安装
pip install ragas

# 完整安装(包含示例和额外依赖)
pip install ragas[examples]

# 从源码安装
git clone https://github.com/explodinggradients/ragas.git
cd ragas
pip install -e .

3.2 版本要求

yaml 复制代码
核心依赖:
  Python: ">=3.8"
  langchain: ">=0.1.0"
  langchain-openai: ">=0.0.5"

可选依赖:
  openai: 用于 GPT 模型
  anthropic: 用于 Claude 模型
  sentence-transformers: 用于本地 embedding

3.3 配置评估器 LLM

方式一:使用 OpenAI
python 复制代码
import os
from langchain_openai import ChatOpenAI
from ragas.llms import LangchainLLMWrapper

# 配置环境变量
os.environ["OPENAI_API_KEY"] = "your-api-key"

# 初始化 LLM
llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0,
    max_tokens=1024
)

# 包装为 Ragas 评估器
evaluator_llm = LangchainLLMWrapper(llm)
方式二:使用本地模型(Ollama)
python 复制代码
from langchain_community.llms import Ollama
from ragas.llms import LangchainLLMWrapper

# 使用本地 Ollama 模型
llm = Ollama(
    model="llama3.2",
    temperature=0
)

evaluator_llm = LangchainLLMWrapper(llm)
方式三:使用 Azure OpenAI
python 复制代码
from langchain_openai import AzureChatOpenAI
from ragas.llms import LangchainLLMWrapper

llm = AzureChatOpenAI(
    azure_endpoint="your-endpoint",
    api_key="your-api-key",
    api_version="2024-02-15-preview",
    deployment_name="your-deployment"
)

evaluator_llm = LangchainLLMWrapper(llm)

3.4 配置 Embedding 模型

python 复制代码
import openai
from ragas.embeddings import OpenAIEmbeddings

# OpenAI Embeddings
openai_client = openai.OpenAI(api_key="your-api-key")
embeddings = OpenAIEmbeddings(client=openai_client)

# 或者使用 HuggingFace
from ragas.embeddings import HuggingfaceEmbeddings

embeddings = HuggingfaceEmbeddings(
    model_name="BAAI/bge-large-zh-v1.5"
)

四、完整使用流程

4.1 构建简单 RAG 系统

python 复制代码
import numpy as np
from langchain_openai import ChatOpenAI
from ragas.embeddings import OpenAIEmbeddings
import openai

class SimpleRAG:
    """
    简单的 RAG 系统实现
    遵循单一职责原则,每个方法只做一件事
    """

    def __init__(self, model: str = "gpt-4o"):
        """
        初始化 RAG 系统

        Args:
            model: 使用的 LLM 模型名称
        """
        self.llm = ChatOpenAI(model=model)
        openai_client = openai.OpenAI()
        self.embeddings = OpenAIEmbeddings(client=openai_client)
        self.doc_embeddings = None
        self.docs = None

    def load_documents(self, documents: list[str]) -> None:
        """
        加载文档并计算向量

        Args:
            documents: 文档列表
        """
        self.docs = documents
        self.doc_embeddings = self.embeddings.embed_texts(documents)

    def _compute_similarity(self, query_embedding: np.ndarray,
                          doc_embedding: np.ndarray) -> float:
        """
        计算查询和文档的余弦相似度

        Args:
            query_embedding: 查询向量
            doc_embedding: 文档向量

        Returns:
            相似度分数
        """
        return np.dot(query_embedding, doc_embedding) / (
            np.linalg.norm(query_embedding) * np.linalg.norm(doc_embedding)
        )

    def get_most_relevant_docs(self, query: str, top_k: int = 1) -> list[str]:
        """
        检索最相关文档

        Args:
            query: 用户查询
            top_k: 返回文档数量

        Returns:
            最相关的文档列表
        """
        if self.docs is None or self.doc_embeddings is None:
            raise ValueError("请先调用 load_documents 加载文档")

        query_embedding = self.embeddings.embed_text(query)
        similarities = [
            self._compute_similarity(query_embedding, doc_emb)
            for doc_emb in self.doc_embeddings
        ]

        # 获取 top_k 个最相关文档的索引
        top_indices = np.argsort(similarities)[-top_k:][::-1]
        return [self.docs[i] for i in top_indices]

    def generate_answer(self, query: str, relevant_docs: list[str]) -> str:
        """
        基于检索到的文档生成答案

        Args:
            query: 用户查询
            relevant_docs: 相关文档列表

        Returns:
            生成的答案
        """
        context = "\n\n".join(relevant_docs)
        prompt = f"问题: {query}\n\n参考文档:\n{context}\n\n请根据参考文档回答问题。"

        messages = [
            ("system", "你是一个有帮助的助手,仅基于提供的文档回答问题。"),
            ("human", prompt),
        ]

        ai_msg = self.llm.invoke(messages)
        return ai_msg.content

    def query(self, query: str, top_k: int = 1) -> dict:
        """
        完整的查询流程

        Args:
            query: 用户查询
            top_k: 检索文档数量

        Returns:
            包含答案和检索文档的字典
        """
        relevant_docs = self.get_most_relevant_docs(query, top_k)
        answer = self.generate_answer(query, relevant_docs)

        return {
            "query": query,
            "answer": answer,
            "retrieved_docs": relevant_docs
        }

4.2 准备测试数据

python 复制代码
from ragas import EvaluationDataset
import pandas as pd

def prepare_test_dataset(rag: SimpleRAG,
                        queries: list[str],
                        references: list[str] | None = None) -> EvaluationDataset:
    """
    准备评估数据集

    Args:
        rag: RAG 系统实例
        queries: 测试查询列表
        references: 参考答案列表(可选)

    Returns:
        EvaluationDataset 对象
    """
    dataset = []

    for i, query in enumerate(queries):
        # 执行查询
        result = rag.query(query, top_k=3)

        # 构建数据样本
        sample = {
            "user_input": query,
            "retrieved_contexts": result["retrieved_docs"],
            "response": result["answer"]
        }

        # 如果有参考答案,添加到样本中
        if references and i < len(references):
            sample["reference"] = references[i]

        dataset.append(sample)

    return EvaluationDataset.from_list(dataset)


# 示例使用
if __name__ == "__main__":
    # 示例文档
    sample_docs = [
        "阿尔伯特·爱因斯坦提出了相对论,这改变了我们对时间、空间和引力的理解。",
        "玛丽·居里是一位物理学家和化学家,她在放射性研究方面做出了开创性工作,并获得了两次诺贝尔奖。",
        "艾萨克·牛顿制定了运动定律和万有引力定律,奠定了经典力学的基础。",
        "查尔斯·达尔文在《物种起源》一书中提出了自然选择进化论。",
        "阿达·洛芙莱斯因其在查尔斯·巴贝奇早期机械计算机分析机上的工作,被认为是第一位计算机程序员。"
    ]

    # 测试查询
    sample_queries = [
        "谁提出了相对论?",
        "谁是第一位计算机程序员?",
        "艾萨克·牛顿对科学有什么贡献?",
        "谁因放射性研究获得了两次诺贝尔奖?"
    ]

    # 参考答案(可选)
    expected_responses = [
        "阿尔伯特·爱因斯坦提出了相对论",
        "阿达·洛芙莱斯被认为是第一位计算机程序员",
        "艾萨克·牛顿制定了运动定律和万有引力定律",
        "玛丽·居里因放射性研究获得了两次诺贝尔奖"
    ]

    # 初始化 RAG 系统
    rag = SimpleRAG()
    rag.load_documents(sample_docs)

    # 准备评估数据集
    evaluation_dataset = prepare_test_dataset(
        rag=rag,
        queries=sample_queries,
        references=expected_responses
    )

    print(f"数据集准备完成,共 {len(evaluation_dataset)} 个样本")

4.3 执行评估

python 复制代码
from ragas import evaluate
from ragas.metrics import (
    LLMContextRecall,
    Faithfulness,
    FactualCorrectness,
    AnswerRelevancy,
    ContextPrecision
)

def run_evaluation(dataset: EvaluationDataset,
                  evaluator_llm,
                  metrics: list | None = None) -> dict:
    """
    运行 Ragas 评估

    Args:
        dataset: 评估数据集
        evaluator_llm: 评估器 LLM
        metrics: 评估指标列表

    Returns:
        评估结果字典
    """
    if metrics is None:
        # 默认使用核心指标
        metrics = [
            LLMContextRecall(),
            Faithfulness(),
            FactualCorrectness()
        ]

    results = evaluate(
        dataset=dataset,
        metrics=metrics,
        llm=evaluator_llm
    )

    return results


# 示例使用
if __name__ == "__main__":
    # 配置评估器
    evaluator_llm = LangchainLLMWrapper(
        ChatOpenAI(model="gpt-4o", temperature=0)
    )

    # 定义评估指标
    metrics = [
        ContextPrecision(),
        LLMContextRecall(),
        Faithfulness(),
        AnswerRelevancy(),
    ]

    # 运行评估
    results = run_evaluation(
        dataset=evaluation_dataset,
        evaluator_llm=evaluator_llm,
        metrics=metrics
    )

    # 输出结果
    print("=" * 50)
    print("Ragas 评估结果")
    print("=" * 50)
    for metric, score in results.items():
        print(f"{metric}: {score:.4f}")
    print("=" * 50)

    # 保存结果
    results_df = results.to_pandas()
    results_df.to_csv("rag_evaluation_results.csv", index=False)

4.4 完整示例脚本

python 复制代码
"""
完整的 Ragas 评估示例脚本
演示从构建 RAG 到评估的完整流程
"""

import os
import pandas as pd
from typing import Optional
import numpy as np
from langchain_openai import ChatOpenAI
from ragas.embeddings import OpenAIEmbeddings
from ragas import EvaluationDataset, evaluate
from ragas.llms import LangchainLLMWrapper
from ragas.metrics import (
    ContextPrecision,
    LLMContextRecall,
    Faithfulness,
    AnswerRelevancy
)
import openai


class RAGEvaluator:
    """
    RAG 系统评估器
    封装完整的评估流程
    """

    def __init__(self,
                 llm_model: str = "gpt-4o",
                 evaluator_model: str = "gpt-4o"):
        """
        初始化评估器

        Args:
            llm_model: RAG 系统使用的 LLM
            evaluator_model: 评估器使用的 LLM
        """
        # 初始化 RAG 系统 LLM
        self.rag_llm = ChatOpenAI(model=llm_model)

        # 初始化评估器 LLM
        self.evaluator_llm = ChatOpenAI(
            model=evaluator_model,
            temperature=0
        )
        evaluator_wrapper = LangchainLLMWrapper(self.evaluator_llm)

        # 初始化 Embeddings
        openai_client = openai.OpenAI()
        self.embeddings = OpenAIEmbeddings(client=openai_client)

        self.doc_embeddings = None
        self.docs = None

    def load_knowledge_base(self, documents: list[str]) -> None:
        """加载知识库"""
        self.docs = documents
        self.doc_embeddings = self.embeddings.embed_texts(documents)

    def _retrieve_docs(self, query: str, top_k: int = 3) -> list[str]:
        """检索相关文档"""
        query_emb = self.embeddings.embed_text(query)
        similarities = [
            np.dot(query_emb, doc_emb) /
            (np.linalg.norm(query_emb) * np.linalg.norm(doc_emb))
            for doc_emb in self.doc_embeddings
        ]
        top_indices = np.argsort(similarities)[-top_k:][::-1]
        return [self.docs[i] for i in top_indices]

    def _generate_response(self, query: str, contexts: list[str]) -> str:
        """生成响应"""
        context_text = "\n\n".join(contexts)
        prompt = f"基于以下文档回答问题:\n\n{context_text}\n\n问题:{query}"

        messages = [
            ("system", "你是一个有帮助的助手。仅基于提供的文档回答问题,不要编造信息。"),
            ("human", prompt)
        ]

        response = self.rag_llm.invoke(messages)
        return response.content

    def build_dataset(self,
                     queries: list[str],
                     references: Optional[list[str]] = None) -> EvaluationDataset:
        """构建评估数据集"""
        dataset = []

        for i, query in enumerate(queries):
            contexts = self._retrieve_docs(query)
            response = self._generate_response(query, contexts)

            sample = {
                "user_input": query,
                "retrieved_contexts": contexts,
                "response": response
            }

            if references and i < len(references):
                sample["reference"] = references[i]

            dataset.append(sample)

        return EvaluationDataset.from_list(dataset)

    def evaluate(self,
                dataset: EvaluationDataset,
                metrics: Optional[list] = None) -> dict:
        """执行评估"""
        if metrics is None:
            metrics = [
                ContextPrecision(),
                LLMContextRecall(),
                Faithfulness(),
                AnswerRelevancy()
            ]

        results = evaluate(
            dataset=dataset,
            metrics=metrics,
            llm=LangchainLLMWrapper(self.evaluator_llm)
        )

        return results

    def run_full_pipeline(self,
                         documents: list[str],
                         queries: list[str],
                         references: Optional[list[str]] = None,
                         save_path: str = "results.csv") -> dict:
        """运行完整的评估流程"""
        # 1. 加载知识库
        self.load_knowledge_base(documents)

        # 2. 构建数据集
        dataset = self.build_dataset(queries, references)

        # 3. 执行评估
        results = self.evaluate(dataset)

        # 4. 保存结果
        results_df = results.to_pandas()
        results_df.to_csv(save_path, index=False)

        return results


# 使用示例
def main():
    """主函数示例"""
    # 设置 API Key
    os.environ["OPENAI_API_KEY"] = "your-api-key"

    # 示例知识库
    documents = [
        "Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。",
        "JavaScript 是一种脚本语言,主要用于 Web 开发,由 Brendan Eich 在 1995 年创建。",
        "Rust 是一种系统编程语言,注重安全、并发和性能,由 Mozilla 开发。",
        "Go 是由 Google 开发的静态类型编程语言,以其简洁性和高效性著称。",
        "TypeScript 是 JavaScript 的超集,添加了静态类型,由 Microsoft 开发。"
    ]

    # 测试查询
    queries = [
        "谁创建了 Python?",
        "JavaScript 主要用于什么?",
        "Rust 的主要特点是什么?"
    ]

    # 参考答案
    references = [
        "Guido van Rossum 在 1991 年创建了 Python",
        "JavaScript 主要用于 Web 开发",
        "Rust 的主要特点是安全、并发和性能"
    ]

    # 初始化评估器
    evaluator = RAGEvaluator(
        llm_model="gpt-4o",
        evaluator_model="gpt-4o"
    )

    # 运行完整评估流程
    results = evaluator.run_full_pipeline(
        documents=documents,
        queries=queries,
        references=references,
        save_path="evaluation_results.csv"
    )

    # 打印结果
    print("\n" + "=" * 60)
    print("Ragas 评估报告")
    print("=" * 60)
    for metric_name, score in results.items():
        print(f"{metric_name:30s}: {score:.4f}")
    print("=" * 60)


if __name__ == "__main__":
    main()

五、自定义评估指标

5.1 离散指标(DiscreteMetric)

python 复制代码
from ragas.metrics import DiscreteMetric

# 创建自定义通过/失败指标
correctness_metric = DiscreteMetric(
    name="correctness",
    prompt="""检查响应是否包含评分标准中提到的要点。
只返回 'pass' 或 'fail'。

响应: {response}
评分标准: {grading_notes}""",
    allowed_values=["pass", "fail"],
)

# 使用自定义指标
score = correctness_metric.score(
    llm=evaluator_llm,
    response="Python 是由 Guido van Rossum 创建的",
    grading_notes="- 必须提及 Guido van Rossum\n- 必须提及编程语言"
)

print(f"评分结果: {score.value}")  # 输出: pass 或 fail

5.2 连续指标(ContinuousMetric)

python 复制代码
from ragas.metrics import ContinuousMetric

# 创建自定义 0-1 评分指标
completeness_metric = ContinuousMetric(
    name="completeness",
    prompt="""评估响应的完整性(0-1 分)。

问题: {question}
响应: {response}
参考答案: {reference}

评分标准:
- 1.0: 完全覆盖所有要点
- 0.5: 覆盖部分要点
- 0.0: 未覆盖任何要点

只返回数字分数。""",
)

# 使用自定义指标
score = completeness_metric.score(
    llm=evaluator_llm,
    question="什么是 Python?",
    response="Python 是一种编程语言",
    reference="Python 是一种高级编程语言,由 Guido van Rossum 创建"
)

print(f"完整性得分: {score.value}")

5.3 带推理的指标

python 复制代码
from ragas.metrics import MetricWithLLM

class CustomMetric(MetricWithLLM):
    """自定义带推理的评估指标"""

    name = "custom_metric"

    def _score(self, row: dict, llm) -> float:
        """计算分数"""
        prompt = f"""
        评估以下响应的质量:

        问题: {row['user_input']}
        上下文: {row['retrieved_contexts']}
        响应: {row['response']}

        给出 0-1 的分数,并简要说明理由。
        """

        response = llm.generate(prompt)
        # 解析响应提取分数
        score = self._extract_score(response)
        return score

    def _extract_score(self, response: str) -> float:
        """从 LLM 响应中提取分数"""
        import re
        match = re.search(r'(\d+\.?\d*)', response)
        if match:
            return float(match.group(1))
        return 0.0

六、最佳实践

6.1 评估驱动开发流程

markdown 复制代码
┌─────────────────────────────────────────────────────────┐
│                  评估驱动开发(EDD)流程                   │
└─────────────────────────────────────────────────────────┘

    1. 定义评估目标
           │
           ▼
    2. 准备测试数据集
           │
           ▼
    3. 实现基础 RAG 系统
           │
           ▼
    4. 运行基准评估
           │
           ▼
    5. 分析瓶颈
           │
           ▼
    6. 优化迭代
           │
           ▼
    7. 重新评估 → 循环至步骤 5

6.2 测试数据集准备

数据集质量标准
维度 标准
覆盖度 覆盖不同类型的问题(事实型、推理型、开放型)
难度梯度 包含简单、中等、困难样本
边界情况 包含无答案、多答案等特殊情况
数据量 建议至少 50-100 个测试样本
测试样本分类
python 复制代码
# 分类示例
test_samples = {
    "factual": [  # 事实型问题
        "Python 的创建者是谁?",
        "JavaScript 什么时候发布?"
    ],
    "reasoning": [  # 推理型问题
        "为什么 Rust 被认为更安全?",
        "比较 Python 和 Go 的适用场景"
    ],
    "open_ended": [  # 开放型问题
        "选择合适的编程语言需要考虑哪些因素?",
        "解释静态类型和动态类型的区别"
    ],
    "edge_cases": [  # 边界情况
        "如何用 Brainfuck 编写 Web 应用?",  # 知识库中无答案
        "什么是这门语言?",  # 模糊指代
    ]
}

6.3 性能优化建议

1. 批量评估
python 复制代码
# 使用批量 API 提高评估速度
from ragas import RunConfig

results = evaluate(
    dataset=dataset,
    metrics=metrics,
    llm=evaluator_llm,
    run_config=RunConfig(
        batch_size=10,  # 批量大小
        timeout=30,     # 超时时间(秒)
    )
)
2. 并行评估
python 复制代码
import asyncio
from concurrent.futures import ThreadPoolExecutor

async def parallel_evaluation(datasets, metrics):
    """并行评估多个数据集"""
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = [
            executor.submit(evaluate, ds, metrics, evaluator_llm)
            for ds in datasets
        ]
        results = [f.result() for f in futures]
    return results
3. 缓存机制
python 复制代码
from functools import lru_cache

@lru_cache(maxsize=1000)
def cached_evaluate(query: str, context: str, response: str):
    """带缓存的评估函数"""
    # 评估逻辑
    pass

6.4 本地模型使用

python 复制代码
"""
使用本地模型降低成本
适用于:敏感数据、成本控制、低延迟场景
"""

# 使用 Ollama 本地模型
from langchain_community.llms import Ollama

# 配置本地评估器
local_evaluator = Ollama(
    model="llama3.2:latest",
    temperature=0,
    num_ctx=4096
)

# 使用本地模型进行评估
results = evaluate(
    dataset=dataset,
    metrics=[ContextPrecision(), Faithfulness()],
    llm=LangchainLLMWrapper(local_evaluator)
)

七、进阶功能

7.1 与 LangChain 集成

python 复制代码
from langchain_core.vectorstores import VectorStore
from langchain_core.retrievers import BaseRetriever
from ragas import evaluate
from ragas.integrations.langchain import EvaluatorChain

# 创建评估链
evaluator_chain = EvaluatorChain(
    metrics=[ContextPrecision(), Faithfulness()],
    evaluator_llm=evaluator_llm
)

# 在 LangChain 管道中使用
from langchain_core.runnables import RunnablePassthrough

rag_chain = (
    {
        "query": RunnablePassthrough(),
        "context": retriever | (lambda docs: "\n".join([d.page_content for d in docs]))
    }
    | prompt
    | llm
    | evaluator_chain  # 添加评估
)

7.2 持续监控

python 复制代码
"""
将 Ragas 集成到 CI/CD 流程
"""

import json
from datetime import datetime

class CICDEvaluator:
    """CI/CD 评估器"""

    def __init__(self, baseline_file: str = "baseline.json"):
        self.baseline_file = baseline_file
        self.baseline = self._load_baseline()

    def _load_baseline(self) -> dict:
        """加载基准分数"""
        try:
            with open(self.baseline_file) as f:
                return json.load(f)
        except FileNotFoundError:
            return {}

    def save_baseline(self, scores: dict) -> None:
        """保存基准分数"""
        with open(self.baseline_file, 'w') as f:
            json.dump(scores, f, indent=2)

    def check_regression(self, current_scores: dict,
                        threshold: float = 0.05) -> dict:
        """检查性能回归"""
        regressions = {}

        for metric, current_score in current_scores.items():
            if metric in self.baseline:
                baseline_score = self.baseline[metric]
                if current_score < baseline_score - threshold:
                    regressions[metric] = {
                        "baseline": baseline_score,
                        "current": current_score,
                        "diff": current_score - baseline_score
                    }

        return regressions

    def run_ci_check(self, dataset: EvaluationDataset) -> bool:
        """运行 CI 检查"""
        # 执行评估
        results = evaluate(dataset=dataset, metrics=metrics)

        # 检查回归
        regressions = self.check_regression(results)

        if regressions:
            print("❌ 发现性能回归:")
            for metric, info in regressions.items():
                print(f"  {metric}: {info['baseline']:.3f} → {info['current']:.3f}")
            return False
        else:
            print("✅ 所有指标正常")
            self.save_baseline(results)
            return True


# 在 CI 脚本中使用
if __name__ == "__main__":
    evaluator = CICDEvaluator()
    passed = evaluator.run_ci_check(evaluation_dataset)

    if not passed:
        exit(1)  # CI 失败

7.3 多模型对比

python 复制代码
"""
对比不同模型的性能
"""

import matplotlib.pyplot as plt

def compare_models(dataset: EvaluationDataset,
                  model_configs: list[dict]) -> pd.DataFrame:
    """
    对比多个模型

    Args:
        dataset: 测试数据集
        model_configs: 模型配置列表
            [{"name": "gpt-4", "model": "gpt-4"},
             {"name": "gpt-3.5", "model": "gpt-3.5-turbo"}]
    """
    results = []

    for config in model_configs:
        # 使用该模型构建 RAG
        rag = SimpleRAG(model=config["model"])

        # 评估
        scores = evaluate(
            dataset=dataset,
            metrics=metrics,
            llm=LangchainLLMWrapper(ChatOpenAI(model=config["model"]))
        )

        # 记录结果
        scores["model"] = config["name"]
        results.append(scores)

    return pd.DataFrame(results)


# 使用示例
model_configs = [
    {"name": "GPT-4", "model": "gpt-4"},
    {"name": "GPT-3.5", "model": "gpt-3.5-turbo"},
    {"name": "Claude-3", "model": "claude-3-opus-20240229"}
]

comparison_df = compare_models(evaluation_dataset, model_configs)

# 可视化
comparison_df.plot(x="model", kind="bar")
plt.title("模型性能对比")
plt.ylabel("分数")
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.savefig("model_comparison.png")

7.4 A/B 测试

python 复制代码
"""
对新版本进行 A/B 测试
"""

class ABTest:
    """A/B 测试框架"""

    def __init__(self, control_rag, treatment_rag, dataset):
        self.control = control_rag
        self.treatment = treatment_rag
        self.dataset = dataset

    def run(self, sample_size: int = 100) -> dict:
        """运行 A/B 测试"""
        # 随机采样
        samples = self.dataset.sample(min(sample_size, len(self.dataset)))

        # 评估对照组
        control_results = self._evaluate_system(self.control, samples)

        # 评估实验组
        treatment_results = self._evaluate_system(self.treatment, samples)

        # 统计显著性测试
        return self._analyze_results(control_results, treatment_results)

    def _evaluate_system(self, rag, samples):
        """评估单个系统"""
        results = []
        for _, row in samples.iterrows():
            result = rag.query(row["query"])
            results.append(result)
        return results

    def _analyze_results(self, control, treatment):
        """分析结果"""
        from scipy import stats

        analysis = {}
        for metric in control.keys():
            # t 检验
            t_stat, p_value = stats.ttest_ind(
                control[metric],
                treatment[metric]
            )
            analysis[metric] = {
                "control_mean": np.mean(control[metric]),
                "treatment_mean": np.mean(treatment[metric]),
                "p_value": p_value,
                "significant": p_value < 0.05
            }

        return analysis

八、常见问题

8.1 安装问题

Q: pip install 失败怎么办?

bash 复制代码
# 尝试升级 pip
python -m pip install --upgrade pip

# 使用国内镜像
pip install ragas -i https://pypi.tuna.tsinghua.edu.cn/simple

# 使用 conda
conda install -c conda-forge ragas

Q: 导入错误?

python 复制代码
# 检查版本兼容性
import ragas
print(ragas.__version__)

# 重新安装
pip uninstall ragas
pip install ragas --no-cache-dir

8.2 评估问题

Q: 评估分数异常(全是 0 或 1)?

python 复制代码
# 检查 1: 验证数据格式
print(evaluation_dataset[0])

# 检查 2: 查看 LLM 响应
# 设置更详细的日志
import logging
logging.basicConfig(level=logging.DEBUG)

# 检查 3: 调整 temperature
evaluator_llm = ChatOpenAI(
    model="gpt-4",
    temperature=0  # 确保为 0
)

Q: 评估速度太慢?

python 复制代码
# 方案 1: 使用批量处理
from ragas import RunConfig
results = evaluate(
    dataset=dataset,
    metrics=metrics,
    run_config=RunConfig(batch_size=20)
)

# 方案 2: 使用更快的模型
evaluator_llm = ChatOpenAI(model="gpt-3.5-turbo")

# 方案 3: 并行评估
# (参考 6.3 节代码)

Q: 内存不足?

python 复制代码
# 分批评估
batch_size = 50
all_results = []

for i in range(0, len(dataset), batch_size):
    batch = dataset[i:i+batch_size]
    results = evaluate(batch, metrics, evaluator_llm)
    all_results.append(results)

# 合并结果
final_results = merge_results(all_results)

8.3 API 问题

Q: OpenAI API 限流?

python 复制代码
import time
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3),
       wait=wait_exponential(multiplier=1, min=4, max=10))
def evaluate_with_retry(dataset, metrics, llm):
    return evaluate(dataset=dataset, metrics=metrics, llm=llm)

Q: 如何使用其他 LLM?

python 复制代码
# 使用 Anthropic Claude
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(
    model="claude-3-opus-20240229",
    api_key="your-api-key"
)

# 使用本地模型 (Ollama)
from langchain_community.llms import Ollama
llm = Ollama(model="llama3.2")

九、相关资源

9.1 官方资源

资源 链接
GitHub 仓库 github.com/explodinggr...
官方文档 docs.ragas.io
快速入门 docs.ragas.io/en/stable/g...
API 参考 docs.ragas.io/en/stable/r...

9.2 中文教程

标题 链接
RAG系统效果难评?2025年必备的RAG评估框架与工具详解 zhuanlan.zhihu.com/p/189252947...
RAG评测终极指南!Ragas+RAGFlow实战 blog.csdn.net/m0_59235945...
深度测评RAG应用评估框架:指标最全面的Ragas cloud.tencent.com/developer/a...
使用本地私有大模型进行RAGAS评估 blog.csdn.net/qq_46024883...

9.3 视频教程

平台 标题 链接
B站 2025年最全最细的大模型RAG教程 www.bilibili.com/video/BV1D3...
YouTube How to Evaluate a RAG Application www.youtube.com/watch?v=5fp...

9.4 社区与支持

资源 链接
Discord 社区 discord.gg/ragas
Stack Overflow [tag:ragas]
论坛讨论 github.com/explodinggr...

附录

A. 快速参考

python 复制代码
# 常用导入
from ragas import evaluate, EvaluationDataset
from ragas.metrics import (
    ContextPrecision,
    LLMContextRecall,
    Faithfulness,
    AnswerRelevancy,
    FactualCorrectness
)
from ragas.llms import LangchainLLMWrapper
from langchain_openai import ChatOpenAI

# 标准评估流程
evaluator_llm = LangchainLLMWrapper(ChatOpenAI(model="gpt-4o"))
results = evaluate(
    dataset=evaluation_dataset,
    metrics=[
        ContextPrecision(),
        LLMContextRecall(),
        Faithfulness()
    ],
    llm=evaluator_llm
)

B. 评估指标速查表

指标 类型 范围 适用场景
Context Precision 检索 0-1 检索质量评估
Context Recall 检索 0-1 检索完整性
Faithfulness 生成 0-1 幻觉检测
Answer Relevancy 生成 0-1 答案质量
Factual Correctness 生成 0-1 事实准确性

C. 配置模板

yaml 复制代码
# ragas_config.yaml
evaluation:
  # 评估器配置
  evaluator:
    model: "gpt-4o"
    temperature: 0
    max_tokens: 1024

  # 指标配置
  metrics:
    - context_precision
    - context_recall
    - faithfulness
    - answer_relevancy

  # 运行配置
  run_config:
    batch_size: 10
    timeout: 30
    max_retries: 3

  # 输出配置
  output:
    format: "csv"
    path: "./results"
    save_detailed: true

文档结束

如有问题或建议,欢迎反馈!

相关推荐
qq_256247052 小时前
拯救“复读机”:从小模型死循环看 Logits 到 Dist 的全流程采样机制
后端
七八星天2 小时前
Exception异常与异常处理(.Net)
后端
千寻技术帮2 小时前
10340_基于Springboot的游戏网站
spring boot·后端·游戏·vue·商城
于顾而言2 小时前
【一文带你搞懂】漏扫核弹Nuclei
后端
WX-bisheyuange2 小时前
基于SpringBoot的诊疗预约平台
java·spring boot·后端·毕业设计
SimonKing2 小时前
基于Netty的WebSocket客户端
java·后端·程序员
麦兜*3 小时前
Spring Boot 整合 Spring Data JPA 入门:只需注解,告别 SQL
spring boot·后端·sql
Sally璐璐3 小时前
RESTful与RPC接口终极对比指南
后端·rpc·restful
J_liaty3 小时前
前后端跨域处理全指南:Java后端+Vue前端完整解决方案
java·前端·vue.js·spring boot·后端