包含原理、图表和代码
如果您为实际业务系统开发了检索增强生成(RAG)应用程序,您很可能会关注其效果。换句话说,您希望评估RAG的表现如何。
此外,如果您发现现有的RAG效果不够理想,您可能需要验证高级RAG改进方法的有效性。换句话说,您需要进行评估,看看这些改进方法是否有效。
在本文中,我们首先介绍由RAGAs(检索增强生成评估)提出的RAG评估指标,这是一个用于评估RAG管道的框架。然后,我们解释如何使用RAGAs + LlamaIndex实现整个评估过程。
RAG评估指标
简而言之,RAG过程涉及三个主要部分:输入查询、检索到的上下文以及LLM生成的响应。这三个元素构成了RAG过程中最重要的三元组,并且相互依赖。
因此,可以通过衡量这些三元组之间的相关性来评估RAG的有效性,如图1所示。
论文中提到了总共3个指标:忠实度(Faithfulness)、答案相关性(Answer Relevance)和上下文相关性(Context Relevance),这些指标不需要访问人工标注的数据集或参考答案。
此外,RAGAs网站还介绍了另外两个指标:上下文精确度(Context Precision)和上下文召回率(Context Recall)。
忠实度/基于事实性
忠实度指的是确保答案基于给定的上下文。这对于避免幻觉和确保检索到的上下文能作为生成答案的依据至关重要。
如果得分较低,表明LLM的回应不符合检索到的知识,提供虚幻答案的可能性增加。例如:
为了评估忠实度,我们首先使用LLM提取一组陈述,**S(a(q))**
。方法是使用以下提示:
给定一个问题和答案,从答案的每个句子中创建一个或多个陈述。
question: [question]
answer: [answer]
生成**S(a(q))**
后,LLM判断每个陈述si是否能从**c(q)**
推断出来。这一验证步骤通过以下提示进行:
考虑给定的上下文和以下陈述,然后判断它们是否得到上下文中信息的支撑。在得出结论(是/否)前,为每个陈述提供简短解释。按照指定格式,在最后依次为每个陈述提供最终结论。请勿偏离指定格式。
statement: [statement 1]
...
statement: [statement n]
最终的忠实度得分**F**
计算为**F = |V| / |S|**
,其中**|V|**
表示LLM支持的陈述数量,**|S|**
表示陈述总数。
答案相关性
此指标衡量生成答案与查询之间的相关性。得分越高,表示相关性越好。例如:
为了估计答案的相关性,我们提示LLM根据给定的答案**a(q)**
生成n个潜在问题**qi**
,如下所示:
Generate a question for the given answer.
answer: [answer]
然后,我们利用文本嵌入模型获取所有问题的嵌入表示。
对于每个**qi**
,我们计算其与原始问题**q**
的相似度**sim(q, qi)**
。这对应于嵌入之间的余弦相似度。问题**q**
的答案相关性得分**AR**
计算如下:
上下文相关性
这是一个衡量检索质量的指标,主要评估检索到的上下文在多大程度上支持查询。低分表明检索到了大量不相关的内容,这可能会影响LLM生成的最终答案。例如:
为了估计上下文的相关性,从上下文(**c(q)**
)中使用LLM提取一组关键句子(**Sext**
)。这些句子对于回答问题至关重要。提示如下:
请从提供的上下文中提取可能有助于回答以下问题的相关句子。
如果未找到相关句子,或者您认为无法根据给定的上下文回答问题,
请返回短语“Insufficient Information”。
在提取候选句子时,不允许对给定上下文中的句子进行任何更改。
然后,在RAGAs中,使用以下公式在句子级别计算相关性:
上下文一致性评估
该指标衡量检索到的上下文与标注答案之间的一致性程度。它通过使用真实标签和检索到的上下文来计算,数值越高表示性能越好。例如:
在实施时,需要提供真实标签数据。
计算公式如下:
上下文精度
该指标相对复杂,用于衡量所有包含真实事实的相关上下文是否都被排在最前面。分数越高,表示精度越高。
该指标的计算公式如下:
上下文精度的优势在于其能够感知排序效果。然而,其缺点是如果相关召回非常少,但它们都排名很高,分数也会很高。因此,需要结合其他几个指标来综合考虑整体效果。
使用 RAGAs + LlamaIndex 进行 RAG 评估
主要流程如图 6 所示:
环境配置
安装 ragas:pip install ragas
。然后,检查当前版本。
(py) Florian:~ Florian$ pip list | grep ragas
ragas 0.0.22
值得一提的是,如果你使用 pip install git+https://github.com/explodinggradients/ragas.git
安装最新版本(v0.1.0rc1),则不支持 LlamaIndex。
接下来,导入相关库,设置环境和全局变量
import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
dir_path = "YOUR_DIR_PATH"
from llama_index import VectorStoreIndex, SimpleDirectoryReader
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_relevancy,
context_recall,
context_precision
)
from ragas.llama_index import evaluate
目录中只有一个PDF文件,使用的是论文“TinyLlama: An Open-Source Small Language Model”。
(py) Florian:~ Florian$ ls /Users/Florian/Downloads/pdf_test/
tinyllama.pdf
使用 LlamaIndex 构建一个简单的 RAG 查询引擎
documents = SimpleDirectoryReader(dir_path).load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
默认情况下,LlamaIndex 使用 OpenAI 模型,LLM 和嵌入模型可以通过 ServiceContext 轻松配置。
构建评估数据集
由于某些指标需要手动标注的数据集,我自行编写了一些问题及其对应的答案。
eval_questions = [
"能否简要描述TinyLlama模型的特点?",
"我想了解TinyLlama在速度优化方面做了哪些改进?",
"为什么TinyLlama使用Grouped-query Attention?",
"TinyLlama模型是开源的吗?",
"请介绍一下starcoderdata数据集",
]
eval_answers = [
"TinyLlama是一个紧凑的1.1B语言模型,在大约1万亿个token上预训练了约3个周期。基于Llama 2的架构和分词器,TinyLlama利用了开源社区贡献的各种先进技术(例如FlashAttention),实现了更好的计算效率。尽管体积相对较小,TinyLlama在一系列下游任务中表现出色,显著优于现有同规模的开放源代码语言模型。",
"在训练过程中,我们的代码库集成了FSDP,以高效利用多GPU和多节点设置。另一个关键改进是集成了Flash Attention,一种优化的注意力机制。我们将xFormers(Lefaudeux等人,2022年)库中的融合SwiGLU模块替换为原始的SwiGLU模块,进一步提高了代码库的效率。通过这些特性,我们可以减少内存占用,使1.1B模型能够适应40GB的GPU内存。",
"为了减少内存带宽开销并加速推理,我们在模型中使用了grouped-query attention。我们的查询注意力有32个头,并使用4组键值头。通过这种技术,模型可以在不牺牲太多性能的情况下,跨多个头共享键和值表示。",
"是的,TinyLlama是开源的。",
"该数据集是为了训练StarCoder(Li等人,2023年),一个强大的开源大型代码语言模型而收集的。它包含约2500亿个token,涵盖86种编程语言。除了代码外,还包括GitHub问题和涉及自然语言的文本-代码对。",
]
eval_answers = [[a] for a in eval_answers]
指标选择与RAGAs评估
metrics = [
faithfulness,
answer_relevancy,
context_relevancy,
context_precision,
context_recall,
]
result = evaluate(query_engine, metrics, eval_questions, eval_answers)
result.to_pandas().to_csv('YOUR_CSV_PATH', sep=',')
需要注意的是,在RAGAs中,默认使用OpenAI模型。
在RAGAs中,如果你想使用其他LLM(如Gemini)结合LlamaIndex进行评估,我在RAGAs版本0.0.22中尚未找到有效方法,即便调试了RAGAs的源代码。
最终代码
import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
dir_path = "YOUR_DIR_PATH"
from llama_index import VectorStoreIndex, SimpleDirectoryReader
from ragas.metrics import (
faithfulness,
answer_relevancy,
context_relevancy,
context_recall,
context_precision
)
from ragas.llama_index import evaluate
documents = SimpleDirectoryReader(dir_path).load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
eval_questions = [
"Can you provide a concise description of the TinyLlama model?",
"I would like to know the speed optimizations that TinyLlama has made.",
"Why TinyLlama uses Grouped-query Attention?",
"Is the TinyLlama model open source?",
"Tell me about starcoderdata dataset",
]
eval_answers = [
"TinyLlama is a compact 1.1B language model pretrained on around 1 trillion tokens for approximately 3 epochs. Building on the architecture and tokenizer of Llama 2, TinyLlama leverages various advances contributed by the open-source community (e.g., FlashAttention), achieving better computational efficiency. Despite its relatively small size, TinyLlama demonstrates remarkable performance in a series of downstream tasks. It significantly outperforms existing open-source language models with comparable sizes.",
"During training, our codebase has integrated FSDP to leverage multi-GPU and multi-node setups efficiently. Another critical improvement is the integration of Flash Attention, an optimized attention mechanism. We have replaced the fused SwiGLU module from the xFormers (Lefaudeux et al., 2022) repository with the original SwiGLU module, further enhancing the efficiency of our codebase. With these features, we can reduce the memory footprint, enabling the 1.1B model to fit within 40GB of GPU RAM.",
"To reduce memory bandwidth overhead and speed up inference, we use grouped-query attention in our model. We have 32 heads for query attention and use 4 groups of key-value heads. With this technique, the model can share key and value representations across multiple heads without sacrificing much performance",
"Yes, TinyLlama is open-source",
"This dataset was collected to train StarCoder (Li et al., 2023), a powerful opensource large code language model. It comprises approximately 250 billion tokens across 86 programming languages. In addition to code, it also includes GitHub issues and text-code pairs that involve natural languages.",
]
eval_answers = [[a] for a in eval_answers]
metrics = [
faithfulness,
answer_relevancy,
context_relevancy,
context_precision,
context_recall,
]
result = evaluate(query_engine, metrics, eval_questions, eval_answers)
result.to_pandas().to_csv('YOUR_CSV_PATH', sep=',')
注意,在终端运行程序时,pandas dataframe 可能无法完全显示。要查看它,可以将其导出为 CSV 文件,如图 6 所示。
从图 6 可以看出,第四个问题“Tell me about starcoderdata dataset
”全是 0,这是因为 LLM 无法提供答案。第二个和第三个问题上下文精度为 0,表明检索到的相关上下文没有排在最前面。第二个问题的上下文召回率为 0,表明检索到的上下文与标注答案不匹配。
现在,让我们看看第 0 到 3 个问题。这些问题的答案相关性得分很高,表明答案与问题之间有很强的关联性。此外,忠实度得分并不低,这表明答案主要来自上下文的推导或总结,可以得出结论,这些答案并非 LLM 幻觉产生。
此外,我们发现尽管上下文相关性得分较低,但 gpt-3.5-turbo-16k(RAGAs 的默认模型)仍能从中推导出答案。
根据结果,显然这个基本的 RAG 系统仍有很大的改进空间。
结论
总体而言,RAGAs 提供了全面的指标来评估 RAG,并提供了便捷的调用方式。目前,RAG 评估框架尚不完善,RAGAs 提供了一个有效的工具。
在调试 RAGAs 的内部源代码后,可以明显看出 RAGAs 仍处于早期开发阶段。我们对其未来的更新和改进持乐观态度。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。