AutoGPT 运行原理解析
简单看了下AutoGPT源码,除了被 Star 趋势震惊,其 “ ☆创新的灵感+ 待完善的代码”的矛盾组合也让我受益匪浅,目前就从运行原理视角简单补充下这个问题
背景
先从直接使用 GPT 等大模型能力会出现的问题说起:
- Token 超出限制怎么办?(目前最新的GPT4支持最多8,192 tokens)
- 任务需要多步串联,仍需要人工介入怎么办?(即如何做到真正的自动化)
- 集成外部能力(搜索,运行脚本、爬取网站等等)?
- 无法获取最新数据,最新的GPT4的训练数据时效为Sep 2021
都是活生生的真实痛点,这时候AutoGPT横空出世了:

AutoGPT的核心逻辑

AutoGPT 的核心逻辑是一个 Prompt Loop,步骤如下
- AutoGPT 会基于一定策略自动组装 Command Prompt (后文会提到),这些首次会包含用户输入的 Name, Role和Goals
- Command Prompt 的目标不是为了拿到最终结果,而是通过 GPT Chat API(对应界面Thinking 的过程)返回下一步的 Command (包含name和arguments, 如
browser_website(url = "www.baidu.com")
)
- 这些 Command 都是可扩展的,每一种命令代表一种外部能力(比如爬虫、Google搜索,也包括GPT的能力),通过这些 Command 调用返回的 Result 又会成为到 Command Prompt 的组成元素,
- 回到第 1 步往复循环,直到拿到最终结果结果(状态为“compelete”)
可以看到 Command Prompt 是整个Loop的发动机,我们先看看它的组成结构
Command Prompt
整个Command Prompt 会组装为Chat GPT (gpt-3.5-turbo) 的Messages 参数,截取中间某次GPT交互的消息格式如下
Demand
Demand是全程固定不变的部分,它有三个用户输入,也就是AutoGPT开头问你的三个问题(Name、Role和Goals),我们以网上常见的投资建议作为范例:
上述很像一个Prompt 书写优化,但它不是最终的Prompt,它产生的 Demand Prompt 部分如下面所示:
组成简要介绍如下表
部分 | 来源 | 描述 |
Name | 用户输入 | ㅤ |
Role | 用户输入 | ㅤ |
Goals | 用户输入 | ㅤ |
Constraints: | 静态 | 对GPT声明制约因素,看起来是为了让GPT对AutoGPT产生的提示的一些策略做说明,比如4000Token的限制导致会删减History信息,过程中希望它自主完成等等 |
Resources: | 静态 | 让GPT对可用资源有感知,让其更好的做出策略。 |
☆ Performance Evaluation: | 静态 | 对GPT提了两个关键要求:(1)☆ 基于过去(Memory和History)反馈进行优化(2)尽量用少的步骤完成目标,减少☆ Long Loop甚至 Infinite Loop的可能 |
☆ Commands: | 基于注册命令 | 这部分是基于注册的命令进行展示,注册机制在 prompt.py 中,如 :commands.append( "Convert Audio to text", "read_audio_from_file", {"file": "<file>"}注册了一个新的"read_audio_from_file" 命令,这个命令实现需要在commands/read_audio_from_file.py 中实现 |
☆ Response Format | 静态 | 限制 GPT 返回的格式为包含thoughts 和 command 的JSON格式 |
Demand是全生命周期不变的,特别是Constraints、Resources和☆ Performance Evaluation 虽然在代码中有类似
addXX
的注册方法,但实际上是启动时写死的,而且后续并不在工程链路上有影响,属于影响 GPT 的“魔法咒语”,这几个部分虽然大家都吹 AutoGPT 有一定的技巧,但你其实没法证明是最优的提示 : )Commands部分则真的会影响工程调用,但实现属实不够优雅,代码中是一段写死的 if/else ,其实简单用一个动态注册和加载的方式会更直观些,也会让后续扩展能力不必需要在代码中进行修改。
Demand 中最重要的其实是代表所谓长期记忆的 Memory 和短期记忆的 History,这也是上面几段“魔法咒语”想让 GPT 明白的。
Prompt Loop 的核心:Memory 和 History
虽然AutoGPT 工程部分的代码并不复杂,其中的核心其实都是为了更好的管理记忆: Memory 和 History。
其中:
- Memory是过往记忆存储,使用Embeddings API(Ada) 计算段落向量并保存到本地、Redis或 Pinecone 向量数据库,由于存储的是归一化后的向量,两份段落的向量可以通过点积计算其相关度。
- History:即历史的 Chat 信息, 会处理成Chat API的消息格式
Token控制的秘密
理论上在每次 GPT 调用时,我们加入全部的 Memory 和 History 的上下文是最佳的,但实际上 GPT 是有 Token 调用上限的,以 AutoGPT 内部用来获得 Command 建议的 GPT3.5 为例,它就有 4096 的 Token 限制.
AutoGPT的策略是按最近的History 和最相关的 Memory的方式来组织GPT的记忆 ,以达到Prompt Loop 在Token限制下也能按越来越趋近完成的方式来运转。
AutoGPT的做法非常暴力,首先给Memory 写死的 2500 的Token上限,提取与最近9条 Message History 最相关的信息,相关代码如下:
其次,剩下的Token除了固定的支出 ( 如 Demand 和 Trigger 部分 ),其余都会给与 History,但实际如果有大范围的查询比如爬虫或 Google 结果的话,History 能进 Command Prompt 的条数不会超过 5 条,相关代码如下:
综上所述,围绕Memory和History的核心逻辑如下:
结论
本质是 AutoGPT 将以往的“配置型策略调度”的 Automate 工具,转换为“ GPT 智能策略调度 ”,虽然其目前大部分应用场景上仍是一个更好的 “ChatGPT”,但这个创意其实应用到其他 GPT 的应用领域。
回到开头的几个关键问题,AutoGPT 对此的解法是:
- Token上限:AutoGPT 内部进行 Token 的自动管理,其中 History 基于最近时间,而 Memory 则是基于相关性(通过 Embeddings API)
- 自动化:通过 Memory 和 History 等记忆代理,辅以一些魔法声明,可以促使 GPT 从记忆中学习,结合Command 驱动的流程架构,使得AutoGPT可以“自主运行”
- 外部能力:任务推进基于 Comand 驱动,AI(GPT 3.5 turbo) 只负责返回Command,单步结果实际由命令组件(组件也可能是 GPT 服务)执行,由于组件是受控且可扩展的,所以扩展和调用外部能力成为可能.
- 新鲜度:既然可以使用 Google,也可以使用爬虫,甚至自定义的 API,当然也解决了内容新鲜度的问题,本质上就是“最新的内容 + GPT的推导”的能力组合,不需要将内容限制在 GPT 模型的训练数据中。
但 AutoGPT 仍然存在以下问题:
- ☆ Infinite Loop 的风险: 把玩过程多次出现, 所以非必要不打开
-continuous
,部分步骤人脑来看纯纯走弯路,不太聪明的亚子。
- ☆ 海量 Token 开销:为了准确性,会尽量带上撑满 Token 上限的 Memory 和 History,一个简单任务都会吃掉数万 Token。
对开发人员的启示
持续把玩GPT的过程中,我最大的感受就是不确定性,因为过往的软件工程经验让我们直观的觉得所有的输入和输出,应该都是可以控制和预测。但 GPT 并不是,所谓的提示工程(Prompt Engineering)有点魔法咒语培训班的味道,所以AutoGPT会不厌其烦的在 Prompt 加入强调和限制来规范 GPT 的策略。
但反过来说,从 AutoGPT 的创新可以看到,一点点的工程能力其实可以拓展 GPT 很大的应用场景,所以技术人员其实根本不用过早的妄自菲薄,结合目前的 AI 服务化的能力,就和之前服务的 PaaS、IaaS 化一样,只是让我们应用开发人员的工具箱更丰富了而已。