讨论 GPT-4 Turbo 128K context window 在实际应用中的局限,揭示大模型上下文需求还在持续膨胀。
OpenAI 最近推出了具有 128K 上下文窗口的 GPT-4 Turbo 模型。这比 GPT-4 之前 32K 的最大值提升了 4 倍。
你知道这个上下文大小足以容纳 1684 条推文或 123 个 StackOverflow 问题吗?或者说,Linux 内核中最大的源文件需要的上下文窗口是 128k 的 540 倍?继续往下看更多对比。
我收集了一些工件,将它们转换为文本表示形式,计算了 token 大小,并计算了有多少工件能装入 128K 的上下文窗口。
这是包含链接/详情的完整表格。
我在文章后续部分论证的结论:
大型语言模型只能处理文本,与新型基础模型——大型多模态模型 (LMMs)——相对。
任何给定的文档/对象/实体都可以用多种方式表示为文本。而且没有完美的方式将不同类型的数字对象转换为文本并保留所有信息。
将文档转换为文本可能会产生信息损失:你会丢失样式、结构、媒体,甚至部分文本信息本身(比如超链接的 URL)。
以这个 StackOverflow 问题为例:
如果我在浏览器中选中部分内容并复制粘贴到文本编辑器,它看起来会这样:
注意投票计数器变成了单个数字(2),代码块没有格式化,链接的 URL(dart:typed_data 和 file)也消失了。
Markdown 格式的源文本包含了更多细节(虽然投票计数器不是 MD 的一部分):
所以向 LLM 输入源文本而不是屏幕上看到的纯文本是有意义的。LLM 很善于理解结构化输入,而且有很多使用 XML、HTML、JSON 等的 prompt 示例都能提供很好的结果。
以我们的 StackOverflow 例子来说,从纯文本复制粘贴转移到 MD 源只增加了 10%(947 vs 1037 token)。但是,不总是能访问源文本(在我的情况下作为作者我可以点击"编辑"),人们可能需要采用某些技术来提取文本并用结构和相关信息丰富它。
虽然即使谈论纯文本对比源标记,并非所有语言都像 Markdown 那样基础和轻量。以网页为例:
说到 HTML,我们谈论的是 10 倍甚至 100 倍的数量级。这个增长的很大部分源于 JavaScript 和 CSS,尽管如此,即使有最大的上下文窗口,LLM 也无法处理原始 HTML 输入。
这是我用来计数 token 的 Google 搜索结果页面的样子:
它有 10 个搜索结果(只要你不向下滚动并加载更多结果),一个带有搜索框的头部,页脚,侧窗格,有一些瓷砖的水平带。131 个这样的页面用复制粘贴的文本表示时(丢失样式、链接、布局、交互性)完全适合 128K 的上下文窗口。同一个页面用源 HTML 表示时则装不下(只能装 52%)。
假设你正在构建一个检索增强的 AI agent(可以请求外部源并将相关信息片段注入到 prompt 中的那种)。该 agent 有工具来发起 HTTP 请求,你使用 OpenAI 的 Chat Completion API,你的模型是 GPT-4 Turbo,拥有 128k 上下文。
这称为 RAG(检索增强生成),通常通过以下方式解决。检索工具发起 API 调用,请求一个页面或读取文件。它精炼检索到的数据以缩小文本/token 的数量同时保留必要信息。然后它使用文本分割器将每个文档转换为一系列块(段落、代码块等),使用特定标准来断句(比如 markdown 中的新标题)并确保每个段落不超过给定大小(比如 1000k token)。然后这些文本片段中的每一个都通过语义索引(通过 embedding 分配数百个数字的向量)并存储在向量数据库中。然后,在生成对用户的回复之前,embedding 被用来选择在语义上相关的(与初始用户请求相关)文本块并将它们插入到 prompt 中。这里的几个关键假设是:
你可以有效地精炼结果为较小的文本并保留必要的信息
Embedding 可以提供相关的信息片段并恢复连接/检索相关信息片段
现在假设我们想要处理任意网页并且不知道网页结构。也就是说,你没有给定页面的转换器或不能使用 CSS/HTML 选择器从已知部分提取某些信息(比如所有驻留在具有 search-result CSS 类的 <div> 元素中的搜索结果)。AI agent 的工作是读取 HTML,理解页面的结构,决定下一步移到哪里以及要点击哪些部分。在这样的假设下,只要我们不想人工参与,就无法有效精炼 HTML 输出。如果 LLM 的任务是探索页面的结构并在其中导航,唯一可能成功的选项似乎是让模型获得页面的全部内容(源 HTML)。而显然,即使 128K 的上下文也不足以让 LLM 可靠地处理你在互联网上找到的普通网页的纯 HTML。
而我们甚至还没有涉及问题的第二部分... 如果知识很复杂,分散在不同文档中,有复杂的关系呢... 而且文本分割和 embedding 不能为 prompt 提供有意义的上下文,你需要更多的原始输入。这让上下文大小的问题变得更加严峻。
我们如何才能构建能够爬取任何网页、查看其中内容、对知识结构做出假设并提取相关数据的通用 AI agent?
在这篇探索 GPT-4V(ision) 能力的论文中,有一个关于 GUI 导航的很好的用例:
"一图胜千言"完美演示了数百万 token(原始 HTML)无法装入 LLM 时如何在改变模态后转变为小的可操作信息。
首先,存在二次方复杂度问题。进行推理时,将输入 prompt 翻倍(请求中的 token 数量)会使 CPU 和内存需求增加 4 倍——更长的请求需要 4 倍的时间才能完成。
此外,要让模型有效地处理更大的上下文窗口,它必须在更大的上下文窗口上进行训练,这也需要更多的计算。
而且还有经验研究和各个开发者的测试描绘了关于宣传的与实际有效上下文窗口之间的严峻图景。你离上下文最大限制越近,LLM 就越有可能开始遗忘或遗漏 prompt 中的某些信息。
对 GPT-4 Turbo 的一个这样的测试说,只要不超过 71k 个 token 长度(约 55%),你可以期望回忆性能(LLM 在 prompt 中查找某些给定信息的能力)没有降低。
这与我使用 GPT-3.5 和 GPT-4 API 的观察一致,如果跨越 50% 上下文长度的边界,你会开始得到更多的幻觉和垃圾。
我使用了 VSCode 和 cptX 扩展。它有一个方便的功能来计数当前打开文档中 token 的数量(使用 OpenAI 的 tokenizer Tiktoken):
工作流如下。我要么在 Safari 上的 Preview(macOS 上)打开文档并选择感兴趣的部分并粘贴到打开的 VSCode 文件中,要么打开文档的源文件(HTML、MD、wiki 文本),也将其粘贴到编辑器中,然后接收 token 的数量,然后我将其放入电子表格。
为了进一步行动,你可能会考虑屏蔽此人和/或报告滥用