Rag Evaluation

zh-CNhf-cookbooknotebooks

RAG 评估

作者 Aymeric Roucher

本 notebook 演示了如何评估你的 RAG(Retrieval Augmented Generation),通过构建一个合成评估数据集并使用 LLM-as-a-judge 来计算你系统的准确性。

对于 RAG 系统的介绍,你可以查看这个技术指南!

RAG 系统很复杂: 这里有一个 RAG 流程图,我们用蓝色标注了系统增强的所有可能性:

实施上述任何改进都可能会带来巨大的性能提升;但如果无法监控对系统性能的影响,那么进行任何更改都是无用的!让我们看看如何评估我们的 RAG 系统。

评估RAG性能

由于有如此多的部分需要调整,这些部分对性能有很大影响,因此对 RAG 系统进行基准测试是至关重要的。

对于我们的评估流水线,我们将需要:

  1. 一个带有问题-答案对的评估数据集(QA 对)
  2. 一个评估器,用于计算我们的系统在上面的评估数据集上的准确性。

➡️ 结果发现,我们可以在整个过程中使用 LLMs 来帮助!

  1. 评估数据集将由 LLM 🤖 合成生成,并且问题将由其他 LLM 🤖 过滤掉
  2. 然后,LLM-as-a-judge 智能体 🤖 将在这个合成数据集上执行评估。

让我们深入挖掘并开始构建我们的评估流水线! 首先,安装所需的模型依赖项。

[ ]
[ ]
[ ]
[ ]

加载你的知识基础

[ ]

1. 为评估构建合成数据集

我们首先构建一个问题和相关上下文的综合数据集。方法是先从我们的知识库中获取元素,并让 LLM 根据这些文档生成问题。

然后,我们设置其他 LLM 智能体作为生成问答对的质置过滤器:每个智能体将作为一个特定缺陷的过滤器。

1.1. 准备源数据文档

[ ]

1.2. 为问题生成设置智能体

我们采用 Mixtral 作为问答对的生成,因为他在各个排行榜上表现极佳,比如 Chatbot Arena。

[ ]
[ ]

现在让我们生成我们的问答对。

对于这个例子,我们只生成 10 个问答对,并从 Hub 加载其余的。

但是对于你的特定知识库,考虑到你想要获得至少约 100 个测试样本,并且考虑到我们稍后会用我们的批判智能体过滤掉大约一半的样本,你应该生成更多的样本,超过 200 个。

[ ]
[ ]

1.3. 设置批判智能体

之前的智能体生成的问题可能存在许多缺陷:在验证这些问题之前,我们应该进行质量检查。

因此,我们构建了批判智能体,它们将根据以下几个标准对每个问题进行评分,这些标准在这篇论文中给出:

  • 具体性(Groundedness):问题是否可以从给定的上下文中得到回答?
  • 相关性(Relevance):问题对用户是否相关?例如,"transformers 4.29.1 发布的日期是什么?"对于 ML 用户来说并不相关。

我们注意到的一个最后的失败案例是,当一个函数是为生成问题的特定环境量身定做的,但本身难以理解,比如"这个指南中使用的函数的名称是什么?"。 我们也为这个标准构建了一个批判智能体:

  • 独立(Stand-alone):对于一个具有领域知识/互联网访问权限的人来说,问题在没有任何上下文的情况下是否可以理解?与此相反的是,对于从特定博客文章生成的问题比如"这篇文章中使用的函数是什么?"

我们系统地用所有这些智能体对函数进行评分,每当任何一个智能体的分数太低时,我们就从我们的评估数据集中删除这个问题。

💡 当要求智能体输出分数时,我们首先要求它们产生其理由。这将帮助我们验证分数,但最重要的是,要求它首先输出理由给了模型更多的 token 来思考和详细阐述答案,然后再将其总结成一个单一的分数 token。

我们现在构建并运行这些批判智能体。

[ ]
[ ]

现在让我们基于我们批判智能体的分数过滤掉不好的问题:

[ ]
Evaluation dataset before filtering:
============================================
Final evaluation dataset:

现在我们合成评估数据集已完成!我们可以在这个评估数据集上评估不同的 RAG 系统。

我们在这里只生成了少数几个问答对,以减少时间和成本。下面,让我们通过加载一个预先生成的数据集来进行下一部分:

[ ]

2. 构建我们的 RAG 系统

2.1. 预处理文档来构建我们的向量数据库

  • 在这一部分,我们将知识库中的文档分割成更小的片段:这些将是被检索器选取的片段,然后被阅读器 LLM 作为支持其答案的元素。
  • 目标是构建语义上相关的片段:不要太小,以免不足以支持答案,也不要太大,以免稀释单个内容。

文本分割有许多选项:

  • 每隔 n 个单词/字符分割,但这有可能割裂段落甚至句子
  • 在 n 个单词/字符后分割,但只在句子边界处
  • 递归分割 尝试通过树状处理文档来保留更多文档结构,首先在最大单元(章节)上分割,然后递归地在更小单元(段落,句子)上分割。 要了解更多关于分块的信息,我建议你阅读由 Greg Kamradt 编写的不错的教程 。

这个 space 让你可视化不同的分割选项是如何影响你得到的片段的流程。

在以下内容中,我们使用 Langchain 的 RecursiveCharacterTextSplitter。 💡 为了在我们的文本分割器中测量片段长度,我们的长度函数将不是字符的数量,而是 token 化文本中的 token 数量:实际上,对于后续处理 token 的嵌入器来说,以 token 为单位测量长度更为相关,并且在经验上表现更好.

[ ]
[ ]

2.2. 检索器 - 嵌入 🗂️

检索器的作用类似于内部搜索引擎:给定用户查询,它从你的知识库中返回最相关的文档。

对于知识库,我们使用 Langchain 向量数据库,因为它提供了一个方便的 FAISS 索引,并允许我们在整个处理过程中保留文档元数据。

🛠️ 包含可选项:

  • 调整分块方法:
    • 片段(chunks)的大小
    • 方法:在不同的分隔符上分割,使用语义分块...
  • 更改嵌入模型
[ ]

2.3. 阅读器 - LLM 💬

在这一部分,LLM 阅读器读取检索到的文档以形成其答案。

🛠️ 为了改善结果,我们尝试了以下选项:

  • 切换重排序开启或关闭的状态
  • 更改阅读器模型
[ ]
[ ]
[ ]

3. 对 RAG 系统进行基准测试

RAG 系统和评估数据集现在准备好了。最后一步是在这个评估数据集上判断 RAG 系统的输出。 为此,我们设置了一个裁判智能体。 ⚖️🤖

在不同的 RAG 评估指标中,我们选择只关注忠实度,因为这是衡量我们系统性能的最佳的端到端指标。

我们使用 GPT4 作为评判者,因为它在实际应用中表现良好,但你也可以尝试其他模型,例如 kaist-ai/prometheus-13b-v1.0 或 BAAI/JudgeLM-33B-v1.0。

💡 在评估提示中,我们给出了每个指标的详细描述,采用 1-5 分的评分刻度,正如 Prometheus 的提示模板 所做的那样:这有助于模型精确地确定其指标。如果你给评判 LLM 一个模糊的评分刻度,那么不同示例之间的输出将不够一致。

💡 再次提示 LLM 在给出最终评分之前先输出其理由,这样它就有更多的 token 来帮助它正式化和详细阐述评判。

[ ]
[ ]
[ ]

🚀 让我们运行一下测试和评估一下答案!👇

[ ]

检查结果

[ ]
[ ]
[ ]
settings
,./output/rag_chunk:200_embeddings:thenlper~gte-small_rerank:False_reader-model:zephyr-7b-beta.json       0.884328
,./output/rag_chunk:200_embeddings:BAAI~bge-base-en-v1.5_rerank:False_reader-model:zephyr-7b-beta.json    0.906716
,./output/rag_chunk:200_embeddings:BAAI~bge-base-en-v1.5_rerank:True_reader-model:zephyr-7b-beta.json     0.906716
,./output/rag_chunk:200_embeddings:thenlper~gte-small_rerank:True_reader-model:mixtral.json               0.906716
,./output/rag_chunk:200_embeddings:thenlper~gte-small_rerank:True_reader-model:zephyr-7b-beta.json        0.921642
,./output/rag_chunk:200_embeddings:thenlper~gte-small_rerank:True_reader-model:mixtral0.json              0.947761
,Name: eval_score_GPT4, dtype: float64

结果示例

让我们加载通过调整这个 notebook 中可用的不同选项所获得的结果。关于这些选项为何有效或无效的更多细节,请参阅 高级 RAG 的 notebook。

正如在下面的图表中所看到的,一些调整并没有带来任何改善,而有些则带来了巨大的性能提升。

➡️ 所以没有单一的好方法:在调整你的 RAG 系统时,应该尝试几种不同的方向。

[ ]
[ ]

如上图所示,这些调整对性能的影响各不相同。尤其是调整片段大小,既简单又非常有影响力。

但这只是针对我们的情况:你的结果可能大不相同:现在你已经有了一个可靠的评估流水线,可以开始探索其他选项了!🗺️