Scaffolded LLM 即自然语言计算机

# Scaffolded LLM 即自然语言计算机

> **来源**:[beren.io](https://www.beren.io/2023-04-11-Scaffolded-LLMs-natural-language-computers/) · 2023-04-11 · Beren Millidge

最近,基于 LLM 的 agent 火得一塌糊涂——AutoGPT 这类项目展示了把 LLM 套进一个简单的 agentic loop、再用 prompt 驱使它去完成现实任务有多容易。更宽泛地,我们可以谈论一类"scaffolded(带支架的)"[^1] LLM 系统——在 LLM 内核外包一层程序化的支架,把若干次独立的 LLM 调用串起来,去完成一个超出单条 prompt 能力范围的更大、更复杂的任务。Scaffolded LLM 这个想法并不新,但有了 GPT4 之后,底层 LLM 的可靠性和指令遵循能力可能已经过线,agent 之类的方案才得以规模化跑通。然而,缺失且紧迫的,是对全局的理解。Scaffolded LLM 不只是好玩的玩具,它实际上是一种新型通用自然语言计算机的底层基板。

![](https://www.beren.io/assets/figures/generative_agent_arch.png)

*'generative agent' 的架构。一个 scaffolded LLM 程序。*

举个例子,看看[最近一篇论文](https://arxiv.org/pdf/2304.03442.pdf) 里的 'generative agent' 架构。架构核心是一个接收指令、执行自然语言任务的 LLM。外面有一组指定这些任务和数据的 prompt 模板,供 LLM 操作。还有一块 memory,存储远超 LLM 单次能消化的上下文,并且可以由计算单元读写。简而言之,这玩意儿造出来长得像下面这个样子:

![](https://www.beren.io/assets/figures/Von_Neumann_Architecture.png)

*冯·诺依曼计算机架构。*

我们干的事情,本质上是重新发明了冯·诺依曼架构,更进一步说,我们重新发明了通用计算机。这种趋同进化并不奇怪——冯·诺依曼架构对设计计算机来说是一个非常自然的抽象。不过,如果我们造出来的是一台计算机,那它是非常特殊的一种。和数字计算机一样,它是完全通用的,但它操作的对象不是 bit,而是 *文本*。我们造出了一台 *自然语言* 计算机,它以自然语言文本为单位输入,产出经过更进一步加工的自然语言文本。和数字计算机一样,我们这台自然语言(NL)计算机理论上完全通用——图灵机的一切操作都可以用自然语言写下来——而且极其有用:现实世界里的许多系统,包括人类自己,更愿意以自然语言运转。很多任务用代码精确描述很困难,但用一两句自然语言就能讲清楚。

带着这个类比,我们尽量把它推到极限,看看会得出什么结论。

先来把 scaffolded LLM 的各个组件和数字计算机的硬件架构对应清楚。LLM 本身显然对应 CPU,是系统中真正发生 "计算" 的地方。但和 CPU 不同,它操作的单位是上下文窗口里的 token,而不是寄存器里的 bit。如果 CPU 的自然类型签名是 `bits -> bits`,那自然语言处理单元(NLPU)的自然类型就是 `strings -> strings`。Prompt 和 "context" 直接对应 RAM——CPU 能快速访问、快速操作的那块易访存储。第三层是 memory。在数字计算机里有显式的存储库或者 "disk" 这种慢速存储。它直接对应 scaffolded LLM 里的向量数据库 memory。我们目前用的那些启发式(比如基于 embedding 的向量搜索)来决定何时取出特定记忆,等同于数字计算机里的 [memory controller](https://en.wikipedia.org/wiki/Memory_controller)(内存控制器)固件,由它处理 CPU 对特定内存地址的访问。最后,CPU 还得跟外部世界交互。在数字计算机里,这是通过 "驱动" 或者特殊的硬件/软件模块实现的,让 CPU 能控制显示器、打印机、鼠标等外设。对 scaffolded LLM,则是 [插件](https://openai.com/blog/chatgpt-plugins) 以及类似机制。最后,还有围绕 LLM 内核的 "scaffolding(支架)" 代码。这层代码实现了把单次 LLM 调用串起来的协议,比如一个 [ReAct agent loop](https://arxiv.org/abs/2210.03629),或者一个 [递归式书籍摘要器](https://arxiv.org/abs/2109.10862)。这些协议就是跑在我们这台自然语言计算机上的 "程序"。

有了这些等价关系,我们也可以来谈核心的性能单位。对数字计算机来说,是 CPU 每秒能执行的操作数量(FLOPs)和系统可用的 RAM。这两个单位在自然语言计算机里都有精确对应。RAM 就是 context length。GPT4 当前的 8K 上下文等价于 8kbit 的 RAM(理论上很快会扩展到 32kbit)。这相当于把我们带回到数字计算机里的 Commodore 64,时间坐标在 80 年代初。FLOP 计数也有等价物。每次 LLM 调用/生成可以视作完成一次计算任务——一次自然语言操作(NLOP)。简单起见,假设从一个 prompt 生成约 100 个 token 算作一次 NLOP,那我们就能算出不同 LLM 的 NLOPs/秒。GPT4 大概是 1 NLOP/秒,GPT3.5 turbo 快约 10 倍,所以是 10 NLOPs/秒。这跟动辄数十亿 FLOPs/秒的 CPU 比相差悬殊。但单次 NLOP 比一条 CPU 指令复杂得多,直接对比并不公平。话虽如此,NLOP 这个数仍然是关键指标。任何认真玩过 GPT4 的人都知道,GPT4 响应的迟缓本身才是核心瓶颈,而不是钱。

有了性能单位之后,下一个问题是:我们是否该期待出现摩尔定律式或其他指数级的能力提升?显然,整个 LLM 范式才 3 年,下定论还太早。但我们已经看到不少翻倍。GPT3 到现在 3 年里,上下文长度翻了 4 倍(2K 到 8K)。底层 LLM 的能力和 NLOP 的速度也大幅上升(GPT3 到 GPT4 至少翻倍),尽管缺乏精确量化。这一切都被 LLM 及其训练 run 的指数级规模与成本驱动着——GPT4 的训练估计花了 1 亿美元,而最大规模的 run 预计在[未来两年](https://techcrunch.com/2023/04/06/anthropics-5b-4-year-plan-to-take-on-openai/)摸到 10 亿美元。我的预测是:指数级提升至少还会持续几年,可能更久。但 5 到 10 年内,单次训练 run 的可投入资金大概率会撞上天花板(10B 这个量级几乎没有玩家能再往上走)。再之后,重要的就不是堆资源,而是参数和数据的高效利用,以及底层 GPU 硬件的进步。

把 scaffolded LLM 概念化为自然语言计算机,除了定义性能单位,还能给出哪些预测或洞察?

## 编程语言

谈数字计算机编程,自然就要谈编程语言。NL 计算机能有编程语言吗?长什么样?显然能有。我们已经在搭最初的原语了。Chain of thought(思维链)。Selection-inference(选择-推断)。Self-correction loops(自纠循环)。Reflection(反思)。这些都比单次 NLOP 抽象层级更高。我们达到了汇编语言的水平。CoT、SI、reflection 就是汇编里大家熟悉的 `mov`、`leq` 和 `goto`。借助 langchain 这类库和复杂的 prompt 模板,我们或许已经在搭最早的编译器,尽管目前非常原始。我们还远没到 C 语言。我们甚至对它会长什么样都没什么把握。再往上走还有大把抽象层我们连边都没摸到。要解锁这些抽象,需要时间,也需要远超当前水平的 NL 算力。因为搭出不漏抽象(non-leaky abstraction)本身有根本成本。函数式或动态语言永远比裸金属 C 慢,这是有原因的——抽象有开销。在 NLOP 像今天这么贵的当下,我们没法真正地用或者拿这些抽象做实验;但我们终会能。

不仅是编程语言,整个为这台自然语言计算机写好 "软件" 的空间,目前也几乎完全没人探。我们还在摸索什么样的硬件合适、最基础的汇编是什么样。我们已经开始开发简单算法——比如递归文本摘要——以及简单的数据结构,比如 "memory stream",但这些只是最初步。还有整片自然语言算法和数据结构的世界,潜伏在可能性的边界之外,对我们而言完全未知。

## 理论

数字计算机出现 *之前*,就已经积累了大量理论。图灵、哥德尔等人在计算机还不存在时就奠定了算法的基础。Lambda 演算 30 年代起步,到 50 年代已经成为高度发达的逻辑分支,那时计算机还又贵又稀有。硬件设计方面,布尔逻辑在它成为数字电路核心之前已被人类掌握了一百年。算法复杂度理论、类型论、编程语言设计这些极其精致的理论与摩尔定律并行了几十年。相比之下,NL 计算机几乎不存在与之对应的形式理论。仅有 [simulators frame](https://www.lesswrong.com/posts/vJFdjigzmcXMhNTsx/simulators) 这类最初步的尝试在去年发表。

举例来说,NLOP 这个概念本身几乎完全未定义。除了"任意自然语言变换"以外,我们对单次 NLOP 的边界没有任何概念。我们没有等价于数字逻辑里 NAND 门那样的最小自然语言电路,能用来表达任意 NL 程序。我们对一门由 NLOP 组成的编程语言会怎么运作、能产生什么算法,也没什么真切的概念。我们也没有底层电路正确行为规范的真值表。

## 执行模型

考虑一下自然语言程序的"执行模型"。CPU 经典上是线性执行:指令一条条读入再串行执行。然而,你想并行调用多少次 LLM 都行。我们这台 NL 计算机的自然执行模型,更像是一个不断扩张的并行 NLOPs DAG,受限于程序本身固有的串行性,而 *不* 受限于 "硬件"。事实上,我们重新发明了 [dataflow architecture](https://en.wikipedia.org/wiki/Dataflow_architecture)(数据流架构)。

计算机硬件本质上是同像(homoiconic)的——CPU 的 opcode 跟其他东西一样都是 bit,可以像 "data" 一样被操作。"指令" 与 "数据" 之间没有原则性区别,只有约定。自然语言计算机也是这样。对一次 NLOP 来说,prompt 就是全部——没有 "context" 和 "instruction" 的区分。但和数字计算机一样,我们正开始在 prompt 里发展把命令与语义内容分开的约定。比如 GPT4 引入 "system prompt" 暗示我们在演化 RAM 里的受保护内存区。在常见用法里,人们经常把 "context" 从 "prompt" 里分离出来,这时 prompt 就更显式地承担 op-code 的角色。比如 prompt 可能是:"请总结这些文档:…[文档列表]"。这里,"summary" 命令是 opcode,文档列表是 RAM 中其余位置的 context。这样一次 LLM 调用就是一次 NLOP。

## 存储层级

当今数字计算机有复杂的存储层级,不同层级在容量、便宜程度与延迟之间做权衡。从 disk(极大、便宜但慢)到 RAM(各方面中等)到片上 cache(极快但极贵且受限)。当前的 scaffolded LLM 只有两层 "cache/RAM"——直接喂给 LLM 的 prompt context,以及 "memory"——通常是个向量数据库或一组外部事实。随着设计成熟,存储层级里大概率会增加更多层。可能包括 LLM 架构 *内部* 的额外 cache 层——比如稠密上下文 vs 稀疏/局部注意上下文;也可能在外部,把一次 NLOP 拆成一组 LLM 子调用,让它们用并选择长期记忆里不同的 context。一种初始做法是:用 LLM 给长期记忆里的各段 context 做相关性排序,只把最相关的塞进真正执行 NLOP 那次 LLM 调用的 context。这里就是用执行排序步骤的成本和时间,去换延迟与容量之间的平衡。

## 基础模型即认知硬件

虽然 scaffolded LLM 整个 stack 严格来说每一层都是软件,但核心 LLM 与 CPU 硬件之间的关系比一般类比要强。基础模型在很多方面更具有经典硬件而非软件的属性——可以把它们看作支撑 "软件" 支架的 "认知硬件"。基础模型本质上是巨大的 I/O 黑盒,坐在围绕它的支架中央。在没有强力可解释性或控制工具的情况下,我们没法轻易拆开它、调试它,乃至修复已知 bug。它没有版本控制,几乎也没有针对其行为的测试。我们只有一个不可解释、又极其昂贵的黑盒。从 ML 模型生产方角度看,基础模型也有相似特征。它们脆弱、昂贵,迭代周期长[^2]。如果一次训练搞砸了,没有 push-to-github 这种简单修复,可能要等几个月才能重启训练。一旦模型上线,它的很多行为基本被锁定。你可以用 fine-tuning、RLHF 和其他后训练手段做一些控制,但大量行为和性能在预训练阶段就已经被烙进去了。这一切都很像硬件公司在部署上面对的难题。

而且和硬件一样,基础模型也是高度通用的。一个模型可以完成许多不同任务,并且像 CPU 那样跑各种各样的 NLOP 和程序。此外,基础模型与跑在其上的 "程序" 已经具有一定可移植性,未来很可能更强。理论上换个模型只要改 API 调用。实务里很少这么省事。为了应对某个特定 LLM 的不可靠和各种失败模式,大量 prompt、保险机制和隐含知识最终都被硬写进程序里。这都限制了即时可移植性。但这本质上只是抽象层不够发达、写代码离金属(离神经元?)太近的症状。早期计算机程序也是针对某种具体硬件架构写的,互相之间不可移植——这种状况一直持续到 90 年代才大幅改善。随着 LLM 变强、变可靠,人们围绕它发展出更好的抽象,可移植性也会改善,硬件-软件解耦与模块化会越来越明显,越来越有用。

scaffolded LLM 中其他 "硬件" 部件在较弱程度上也是这样。比如 memory 通常是 faiss 这类向量数据库,对大多数人同样是个难替换、难适配的黑盒 API 调用。而 memory-controller "固件"——也就是写出来的、用于寻址和管理 LLM 长期记忆的启发式逻辑——则容易理解、更新和替换。这意味着,一旦自然语言程序与 "软件" 开始普及,我们应该能预期它会出现今天硬件与软件之间相同的动态:生产 NL 程序会比生产 "硬件" 便宜得多、入门门槛低得多,"硬件" 几乎对所有人都贵得不切实际。NL 软件迭代速度远快于硬件,会成为分布式创新的主要发生地。

## 与数字计算机的本质差异

把 scaffolded LLM 与数字计算机的类比推得很远,但这个类比也在若干重要方向上发散,几乎所有发散都围绕 NLOP 这个概念以及把 LLM 当作 NLPU 这件事。和数字 CPU 不同,LLM 有些不太顺手的属性,让我们当下很难用它构建高度可靠的链式程序。NLOP 的昂贵和缓慢已经显而易见,且严重约束当前的程序设计。这些问题随时间应能缓解。其他关键差异是当前 NLOP 的不可靠性、不充分定义(underspecifiability)和非确定性。

拿 NLOP 的一个经典例子:文本摘要。摘要看起来是个有用的自然语言原语,对人类有内在用途,并且开始在自然语言数据结构里扮演关键角色——把记忆和上下文压成能塞进有限 context 的样子。但和 CPU 操作不同,摘要是不充分定义的:从输入到输出是一对多映射。同一段文本有许多有效的摘要,质量参差。我们没有一张通往 "最优" 摘要的地图,甚至连这个概念在多目标多约束下意味着什么都不清楚。摘要也是不可靠的:不同的 LLM[^3]、不同的 prompt(甚至同一个 prompt 在高 temperature 下)能给出质量与价值差异巨大的摘要。LLM 甚至连零 temperature 下都不是确定性的(这点听起来反常但属实,自己跑就能验证。原因是为加速推理而启用的非确定性 CUDA 优化)。这一切都和数字硬件极其不一样——后者极度可靠,I/O 规范固定且已知。

这意味着,在我们能开始搭起强大的抽象和抽象语言之前,单次 NLOP 的可靠性必须被显著提高。抽象需要可靠的底座。数字计算机适合在上面盖抽象塔,正是因为这种可靠性。如果你能高度信任系统的所有组件,就可以构造精巧的组合链。否则,你就一直在和混沌发散对抗。提升可靠性的方法包括:更好的 prompting、更好的 LLM 组件、更好的 tuning,以及叠加大量纠错层。纠错本身在硬件领域并非新事——大量研究花在了修复 bit-flip 的纠错码上。我们大概率也需要类似的 "语义纠错码" 来对 LLM 的输出做处理,才能把一长串 NLOP 高度连贯一致地拼接起来。

不过,虽然 NLOP 的不可靠和不充分定义难以承重,但也带来巨大的机会。LLM 的灵活性无可匹敌。和有固定指令集和已知 op-code 的 CPU 不同,理论上你可以 prompt 一个 LLM 去尝试几乎任意一个自然语言任务。op-code 集合不再固定,而是不断膨胀。就像我们一直在发现新的逻辑门。任务原语的总量到底多大、是否最终会像逻辑电路那样存在完整分解,目前尚不清楚。不止于此,把 prompt(或者 op-code)合并、串联起来,得到的行为是半组合(且不可靠)的——这非常顺手。我们可以基于 prompt 模板方案造出整套语言。从指令集架构的视角看,CPU 那边 RISC 看上去赢了,但基于 LLM 的"计算机"内在地像在 CISC 模式下运转。未来(甚至现在)大概会有一个与 RISC vs CISC 同构的争论:是把许多简单 prompt 复杂地串起来更好,还是用更少但更复杂的 prompt 更好。

---

## 脚注

[^1]: 我在这里说 "scaffolded" LLM 而不是某篇 [近期文章](https://www.lesswrong.com/posts/dcoxvEhAfYcov2LA6/agentized-llms-will-change-the-alignment-landscape) 里那种 "agentized" LLM,是因为 agent 现在虽然热门,但这个想法的范畴更广。不是所有自然语言程序都需要做成 agent。Agent 是对某一类任务很自然的抽象,但还有别的。

[^2]: 这个类比一个有趣的副产品是它澄清了 OpenAI 这类基础模型供应商当前所处的角色和经济地位。它们基本与数字计算机时代的大芯片厂(如 Intel)占据同一个经济生态位。商业结构非常相似:训练基础模型有巨额固定资本支出(建新晶圆厂也是);它们都面对一个不断改进、新一代远比旧一代强的技术(摩尔定律 vs 当代 AI scaling);都以大批量、高毛利但伴随显著边际成本的方式售卖商品化产品(芯片 vs API 调用)(实际制造每块芯片 vs 每次模型推理)。如果这些等价关系成立,我们就能大致猜到这个行业长期会长成什么样——也就是当前以及历史上的半导体业。我们应该预期它会整合成几家寡头巨头,每家都背着巨额固定成本、保持激烈竞争,而不会像 SaaS 或纯软件公司那样以极高利润率印钞。

[^3]: NLOP 与标准 FLOP 还有一个关键差别:它们的"内在难度"分级不同。一个小语言模型能完成某些任务,另一些则需要最先进的大模型。随着 NL 程序变得越来越复杂精巧,对各类 op 难度的理解也会加深,每个 op 都会被委派给"能可靠完成它的最小最便宜的语言模型"。这样,NL 程序不会有一个统一的 "CPU"(LLM)内核,而是会由对许多不同规模、不同专长的语言模型的异构调用组成。

---

**原文链接**: https://www.beren.io/2023-04-11-Scaffolded-LLMs-natural-language-computers/