自然语言编程: 从 AutoGPT 往前迈的一小步
这段时间看到了许多使用 AI 编写代码的故事或是示例,但也许自然语言编程并不需要是像之前想象那样,使用 AI 生成代码,并且自动执行它;全自动生成软件成品是一个科幻元素,但使用 AI 去生成代码有时可能也是个伪需求。也许我们要重新审视在 AI 时代下的编程、程序,乃至于软件工程意味着什么。
另一方面,如果我们能给 AI 明确的、复杂的多步任务和指导,让它遵照执行,也可能能极大地提升 AI 的逻辑分析能力与规划能力 —- 像 AutoGPT 那样全自动分解、规划和执行任务目标,可能并不是最好的方案,我们可以有更好的方式让 AI 完成我们的目标。
引子,与历史
自然语言编程(Natural Language Programming)是一种研究领域,它的目标是让计算机能够理解和执行人类的自然语言指令。这个领域的起源可以追溯到计算机科学的早期阶段。在 20 世纪 50 年代和 60 年代,人们开始尝试使用自然语言来与计算机进行交互。这个时期的研究主要集中在自然语言理解(Natural Language Understanding)上,目标是让计算机能够理解人类的语言。这包括了早期的聊天机器人,如ELIZA 和 SHRDLU。
然而,真正的自然语言编程需要计算机不仅能理解人类的语言,还能根据这些语言来执行任务。只有到最近,使用 LLM 调用 API、AutoGPT 的 Agent 等的出现,才使这一切成为可能。
AutoGPT 的限制
AutoGPT是一个实验性的开源应用,它使用 GPT-4 语言模型来自动执行用户设定的目标。AutoGPT 的核心是自动创建任务并执行任务,它具有接收模糊问题、任务拆解分析和自我成长能力。例如,AutoGPT 的 prompt 之一如下:
1 | Your task is to devise up to 5 highly effective goals and an appropriate role-based name (_GPT) for an autonomous agent, ensuring that the goals are optimally aligned with the successful completion of its assigned task. |
这个prompt的目标是为一个自主代理设定高效的目标,并为其赋予一个基于角色的名称(_GPT)。这个代理的任务是帮助用户完成特定的任务,例如在这个例子中,帮助用户进行商业营销。输入是用户提供的任务,输出是代理的名称、描述和目标。输出的格式非常明确,不包含任何解释或对话;代理的名称是CMOGPT,这是基于其角色——虚拟首席营销官(Chief Marketing Officer)的缩写。描述部分详细阐述了这个代理的专业领域和服务对象,即为独立创业者提供营销问题解决方案。
目标部分列出了四个具体的目标,这些目标都与成功完成其分配任务——帮助用户进行商业营销——紧密相关。这些目标包括有效的问题解决、提供具体和可行的建议、识别和优先处理快速获胜和成本效益高的活动,以及在面临不清晰的信息或不确定性时主动引导用户和提供建议。
这只是 AutoGPT 的 prompt 的一部分,接下来,就可以根据划分的任务目标和具体的任务,进行分析和执行,完成一个复杂的需求。
作为首个完全自主运行的GPT-4示例,AutoGPT 的任务规划、分解、执行的方案是基于 GPT-4 的自然语言生成和理解能力,以及多种数据源和工具的调用。babyAGI 也是类似的思路,它是一个自然语言编程系统,通过创建三个代理(任务执行代理、任务创建代理和任务优先级代理)来执行目标。每个代理都有自己的提示和约束,包括来自每个相关任务执行的上下文。这个过程将循环执行,直到没有剩余的任务并且目标完成。
例如,我们可以尝试给 AutoGPT 两个问题:
测试问题1:ETH和特斯拉,哪一个值得在未来5年内投资?它一开始就会把问题拆成 3 个子任务:收集历史数据表现、分析数据趋势和模式、提供最终建议。对于比较的维度,一开始只有历史表现,然后逐步增加了更多维度,包括风险分析(市场条件、监管变化和其他)、新兴技术、公司财务、盈利能力、未来增长能力等,也就是说,AgentGPT 的思考变的越来越全面.在增加比较维度后,AgentGPT 会主动迭代其答案,给出最新建议。测试问题2:如何在加密货币世界中进行聪明的投资.这个问题比上一个更模糊。没有明确的比较标的,需要 AgentGPT 去寻找和定义。没有明确的投资期限,看 AgentGPT 如何处理。可以同样把这个问题抛给 ChatGPT 和 AgentGPT, 这次 AgentGPT 疯狂拆解和新增子任务,在运行的 20 分钟内生成了 53 个子任务,输出超过了 1.5w 字,最终被手动停止。一开始 AgentGPT 还比较正常,仍然把问题拆成 3 个子任务:收集历史数据表现、分析当前市场趋势和潜在发展、在风险管理策略下提供最终建议。但可能因为没有具体的标的,维度发散起来就收不住:历史数据、市场趋势、未来潜力、风险管理、监管影响、多元投资、市场波动、止损、基本面、流动性、经济事件、社区情绪、KOL 情绪…
很明显,AutoGPT 本身的架构并不是为了执行特定的任务或解决特定的问题而设计的,它会存在很多类似的问题:
- 由于GPT-4语言模型的 token 很贵,其使用费用可能很高,但实际上大多数费用可能被浪费在了无意义的探索上面。
- 作为一项自主实验,Auto-GPT可能会产生不符合现实世界商业惯例或法律要求的内容或采取的行动。您有责任确保基于本软件输出的任何行动或决定符合所有适用的法律、法规和道德标准。
- AutoGPT 会重复类似的问题(没有足够好的记忆和推理、复用之前的结果的能力)、发散、不可预测。
可以发现,即使 AutoGPT 目前具有任务拆解和自我成长能力,但实际上,我们很难完全放手让 GPT 的 agent 在一个开放和模糊的空间中,自行探索和解决问题。这样大概率解决的方案和人类的意图是难以对齐的,最终不得不被停止。尽管还有缺陷,AutoGPT 显示出的能力,依然将人和 AI 的边界继续向前推进了一步。
下一步是什么?
有些对于 AutoGPT 和类似的 AI 系统的改进和解决方案,例如:
- 增加对应的任务记忆功能:通过增加记忆功能,AutoGPT可以避免重复执行相同的任务。也能大量节约 token。例如 GPTcache:
传统的缓存系统通常利用一个新的查询和一个缓存查询之间的精确匹配来确定所请求的内容在获取数据之前是否在缓存中可用。然而,由于LLM查询的复杂性和可变性,对LLM缓存使用精确匹配的方法不太有效,导致缓存命中率低。为了解决这个问题,GPTCache采用了语义缓存等替代策略。语义缓存可以识别并存储类似或相关的查询,从而提高缓存的命中率,增强整体缓存效率。
GPTCache采用嵌入算法将查询转换为嵌入,并使用向量存储对这些嵌入进行相似性搜索。这个过程允许GPTCache识别并从缓存存储中检索相似或相关的查询,如模块部分所说明的。
- 设定任务拆解的限制:通过在 AutoGPT 中设定任务拆解的限制,可以防止任务过于发散;同时,可以让 AI 自动规划不同的模型和通过token的使用,降低AutoGPT的运行成本。例如,复杂任务可以自动采用 GPT4 的模型,对于简单的翻译使用 GPT 3.5;或者通过 GPT4 进行任务规划和分析,而使用 3.5 执行具体的任务。
更常见的方案是引入人类监督和交互。可以通过人类每隔一段时间,或者在有需要的时候去监督一下 AI 的执行情况,并确保AutoGPT的行为符合现实世界的商业惯例和法律要求。如果不符合人类的意图的话,通过对话可以对 Agent 进行调整,要求它做更符合人类意图的事情(实际上这在多人合作完成任务的场景下,例如公司或组织中,也是非常常见的)。但相对来说,这种方式经常低效而且缓慢:如果我需要监督 AI 才能保证它不出错,为什么我不自己做呢?
有没有更好的方式?
但实际上,在现实世界中,也许我们有更好的方式让 AI agent 和人类的意图对齐。想象这样的场景:你希望一个对某件复杂任务的流程不了解的人,完成一项特定任务:例如上手一个代码项目的开发和环境配置,学习一门新的编程语言,或者编写一本长篇小说、分析某个商业投资的可行性等等。也许这种情况下,我们可以有一本手册或者教程,它并不需要是精确的、一步一步的指令,但是它会包含一个大致的流程和任务分解,让人类能够快速上手完成对应的任务。那么,我们为什么不能用非常轻松的方式,给 AI 一些大概的指示和任务描述,让它根据这些任务来完成对应的工作呢?
相比 AutoGPT,我们实际上需要的是:
- 更强的可控性,让它和人类意图进行充分的对齐;
- 比 CoT(思维链)走的更远,让 AI 能够完成更加复杂的任务,同时不仅限于一步步执行,还需要有递归、循环、条件判断等等特性;
- 可以由人类给予更加明确的指导,让 AI 完成复杂的任务,而不是让 AI 完全自己探索如何分解任务;
- 保留一定的灵活性和机动能力,同时让编写指令尽可能简单。实际上,我们可能并不需要用代码开发和精确的链条来介入这个流程,现实世界大多数充斥着模糊、不确定、近似和时刻需要动态调整的部分,设计一个合理的抽象反而是非常困难的。langchain 那种以代码开发为核心的形态,也许并不会是一个合理的答案,AutoGPT 的出现也证明了这一点。
根据 wiki 百科,计算机程序(Computer Program)可以定义为指一组指示电子计算机或其他具有消息处理能力的电子设备每一步动作的指令序列。也许,某种意义上它也是一种 “程序”,但并不是传统的编程语言:自然语言适合模糊化、灵活、可高效扩展的需求,而传统的程序设计语言实际上是一种精确的抽象和计算,二者缺一不可,它们可以相互转化,但是并不一定需要是从自然语言描述转化为精确的计算机指令。未来,每个人都可以是程序员,只要能够用自然语言描述出对应的需求和步骤,无论清晰或者模糊。
自然语言编程
自然语言编程不应该是:
1 | +++ proc1 |
用自然语言编程模拟计算机程序的编写没有意义,不需要有明确的定义、关键词、语法等等。
自然语言编程是:
1 | 把 asserts 目录下所有的以 txt 结尾的文档翻译成英文,然后喂给 AI 做训练 |
或者一个更复杂的例子:
1 | 3 由质谱推测分子结构的一般程序 |
这里是另外一个例子,我们希望使用自然语言,来指导 AI 完成一个长篇小说的创作。
1 | 有一个任务叫做“翻译和根据大纲创作小说章节”。 |
在这个情况下,我们可以将自然语言编写的一系列视为一种任务分解和执行的过程。我们可以通过定义一些特定的关键词和语法规则来实现这个目标。我们的目标是将自然语言脚本分解为一系列的指令和参数,然后执行这些指令。
自然语言编程不是,也不应该是通常意义上的编程语言编程。我们并不进行自然语言到代码的转换,没有确定的语法、语言和编程范式,大语言模型就是我们的解释器、CPU 和内存;自然语言适合处理需求模糊、信息密度高的应用,代码适合处理精确、可靠的部分。或者说,自然语言编程实际上是 prompt engineering 的高阶形态,自然语言的指令不再局限于单次和 AI 的交互上下文,并且希望能够借助它来增加和扩展 AI 完成复杂推理、复杂任务执行的能力。
以下是一些可能的步骤和考虑因素:
- 函数(任务):在自然语言编程中,函数可以被视为一种任务或者目标。例如,在你的脚本中,“作品创作和翻译”就可以被视为一个函数,它需要接收一些参数(例如,主题、章节数量、每章字数等),然后执行一系列的步骤来完成这个任务。
- 变量:全局变量可以被视为在整个脚本中都可以访问的信息、概念、知识。在你的脚本中,例如“小说的主题”、“章节数量”、“每章字数”等都可以被视为全局变量。
- 指令:在自然语言编程中,指令可以被视为一种行为或者动作。例如,“写出主题”、“搜索背景资料”、“列出大纲”等都可以被视为指令。这些指令可以是顺序执行的,也可以是选择执行的,甚至可以是循环执行的。
- 执行流程:执行流程是指如何按照一定的顺序和逻辑来执行这些指令。在你的脚本中,执行流程可能是这样的:首先,执行“写出主题”这个指令,然后执行“搜索背景资料”这个指令,接着执行“列出大纲”这个指令,然后对于每个章节,执行“翻译和根据大纲创作小说章节”这个指令,最后执行“拼凑章节”和“保存文件”这两个指令。
- 分析自然语言脚本:分析自然语言脚本的目标是将脚本中的语句分解为一系列的指令和参数。这可能需要使用一些自然语言处理(NLP)的技术,例如语义分析、实体识别等。例如,从“作品创作和翻译一本关于“猫”的童话小说,一共有10个章节,每个章节大概 500 字。”这个语句中,我们可以识别出“作品创作和翻译”是一个函数,“猫”、“童话小说”、“10个章节”、“每章500字”是这个函数的参数。
- 执行指令:执行指令的目标是按照分析出的指令和参数来完成任务。这可能需要调用一些外部的API或者服务。例如,执行“翻译和根据大纲创作小说章节”这个指令可能需要调用一个文本生成的API,执行“翻译”这个指令可能需要调用一个翻译的API。
一个可能的思路
为了正确、可控地执行它,我们首先定义函数(任务)、变量和执行流程,然后通过一系列的提示来提取这些信息,并最后让AI处理对应的执行流程。以下是一种可能的方式,以及示例的提示信息(实际上的提示比这个复杂得多):
- 定义和提取函数(任务):
- 函数(任务)是一个具有明确输入和输出的可复用单元。在自然语言脚本中,函数(任务)通常是一些需要完成的目标或动作。
- 示例提示:请在你的脚本中找出所有的任务或目标。这些通常是一些动词短语,例如“写出主题”、“搜索背景资料”、“列出大纲”等。例如,”作品创作和翻译”可以被视为一个函数,它需要接收一些参数(例如,主题、章节数量、每章字数等),然后执行一系列的步骤来完成这个任务。
- 定义和提取变量:
- 变量是在整个脚本中都可以访问的信息,它可以是一些知识、概念、信息,一段文本等等。
- 示例提示:请在你的脚本中找出所有的变量。这些通常是一些名词或名词短语,例如“小说的主题”、“章节数量”、“每章字数”等。
- 定义和提取执行流程:
- 执行流程是指如何按照一定的顺序和逻辑来执行这些指令。在你的脚本中,执行流程可能是这样的:首先,执行“写出主题”这个指令,然后执行“搜索背景资料”这个指令,接着执行“列出大纲”这个指令,然后对于每个章节,执行“翻译和根据大纲创作小说章节”这个指令,最后执行“拼凑章节”和“保存文件”这两个指令。
- 示例提示:请在你的脚本中找出每个任务或目标的执行流程。这通常是一系列的步骤或指令,例如“首先,写出主题,然后,搜索背景资料,接着,列出大纲,然后对于每个章节,翻译和根据大纲创作小说章节,最后,拼凑章节,保存文件”。
- 处理执行流程:
- 根据提取出的执行流程,AI需要处理对应的执行流程。根据循环、分支、顺序执行做出不同的处理。
- 示例提示:现在,我将开始根据提取出的执行流程来处理每个任务。例如,对于“翻
译和根据大纲创作小说章节”这个任务,我将首先根据大纲创作章节的内容,然后将内容翻译成英文。
这样的流程可以帮助我们将自然语言脚本转化为可执行的任务。但是请注意,这需要一些自然语言处理和分析的技能,以及对脚本内容的深入理解。此外,AI的处理能力也会受到一些限制,例如,它可能无法直接处理一些过于复杂的任务(可以在脚本中进一步划分和明确任务),或者需要人类的帮助来完成一些步骤。
自然语言脚本编译器与运行时:langScript
我们做了一个简单的开源项目实验,来完成这个目标和执行自然语言编写的脚本 —- 它不需要有完全确定的语法和格式,也并不需要像学习一门编程语言一样学习它。本质上,它只是对于需求和任务稍微明确一些的指引和抽象,我们可以更方便地使用自然语言定义流程和指导 AI 完成复杂工作。
未来:AI 还是软件?
也许我们很快就要重新思考软件工程是什么这个问题:
- AI 和更广义的 “软件” 之间有什么区别呢?
- 一个软件中的哪些部分可以被 AI 替代?
- AI 可以怎样重塑软件的生命周期、开发方式?
- 自然语言的部分和代码的部分各有什么优势和劣势?哪些情况下我们可以直接使用自然语言,哪些情况下需要代码进行抽象?
- 在一个软件的组成部分中,用 AI 替换掉代码,能带来哪些变革? 会不会能更好的完成对应的需求?
- 更进一步,一个完整的信息系统(以处理信息流为目的的人机一体化系统,有软件、硬件和人类的部分)和 AI 的关系是什么? AI在信息中是什么样的地位? AI 会怎样从信息的角度重塑我们的社会结构和组织模式?
目前来看,我们还远远没有答案。
原 Netscape(网景公司)创始人 Marc Andreessen 说过一句经典的话:软件正在吞噬世界。人工智能领域知名科学家 Andrej Karpathy 在 2017 年为上面的话做了补充:软件(1.0)正在吞噬世界,现在人工智能(软件2.0)正在吞噬软件
Software (1.0) is eating the world, and now AI (Software 2.0) is eating software.
自然语言编程: 从 AutoGPT 往前迈的一小步
https://www.yunwei37.com/2023/06/14/natual-language-program/