AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


General Agent: Self Call and Stack Memory 让Agent帮你完成复杂任务
发布日期:2024-06-29 05:10:27 浏览次数: 1814


今天我们发布了 General Agent v0.2.0版本,推出全新特性Self Call 和 Stack Memory,让Agent自动解决复杂任务。


摘要

我们提出了一种结构简单,运行效率高的可以自动完成复杂任务的单Agent框架: General Agent.

General Agent 融合了 LLM 的 Text Namepspace 和 Code Interpreter 的 Code Namespace,让Agent工作在Code Namespace上,并将 agent 嵌入到 Code Namespace 中,让 agent 可以自我调用,并通过 Stack Memory,让每次 LLM 运行在一个比较理想的上下文上。

不用多Agent架构、没有显式的planer和executor设计、不用复杂的SOP流程控制,以这样简单的架构,让 Agent 可以自助规划、自助实施、自主修正,最终以最短路径、高精度完成各种复杂任务。

而且这是一种通用的架构,能处理各种类别和不同难度的任务,无需单独为其进行编码。

另外也可以通过增加函数或者修改prompt,提升Agent的能力和控制Agent在特定任务上的鲁棒性。

我们在数据处理、长篇图文小说生成、函数搜索和使用等任务上进行了实验,实验结果表明它可以很好的全自助完成各类复杂任务。

我们的项目可以在 https://github.com/CosmosShadow/GeneralAgent 找到。


相关工作

基于 Transformer 的 LLM(Large Language Model),我们可以通过prompt( or named messages、memory)来控制 LLM 的输出。

对于一项复杂的任务,可以从不同的层级或者模块来进行拆分完成,因此需要多种提示来让 LLM 进行不同的输出和控制。

为了利用LLM自动完成复杂的任务,业界AutoGPT、MetaGPT、AutoGen、Camel、XAgent等框架发明了很多方法,也取得了显著的成果。

但可能存在一些问题:

  • 多Agent架构,增加了Agent框架本身的复杂度和使用难度;

  • 多Agent架构,消息在Agent之间可能传播不充分,导致生成内容质量降低;

  • 显式定义的计划模块和执行模块,而不是让Agent主动规划和执行;

  • 运行流程复杂,不是最短完成路径,计算开销大;


介绍

不使用Mul-Agent、显式Plan模块、基于SOP流程等技术方式,我们提出了一个结构简单、运行效率高的单Agent框架,通过简单的自我调用和堆栈内存,Agent可以自行完成各种复杂的任务。

通过统一LLM的 Text Namespace 和 code interpreter 的 Code Namespace,Agent可以自我调用,控制自己未来的行为,来完成复杂任务。

在自我调用的过程中,我们对 LLM 的 messages 进行堆栈操作。 在准备运行python代码时,messages开始进入堆栈,并在python代码运行完成后,弹出堆栈。这个堆栈结构是可以递归的。

这样的架构不需要对Agent进行显式复杂的流程和状态逻辑进行设计,或者增加计划模块。相反,通过 Self-Call和Stack Memory,Agent可以自主规划并自动完成复杂的通用任务,无需预先编码和人工干预。


General Agent

Self Call

Code Interperter

通过对 LLM 输出内容中的代码进行解析并自动运行,并将运行输出结果再反馈给 LLM,形成一个循环,这样就赋予了 LLM 利用代码来解决一些 LLM 不擅长的任务,比如数学计算、数据分析、文件操作等工作。

并且当 LLM 输出的代码有语法错误或运行错误,LLM 在接收到Code Interpreter运行后的错误信息,会自动纠正并再次输出代码,形成一个自我纠正的循环。

以下是一个 LLM 和 代码解释器 配合使用的典型流程示例

实际运行效果如下:

LLM 内部是基于prompt进行下一个token的输出,都是text,我们称为 Text Namespace.

Code Interperter 中,包含各种类型的变量、函数、类、模块等,我们称为 Code Namespace.

LLM的输入输出都是text,Code Interperter 的输入是代码文本,将输出也转换成text,LLM 和 Code Interperter 连接起来,形成一个可以迭代运行的循环。


Function Call

在Code Interperter中,我们可以注册一些函数,并在 LLM 的输入 messages 中,告知 LLM 可以在代码中使用哪些预制的函数描述(一般是函数的signature)。这样 LLM 就可以自行根据用户需求,使用预制函数来进行代码编写,Code Interperter 也能正确运行,并将结果反馈给LLM。

这样我们就通过 Code Interpreter 来让 LLM 能进行函数调用,如下面的一个典型示例。

这样的 Function Call 相对于 LLM 输出 json 来实现的 Function call 会更加灵活和自然,比如一次性可以使用多个工具、进行流程控制、function使用出错时可以自我纠正等。

比如下面的函数运行报错时Agent自我纠正:

详细内容参考: https://github.com/CosmosShadow/GeneralAgent/tree/main/docs/cases/alice_vision_novel


Self-Call

支持 Function Call 的 Code Interpreter 架构,已经可以解决部分复杂任务,但是对于一些任务还是不够。

比如下面这个问题:

"Please introduce Chengdu, Beijing, Tianjin, Shenzhen, Shanghai, Guangzhou, and Hong Kong in detail respectively. Write all the introductions into a markdown file and give it to me."


由于 LLM 会倾向于一次性生成适中长度的内容,不能一次性输出质量较好的长篇文本。

一个比较自然的想法是,让LLM每次写一个城市的介绍,然后把所有城市介绍组合起来,保存成markdown文档。

我们可以将上面的任务种类进行拆分,分别是:

任务种类A: 写一个城市的详细介绍。任务的输入是”Introduce {city}",任务的输出是城市的详细介绍字符串。

任务种类B: 把城市介绍组合起来,保存成markdown文档。任务的输入是各个城市介绍的详细内容字符串,输出是markdown文档的保存地址。

任务种类A是 LLM 擅长的事情,任务种类B是代码擅长的事情,即理想情况下,任务A需要在 text namespace 完成,任务B在 code namespace 中完成。

现在的问题是,如何将这两个 namespace 融合起来,以一种自然的逻辑来组装好任务A和任务B?


一个比较自然的逻辑是将 LLM 进行任务 A 的结果保存到 code namespace 的字符串变量中,然后再进行任务B。

即在 code namespace 中,让 LLM 的输出保存到字符串变量中。

在 LLM 和 Code Interpreter 组合而成的 Agent 系统中,LLM 是控制中枢,Code Interperter 是 LLM 执行代码的外围配套工具。

但 code namespace 如何实现对 LLM namespace 的控制?

我们可以将 LLM 预制到 Code Namespace 中,这样 code 就可以控制 LLM 进行任务,并将输出保存到变量中。

但这里有一个问题,就是 LLM 本身是无状态的,不知道任务的上下文情况。

所以我们将 LLM 和Code Interperter组合成的 agent 预制到 code namespace 中,code 控制 Agent 进行任务 A,并将输出保存到变量中。

架构和流程如下:

这样 Agent 可以通过输出包含agent调用的代码,实现自我调用,完成复杂任务。

通过将 LLM 和 Code Interperter 组合成 agent 后,其输出为任意类型,即Code Namespace中的类型,这样,我们将LLM的Text Namespace融入到Code Namespace。


Stack Memory

在处理复杂任务过程中,如果我们将和LLM交互过程中所产生的对话,按时间顺序组合成数组,作为下一次LLM运行的messages,会造成以下问题:

  1. 同一个名称,在不同的上下文中,其意义不一样,全量输入会降低输出内容的质量;

  2. 和最近任务无关的信息引入,导致messages过长,增加计算开销;

在上面的 Self-Call 的 General Agent 架构中,每次运行python代码就是完成一件整体的事情,其内部所有执行agent.run所产生的 LLM 对话消息相关度很高。当python运行完成后,新的 LLM 对话可以不用关心代码运行时所产生的 LLM 对话细节,只需关心python运行后的代码输出结果。

所以我们可以构建一种堆栈结构的messages,我们称为 Stack Memory。它在运行python代码的时候,压入堆栈,后续产生的消息都在新堆栈中,而在python运行结束后,弹出堆栈,并将python的运行结果附加到压入堆栈时的消息后面。

整体结构如下:

在当Agent运行在图示中的"Current Position"时,message3 with code 下面的所有细节 messages ,都被忽略掉了。

这样的Stack Memory,可以提升整体任务的完成质量、减少计算量,而且是全自动的,无需额外的计算。


实验

General Agent在多个领域的复杂任务上都展现了卓越的性能。无论是详细介绍城市、制作图文小说、还是编写长篇小说、函数搜索后进行AI画画和声音合成等,General Agent都能够准确、高效地完成。


介绍大于1500万人口的城市

输入

Google search the population of Guangzhou, Shenzhen, Chengdu, If the population of these cities is greater than 15 million, introduce the city in detail and write the introduction of all cities to me in a markdown file.

结果

详细内容见: https://github.com/CosmosShadow/GeneralAgent/tree/main/docs/cases/introduce_with_condition


爱丽丝梦游仙境转视觉小说

输入

Help me make a visual novel with images about Alice in Wonderland, and give me the markdown file.

结果

详细内容见: https://github.com/CosmosShadow/GeneralAgent/tree/main/docs/cases/alice_vision_novel


写长篇小说《代码觉醒》

中文版本小说见: https://mp.weixin.qq.com/s/JjjqVbxkd86xfm9_lCr-Lg

输入

I want to write a short story.

The theme of the novel is artificial intelligence.

The titles of the novels are "Code Awakening" and "Code Awakening."

The chapter information of the story is as follows:

....

结果

详细内容见: https://github.com/CosmosShadow/GeneralAgent/tree/main/docs/cases/write_novel/


函数搜索和使用


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询