定量评估RAG及可视化

182 阅读50分钟

评估在构建和维护检索增强生成(RAG)管道中起着至关重要的作用。在构建管道时,评估可以帮助你识别需要改进的领域,优化系统的性能,并系统地衡量改进的效果。当RAG系统部署后,评估可以确保系统的有效性、可靠性和性能。

在本章中,我们将讨论以下主题:

  • 构建RAG应用时的评估
  • 部署后RAG应用的评估
  • 标准化的评估框架
  • 真实情况(Ground Truth)
  • 代码实验9.1 – ragas
  • RAG系统的其他评估技术

我们从讨论评估如何在构建RAG系统的初始阶段中起到作用开始。

技术要求

本章的代码位于以下GitHub仓库:github.com/PacktPublis…

在构建过程中进行评估

评估在RAG管道的开发过程中起着至关重要的作用。通过在构建系统的同时持续进行评估,您可以识别需要改进的地方,优化系统性能,并系统地衡量任何修改或增强的影响。

评估对于理解RAG管道中不同方法的权衡和局限性至关重要。RAG管道通常涉及各种技术选择,例如向量存储、检索算法和语言生成模型。这些组件中的每一个都可能对系统的整体性能产生重大影响。通过系统地评估这些组件的不同组合,您可以深入了解哪些方法在特定任务和领域中能产生最佳结果。

例如,您可以尝试不同的嵌入模型,例如本地开源模型(可以免费下载)或每次将文本转换为嵌入时需要付费的云服务API。您可能需要了解云API服务是否优于免费的模型,如果优于,是否足够好以弥补额外的成本。同样,您可以评估各种语言生成模型的性能,如ChatGPT、Llama和Claude。

这种迭代的评估过程帮助您做出关于RAG管道最合适架构和组件的明智决策。通过考虑效率、可扩展性和泛化能力等因素,您可以调整系统,达到最佳性能,同时最小化计算成本,并确保在不同场景下的稳健性。

评估对于理解RAG管道中不同方法的权衡和局限性至关重要。但是,评估在部署后也同样有用,接下来我们将讨论这一点。

部署后进行评估

一旦您的RAG系统部署完成,评估依然是确保其持续有效性、可靠性和性能的关键。对已部署的RAG管道进行持续监控和评估,对于保持系统质量和发现任何潜在问题或性能退化至关重要。

有许多原因可能导致RAG系统的性能在部署后下降。例如,用于检索的数据可能会随着新信息的出现而变得过时或不相关。语言生成模型可能无法适应不断变化的用户查询或目标领域的变化。此外,底层基础设施(如硬件或软件组件)可能会出现性能问题或故障。

设想一个情境,假设您在一家金融财富管理公司,使用RAG应用帮助用户了解最有可能影响他们财务投资组合的因素。您的数据源可能包括过去五年内主要金融公司发布的所有分析报告,涵盖了所有客户所涉及的金融资产。

然而,在金融市场中,世界范围内的重大事件(宏观事件)可能对这些投资组合产生剧烈影响,而这些事件并未被过去五年的数据捕捉到。例如,重大灾难、政治不稳定,或某些股票的区域性事件可能会为其业绩带来新的轨迹。对于您的RAG应用来说,这代表了数据为终端用户提供的价值的变化,随着时间推移,如果没有适时的更新,数据的价值可能会迅速下降。用户可能开始提出一些关于特定事件的问题,RAG应用无法处理,例如:“刚刚发生的五级飓风会在明年对我的投资组合产生什么影响?”但通过持续更新和监控,特别是有关飓风影响的最新报告,这些问题可能会得到很好的解决。

为了减轻这些风险,持续监控RAG系统至关重要,特别是在常见的故障点上。通过持续评估RAG管道中的这些关键组件,您可以主动识别并解决任何性能退化问题。这可能涉及更新检索语料库,以便包含最新且相关的数据,或者对语言生成模型进行微调,使用新数据,或者优化系统的基础设施,以应对更大的负载或解决性能瓶颈。

此外,建立一个反馈循环是至关重要的,它允许用户报告问题或提供改进建议。通过积极征求并采纳用户反馈,您可以不断地改进和增强RAG系统,以更好地满足用户需求。这还可以包括监控诸如用户界面使用、响应时间以及用户角度生成内容的相关性和有用性等方面。进行用户调查、分析用户互动日志并监控用户满意度指标,可以为您提供宝贵的见解,帮助您评估RAG系统的实际效果。如何利用这些信息将取决于您所开发的RAG应用类型,但通常来说,这些都是持续改进部署后的RAG应用的最常见监控领域。

通过定期评估已部署的RAG系统,您可以确保其长期的有效性、可靠性和性能。持续监控、主动检测问题并承诺不断改进,是保持高质量RAG管道并长期为用户提供价值的关键。

评估帮助你不断进步

为什么评估如此重要?简单来说,如果你不衡量当前的状态,并且在做出改进后重新衡量,那么很难理解是什么改进(或损害)了RAG系统的性能。

当系统出现问题时,如果没有客观的标准进行比较,也很难理解出问题的原因。是检索机制出了问题吗?是提示语的问题吗?还是LLM(大语言模型)的响应有问题?这些都是一个好的评估系统可以帮助解答的问题。

评估提供了一种系统化、客观的方式来衡量管道的性能,识别改进领域,并跟踪你做出的任何更改或改进的影响。没有一个健全的评估框架,就很难理解RAG系统的进展情况以及在哪些方面需要进一步完善。

通过将评估作为开发过程的核心组成部分,你可以持续优化和改进你的RAG管道,确保其能够提供最佳的结果,并满足用户不断变化的需求。

在RAG系统开发的初期,你必须开始做出关于技术组件的选择。在此时,你甚至还没有安装任何东西,因此无法直接评估代码,但你仍然可以使用标准化的评估框架来缩小考虑范围。接下来,我们将讨论一些最常见RAG系统元素的标准化评估框架。

标准化评估框架

RAG系统的关键技术组件包括生成嵌入的嵌入模型、向量存储、向量检索和LLM(大语言模型)。当你考虑每个技术组件的不同选项时,每个组件都有一些标准化的指标可以帮助你进行比较。以下是各类别的常见评估指标。

嵌入模型基准

Massive Text Embedding Benchmark (MTEB) 检索排行榜评估了嵌入模型在不同数据集上的各种检索任务表现。MTEB排行榜根据模型在多个嵌入和检索相关任务中的平均表现对模型进行排名。你可以通过以下链接访问排行榜:huggingface.co/spaces/mteb…

访问此网页后,点击“Retrieval”和“Retrieval w/Instructions”标签,查看针对检索特定的嵌入评分。为了评估排行榜中的每个模型,模型的输出将使用多个数据集进行测试,这些数据集覆盖了广泛的领域,包括:

  • 论点检索(ArguAna)
  • 气候事实检索(ClimateFEVER)
  • 重复问题检索(CQADupstackRetrieval)
  • 实体检索(DBPedia)
  • 事实提取与验证(FEVER)
  • 金融问答(FiQA2018)
  • 多跳问答(HotpotQA)
  • 段落与文档排序(MSMARCO)
  • 事实核查(NFCorpus)
  • 开放领域问答(NQ)
  • 重复问题检测(QuoraRetrieval)
  • 科学文献检索(SCIDOCS)
  • 科学声明验证(SciFact)
  • 论点检索(Touche2020)
  • COVID-19相关信息检索(TRECCOVID)

排行榜基于这些任务的平均表现对嵌入模型进行排名,提供了关于它们优缺点的全面视图。你还可以点击任何指标,通过该指标对排行榜进行排序。例如,如果你对金融问答更感兴趣,可以查看在FiQA2018数据集上得分最高的模型。

向量存储和向量检索基准

ANN-Benchmarks 是一个评估近似最近邻(ANN)算法性能的基准工具,我们在第8章中已详细讨论过。ANN-Benchmarks评估了不同向量检索工具在多个数据集上的检索精度、速度和内存使用情况,其中包括我们在第8章中提到的向量检索工具——Facebook AI Similarity Search(FAISS)、Approximate Nearest Neighbors Oh Yeah(ANNOY)和Hierarchical Navigable Small Worlds(HNSW)。

Benchmarking IR (BEIR) 是另一个评估向量存储和检索算法的有用资源。它提供了一个异构基准,用于零-shot评估信息检索模型,涵盖多个领域,包括问答、事实核查和实体检索。我们将在第13章进一步讨论零-shot的含义,基本上它指的是没有示例的用户查询或问题,这在RAG中是常见的情况。BEIR提供了一个标准化的评估框架,并包括以下流行数据集:

  • MSMARCO:来自真实世界查询和答案的大规模数据集,用于评估深度学习模型在检索和问答中的表现。
  • HotpotQA:包含自然、多跳问题的数据集,具有强监督支持事实,并支持更可解释的问答系统。
  • CQADupStack:一个来自12个Stack Exchange子论坛的社区问答(cQA)基准数据集,附有重复问题信息。

这些数据集以及BEIR基准中的其他数据集涵盖了多种领域和信息检索任务,允许你在不同的情境下评估检索系统的性能,并将其与最新的检索方法进行比较。

LLM基准

Artificial Analysis LLM性能排行榜 是一个全面的资源,用于评估开源和专有语言模型,如ChatGPT、Claude和Llama。它评估了模型在广泛任务上的表现。为便于质量比较,它使用了多个子排行榜:

  • 通用能力:Chatbot Arena

  • 推理与知识

    • 大规模多任务语言理解(MMLU)
    • 多轮基准(MT Bench)

它们还追踪速度和价格,并提供分析,帮助你平衡各个领域的性能。通过基于这些任务的表现对模型进行排名,排行榜提供了一个全面的视角来理解模型的能力。

该排行榜可以在此找到:artificialanalysis.ai/

除了通用的LLM排行榜外,还有一些专门聚焦于LLM性能特定方面的排行榜。Artificial Analysis LLM Performance Leaderboard 评估了LLM的技术特性,如推理速度、内存消耗和可扩展性。它包括以下指标:吞吐量(每秒处理的标记数)、延迟(生成响应的时间)、内存占用和扩展效率。这些指标帮助你理解不同LLM的计算需求和性能特征。

Open LLM排行榜 跟踪开源语言模型在各种自然语言理解和生成任务中的表现。它包括以下基准:

  • AI2推理挑战(ARC) :用于复杂科学推理
  • HellaSwag:用于常识推理
  • MMLU:用于特定领域的表现
  • TruthfulQA:用于生成真实且信息丰富的回答
  • WinoGrande:通过代词消歧进行常识推理
  • Grade School Math 8K(GSM8K) :用于数学推理能力的评估

关于标准化评估框架的最终思考

使用标准化评估框架和基准为比较RAG管道中不同组件的性能提供了一个宝贵的起点。它们涵盖了广泛的任务和领域,帮助你评估各种方法的优缺点。通过考虑这些基准的结果,以及计算效率、集成简便性等其他因素,你可以缩小选择范围,并在选择最适合你特定RAG应用的组件时做出更明智的决策。

然而,需要注意的是,虽然这些标准化评估指标对于初步的组件选择非常有帮助,但它们可能无法完全捕捉到你特定RAG管道在独特输入和输出情况下的表现。为了真正了解你的RAG系统在特定使用场景中的表现,你需要建立一个专门为你的具体需求量身定制的评估框架。这个定制化的评估系统将为你提供最准确、最相关的关于RAG管道性能的见解。

接下来,我们需要讨论RAG评估中最重要且常被忽视的一个方面——你的真值数据(ground-truth data)。

什么是“真值”数据?

简单来说,真值数据是代表你期望在RAG系统达到最佳性能时获得的理想响应的数据。

举个实际的例子,如果你的RAG系统是针对允许用户查询关于狗类兽医学中最新癌症研究的系统,而你的数据来源是所有已提交到PubMed的相关最新研究论文,那么你的真值数据很可能是那些可以在该数据中提问和回答的问题。你应该使用目标受众可能提出的现实问题,而答案则应该是你认为从LLM中得到的理想答案。这可能是相对客观的,但无论如何,拥有一套真值数据来与RAG系统的输入输出进行比较,都是帮助评估你所做更改影响的关键方式,最终使系统更有效。

如何使用真值数据?

真值数据作为衡量RAG系统性能的基准。通过将RAG系统生成的输出与真值进行比较,你可以评估系统在检索相关信息和生成准确且连贯的响应方面的表现。真值帮助量化不同RAG方法的有效性,并识别改进的方向。

生成真值数据

手动创建真值数据可能会非常耗时。如果你的公司已经拥有特定查询或提示的理想响应数据集,那将是一个宝贵的资源。然而,如果此类数据不容易获得,接下来我们将探讨一些替代方法来获取真值数据。

人工注释

你可以雇佣人工注释员手动创建一组查询或提示的理想响应。这能确保高质量的真值数据,但对于大规模评估来说,这种方式可能成本高且耗时。

专家知识

在某些领域,你可能能够访问到领域专家(SMEs),他们可以根据自己的专业知识提供真值响应。这对于一些专业或技术领域尤为有用,因为在这些领域,准确信息至关重要。

帮助这个方法的一种常见方式是基于规则的生成。使用基于规则的生成,对于特定的领域或任务,你可以定义一套规则或模板来生成合成的真值,并利用你的SMEs来填充模板。通过利用领域知识和预定义的模式,你可以创建与预期格式和内容一致的响应。

例如,如果你正在构建一个支持手机的客户支持聊天机器人,你可能会有这样的模板:要解决[问题],你可以尝试[解决方案]。你的SMEs可以填充各种问题和解决方案,假设问题是“电池电量消耗”,而解决方案是“调低屏幕亮度和关闭后台应用”。这个模板(我们称之为“补充”)最终的输出可能是:要解决[电池电量消耗],你可以尝试[调低屏幕亮度和关闭后台应用]。

众包

平台如Amazon Mechanical Turk和Figure Eight允许你将创建真值数据的任务外包给大量工作人员。通过提供明确的指示和质量控制措施,你可以获得多样化的响应。

合成真值

在获取真实真值数据具有挑战性或不可行的情况下,生成合成真值可能是一个可行的替代方案。合成真值涉及使用现有的LLM或技术自动生成合理的响应。以下是一些方法:

  • 微调语言模型:你可以在一个小的数据集上微调LLM,该数据集包含高质量的响应。通过为模型提供理想响应的示例,它可以学习为新的查询或提示生成类似的响应。这些生成的响应可以作为合成的真值。
  • 基于检索的方法:如果你有一个大量高质量的文本数据集,你可以使用基于检索的方法来找到与查询或提示最匹配的相关段落或句子。这些检索到的段落可以作为真值响应的替代。

获取真值数据可能是构建RAG系统中的一个具有挑战性的步骤,但一旦获得真值数据,你将为有效的RAG评估奠定坚实的基础。在下一节,我们将介绍如何生成合成的真值数据,并将一个有用的评估平台集成到我们的RAG系统中,帮助我们了解上一章中使用的混合搜索对结果的影响。

代码实验 9.1 – ragas

检索增强生成评估(ragas)是一个专为RAG设计的评估平台。在本次代码实验中,我们将逐步实现ragas,并生成合成的真值数据,然后建立一套全面的评估指标,可以将其集成到你的RAG系统中。但是,评估系统是用来评估某些内容的,对吧?在我们的代码实验中,我们将评估什么呢?

如果你还记得第8章,我们介绍了一种新的检索方法,称为混合检索。在本次代码实验中,我们将实现原始的基于密集向量语义的检索方法,然后使用ragas评估混合检索方法的影响。这将为你提供一个真实的工作示例,展示如何在自己的代码中实现全面的评估系统!

在深入讨论如何使用ragas之前,重要的是要注意它是一个高度发展的项目。随着新版本的发布,新的功能和API更改频繁发生,因此在浏览代码示例时,请务必参考文档网站:docs.ragas.io/

本次代码实验将从我们在上一章中添加的LangChain中的EnsembleRetriever(代码实验 8.3)开始:

首先,安装一些新的包:

$ pip install ragas

$ pip install tqdm -q --user

$ pip install matplotlib

我们安装了ragas,这是我们将在本次代码实验中重点关注的评估平台。tqdm包是ragas使用的一个流行Python库,用于创建进度条并显示迭代过程中进度信息。你可能以前遇到过matplotlib包,因为它是一个广泛使用的Python绘图库。我们将使用它来为评估指标结果提供可视化。

接下来,我们需要添加几个与刚才安装的库相关的导入:

import tqdm as notebook_tqdm

import pandas as pd

import matplotlib.pyplot as plt

from datasets import Dataset

from ragas import evaluate

from ragas.testset.generator import TestsetGenerator

from ragas.testset.evolutions import (
    simple, reasoning, multi_context)

from ragas.metrics import (
    answer_relevancy,
    faithfulness,
    context_recall,
    context_precision,
    answer_correctness,
    answer_similarity
)

如前所述,tqdm将为我们的ragas平台提供在执行耗时处理任务时使用进度条的能力。我们将使用流行的pandas数据处理和分析库,将数据提取到DataFrame中,作为分析的一部分。matplotlib.pyplot as plt导入使我们能够为指标结果添加可视化(在本例中是图表)。我们还导入了来自datasets的Dataset。datasets库是由Hugging Face开发和维护的一个开源库,提供了一个标准化的接口,用于访问和处理各种数据集,通常专注于自然语言处理(NLP)领域。最后,我们从ragas库中导入了一些包。让我们深入了解每一个导入的功能:

  • from ragas import evaluateevaluate函数接收一个ragas格式的数据集,以及可选的指标、语言模型、嵌入和其他配置,并对RAG管道进行评估。evaluate函数返回一个Result对象,包含每个指标的分数,提供了一个方便的方式来评估使用各种指标和配置的RAG管道的性能。

  • from ragas.testset.generator import TestsetGeneratorTestsetGenerator类用于生成合成的真值数据集,用于评估RAG管道。它接收一组文档,并生成问答对以及相应的上下文。TestsetGenerator的一个关键特性是它允许通过distributions参数自定义测试数据的分布,指定不同问题类型(如简单问题、多上下文问题或推理问题)的比例。它支持使用LangChain和LlamaIndex文档加载器生成测试集。

  • from ragas.testset.evolutions import simple, reasoning, multi_context:这些导入代表了在测试数据集生成过程中使用的不同类型的问题演变。这些演变帮助创建一个多样化且全面的测试数据集,涵盖了在现实场景中遇到的各种类型的问题:

    • 简单演变:基于提供的文档生成简单问题。
    • 推理演变:创建需要推理技能才能有效回答的问题。
    • 多上下文演变:生成需要多个相关部分或段落信息才能得出答案的问题。
  • from ragas.metrics import …() :此导入语句引入了ragas库提供的各种评估指标。导入的指标包括answer_relevancyfaithfulnesscontext_recallcontext_precisionanswer_correctnessanswer_similarity。目前还有两个组件级指标(context relevancycontext entity recall)可以导入,但为了简化,我们在这里跳过它们。我们将在代码实验的后面讨论你可以使用的附加指标。这些指标评估与检索和生成相关的RAG管道的各个方面,整体上涵盖了RAG管道的端到端各个阶段。

总体而言,来自ragas库的这些导入提供了一整套工具,用于生成合成的测试数据集,使用各种指标评估RAG管道,并分析性能结果。

设置LLM/嵌入模型

现在,我们将升级处理LLM和嵌入服务的方式。通过ragas,我们引入了更多的复杂性来管理我们使用的LLM数量;我们希望通过提前设置嵌入服务和LLM服务的初始化来更好地管理这一点。让我们来看一下代码:

embedding_ada = "text-embedding-ada-002"
model_gpt35 = "gpt-3.5-turbo"
model_gpt4 = "gpt-4o-mini"
embedding_function = OpenAIEmbeddings(
    model=embedding_ada, openai_api_key=openai.api_key)
llm = ChatOpenAI(model=model_gpt35,
    openai_api_key=openai.api_key, temperature=0.0)
generator_llm = ChatOpenAI(model=model_gpt35,
    openai_api_key=openai.api_key, temperature=0.0)
critic_llm = ChatOpenAI(model=model_gpt4,
    openai_api_key=openai.api_key, temperature=0.0)

注意,虽然我们仍然只使用一个嵌入服务,但现在我们有两个不同的LLM可以调用。这样做的主要目的是建立我们希望直接使用的主LLM(llm),然后再设定两个专门用于评估过程的LLM(generator_llmcritic_llm)。

我们可以利用一个更先进的LLM——ChatGPT-4o-mini作为评估LLM(critic_llm)。理论上,这意味着它可以更有效地评估我们输入给它的数据。这并不总是成立,或者你可能会有一个专门为评估任务微调的LLM。无论如何,将这些LLM分配到不同的角色展示了在RAG系统中,不同的LLM可以用于不同的目的。你可以删除原始代码中的以下一行,它初始化了我们最初使用的LLM对象:

llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)

接下来,我们将添加一个新的RAG链,用于运行相似性检索(这就是我们之前仅使用密集嵌入进行的检索):

rag_chain_similarity = RunnableParallel(
        {"context": dense_retriever,
        "question": RunnablePassthrough()
}).assign(answer=rag_chain_from_docs)

为了使事情更加清晰,我们将更新混合RAG链的名称:

rag_chain_hybrid = RunnableParallel(
        {"context": ensemble_retriever,
        "question": RunnablePassthrough()
}).assign(answer=rag_chain_from_docs)

注意变量的变化,粗体部分曾经是rag_chain_with_source,现在被命名为rag_chain_hybrid,表示混合搜索的部分。

现在我们将更新原始代码,以提交用户查询。这次,我们将同时使用相似性检索和混合检索版本。

创建相似性版本:

user_query = "What are Google's environmental initiatives?"
result = rag_chain_similarity.invoke(user_query)
retrieved_docs = result['context']
print(f"Original Question to Similarity Search: {user_query}\n")
print(f"Relevance Score: {result['answer']['relevance_score']}\n")
print(f"Final Answer:\n{result['answer']['final_answer']}\n\n")
print("Retrieved Documents:")
for i, doc in enumerate(retrieved_docs, start=1):
    print(f"Document {i}: Document ID: {doc.metadata['id']}")
    print(f"source: {doc.metadata['source']}")
    print(f"Content:\n{doc.page_content}\n")

现在,创建混合版本:

user_query = "What are Google's environmental initiatives?"
result = rag_chain_hybrid.invoke(user_query)
retrieved_docs = result['context']
print(f"Original Question to Dense Search: {user_query}\n")
print(f"Relevance Score: {result['answer']['relevance_score']}\n")
print(f"Final Answer:\n{result['answer']['final_answer']}\n\n")
print("Retrieved Documents:")
for i, doc in enumerate(retrieved_docs, start=1):
    print(f"Document {i}: Document ID: {doc.metadata['id']}")
    print(f"source: {doc.metadata['source']}")
    print(f"Content:\n{doc.page_content}\n")

这两段代码的主要区别在于,它们展示了我们创建的不同RAG链——rag_chain_similarityrag_chain_hybrid的使用。

首先,让我们看一下相似性检索的输出:

Google's environmental initiatives include empowering individuals to take action, working together with partners and customers, operating sustainably, achieving net-zero carbon emissions, water stewardship, and promoting a circular economy. They have implemented sustainability features in products like Google Maps, Google Nest thermostats, and Google Flights to help individuals make more sustainable choices. Google also supports various environmental organizations and initiatives, such as the iMasons Climate Accord, ReFED, and The Nature Conservancy, to accelerate climate action and address environmental challenges. Additionally, Google is involved in public policy advocacy and is committed to reducing its environmental impact through its operations and value chain.

接下来是混合检索的输出:

Google's environmental initiatives include empowering individuals to take action, working together with partners and customers, operating sustainably, achieving net-zero carbon emissions, focusing on water stewardship, promoting a circular economy, engaging with suppliers to reduce energy consumption and greenhouse gas emissions, and reporting environmental data. They also support public policy and advocacy for low-carbon economies, participate in initiatives like the iMasons Climate Accord and ReFED, and support projects with organizations like The Nature Conservancy. Additionally, Google is involved in initiatives with the World Business Council for Sustainable Development and the World Resources Institute to improve well-being for people and the planet. They are also working on using technology and platforms to organize information about the planet and make it actionable to help partners and customers create a positive impact.

说哪个更好可能是主观的,但如果你回顾第8章的代码,你会发现每个链的检索机制返回的数据集不同,这些数据将作为LLM回答用户查询的基础。你可以在前面的回答中看到这些差异,每个回答的内容略有不同,强调了不同的信息和不同的方面。

到目前为止,我们已经设置了RAG系统,能够使用两种不同的RAG链,一个专注于仅使用相似性/密集搜索,另一个使用混合搜索。这为在代码中应用ragas奠定了基础,从而为评估我们从这两种链中获得的结果提供一种更客观的方法。

生成合成的地面真相数据

正如我们在前一节中提到的,地面真相是进行评估分析的关键元素。但我们没有地面真相——天哪!没问题,我们可以使用ragas来生成合成数据以供此用途。

警告
ragas库大量使用了你的LLM API。ragas提供的分析是LLM辅助评估,这意味着每当生成或评估一个地面真相示例时,都会调用LLM(有时一个度量会调用多次),并且会产生API费用。如果你生成了100个地面真相示例,包括生成问题和答案,然后运行六个不同的评估度量,那么你所做的LLM API调用数量将大大增加,达到数千次调用。建议在掌握调用频率之前谨慎使用。因为这些是会产生费用的API调用,它们可能会迅速增加LLM API的账单!在写这段话时,每次运行整个代码实验室(仅10个地面真相示例和6个度量)时,我的费用大约为2到2.5美元。如果你有更大的数据集或为测试集生成器设置了更大的test_size以生成超过10个示例,费用将大幅增加。

我们首先创建一个生成器实例,用于生成我们的地面真相数据集:

generator = TestsetGenerator.from_langchain(
    generator_llm,
    critic_llm,
    embedding_function
)
documents = [Document(page_content=chunk) for chunk in splits]
testset = generator.generate_with_langchain_docs(
    documents,
    test_size=10,
    distributions={
        simple: 0.5,
        reasoning: 0.25,
        multi_context: 0.25
    }
)
testset_df = testset.to_pandas()
testset_df.to_csv(
    os.path.join('testset_data.csv'), index=False)
print("testset DataFrame saved successfully in the local directory.")

如代码所示,我们使用了generator_llmcritic_llm以及embedding_function。正如前面的警告框所述,请小心使用这些!这是三个不同的API,如果不小心配置代码中的设置,可能会产生相当可观的费用。在这段代码中,我们还将先前生成的数据分块(splits)进行预处理,以便更有效地与ragas一起工作。splits中的每一块都被假设为代表文档的一部分的字符串。Document类来自LangChain库,是一种方便的方式来表示带有其内容的文档。

testset使用我们生成器对象中的generator_with_langchain_docs函数来生成合成的测试集。这个函数接收documents列表作为输入。test_size参数设置了要生成的测试问题的数量(此例中为10)。distributions参数定义了问题类型的分布,在本例中,简单问题占50%,推理问题占25%,多上下文问题占25%。然后我们将testset转换为一个pandas DataFrame,以便查看结果,并将其保存为一个文件。考虑到我们刚刚提到的费用,将数据保存为CSV文件,可以方便地在文件目录中持久化,提供了仅需运行一次代码的额外便利!

现在,让我们把保存的测试集数据重新加载并查看它!

saved_testset_df = pd.read_csv(os.path.join('testset_data.csv'))
print("testset DataFrame loaded successfully from local directory.")
saved_testset_df.head(5)

输出应该类似于图9.1中所看到的内容:

image.png

在这个数据集中,你会看到由你先前初始化的generator_llm实例生成的问题和答案(地面真相)。现在你就有了地面真相数据!LLM将尝试为我们的地面真相生成10对不同的问题和答案,但在某些情况下,可能会发生失败,限制了生成过程。这将导致生成的地面真相示例少于你在test_size变量中设置的数量。在这种情况下,生成的示例为7个,而不是10个。总体来说,你可能希望生成超过10个示例,以便对RAG系统进行全面的测试。不过,在这个简单示例中,我们接受7个示例,主要是为了降低API费用!

接下来,让我们准备相似度数据集:

saved_testing_data = \
    saved_testset_df.astype(str).to_dict(orient='list')
saved_testing_dataset = Dataset.from_dict(saved_testing_data)
saved_testing_dataset_sm = saved_testing_dataset.remove_columns(
    ["evolution_type", "episode_done"])

在这里,我们进行了一些数据转换,以使格式与代码的其他部分兼容(在本例中是ragas的输入)。我们首先使用astype(str)将所有列转换为字符串类型,然后使用to_dict(orient='list')saved_testset_df DataFrame转换为字典格式。生成的saved_testing_data字典随后被用来通过from_dict()方法创建一个Dataset对象saved_testing_dataset。我们还创建了一个新的数据集saved_testing_dataset_sm,它只包含我们需要的列。

在这个过程中,我们通过remove_columns()方法去除了evolution_typeepisode_done列。接下来,我们可以查看结果:

saved_testing_dataset_sm

输出应如下所示:

Dataset({
    features: ['question', 'contexts', 'ground_truth', 'metadata'],
    num_rows: 7
})

如果你有更多的地面真相示例,num_rows变量将反映出来,但其余部分应该保持不变。Dataset对象显示了我们拥有的“特征”,即我们传入的列,接着显示我们有7行数据。

接下来,我们将设置一个函数,来运行我们传入的RAG链,并添加一些额外的格式化,使其能够与ragas一起使用:

def generate_answer(question, ground_truth, rag_chain):
    result = rag_chain.invoke(question)
    return {
        "question": question,
        "answer": result["answer"]["final_answer"],
        "contexts": [doc.page_content for doc in result["context"]],
        "ground_truth": ground_truth
    }

这个函数generate_answer()接受一个问题、地面真相数据和rag_chain作为输入。这个函数是灵活的,能够接受我们传给它的任一链,在生成相似度链和混合链分析时将非常有用。函数的第一步是调用传入的rag_chain链,使用给定的问题获取结果。第二步是返回一个包含问题、结果中的最终答案、从结果中提取的上下文以及地面真相的字典。

现在,我们准备好进一步处理数据集,使其能够与ragas一起工作:

testing_dataset_similarity = saved_testing_dataset_sm.map(
    lambda x: generate_answer(x["question"],
        x["ground_truth"], rag_chain_similarity),
    remove_columns=saved_testing_dataset_sm.column_names)
testing_dataset_hybrid = saved_testing_dataset_sm.map(
    lambda x: generate_answer(x["question"],
        x["ground_truth"], rag_chain_hybrid),
    remove_columns=saved_testing_dataset_sm.column_names)

在这段代码中,我们创建了两个新的数据集,testing_dataset_similaritytesting_dataset_hybrid,通过将generate_answer()函数应用于saved_testing_dataset_sm的每一行来实现,分别使用相似度链(rag_chain_similarity)和混合链(rag_chain_hybrid)。rag_chain_similarityrag_chain_hybrid作为rag_chain参数在各自的数据集创建中被使用。通过remove_columns=saved_testing_dataset_sm.column_names,我们删除了saved_testing_dataset_sm的原始列。

最后,我们将在这两个数据集上运行ragas。以下是对相似度RAG链应用ragas的代码:

score_similarity = evaluate(
    testing_dataset_similarity,
    metrics=[
        faithfulness,
        answer_relevancy,
        context_precision,
        context_recall,
        answer_correctness,
        answer_similarity
    ]
)
similarity_df = score_similarity.to_pandas()

在这里,我们使用ragas库的evaluate()函数对testing_dataset_similarity进行评估。评估使用了指定的度量,包括faithfulnessanswer_relevancycontext_precisioncontext_recallanswer_correctnessanswer_similarity。评估结果存储在score_similarity变量中,并通过to_pandas()方法转换为一个pandas DataFrame,similarity_df

我们对混合数据集执行相同操作:

score_hybrid = evaluate(
    testing_dataset_hybrid,
    metrics=[
        faithfulness,
        answer_relevancy,
        context_precision,
        context_recall,
        answer_correctness,
        answer_similarity
    ]
)
hybrid_df = score_hybrid.to_pandas()

一旦你完成了这些步骤,ragas的使用就结束了!我们现在已经完成了对两个链(相似度链和混合链)的全面评估,在这两个DataFrame中,similarity_dfhybrid_df中包含了所有的度量数据。接下来,我们只需要分析ragas提供的数据。

分析RAGAS结果

我们将花费余下的代码实验室时间对数据进行格式化,以便我们可以先保存并持久化它(因为这可能是我们RAG系统中更为昂贵的部分)。这些代码将来可以重用,用于从保存的.csv文件中提取数据,避免你需要重新执行这个潜在昂贵的评估过程。

让我们先设置一些重要的变量,然后将我们收集的数据保存到CSV文件中:

key_columns = [
    'faithfulness',
    'answer_relevancy',
    'context_precision',
    'context_recall',
    'answer_correctness',
    'answer_similarity'
]
similarity_means = similarity_df[key_columns].mean()
hybrid_means = hybrid_df[key_columns].mean()
comparison_df = pd.DataFrame(
        {'Similarity Run': similarity_means,
        'Hybrid Run': hybrid_means})
comparison_df['Difference'] = comparison_df['Similarity Run'] \
        - comparison_df['Hybrid Run']
similarity_df.to_csv(
    os.path.join('similarity_run_data.csv'), index=False)
hybrid_df.to_csv(
    os.path.join('hybrid_run_data.csv'), index=False)
comparison_df.to_csv(os.path.join('comparison_data.csv'), index=True)
print("Dataframes saved successfully in the local directory.")

在这段代码中,我们首先定义了一个key_columns列表,其中包含了需要进行比较的关键列名称。接着,我们使用mean()方法分别计算similarity_dfhybrid_df中每一列的均值,并将它们存储在similarity_meanshybrid_means中。

接下来,我们创建了一个名为comparison_df的新DataFrame,用于比较相似性运行(Similarity Run)和混合运行(Hybrid Run)的均值。Difference列用于计算相似性运行和混合运行的均值差。最后,我们将similarity_dfhybrid_dfcomparison_df保存为.csv文件。保存这些文件后,未来如果需要分析,可以直接从这些文件加载数据,而不必重新生成整个评估过程。

另外,值得注意的是,这只是进行分析的一种方式。你可以根据自己的需要调整代码,进行更有针对性的分析,专注于你认为在特定RAG系统中重要的方面。例如,可能你主要关注如何改进检索机制,或者你正在分析来自已部署环境的流数据,这种情况下你可能没有地面真相(ground truth),并需要专注于可以在没有地面真相的情况下工作的评估指标(请参阅本章后续部分的ragas创始人见解,了解更多关于此概念的信息)。

继续我们的分析,我们现在需要加载之前保存的文件,以完成剩余的分析,并打印出我们对两个不同链条中RAG系统各个阶段的分析结果:

sem_df = pd.read_csv(os.path.join('similarity_run_data.csv'))
rec_df = pd.read_csv(os.path.join('hybrid_run_data.csv'))
comparison_df = pd.read_csv(
    os.path.join('comparison_data.csv'), index_col=0)
print("Dataframes loaded successfully from the local directory.")
print("Performance Comparison:")
print("\n**Retrieval**:")
print(comparison_df.loc[['context_precision', 'context_recall']])
print("\n**Generation**:")
print(comparison_df.loc[['faithfulness', 'answer_relevancy']])
print("\n**End-to-end evaluation**:")
print(comparison_df.loc[['answer_correctness', 'answer_similarity']])

这段代码将生成一组指标,接下来我们会进一步分析它们。我们首先加载从CSV文件中导入的DataFrame,然后应用分析方法,将所有结果整合为更易于阅读的评分。

接下来,我们使用前一段代码中定义的变量来帮助我们生成图形,利用matplotlib来绘制图表:

fig, axes = plt.subplots(3, 1, figsize=(12, 18), sharex=False)
bar_width = 0.35
categories = ['Retrieval', 'Generation', 'End-to-end evaluation']
metrics = [
    ['context_precision', 'context_recall'],
    ['faithfulness', 'answer_relevancy'],
    ['answer_correctness', 'answer_similarity']
]

在这里,我们为每个类别创建了子图,并增加了间距。

接下来,我们遍历每个类别,并绘制相应的指标:

for i, (category, metric_list) in enumerate(zip(categories, metrics)):
    ax = axes[i]
    x = range(len(metric_list))
    similarity_bars = ax.bar(
    x, comparison_df.loc[metric_list, 'Similarity Run'],
    width=bar_width, label='Similarity Run',
    color='#D51900')
    for bar in similarity_bars:
        height = bar.get_height()
        ax.text(
            bar.get_x() + bar.get_width() / 2,
            height, f'{height:.1%}', ha='center',
            va='bottom', fontsize=10)
    hybrid_bars = ax.bar(
    [i + bar_width for i in x],
    comparison_df.loc[metric_list, 'Hybrid Run'],
    width=bar_width, label='Hybrid Run',
    color='#992111')
    for bar in hybrid_bars:
        height = bar.get_height()
        ax.text(
            bar.get_x() + bar.get_width() / 2,
            height, f'{height:.1%}', ha='center',
            va='bottom', fontsize=10)
    ax.set_title(category, fontsize=14, pad=20)
    ax.set_xticks([i + bar_width / 2 for i in x])
    ax.set_xticklabels(metric_list, rotation=45,
        ha='right', fontsize=12)
    ax.legend(fontsize=12, loc='lower right',
        bbox_to_anchor=(1, 0))

这段代码的主要任务是格式化我们的可视化效果,包括为相似性和混合运行分别绘制条形图,并在条形图上添加数值。我们还为条形图选择了颜色,并增加了哈希条纹,以提高视觉无障碍性。

接下来,我们对可视化做最后的调整:

fig.text(0.04, 0.5, 'Scores', va='center',
    rotation='vertical', fontsize=14)
fig.suptitle('Performance Comparison', fontsize=16)
plt.tight_layout(rect=[0.05, 0.03, 1, 0.95])
plt.subplots_adjust(hspace=0.6, top=0.92)
plt.show()

在这段代码中,我们为可视化添加了标签和标题,调整了子图之间的间距,并增加了顶部边距。最后,使用plt.show()在笔记本界面中展示可视化效果。

总体来说,这一部分的代码将生成一个文本分析结果,显示来自两个链条的结果,然后生成一个条形图可视化对比结果。虽然这段代码会同时生成所有这些内容,我们将分开讨论每一部分输出,并分析它们与RAG系统主要阶段的关系。

正如我们在前面的章节中讨论的,RAG在启动时有两个主要的阶段:检索(Retrieval)和生成(Generation)。在评估RAG系统时,你也可以将评估按这两个类别进行划分。让我们先讨论如何评估检索阶段。

检索评估

Ragas 提供了用于独立评估 RAG 流水线每个阶段的指标。对于检索,Ragas 有两个指标,分别是上下文精度(context precision)和上下文召回率(context recall)。你可以在以下输出和图表中看到这些指标:

性能比较:
检索

相似性运行 (Similarity Run)混合运行 (Hybrid Run)差异 (Difference)
上下文精度 (context_precision)0.9061130.8412670.064846
上下文召回率 (context_recall)0.9500000.9250000.025000

你可以在图 9.2 中看到检索指标的图表:

image.png

检索评估的重点是评估检索到的文档的准确性和相关性。我们通过 Ragas 使用以下两个指标来进行评估,具体描述可以参考 Ragas 文档网站:

  • 上下文精度(context_precision) :检索上下文的信噪比。上下文精度是一个评估指标,用于判断所有在上下文中与真实答案相关的项是否排在更高的排名。理想情况下,所有相关的片段应该出现在排名前列。这个指标是通过问题、真实答案(ground_truth)和上下文计算得出的,值在 0 到 1 之间,得分越高,表示精度越好。
  • 上下文召回率(context_recall) :它能否检索到回答问题所需的所有相关信息?上下文召回率衡量检索到的上下文与标注答案的匹配程度,答案被视为真实答案。它是基于真实答案和检索上下文计算得出的,值范围在 0 到 1 之间,值越高,表示性能越好。

如果你来自传统的数据科学或信息检索背景,可能会认出“精度”(precision)和“召回率”(recall)这两个术语,并且想知道它们是否与这些术语有关。Ragas 中使用的上下文精度和上下文召回率在概念上类似于传统的精度和召回率指标。

在传统的定义中,精度衡量的是检索到的项中相关项的比例,而召回率衡量的是所有相关项中被检索到的比例。类似地,上下文精度通过评估是否将真实相关的项排在更高位置,来评估检索到的上下文的相关性,而上下文召回率则衡量检索到的上下文覆盖回答问题所需相关信息的程度。

然而,也有一些关键区别需要注意:

  • 传统的精度和召回率通常是基于二元相关判断(相关或不相关)计算的,而 Ragas 中的上下文精度和上下文召回率则考虑了检索到的上下文的排名和与真实答案的对齐程度。
  • 此外,上下文精度和上下文召回率是专门为评估在问答任务中的检索性能而设计的,考虑到检索相关信息以回答给定问题的具体要求。

在查看分析结果时,我们需要记住,我们使用的真实答案数据集较小。实际上,整个 RAG 系统所依赖的原始数据集就很小,这可能会影响我们的结果。因此,不要过于解读这里的数字。然而,这些数据确实展示了如何使用 Ragas 进行分析,并为我们提供了有关 RAG 系统检索阶段发生了什么的有价值的表示。这一代码实验室的主要目的是展示在构建 RAG 系统时你可能遇到的实际挑战,在此过程中你需要考虑不同指标在特定用例中的背景、不同指标之间的权衡,以及决定哪种方法最有效地满足你的需求。

接下来,我们将回顾在 RAG 系统生成阶段的类似分析。

生成评估

如前所述,Ragas 提供了用于独立评估 RAG 流水线每个阶段的指标。对于生成阶段,Ragas 有两个指标,分别是忠诚度(faithfulness)和答案相关性(answer relevancy),如以下输出和图表所示:

生成

相似性运行 (Similarity Run)混合运行 (Hybrid Run)差异 (Difference)
忠诚度 (faithfulness)0.9775000.9458330.031667
答案相关性 (answer_relevancy)0.9682220.9652470.002976

生成阶段的指标可以在图 9.3 中看到:

image.png

生成评估衡量的是当提供上下文时,系统生成的响应是否合适。我们通过 Ragas 使用以下两个指标来进行评估,具体描述可以参考 Ragas 文档:

  • 忠诚度(faithfulness) :生成的答案在事实上的准确性如何?这个指标衡量的是生成的答案与给定上下文的一致性。它是通过答案和检索到的上下文来计算的。答案的得分范围是 (0-1),得分越高,表示答案越准确。
  • 答案相关性(answer_relevancy) :生成的答案与问题的相关性如何?答案相关性主要评估生成的答案与给定提示的相关性。对于不完整或包含冗余信息的答案,会给出较低的分数,而相关性更强的答案会得到更高的分数。这个指标是通过问题、上下文和答案计算得出的。

再次强调,我们使用的小数据集作为真实答案和数据集,可能导致这些结果的可靠性较低。但你可以看到,这些结果为我们提供了一个非常有价值的基础,用于展示在 RAG 系统生成阶段发生的情况。

接下来,我们将讨论我们的下一组指标——端到端评估指标。

端到端评估

除了提供用于单独评估 RAG 流水线各个阶段的指标外,Ragas 还提供了整个 RAG 系统的端到端评估指标。对于生成阶段,Ragas 提供了两个指标,分别是答案正确性(answer correctness)和答案相似度(answer similarity),这些可以在输出的最后部分和图表中看到:

端到端评估

                    Similarity Run    Hybrid Run    Difference
answer_correctness     0.776018        0.717365        0.058653
answer_similarity      0.969899        0.969170        0.000729

图 9.4 中展示了这些结果的可视化图表:

image.png

端到端评估指标用于评估流水线的整体性能,衡量使用流水线的整体体验。结合这些指标,可以对 RAG 流水线进行全面评估。我们使用 Ragas 提供以下两个指标,如 Ragas 文档中所述:

答案正确性 (answer_correctness) :衡量生成的答案与真实答案的准确性。答案正确性评估的是生成的答案与真实答案之间的准确性对比。该评估依赖于真实答案和生成的答案,得分范围为 0 到 1。较高的分数表示生成的答案与真实答案之间的一致性较好,意味着答案正确性较高。

答案相似度 (answer_similarity) :评估生成的答案与真实答案的语义相似度。答案语义相似度是指评估生成的答案与真实答案之间的语义相似度。该评估基于真实答案和生成的答案,得分范围为 0 到 1。较高的分数表示生成的答案与真实答案之间的语义对齐程度较高。

评估流水线的端到端性能至关重要,因为它直接影响用户体验,并帮助确保全面的评估。

为了简化本次代码实验,我们省略了您在分析中可能还需要考虑的几个其他指标。接下来我们将讨论这些指标。

其他组件级评估

组件级评估涉及对流水线中各个组件的评估,如检索和生成阶段,以便深入了解它们的有效性并识别改进空间。我们已经分享了每个阶段的两个指标,但在 Ragas 平台中,还有一些其他可用的评估指标:

上下文相关性 (Context relevancy) :此指标衡量检索到的上下文的相关性,基于问题和上下文计算。得分范围为 0 到 1,较高的得分表示相关性较好。

上下文实体召回 (Context entity recall) :此指标衡量检索到的上下文的召回率,基于同时出现在真实数据(ground_truth)和上下文数据中的实体数量,与仅出现在真实数据中的实体数量之比。简而言之,它是衡量从真实数据中召回的实体比例。这个指标在基于事实的应用场景中尤为重要,如旅游服务台和历史问答等。该指标有助于评估检索机制在实体上的表现,尤其是在实体相关的场景中,我们需要包含这些实体的上下文。

方面评估 (Aspect critique) :方面评估旨在根据预定义的方面(如无害性和正确性)评估提交内容。此外,用户还可以根据特定的标准灵活定义自己的评估方面。方面评估的输出是二值的,表示提交内容是否符合定义的方面。该评估使用“答案”作为输入进行执行。

这些额外的组件级评估指标为评估检索到的上下文和生成的答案提供了更细致的度量。

创始人视角

在准备本章内容时,我们有机会与 Ragas 的创始人之一 Shahul Es 进行交流,以获得有关平台的更多见解,并帮助您更好地利用该平台进行 RAG 开发和评估。Ragas 是一个年轻的平台,但正如您在代码实验中所见,它已经具备了评估 RAG 系统的稳固指标基础。但这也意味着 Ragas 仍有很大的发展空间,这个平台是专为 RAG 实现而设计的,将继续发展壮大。Shahul 提供了一些有用的建议和见解,我们将在以下部分总结并与您分享。

Ragas 创始人见解

以下是与 Ragas 联合创始人 Shahul Es 讨论如何使用 Ragas 进行 RAG 评估时的一些笔记:

合成数据生成 (Synthetic data generation) :人们在进行 RAG 评估时通常面临的第一个障碍是没有足够的测试真实数据。Ragas 的主要目标是创建一个算法,能够生成涵盖多种问题类型的测试数据集,从而实现其合成数据生成能力。使用 Ragas 合成真实数据后,检查所生成的真实数据并挑选出不合适的问题是非常有帮助的。

反馈指标 (Feedback metrics) :Ragas 团队目前正在开发过程中强调将各种反馈循环纳入评估,包括性能反馈和用户反馈,其中有显式指标(例如某些操作出错)和隐式指标(如满意度级别、点赞/点踩等机制)。任何与用户的互动都可能是隐式反馈。从数据角度看,隐式反馈可能会有噪音,但如果正确使用,仍然是有价值的。

参考指标和无参考指标 (Reference and reference-free metrics) :Shahul 将指标分为参考指标和无参考指标,其中参考指标需要真实数据来进行处理。Ragas 团队在工作中强调构建无参考指标,您可以在 Ragas 的论文中了解更多相关内容(arxiv.org/abs/2309.15…)。对于许多领域,真实数据难以收集,这是一个重要的点,因为这使得至少部分评估仍然是可能的。忠实度(faithfulness)和答案相关性(answer relevance)是 Shahul 提到的无参考指标。

部署评估 (Deployment evaluation) :无参考评估指标也非常适合用于部署评估,因为在部署过程中,您很可能无法获得真实数据。

这些是一些关键见解,期待 Ragas 在未来的发展,帮助我们不断改进 RAG 系统。您可以在此处查看最新的 Ragas 文档:docs.ragas.io/en/stable/

这就是我们使用 Ragas 进行评估的代码实验室内容。但 Ragas 并不是唯一用于 RAG 评估的工具;还有许多其他工具!接下来,我们将讨论一些您可以考虑的其他方法。

其他评估技术

Ragas 只是众多用于评估 RAG 系统的工具和技术之一。以下内容不是一个详尽无遗的列表,但在接下来的子部分中,我们将讨论一些更常用的技术,您可以在获得或生成真实数据后,用来评估 RAG 系统的性能。

双语评估替代指标 (BLEU)

BLEU 衡量生成响应与真实响应之间 n-gram 的重叠程度。它提供一个分数,表示两者之间的相似性。在 RAG 的上下文中,BLEU 可以通过将生成的答案与真实答案进行比较,评估生成答案的质量。通过计算 n-gram 的重叠,BLEU 评估生成的答案在用词和措辞上与参考答案的匹配程度。然而,值得注意的是,BLEU 更注重表面层的相似性,可能无法捕捉生成答案的语义含义或相关性。

回忆导向的摘要评估 (ROUGE)

ROUGE 通过比较生成响应与真实数据的回忆来评估生成响应的质量。它衡量生成响应中包含了多少真实数据。对于 RAG 评估,ROUGE 可用于评估生成答案的覆盖率和完整性。通过计算生成答案与真实答案之间的回忆,ROUGE 评估生成的答案在捕捉参考答案中的关键信息和细节方面的效果。ROUGE 在真实答案较长或更详细时特别有用,因为它侧重于信息的重叠,而不是精确的单词匹配。

语义相似度

诸如余弦相似度或语义文本相似度(STS)等指标可以用来评估生成响应与真实答案之间的语义相关性。这些指标捕捉的是超越精确单词匹配的意义和上下文。在 RAG 评估中,语义相似度指标可以用来评估生成答案的语义一致性和相关性。通过比较生成答案和真实答案的语义表示,这些指标评估生成的答案在捕捉参考答案的基本意义和上下文方面的效果。语义相似度指标尤其在生成答案可能使用不同单词或措辞,但仍传达与真实答案相同的含义时非常有用。

人工评估

虽然自动化指标提供了定量评估,但人工评估在评估生成响应的连贯性、流畅性和总体质量时仍然至关重要,尤其是与真实答案相比。在 RAG 的上下文中,人工评估涉及让人工评审员根据各种标准评估生成的答案。这些标准可能包括与问题的相关性、事实正确性、答案的清晰度以及整体连贯性。人工评估员可以提供自动化指标无法捕捉的定性反馈和见解,例如答案语气的恰当性、是否存在不一致或矛盾以及整体用户体验。人工评估可以通过提供更全面和细致的评估,补充自动化指标,从而更全面地评估 RAG 系统的表现。

在评估 RAG 系统时,通常使用这些评估技术的组合会更有益,以便全面了解系统的性能。每种技术都有其优点和局限性,使用多种指标可以提供更稳健和全面的评估。此外,在选择适当的评估技术时,考虑 RAG 应用的具体需求和目标也很重要。某些应用可能更关注事实正确性,而其他应用可能更侧重于生成答案的流畅性和连贯性。通过将评估技术与您的具体需求对齐,您可以有效地评估 RAG 系统的性能并识别改进的领域。

总结

在本章中,我们探讨了评估在构建和维护 RAG 管道中的关键作用。我们讨论了评估如何帮助开发者识别改进的领域、优化系统性能,以及衡量在开发过程中对系统进行修改的影响。我们还强调了在部署后对系统进行评估的重要性,以确保系统的持续有效性、可靠性和性能。

我们介绍了 RAG 管道各个组件的标准化评估框架,如嵌入模型、向量存储、向量搜索和 LLM。这些框架为不同模型和组件的性能比较提供了有价值的基准。我们强调了真实数据在 RAG 评估中的重要性,并讨论了获取或生成真实数据的方法,包括人工标注、专家知识、众包和合成真实数据生成。

本章还包括一个实践代码实验,我们将 ragas 评估平台集成到 RAG 系统中。我们生成了合成的真实数据,并建立了一套全面的指标来评估使用混合搜索与原始基于密集向量语义搜索的影响。我们探讨了 RAG 评估的不同阶段,包括检索评估、生成评估和端到端评估,并分析了我们评估中获得的结果。代码实验提供了一个在 RAG 管道中实现全面评估系统的真实世界示例,展示了开发者如何利用评估指标获得见解并做出数据驱动的决策,以改善他们的 RAG 管道。我们还分享了来自 ragas 创始人的一些关键见解,进一步帮助您的 RAG 评估工作。

在下一章中,我们将开始讨论如何以最有效的方式利用 LangChain 和 RAG 系统的关键组件。

参考文献