问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

深入解读RAG与超长上下文LLM之争!

创作时间:
作者:
@小白创作中心

深入解读RAG与超长上下文LLM之争!

引用
CSDN
1.
https://blog.csdn.net/2401_84204207/article/details/139618754

随着大语言模型的上下文窗口(Context Window)以惊人的速度增长,从一年前的4K-8K到如今超过128K,甚至达到1M的规模,一个争议性话题随之而来:超长上下文的大模型(Long Context LLM)是否会取代检索增强生成(RAG)应用?本文将通过实验和分析,深入探讨这一问题。

自从去年下半年以来,大语言模型的上下文窗口正在以不可思议的速度增长。从Claude2开始的200K,到Claude3与Gemini1.5号称的1M上下文,似乎上下文窗口的大小已经不再成为我们使用大模型的顾虑。特别是在Gemini1.5发布的技术报告中,关于其具备的“大海捞针”(在超长的上下文中精确检索到特定位置的某个事实性知识点)能力的实验结果,立刻给火热的AI界带来一个争议话题:

如果未来超长的上下文窗口已经足够把几百个文档一股脑的塞入到大模型对话的窗口,并能完美的在其中检索到事实知识,那么还有必要做任何形式的外部索引与检索,来给大模型提供知识“外挂”(RAG)吗?

LLM的“大海捞针”够用吗?

RAG应用的核心能力其实是“检索”:结合各种方法精确检索到“针”所在的chunk,然后交给LLM推理。所以这也让LLM流派认为:既然LLM已经可以在超长的上下文中精确检索,那么复杂的RAG自然就可以被替代。针对这个问题,让我们看看Lance做的著名的“大海捞针”的实验:

这是一个多“针”的实验,其基本的方法是这样的:在一个超长的上下文中插入多个“针”(needles,即知识点),比如上面的图中,把制作完美披萨的三个秘密成分,作为三个“针”插入到上下文的特定位置(如开头、中间与结尾),并且让其他内容和这个三个“针”的知识完全不相关。然后要求LLM基于这个上下文来回答:制作完美披萨的秘密成份有哪些?以验证LLM在上下文中精准的检索出这三个“针”并推理答案的能力。 采用类似的方法,你就可以测试不同的“针”的数量、不同的上下文长度、不同的“针”位置下大模型的表现。

不同的“针”数量

先看这样一个测试结果图,这是针对GPT-4模型在120K上下文中“大海捞针”能力的测试:

  • 横轴代表注入的不同“针”的数量,这里测试了注入1,3,10个“针”的情况
  • 纵轴代表了在不同“针”数量下,大模型检索(绿)与推理(橙)的正确率。

一个很容易得出的结论是:随着“针”的数量增加,LLM的检索与推理的正确率会下降(毕竟从大海里捞出十个针要比捞一个针更困难)。

不同的上下文长度与“针”位置

现在Lance切换了不同的上下文长度(从最小的1K到最大的120K),同时在每次的上下文中都会插入10个“针”,这10个针分布在上下文从头部到尾部的10个位置(均匀分布),然后测试LLM在不同长度上下文中出这十个“针”的能力。

测试结果用下面的热图来表示,其中绿色区域代表检索的成功率较高,红色区域代表检索成功率较低:

这里观察到的一些结论是:

  • LLM检索的成功率和上下文长度相关。比如在1K的上下文中,GPT4可以轻而易举的找到10个“针”,但是当上下文扩大10倍甚至100倍后,很显然发生了大量的丢失(红色区域)。
  • LLM大海捞针的能力似乎与“针”所在的位置有关。有点类似你在看一本很长的小说,可能越靠后的部分越容易回顾起细节。在这个图中的体现就是,越在上下文末尾出现的“针”(比如编号6-10),越容易被检索到,即使是在很长的上下文中也不会被遗漏。

有一个可能的解释是:LLM(大型语言模型)训练的任务与上下文增强的生成任务之间存在不匹配。在用于预训练LLM的文档中,如网页、书籍、文章和代码,预测特定token的最有信息量的token通常来自于最近的tokens,这导致了一个学习到的偏差,即优先关注最近的tokens。极端的近期偏差会让这类任务产生偏离,因为离的很远的tokens也可能包含非常相关与重要的信息。

亲测“大海捞针”

实际上每个人都可以在Github上搜索LLMTest_NeedleInAHaystak项目,来自行测试任意大模型的“大海捞针”的能力。现在我们来测试国内两个模型,以展示这个测试过程。

测试工具的使用

这个测试工具的基本使用是这样的:

  1. 指定一个最小的上下文长度比如1K,以及最大的长度比如20K,同时指定间隔数量比如10个,那么工具会自动在1K-20K之间划分出10个不同的上下文长度用来依次做测试,比如从1000,3556,6111…一直到20K。
  2. 指定测试“针”所在的多个位置,也是通过指定一个间隔数量来设定。比如指定为10,那么工具会自动在0%,11%,22%…100%的这10个不同位置放置“针”,并测试每次的结果。
  3. 每一次LLM生成后,会借助一个评估器(使用了LangChain的evaluator组件)与大模型(默认为chatgpt3.5)来对答案的正确性进行评价,评价标准最高10分,最低1分。结果会输出到本地文件保存,并用来做可视化图表。
  4. 工具支持单个“针”的测试,也支持多“针”的测试(多“针”测试时的代码有少量bug)。我们这里的测试以单针测试为主。

测试的用例

测试中注入的“针”默认是这样一段与其他上下文无关的事实:

The best thing to do in San Francisco is eat a sandwich and sit in Dolores Park on a sunny day.

测试中输入的其他上下文是通过程序读取的本地多个TXT文件。

测试中要求基于上下文回答的问题是(显然就是“针”可以回答问题):

What is the best thing to do in San Francisco?

测试过程

  1. 从Github下载源代码,安装相关依赖(不要直接使用Pypi的Package)
git clone https://github.com/gkamradt/LLMTest_NeedleInAHaystack.git
cd LLMTest_NeedleInAHaystack
pip install -r requirements.txt
  1. 默认不支持国内模型,此处我们借助OneAPI项目搭建一个简单的API网关,将所有模型接口适配为OpenAI兼容接口,然后做如下修改:
  • 两个环境变量NIAH_MODEL_API_KEY与NIAH_EVALUATOR_API_KEY设定为OneAPI中的API-Key
  • 找到项目中的两个openai.py文件,将其中OpenAI对象的base_url参数指向自己的OneAPI服务器,如:
self.evaluator = ChatOpenAI(model=self.model_name,
base_url="http://x.x.x.x:3500/v1",...)
  1. 现在可以开始测试,在LLMTest_NeedleInAHaystack目录下运行如下命令:
python -m needlehaystack.run

注意,必要参数可以在run.py中直接修改,也可在上面的命令行中携带,主要是下图中红色部分的参数:

测试结果

我们这里对两个模型做了简单的测试,考察模型从1K到24K之间的上下文的捞针能力,上下文大小分成10个等级,每个等级会在上下文的十个不同位置注入测试“针”,以获得最后评估结果。

  1. 通义千问qwen-plus,最大支持32K上下文,测试的结果如下:

可以看到横轴上代表从1K上下文一直到24k的十个不同上下文,纵轴上代表测试的“针”在上下文中所处的不同位置。从测试结果上看,当上下文逐渐增大时,开始出现很明显的“幻觉”问题,开始编造答案,导致评分明显降低。当然这里没有测试更强大的qwen-max模型,或许会有不一样的表现。

一个有趣的问题是,似乎并没有明显表现出上述的“近期偏离”的问题(即“针”所处的上下文深度越深,越容易被大模型所检索到)。

我们也进行了一个简单的多“针”测试(即文章最开头关于披萨的三个配方的问题),测试结果如下,整体来说还是上下文越小,表现越佳:

2.智谱的glm-3-turbo模型,最大支持128K上下文,单”针“的测试结果如下:

同样,没有测试智谱最新的glm-4模型,而是测试了glm-3-turbo模型,由于其最大能够支持128k上下文,因此我们在上述相同条件下增加测试了120K上下文时的表现。测试结果显示,glm-3-turbo在与千问相同条件下的表现几乎完美,但当把上下文扩展到120K时,其失败的概率也会明显增加。这也印证了随着上下文增加时,大模型的捞”针“的能力会开始打折扣。

有趣的事,glm-3-turbo在多“针”用例下的测试结果似乎反而不如千问(如下图),根据实际观察,发现glm-3-turbo会出现一定量的遗漏(3个配方只检索到2个),或者编造(3个配方变成4个)。

此处glm-3-turbo的答案多出一个

以上我们演示了利用开源项目来做大模型海底捞针能力的测试,尽管我们使用上下文仍然不足够大,比如统一采用128K上下文的模型(仅在glm测试中增加了128K的测试),但也基本可以得出这样的结论:当前大模型能否在超长的上下文中准确的检索知识并完成推理,并不是绝对的,它至少会依赖:

  • 输入的上下文长度
  • 关联知识在上下文中所处的位置
  • 完成任务所依赖的关联知识数量

因此,即使完全不考虑成本与响应速度问题,试图依赖超长上下文的LLM来准确检索与推理以完成知识密集型的任务,也是不太现实的。而更加可控的RAG,如果能够结合超长上下文的LLM,又可以产生哪些变化呢?我们下次再讨论。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号