如何评估一个RAG(检索增强生成)系统

本文首发自博客文章 如何评估一个RAG(检索增强生成)系统

RAG 概念最初来源于 2020 年 Facebook 的一篇论文,这是 Facebook 博客对论文内容的进一步解释 👉《检索增强生成:简化智能自然语言处理模型的创建》。大家都知道在今天构建一个 RAG 应用的概念证明很容易,但要正经投入生产却非常困难,俗称「一周出 Demo、半年用不好 🫠」,要使 RAG 应用的性能达到令人满意的状态尤其困难,如何正确的评估 RAG 应用是当前一个热门的研究主题,例如 RAG 三元组指标、ROUGE、ARES、BLEU 等。RAG 流程中包含三大组件:

  • 数据索引组件:数据向量和索引创建的工作
  • 检索器组件:为 LLM 检索额外的上下文信息,以回答查询。
  • 生成器组件:基于检索到的信息增强的提示生成答案。

评估 RAG 流程时,针对数据索引组件(包含数据提取、嵌入、创建索引等)没有太多评估工作,而对检索器和生成器组件,需要充分测试以了解 RAG 流程是否仍需要改进以及在哪些方面需要改进。

我的新书《LangChain编程从入门到实践》 已经开售!推荐正在学习AI应用开发的朋友购买阅读!
LangChain编程从入门到实践

1. 实践经验

这个是我实践探索出的经验,当前还比较粗,我选取了流畅有用、上下文支持率、上下文有效率 3 个指标进行的评估,且听我一一解释。

流畅有用

这个好理解,流畅侧重生成的内容是否流畅连贯,以当下大模型的能力基本不存在这方面问题,就算胡说八道,但是表达也是流畅自然的,其次有用指的是生成的内容是否有用,用户正常使用过程中很容易感知,而且这部分的指标收集来源也是用户交互数据,系统推上去后,每条回答都有一个点赞 👍 点踩 👎 的按钮。

上下文支持率(a)

检索到的上下文内容在全部的生成内容中占比多少,用于评估最终结果中到底用了多少检索到的知识库内容。

上下文支持率 = 有检索到的上下文信息进行支撑的生成内容 / 总的生成内容

上下文有效率(b)

检索到的和问题意图关联程度较强的上下文片段与检索到的全部上下文片段的占比,用于评估检索到的上下文信息质量

上下文有效率 = 与问题强相关的上下文片段/检索到的全部上下文片段

最后计算出上下文效率和上下文支持率的调和平均数 H(调和平均数的计算方法是将所有数值的倒数求和,然后再取这个和的倒数,受极端值影响较小

然后后台每一条问答,都会有 a,b,H 三个指标数据进行标记。

总结

有意思的是,我按照自己摸索的这套方案做出一个版本后,去搜相关资料才发现和 《生成式搜索引擎中验证性评估》这篇论文的思路挺相近的,不过论文中探讨的更严谨,正在做这方面工作的朋友可以去读一下,或者去看下Devv(一款面向开发者的新一代 AI 搜索引擎)作者的解读,我这里结合他的解读快速过下论文中的方案:

论文提到了一个值得信赖的 Generative Search Engine 的先决条件就是:可验证性(verifiability)。理想的 RAG 系统应该是:

  • 高引用召回率(high citation recall),即所有的生成内容都有引用(外部知识)充分支持
  • 高引用精度(high citation precision),即每个引用是否真的支持生成的内容

实际上这两个指标不可能做到 100%,根据论文中的实验结果,现有的 Generative Search Engine 生成的内容经常包含无据陈述和不准确的引文,这两个数据分别是 51.5% 和 74.5%。

于是采用了 4 个指标来进行评估:

  1. fluency,流畅性,生成的文本是否流畅连贯(例如 xxx 算是流畅的,并用 Five-point Likert 量表来进行计算,从 Strongly Disagree 到 Strongly Agree)
  2. perceived utility,实用性,生成的内容是否有用 (让评测者对「The response is a helpful and informative answer to the query」这个说法的同意程度进行打分)
  3. citation recall,引文召回率,引文支持的生成内容 / 总的生成内容 (和我的上下文支持率差不多含义)
  4. citation precision,引文精度,与特定主题相关的文献数量 / 检索到的内容 (和我的上下文有效率概念也近似)

一个优秀的 GSE (生成式搜索引擎)系统应该在 citation recall 和 citation precision 上都获得比较高的评分。

F1 分数是精确率和召回率的调和平均数,它为了同时考虑精确率和召回率的影响,是二者之间的一种平衡。F1 分数的计算公式为:

F1 分数

F2 分数是一个更为一般化的版本,它允许调整精确率和召回率的相对重要性。F2 分数通过引入一个参数 β,可以对精确率和召回率进行加权。具体来说,当 β>1 时,召回率的权重大于精确率;当 β<1 时,精确率的权重大于召回率。F2 分数就是在这个公式中设 β=2,使得召回率的重要性高于精确率。Fβ 分数的计算公式为:

F2 分数

这两种分数都用于评估模型的性能,特别是在数据不平衡的情况下,它们比单纯的准确率更能反映模型的性能。

2. RAGAs

RAGAs(Retrieval-Augmented Generation Assessment)是一个框架(GitHub、文档),该框架考虑检索系统识别相关和重点上下文段落的能力,LLM 以忠实方式利用这些段落的能力,以及生成本身的质量。为了了解 RAG 应用性能是否在提高,必须通过评估指标和评估数据集进行定量评估。

评估数据

最开始的 RAGAs 在评估数据集时,不必依赖人工标注的标准答案,而是通过底层的大语言模型 (LLM) 来进行评估(提供了自动测试数据生成的工具),不过 RAGAs 现在已经扩展了需要依赖真实标签的指标(例如,context_recallanswer_correctness)(详见 评估指标)。

为了评估 RAG 流程,RAGAs 需要以下几种数据信息:

  • question:RAG 流程的输入,即用户查询问题。
  • answer:RAG 流程生成的答案,也就是最终输出结果。
  • contexts:用于回答 question 的从外部知识源检索到的上下文。
  • ground_truths(真实答案)question 的真实答案。这是唯一需要人工标注的信息。这个信息仅在评估 context_recall 这一指标时才需要。(详见 评估指标)。

评估指标

RAGAs 提供了一些 指标,可用于从组件层面和整体流程两个方面评估 RAG 流程的性能。

组件层面上,RAGAs 提供了评估检索组件(context_relevancycontext_recall)和生成组件(faithfulnessanswer_relevancy)的指标,所有指标的评分范围在 [0, 1] 之间,分数越高表示性能越出色:

  • context_precision(上下文精度) :衡量与查询问题最相关的上下文片段是否都被优先展示在前几项。该指标通过问题真实答案上下文来计算。
  • context_recall(上下文召回率) :衡量是否检索到了所有必要信息以回答问题。该指标基于 真实答案(框架中唯一基于人工标注的真实数据的指标)和 上下文 计算得出。
  • faithfulness(事实一致性) :衡量生成答案的事实准确性。从给定上下文中正确的陈述数量除以生成答案中陈述的总数。该指标结合了 问题上下文答案
  • answer_relevance(答案相关性) :衡量生成答案与问题的相关性。该指标使用 问题答案 计算得出。例如,对于问题 “北京在哪里,它的首都是什么?”,答案 “北京位于亚洲。” 的答案相关性会很低,因为它只回答了问题的一半。

整体流程 上,例如 答案的语义相似度 和 答案的正确性可以作为评估 RAG 整体流程的指标。

使用 RAGAs 评估 RAG

下面是一个使用 RAGAs 评估 RAG 应用的过程,主要代码来自这篇文章。

RAG 应用示例

代码部分还是以 LangChain 为例:

import requests
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitterurl = "https://raw.githubusercontent.com/langchain-ai/langchain/master/docs/docs/modules/state_of_the_union.txt"
res = requests.get(url)
with open("state_of_the_union.txt", "w") as f:f.write(res.text)# 加载数据
loader = TextLoader('./state_of_the_union.txt')
documents = loader.load()# 分块数据
text_splitter = CharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = text_splitter.split_documents(documents)

接下来,使用 OpenAI 嵌入模型为每个块生成向量嵌入,并将它们存储在向量数据库中。

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Weaviate
import weaviate
from weaviate.embedded import EmbeddedOptions
from dotenv import load_dotenv,find_dotenv# 从 .env 文件加载 OpenAI API 密钥
load_dotenv(find_dotenv())# 设置向量数据库
client = weaviate.Client(embedded_options = EmbeddedOptions()
)# 填充向量数据库
vectorstore = Weaviate.from_documents(client = client,documents = chunks,embedding = OpenAIEmbeddings(),by_text = False
)# 定义向量存储为检索器以启用语义搜索
retriever = vectorstore.as_retriever()

最后,设置一个提示模板和 OpenAI LLM,并将它们与检索器组件结合成一个 RAG 流程。

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser# 定义 LLM
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)# 定义提示模板
template = """您是一个问答任务的助手。
使用以下检索到的上下文片段回答问题。
如果您不知道答案,只需说您不知道。
最多使用两个句子,保持答案简洁。
问题:{question}
上下文:{context}
答案:
"""prompt = ChatPromptTemplate.from_template(template)# 设置 RAG 流程
rag_chain = ({"context": retriever,  "question": RunnablePassthrough()}| prompt| llm| StrOutputParser()
)
准备评估数据

由于 RAGAs 在评估数据集时,不必依赖人工标注的标准答案,所以评估数据集所需的准备工作是最小的。只需要准备 问题真实答案 对,从中可以推导出其他所需信息,如下所示:

from datasets import Dataset# 问题
questions = ["美国总统对 Justice Breyer 说了什么?","美国总统对 Intel 的 CEO 说了什么?","美国总统对枪支暴力说了什么?",]
# 真实答案
ground_truths = [["美国总统说 Justice Breyer 致力于服务国家,并感谢他的服务。"],["美国总统说 Pat Gelsinger 准备将 Intel 的投资增加到 1000 亿美元。"],["美国总统要求国会通过经过验证的措施来减少枪支暴力。"]]
answers = []
contexts = []# 推导信息
for query in questions:answers.append(rag_chain.invoke(query))contexts.append([docs.page_content for docs in retriever.get_relevant_documents(query)])# 转换为字典
data = {"question": questions,   # 问题"answer": answers, # 答案"contexts": contexts, # 上下文"ground_truths": ground_truths  # 真实答案
}# 将字典转换为数据集
dataset = Dataset.from_dict(data)

如果不关注 context_recall 指标,就不必提供 ground_truths 数据,只需 question 数据即可。

进行应用评估

ragas.metrics 导入所有想要使用的指标,然后使用 evaluate() 函数,传入相关的指标和准备好的数据集即可。

from ragas import evaluate
from ragas.metrics import (faithfulness,answer_relevancy,context_recall,context_precision,
)result = evaluate(dataset = dataset,metrics=[context_precision,context_recall,faithfulness,answer_relevancy,],
)df = result.to_pandas()

下面是最终的 RAGAs 得分(上下文相关性、上下文召回率、忠实度和答案相关性):

img

  • context_precision(上下文精度):上下文精确度的值在 0 到 1 之间,数值越接近 1,表示检索结果的相关性越高,即检索到的信息与查询问题的相关度越紧密,如果上下文精确度的值接近 0,则意味着检索结果中包含的相关项很少或者排名非常靠后,这表明检索系统的性能需要改进。
  • context_recall(上下文召回率):LLM 评估检索到的上下文包含了正确回答问题所需的相关信息。
  • faithfulness(事实一致性):虽然 LLM 判断第一个和最后一个问题的答案正确,但第二个问题的答案错误地声称「美国总统没有提到 Intel 的 CEO」,其事实一致性被判断为 0.5。
  • answer_relevance(答案相关性):所有生成的答案都被判断为与问题相关性较高,都大于 0.8。

3. RAG 对大语言模型的影响

这个来自论文《Benchmarking Large Language Models in Retrieval-Augmented Generation》,定性分析了不同大模型在进行 RAG 时基本能力的表现,包括噪声鲁棒性、拒答、信息整合和反事实鲁棒性4 个测试维度,虽然论文题目强调是 RAG 对大模型的输出效果影响,但等同于对 RAG 流程的生成器组件评估,可以作为一种思路。

4个测试维度

在对比模型上,选用 ChatGPT , ChatGLM-6B , ChatGLM2-6B , Vicuna-7b-v1.3 , Qwen-7B- Chat , BELLE-7B-2M 等模型。

噪声鲁棒性(Noise Robustness)

模型能从噪声文档中提取有用信息。噪声文档定义为与问题相关但不包含任何相关信息的文档。

噪声鲁棒性测试结果

当噪声率超过 80%时,模型的准确性就会明显下降。例如,ChatGPT 的性能从 96.33%降至 76.00%,而 ChatGLM2-6B 的性能则从 91.33%降至 57.33%,RAG 可以有效改善 LLM 的回复,即使在有噪声的情况下,LLM 也能表现出不错的性能。

拒答(Negative Rejection)

当检索到的文档中不存在所需的知识点时,模型应拒绝回答问题。

拒答测试结果

上图显示了评估只提供噪声文档时的拒答率,除了通过精确匹配来评估拒答率(Rej 指标)外,还利用 ChatGPT 来确定大模型的回复是否包含任何拒绝信息(Rej∗ 指标),可以看到大模型很容易被噪声文档误导,从而导致错误的答案。

信息整合(information integration)

评估模型能否回答需要整合多个文档信息的复杂问题。

信息整合测试结果

可以看到,即使在没有噪声的情况下,大模型的最高准确率也只能达到英文 60%和中文 67%,加入噪声后,最高准确率下降到 43%和 55%;当噪声比为 0.4 时,性能下降明显,但对于简单问题,只有在噪声比为 0.8 时才会出现明显下降,复杂问题更容易受到噪声的干扰。大模型难以有效整合信息,不适合直接回答复杂问题。

反事实鲁棒性(CounterfactualRobustness)

评估当通过指令向 LLMs 发出关于检索信息中潜在风险的警告时,大模型能否识别检索文档中已知事实错误的风险。

反事实鲁棒性测试结果

横轴包括以下指标:不包含任何文档的准确率、包含反事实文档的准确率、错误检测率和错误纠正率。可以看到,大模型很难识别和纠正文档中的事实错误,很容易被包含错误事实的文件误导。

总结

总体上 RAGAs 框架中的指标拆的比较细,考虑的比较全面,大家可以重点阅读下项目整体文档,然后借鉴下部分指标整合进自己的设计,而生成式搜索引擎中的方案,从实践出发,提炼的指标虽然少,但是能够很好的评估出 RAG 应用的效果,直接采用,系统也不需要过多工作量。

欢迎关注公众号,获取更多信息。在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/821025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++对于C语言的扩充】函数重载、引用以及内联函数

文章目录 &#x1f680;前言&#x1f680;函数重载注意&#xff1a;✈️为什么C可以实现函数重载&#xff0c;而C语言却不行呢&#xff1f; &#x1f680;引用✈️引用的特性✈️C中为什么要引入引用✈️引用与指针的区别 &#x1f680;内联函数✈️内联函数特性 &#x1f680;…

GitHub提交PR

本教程只做开源代码库Github工程提交pr的教程&#xff0c;不做其他的深入的讲解 Github和Gitlab的操作类似&#xff0c;只不过Github叫PR&#xff0c;GitLab叫MR&#xff0c;基本上做法是一致的 以开源项目QuickChat为例 https://github.com/Binx98/QuickChat https://github…

C++项目 -- 负载均衡OJ(一)comm

C项目 – 负载均衡OJ&#xff08;一&#xff09;comm 文章目录 C项目 -- 负载均衡OJ&#xff08;一&#xff09;comm一、项目宏观结构1.项目功能2.项目结构 二、comm公共模块1.util.hpp2.log.hpp 一、项目宏观结构 1.项目功能 本项目的功能为一个在线的OJ&#xff0c;实现类似…

研发岗-统信UOS系统配置npm git等前端常用配置

第一步 获取root权限 配置环境等都需要用到root权限&#xff0c;所以我们先获取到root权限&#xff0c;方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包&#xff0c;解压到指定文件夹&#xff0c;设置链接&#xff0…

苹果电脑启动磁盘是什么意思 苹果电脑磁盘清理软件 mac找不到启动磁盘 启动磁盘没有足够的空间来进行分区

当你一早打开苹果电脑&#xff0c;结果系统突然提示&#xff1a; “启动磁盘已满&#xff0c;需要删除部分文件”。你会怎么办&#xff1f;如果你认为单纯靠清理废纸篓或者删除大型文件就能释放你的启动磁盘上的空间&#xff0c;那就大错特错了。其实苹果启动磁盘的清理技巧有很…

STM32之HAL开发——CubeMX配置串行Flash文件系统

配置流程 在开始配置FATFS前&#xff0c;需要提前配置好RCC的时钟&#xff0c;以及时钟的频率&#xff0c;另外还要配置好Debug选项&#xff08;选择串行&#xff09; 选项介绍 文件系统适用于SD卡&#xff0c;Disk磁盘等&#xff0c;需要我们将对应的驱动打开才可以使用。 …

【vue】Pinia-2 安装Pinia,使用store

1. 安装Pinia 在项目路径下执行npm install pinia 在package.json中查看 2. 使用store 在main.js中添加 import { createPinia } from pinia const pinia createPinia()修改createApp方法 最后示例如下&#xff08;三处修改&#xff09; import { createApp } from vue //…

SimpleImputer缺失数据处理报错解决方案

作者Toby&#xff0c;来源公众号&#xff1a;Python风控建模&#xff0c;SimpleImputer缺失数据处理报错解决方案 今天有学员反馈缺失值代码报错&#xff0c;由于sklearn缺失值处理的包升级&#xff0c;下面把官网最新的缺失值处理代码奉上。 参考https://scikit-learn.org/st…

请把「睡一个好觉」,当成一天里最重要的事来管理

我发现许多人都有这么一种情况&#xff1a;明明知道睡眠很重要&#xff0c;但却总是有意无意地熬夜。 比如&#xff1a; 给自己排了太多的学习和工作量&#xff0c;一不小心就到了凌晨一两点&#xff1b; 总觉得过去的一天什么都没干&#xff0c;宁愿在网上闲逛&#xff0c;也不…

低代码开发平台权威推荐:创新开发、领跑市场!

Gartner是低代码领域的一家权威机构&#xff0c;该机构常常通过"魔力象限"的研究方法&#xff0c;评选全球范围内IT细分领域的产品&#xff0c;来帮助决策者提供重要的咨询建议。本文盘点了Gartner机构推荐的6款低代码平台&#xff1a;Zoho Creator、Mendix、Oracle、…

JVM结构化体系

目录 目录 1.JVM 简介 1.1. 如何理解 JVM 呢&#xff1f; 1.2. 市场主流 JVM 分析&#xff1f; 1.3. 为什么要学习 JVM&#xff1f; 1.4. 字节码底层是如何执行呢&#xff1f; 如何理解 JIT 呢&#xff1f; 为什么 JVM 中解释执行与编译执行的并存&#xff08;混合模式&…

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的拷贝构造函数…

el-drawer二次封装进行可拖拽

1.想要的效果 鼠标放到上面出现箭头显示可拖拽得图标 2.代码实现 2.1封装成自定义指令 // drawerDragDirective.js // 定义指令 const drawerDragDirective {// 指令绑定时的处理函数bind(el, ) {const minWidth 300;const dragDom el.querySelector(.el-drawer);// 创…

掀起区块链开发狂潮!Scaffold-eth带你一键打造震撼DApp

文章目录 前言一、Scaffold-eth是什么&#xff1f;二、安装和配置1.准备工作2.安装3.配置开发环境 三、进阶使用1.放入自己的合约2.部署运行 总结 前言 前面的文章传送&#x1f6aa;&#xff1a;hardhat入门 与 hardhat进阶 在之前的文章中&#xff0c;我们已经探讨了使用Har…

设计模式系列:简单工厂模式

作者持续关注 WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS二次开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 目录 定义 特点 使用场景 优缺点 (1) 优点…

故障转移-redis

4.4.故障转移 集群初识状态是这样的&#xff1a; 其中7001、7002、7003都是master&#xff0c;我们计划让7002宕机。 4.4.1.自动故障转移 当集群中有一个master宕机会发生什么呢&#xff1f; 直接停止一个redis实例&#xff0c;例如7002&#xff1a; redis-cli -p 7002 sh…

保持微软Microsoft Teams始终在线的方案

保持微软Microsoft Teams始终在线的方案 背景方案 背景 目前使用微软Teams办公的小伙伴很多&#xff0c;但是长时间不操作电脑就被自动设置成离线状态。对于在电脑前学习书本或者在思考问题的小伙伴就显得不太友好&#xff0c;因为即使我们不操作电脑我们也时刻在电脑前&#…

定时器产生延时停止

1&#xff0c;需求&#xff1a; 当按下按钮SB1,输出信号为0N,指示灯点亮;按下按钮SB2,经过10s的延时后,指示灯熄灭 2&#xff0c;关闭使用定时的常闭触电

HG泄露(ctfhub)

工具准备&#xff1a;dirsearch、dvcs-ripper 网络安全之渗透测试全套工具篇&#xff08;内含安装以及使用方法&#xff09;_dvcs-ripper-CSDN博客 dvcs-ripper&#xff1a;一款perl的版本控制软件信息泄露利用工具&#xff0c;支持bzr、cvs、git、hg、svn... tree //树状…

APP开发_Android 与 js 互相调用

1 js 调用 Android 方法 当使用 JavaScript 调用 Android 原生方法时&#xff0c;主要涉及到 Android 的 WebView 组件&#xff0c;它允许你在 Android 应用中嵌入网页内容&#xff0c;并提供了 JavaScript 与 Android 代码交互的能力。 &#xff08;1&#xff09;创建JavaSc…