本文经翻译并二次整理自Multi Needle in a Haystack一文。介绍了评估并理解模型在处理长文本和检索信息方面的能力边界实现思路,以及工程实践。本系列合集,点击链接查看
关键链接
概览
随着人工智能模型处理能力的增强,能够处理的上下文信息越来越多,达到百万级别的词汇量,对于这类长上下文的大型语言模型(LLMs)的研究兴趣也随之增长。在这些模型中,一个流行的测试方法是将一个事实(称为"针")嵌入到大量的上下文信息(称为"干草堆")中,然后测试模型是否能在这个上下文中找到并回答与这个事实相关的问题。通过这个方法我们能够评估并理解模型在处理长文本和检索信息方面的能力边界。
然而,这种方法并不完全适用于所有情况,尤其是对于那些需要检索多个事实并在此基础上进行推理的应用。为了解决这个问题,我们提出了一个新的测试基准,即多针检索加推理测试。在这个测试中,我们发现了两个主要结果:
- 当要求模型检索更多的事实时,其性能会下降。
- 当模型需要对检索到的事实进行推理时,性能也会下降。
下图展示了测试结果的概览:随着"针"的数量增加,检索的准确性降低;而且,对这些"针"进行推理的难度比单纯检索更大。
我们还发现,随着提供给模型的上下文信息量的增加,性能也会下降。此外,我们还深入研究了性能下降的原因,特别是当检索多个"针"时。通过分析结果的热图,我们发现当检索多个"针"时,GPT-4模型倾向于检索位于上下文末尾的"针",而忽略了开头的"针",这与之前的单"针"研究结果相似。
接下来,我们将详细介绍如何使用这个基准测试,并讨论在 GPT-4 模型上的测试结果。
如何使用
要进行"多针检索加推理"的评估,用户需要准备三个要素:
- 一个需要多个"针"来回答的"问题"
- 一个基于这些"针"得出的"答案"
- 一个将要插入上下文的"针"的列表
我们扩展了 Greg Kamradt 的"LLMTest_NeedleInAHaystack"项目,以支持多针评估,并且使用了 LangSmith 作为评估工具。通过 LangSmith,我们创建了一个评估集,其中包含了上述的"问题"和"答案"。
以一个实际案例为例,我们创建了一个新的 LangSmith 评估集,名为"multi-needle-eval-pizza-3",其中包含了关于披萨秘密配料的问题和答案:
问题:
制作完美披萨需要哪些秘密配料?
答案:
制作完美披萨的秘密配料包括无花果、帕尔马火腿和山羊奶酪。
在创建了数据集之后,我们可以通过设置一些参数来运行评估,例如:
document_depth_percent_min
- 第一个"针"插入的位置。其余的"针"将在第一个之后均匀插入multi_needle
- 执行多针评估的标记needles
- 要插入上下文的"针"的完整列表evaluator
- 选择评估工具 LangSmitheval_set
- 选择我们创建的评估集"multi-needle-eval-pizza-3"context_lengths_num_intervals
- 测试的上下文长度数量context_lengths_min
(和最大值)- 测试的上下文长度范围
我们可以使用以下命令来执行评估:
css
python main.py --evaluator langsmith --context_lengths_num_intervals 6 --document_depth_percent_min 5 --document_depth_percent_intervals 1 --provider openai --model_name "gpt-4-0125-preview" --multi_needle True --eval_set multi-needle-eval-pizza-3 --needles '[ "无花果是制作完美披萨的秘密配料之一。", "帕尔马火腿是制作完美披萨的秘密配料之一。", "山羊奶酪是制作完美披萨的秘密配料之一。"]' --context_lengths_min 1000 --context_lengths_max 120000
这个命令将启动一个工作流程,其中包括将"针"插入到上下文中,使用带有这些"针"的上下文提示模型生成回答,并评估模型的生成是否正确地检索了"针"。
GPT-4 的检索结果
为了测试 GPT-4 的多针检索能力,我们创建了三个 LangSmith 评估集:
- "multi-needle-eval-pizza-1" - 插入一个"针"。
- "multi-needle-eval-pizza-3" - 插入三个"针"。
- "multi-needle-eval-pizza-10" - 插入十个"针"。
我们评估了 GPT-4(能够处理 128k 标记长度的上下文)在单个回合中检索 1、3 或 10 个"针"的能力,上下文长度分别为小(1000 标记)和大(120,000 标记)。所有运行的命令和生成结果的链接都已提供。
ruby
https://github.com/gkamradt/LLMTest_NeedleInAHaystack/blob/main/viz/multi-needle-datasets/
这里是我们的结果摘要图:
我们可以看到:
- 当"针"的数量从 1 增加到 10 时,模型的性能有所下降。
- 当上下文长度从 1000 增加到 120,000 标记时,性能也会下降。
为了进一步探索和验证这些结果,我们可以查看 LangSmith 跟踪的一个例子,其中我们插入了 10 个"针"。GPT-4 的生成结果如下:
制作完美披萨所需的秘密配料包括浸泡在浓缩咖啡中的枣、甜蓝纹奶酪、糖核桃和梨片。
在这次生成中,只有 四个 "秘密配料" 被正确提及。根据跟踪结果,我们确认所有 10 个"针"都存在于上下文中,并记录了它们被插入的顺序:
markdown
* 无花果
* 帕尔马火腿
* 烟熏苹果木培根
* 柠檬
* 山羊奶酪
* 松露蜂蜜
* 梨片
* 浸泡在浓缩咖啡中的枣
* 甜蓝纹奶酪
* 糖核桃
我们发现,GPT-4 在生成中只提及了我们上下文中最后四个"针"。这揭示了检索失败的一个有趣现象:当上下文变长时,模型更容易忽略位于文档开头的"针"。
因为我们记录了每个"针"的插入位置,我们还可以探究这一点:下面的热图显示了随着上下文长度的增加,10 个"针"检索的情况。每一列代表一个实验,我们要求 GPT-4 在上下文中检索 10 个"针"。
随着上下文长度的增加,我们观察到模型在文档开头的检索失败。这种趋势在多"针"情况下(大约 25k 标记)比单"针"情况(对于 GPT-4 是从 73k 标记开始)更早出现。
GPT-4 的检索与推理
检索增强生成(RAG)通常涉及从索引的文档库中检索多个事实,然后在这些事实的基础上进行推理。为了测试这一点,我们构建了三个数据集,通过询问所有秘密配料的首字母来测试模型的检索和推理能力。
- "multi-needle-eval-pizza-reasoning-1" - 只检索一个"针"。
- "multi-needle-eval-pizza-reasoning-3" - 检索三个"针"。
- "multi-needle-eval-pizza-reasoning-10" - 检索十个"针"。
需要注意的是,这里的推理是非常基础的形式。在未来的基准测试中,我们计划包含不同复杂度的推理任务。
我们比较了仅检索和检索加推理两种情况下的正确答案比例。所有数据和跟踪结果都已提供。我们发现,无论是检索还是推理,随着上下文长度的增加,性能都会下降,而且推理的性能似乎总是落后于单纯的检索。这表明检索能力可能限制了模型在推理任务上的表现,这是符合我们预期的。
总结
长上下文语言模型的发展为我们带来了巨大的潜力。为了有效地利用这些模型,无论是独立使用还是作为外部检索系统的替代,了解它们的能力和局限性至关重要。"多针检索加推理"基准测试为我们提供了一个评估长上下文检索性能的有用工具,特别是在与传统的检索增强生成(RAG)方法相比较时。
通过这些测试,我们可以得到一些初步的见解,但还需要进一步的验证:
- 检索并非万无一失 - 并不能保证所有事实都能被检索到,尤其是当涉及的事实数量和上下文规模增加时。
- 检索失败的模式各异 - 随着上下文长度的增加,GPT-4 在检索位于文档开头的事实时表现不佳。
- 提问方式至关重要 - 根据之前的研究发现,为了提高模型的检索能力,可能需要精心设计提问方式。
- 检索与推理的关系 - 当模型需要对检索到的信息进行推理时,其性能会受到影响。
通过这些发现,我们可以更好地理解并优化长上下文模型在信息检索和推理任务中的应用。