Prime Intellect 撰文解析多智能体系统的上下文扩容与群集结构
On the Nature of the Swarm
Prime Intellect 发表长文,提出模型的总上下文容量概念,指出 compaction、磁盘卸载、子智能体与持久化子智能体各有保留信息与重建理解的取舍,多智能体并非新的扩展维度而是更结构化的推理算力扩展。文章认为树状结构会把上下文问题压到根节点,规模大时应转向无根的网状群集,先借用人类组织结构再让智能体自行演化。
作者提出了总上下文容量框架,逐层分析压缩、磁盘、子智能体到持久化智能体的取舍,并借经济学解释无根网状结构。
论集群的本质
最初于10月6日发表在我的个人博客上。
让我们从一个人人都应认同的观点开始:推理扩展是有效的。事实上,它有效到让LLM如今能够完成一些令人惊叹的壮举,比如可信地声称解决了一个千禧年大奖难题——在我们发现推理遵循扩展定律之前,这似乎是不可能的。在测试时给模型更多算力(让它思考更久、调用更多工具、检查自己的工作),它就能在任务上表现更好。但只有一个问题:最终,你的上下文会用尽。
我是说字面意义上的:你填满了预定义的上下文窗口。1 上下文窗口也没有变得更大:当前的前沿模型都止步于约100万token。例如,你看不到任何严肃的模型拥有1亿token的上下文窗口。然而,如今的智能体经常执行那些仅靠100万token上下文本应无法解决的任务。这怎么可能?
如果你在过去一年里用过编码智能体,你就已经知道解释这一差异的魔术了……压缩!
压缩
压缩的工作原理是这样的:一旦你接近上下文窗口的末尾,你就让智能体写一份摘要,并将其工作交接给一个全新的上下文,在那里继续工作,直到上下文窗口再次被填满,你又得再次压缩。你一直这样做,直到(智能体认为)任务被解决。
压缩非常神奇。它让你能让同一个智能体会话持续数天(或数周)而不会耗尽上下文。问题解决了,无限上下文,无限推理扩展,一切皆有可能。那我为什么还要写这篇博客文章呢?
嗯……压缩实际上并没有给你无限上下文。它做的是另一件事。一件更微妙的事。它提升了模型的总上下文容量2,粗略地定义为模型能承担的最大任务,其中任务的大小是你一次性完成它所需的窗口大小。压缩能超出模型预定义上下文窗口多少,取决于智能体已完成的多少工作必须在每次交接中存活下来。
这一限制背后的基本原则是,每一次压缩都是一次赌注。进行总结的智能体必须现在就决定什么在以后会重要。通常它猜得足够好,3但有些任务比其他任务更不容出错。4大多数真实任务也是部分可观察的,所以你看到的东西是否重要,往往取决于你尚未看到的东西。正如俗话所说,“预测很难,尤其是关于未来的预测”。5
让摘要损失更小(或者用我们的术语来说,提升总上下文容量)的一种方法是让智能体使用文件系统或REPL来卸载记忆。例如,智能体可以将某个复杂工作流的细节写入磁盘,并在摘要中放置指向相关文件的指针。
这其实帮了大忙!没有任何东西会因压缩而丢失。摘要只需说明东西在哪里。所以我们的赌注变得没那么可怕了:问题过去是“我需要记住什么?”,现在变成了“我需要知道什么东西存在?”这让人想起那句名言:“绅士不必懂拉丁语,但至少应该把它忘掉。”6
但这仍然是一场赌注,而且带来了新的成本。磁盘上的文件本身什么也不做;它们只是静静地待在那里。7 要让这些文件发挥作用,下一个 agent 必须 (a) 意识到它们相关,(b) 去找到它们,(c) 把它们读回自己的上下文中。最后一步相当烦人,因为读取会消耗上下文,而这正是我们一开始就快用完的东西。8
换句话说,卸载到磁盘让我们能持久保存信息,但前一个上下文窗口中的 agent 通过阅读全部内容所理解到的东西已经消失了,每次有人需要时都得重新构建。
那么我们完蛋了吗?也许吧。但我们还有几招没使出来。
多 agent 系统
首先,注意我们可以把压缩看作一个(退化的)多 agent 系统:9 每次压缩都会启动一个新的 agent,其初始上下文是上一个 agent 摘要的函数。
第二种多 agent 系统是主 agent 协调子 agent。思路很简单:主 agent 启动一个带着任务的新 agent(“找到重试逻辑在哪里”、“弄清楚这个测试为什么不稳定”),然后拿回一个答案。子 agent 可能烧掉 20 万 token 来读文件、跑东西。主 agent 的上下文只增加任务和答案,可能也就几千 token。
现在有趣的部分来了。在我们的框架里,子 agent 的答案就是……它上下文的摘要。所以子 agent 实际上也是一种做压缩的方式!但有一个关键区别:摘要是在问题已知之后才写的。压缩必须猜测以后什么会重要。卸载到子 agent 则不需要猜测,因为你是在需要时才启动子 agent。10
额外的好处是,如果你有几个独立的问题,可以同时启动多个子 agent。并行是个不错的加分项,但即使它们必须一个接一个地跑,基于上述原因,子 agent 在这些任务上仍然会胜过压缩。(这一点后面会很重要。)
子 agent 特别适合那些可以分解为子任务、并且在交接和交付时有清晰边界的工作负载。对于这类任务,它们提升总上下文容量的效果远超压缩,因为主 agent 永远不必持有混乱的中间部分。
但子 agent 也并非没有缺点。它们有和磁盘相反的问题:它们会忘掉一切。子 agent 一旦给出答案,它就消失了,连同它那 20 万 token 的读代码、跑测试、排除各种可能性的经历一起消失。下次你有相关问题时,你得启动一个新的,它会把那些阅读全部再做一遍。你也没法追问它,比如在十轮之后问“等等,你刚才那是什么意思?”
所以现在我们有两个半吊子解决方案。卸载到磁盘能记住,但不能思考。子 agent 能思考,但不能记住。嗯。
雇一个子 agent
你大概能看出这要往哪儿走了。第四个角显而易见:就是……别杀掉子代理。把它留着。实在不行就雇着它。总之别把它拆掉。
一个持久化子代理会保留它的上下文(还有它的文件,以及它留下的任何还在运行的东西)。当你对它处理过的事情有新的问题时,直接问它就行。它已经读过所有内容,所以不必从头开始,而你自己的上下文只增加问题和答案那部分。
现在我们两全其美了。像磁盘那样,什么都不丢。像子代理那样,摘要在你明确需要什么之后才写。又不像这两者中的任何一个,你明天还能带着不同的问题再问一次。这意味着压缩不再是一次性的赌注。你永远不必事先决定要保留什么,因为你随时可以回来再问。
现在回到我们那个退化的多代理系统。压缩是一串代理串联工作,每一个都依赖前一个,而且任何时刻只有一个“活着”。没进摘要的东西就没了,因为知道它的那个代理已经没了。
有了持久化代理,好几个可以同时活着。当然,它们也可以同时运行:把问题拆成子问题,并行解决,更快完成。11这是多代理最显而易见的论据,12而且确实成立。从基础设施的角度,有很多很好的理由说明这为什么重要。但即便它们必须轮流来、一个接一个,它们的上下文仍然会并排存在。它们也是上下文层面的并行,而这正是如今讨论不足的地方:总上下文容量增长到(大致)每个代理一个窗口。13
当然,这些代理每一个仍然可以压缩!一个已经干了一阵子的子代理可以总结一下然后继续,跟以前一样。所以这两者能很好地叠加:压缩让每个代理沿时间方向延展,更多代理则让整个系统横向延展。你最终得到几条并排的链,它们可以互相提问。
没有免费的午餐
让我们先拉远一点看。这些技巧到底在做什么?压缩、卸载到磁盘、子代理、持久化代理:它们都是构建上下文的方式。在理想世界里,你早就该在一个窗口里拥有恰好正确的上下文,然后让模型直接吐出答案(或采取正确的动作序列)。14而在实践中,模型必须自己去构建它。推理通过思考来构建,代理通过行动(读文件、跑测试)来构建,而上面这一切都是关于构建出比一个窗口能容纳的更多的上下文。
一旦代理在真实世界里行动,构建上下文基本上就是推理扩展的主要形态。这也是为什么我强烈反对像很多人那样把多代理称为“新的扩展轴”。我们仍然在扩展推理算力,只是以一种更有结构的方式在做。
当然,没有免费的午餐。代价是通信。每当一段上下文需要从一个代理传到另一个代理,它都得被塞进一条消息里,这要消耗 token,而且本身是有损的。15如果一项任务最难的部分需要所有东西同时集中在一处,那把它拆开根本帮不上忙。
需要说明的是,这一切都没有让我变得不那么乐观。OpenAI 刚刚让 10,000 个智能体解决了 Navier-Stokes 方程。16 两年前,你很难找到一个理智的人会认为这能实现。但集群并非万能灵药。你不能只是把一百万个智能体扔向一个难题,然后指望答案自己掉出来。首先,智能体本身必须足够好——好到能够自我组织、有效协调,而不是仅仅重复彼此的工作。诚然,很多开销可能可以通过训练消除(那些擅长与成千上万个自身副本协作的智能体),但有些通信成本是结构性的。
从树到集群
到目前为止,一切都是树状的:一个根智能体生成子智能体,子智能体再生成自己的子智能体,结果向上回流。但一旦智能体之间可以互相发消息,树结构就会让每一次对话都经过根节点。根节点的上下文被填满,于是它必须压缩,然后……我们又回到了起点,只是上升了一个层级。树结构把上下文问题转移到了根节点。
显而易见的解决办法是让同级智能体直接对话。但一旦同级智能体可以联系任何需要的对象,你就得问:根节点到底是干什么用的?没有人需要为了完成工作而听命于上级。不如让它们全部成为对等节点。
所以:没有根节点。你把若干智能体放进一个共享世界,让它们作为网状结构中的对等节点彼此协调。就像每个智能体仍然可以压缩一样,每个智能体也仍然可以生成自己的子智能体。所以你可以在网状结构中拥有树。
这没问题。去掉根节点并不意味着层级结构毫无用处——毕竟公司仍然有 CEO。科斯在近 90 年前就问过这个问题:如果市场如此擅长协调,为什么公司还会存在?17 他的答案是:因为利用市场并非免费。每一次,你都必须找到合适的人,解释你想要什么,并就条件达成一致。而在公司内部,有人可以直接决定。所以,公司恰恰存在于那种比以对等身份协调更便宜的地方。智能体也是如此:从没有层级开始,在能带来收益的地方添加一点层级。
这种方法奏效的原因之一是专业化。在集群中,没有人需要分配角色;角色会自然形成。假设某个智能体碰巧先看了前端。现在它在那里有了上下文,也许还构建了一个小工具。于是下一个前端问题就会交给它,因为这比让其他任何人从头开始都更便宜,而它回答的每一个问题都会让它在前端工作上更擅长一点。一个随机的早期差异会随着时间推移固化为一个角色。
这正是树结构真正有害的地方。下两级的子智能体受制于其父节点:它只为生成它的那个智能体工作。所以,如果我们的前端专家位于某个分支,而另一个分支中的智能体有一个前端问题,它不能直接去问。问题必须向上传到它们的共同祖先,再向下传回来,途中经过那些完全不关心前端的上下文。
所以树结构有两个选择,都很糟糕。要么每个分支都培养自己的前端专家,于是我们又回到了一遍又一遍重新发现同样东西的老路(而这正是持久化本应解决的问题)。要么其他分支没有前端专家可用,于是专家学到的一切只能帮助一个分支。而在网状结构中,任何人都可以直接问它。它的上下文会被任何需要的人复用。
代理越多,这个问题就越严重。有 10 个代理时,树状结构大概还行。但到了 10,000 个,让对等节点彼此发现并自行分工就合理得多了。18
经济学家在大约 80 年前就有过这场争论。哈耶克的观点19是:中央计划之所以失败,是因为运行一个经济体所需的知识分散在数百万人手中,无法全部汇聚到中心。根代理就是一个中央计划者。要想规划得好,它需要全部上下文,而全部上下文恰恰是塞不进一个窗口的东西。(要让这个类比成立,群体并不需要价格或市场。关键只在于知识存在于哪里,以及谁有权据此行动。)
群体应该是什么样子?
现在,我还不知道正确的结构是什么。纯粹的网状结构大概也不是答案。我的猜测是,我们先照搬人类组织的方式。给代理们我们用的工具(共享的 git 仓库、问题追踪器、Slack),让它们对共享状态有结构化的访问,这个共享状态可以作为唯一事实来源。正确的结构可能还取决于规模:五人的初创公司靠几个 Slack 频道就能运转,而一万人的公司则不行。布鲁克斯定律之类的。20
但关键在于:我们甚至不必把结构固定下来。我们可以让代理自己改变结构,这样我们就能把苦涩的教训重新引回来。21 所以我们可以用人类的结构来初始化这个群体,然后让代理在解决手头问题的过程中对它加以改进。
关于如何构建一个代理群体,还有很多可说的,但我留到下次再说。
感谢 Sebastian Müller 和 Sami Jaghouar 的校对和宝贵反馈!
脚注
-
不要与上下文腐化混淆:后者指的是代理随着上下文填满而表现变差,因此“有效”上下文窗口(代理表现最佳的区间)比宣传的要小。↩
-
这是我编的。如果你有更好的名字,或者已经以别的名字发明了这个概念,请告诉我。↩
-
根据我的经验,对大多数任务来说,100 万 token 的工作上下文可以相当好地压缩到 16k token。↩
-
想想一次漫长的调试过程:第一天,一次不稳定的测试运行打印出一行奇怪的输出,你把它当作噪声忽略掉,于是摘要里就把它删了。这个不稳定问题再也没出现过。到了第三天,那行输出本会是整个 bug 的关键,但没人记得它存在过。注意,更聪明的摘要器在这里也救不了你:在第一天,鉴于当时任何人所知道的,丢掉那行是合理的判断。↩
-
通常被归功于尼尔斯·玻尔或约吉·贝拉,但它似乎是一句古老的丹麦谚语。最早见于印刷品的版本出现在 Karl Kristian Steincke 1948 年的回忆录中。↩
-
通常被归于 Brander Matthews。塞缪尔·约翰逊在 1775 年更直白地表达了同样的观点,据詹姆斯·博斯韦尔记载:“知识有两种。要么我们自己知道一个主题,要么我们知道去哪里能找到关于它的信息。”↩
-
而当它们坐在那里时,世界仍在前进:文件被覆盖,状态发生变化,所以你保存下来的东西可能会悄悄过时。这个问题有它自己的解决办法,而且并不是真正的多代理问题,所以我就说到这里。↩
-
还记得那次不稳定运行中出现的那行奇怪输出吗?它现在就在磁盘上的某个地方。但第三天的 agent 并不知道它存在,更不知道它重要,所以它不知道要去找它,也不知道该 grep 什么。它又回到了阅读状态。↩
-
它仍然可能误读问题或带回错误的东西。但向一个已知目标压缩,比向一个未知目标压缩要容易得多。↩
-
当然,是在不违反 Amdahl 定律的前提下。↩
-
Noam Brown 在 Dwarkesh Podcast 上称之为“一种并行而非纯串行地扩展测试时计算的方式”。↩
-
只要任务能拆分成各部分之间靠短消息就能应付的程度。如果每个部分都需要其他所有部分的完整上下文,那么再怎么拆分也无济于事,你又回到了需要更大窗口的境地。↩
-
这假设模型能完美利用其上下文。在实践中,一个小而聚焦的上下文往往胜过庞大而杂乱的上下文,但那就是我说过要忽略的上下文腐化问题。↩
-
这有个花哨的名字叫通信复杂度:当各方各自掌握问题的一部分时,他们需要交换多少信息才能解决问题。↩
-
OpenAI 的说法,数学家们仍在验证。↩
-
Ronald Coase,The Nature of the Firm(1937)。↩
-
人类组织也弄明白了这一点:大公司里的数据库专家会收到来自各个团队的问题。如果他们只能为自己的经理工作,那每个团队都得配一个。↩
-
F. A. Hayek,The Use of Knowledge in Society(1945)。↩
-
出自 Fred Brooks 的The Mythical Man-Month:给一个已经延期的软件项目增加人手只会让它更延期,部分原因是沟通路径的数量大致随团队规模的平方增长。↩
-
Rich Sutton,The Bitter Lesson(2019):随计算规模扩展的通用方法最终会击败建立在人类知识之上的方法。↩
来源:Prime Intellect · primeintellect.ai