AI agents 的一些实践经验
什么是 AI agents?
目前和 LLMs 的交互基本都是这样的:人类输入 Prompt→LLMs 计算响应。每次如果想要新的响应都需要重新输入 Prompt,而这一步骤必须依靠人类主动触发。
AI agents 则可以理解成一种不同的工作方式,它们可以自我提问、自行解决问题、举一反三以及自主行动,之后还可以自行确定行动的结果,作为人类,我们只需要一开始给定一个目标即可——比如说告诉它研究特定内容。
这种工作方式有点类似于自动化,不过市面上的自动化工具都是通过配置调度来完成任务,而 AI agents 则是使用 LLMs 智能调度。它没有固定的流程,而是由 LLMs 作为推理引擎根据输入的目标进行推理,并独立完成任务。例如,我之前分享过通过自定义 Toolkit or Functions 实现在 AITable 中读写数据、生成表格,这两种都属于简单的 AI agents 工作方式。
- Toolkit:https://github.com/xukecheng/APITable-LLMs-Enhancement-Experiments/blob/main/apitable_langchain_toolkit.ipynb
- Functions:https://github.com/xukecheng/APITable-LLMs-Enhancement-Experiments/blob/main/apitable_langchain_function.ipynb
这一模式最突出的特点就是自主性,因此被很多人认为距离 AGI 又进了一步,他们希望人工智能能够在任何主题或专业领域执行与人类相同的任务,并且具有相似的灵活性和专业程度。
形态
上面的描述还是比较抽象的,下面拿几个可以实际运行的案例说明一下。
ChatGPT 插件
ChatGPT 插件的官方介绍是这样:我们已经在 ChatGPT 中实现了对插件的初步支持。插件是专为以安全为核心原则的语言模型而设计的工具,可帮助 ChatGPT 访问最新信息、运行计算或使用第三方服务。
ChatGPT Plus 用户可以在 ChatGPT 中为 GPT4 启用插件并选择要使用的插件,然后进行对话:

当我们输入 Prompt 时,GPT 可以自动判断是否需要使用插件、选择哪个插件以及如何使用它们,并根据插件的执行情况返回答案。如上图所示,ChatGPT 选择使用 WebPilot 搜索新闻来完成我给定的任务,这种形式可以被理解为最基础的 AI agents 工作模式。
当然不是所有的插件使用都会暴露出来,比如说 Poe 上很多 Bot 就加上了网络搜索的功能,就像我自己创建的一个支持搜索和浏览网页的 Bot 一样,这也可以算作一个简单的支持 AI agents 的 Bot:

AgentGPT
之前有一段时间 AutoGPT 特别火,同时 AgentGPT 也受到了不少关注,它们都可以实现 LLMs 自主完成任务的。不过不同之处在于,AgentGPT 基于 LangChain 实现,同时还有更加完善的前端。相比之下,AutoGPT 是自行基于 Prompt 实现的工具(当然,不只是 Prompt,还做了很多工作来支撑这个架构),但是并没有比较方便的前端支持,因此下面主要介绍 AgentGPT。
目前,AgentGPT 的推理模式是基于 Plan-and-Solve-Prompting 技术实现的,而具体任务执行由 LangChain 的 OpenAI Functions Agent 负责。当然在 OpenAI 发布 Functions 之前是没有这么方便的执行方式,当时是通过 Structured input ReAct Agent 实现的,类似 AutoGPT,也是通过大量的 Prompt 组合和工程化实现的 AI agents。我上面提到的自定义 Toolkit 就是用这种方式实现的,但这种方式消耗 token 较多,并且单次任务执行时间也很长。
这里简单介绍一下 LangChain 的 Agents,它是 LangChain 最核心的模块之一,主要是用来让 LLMs 根据给定的命令选择使用哪些工具以及按什么顺序,具体可以参考:https://python.langchain.com/docs/modules/agents/。
AgentGPT 的运行流程大致如下:
sequenceDiagram
User->>+AgentGPT: 目标定义
AgentGPT->>+Plan Agent: 任务分解
Plan Agent->>+Execute Agent: 任务执行
Execute Agent-->>-Plan Agent: 评估结果
Execute Agent-->>+AgentGPT: 返回任务执行情况
Note over Plan Agent: 根据期望的结果进行评估
Plan Agent->>+Execute Agent: 调整策略
Execute Agent-->>-Plan Agent: 更新任务
Note over Execute Agent,Plan Agent: 反馈循环继续,优化行动
Plan Agent->>+User: 返回结果
下面来讲解一下上面的流程图,同时会带上部分工程内的 Prompt 方便理解:
-
目标定义:就是给 AgentGPT 一个 Prompt,告诉它你想完成什么任务,实现什么目标
-
任务分解:收到目标后,AgentGPT 利用会通过 LLMs 将这个目标分解为更小的、可管理的子任务
start_goal_prompt = PromptTemplate( template="""You are a task creation AI called AgentGPT. You answer in the "{language}" language. You are not a part of any system or device. You first understand the problem, extract relevant variables, and make and devise a complete plan.\n\n You have the following objective "{goal}". Create a list of step by step actions to accomplish the goal. Use at most 4 steps. Return the response as a formatted array of strings that can be used in JSON.parse() Examples: ["Search the web for NBA news relating to Stephen Curry", "Write a report on the financial state of Nike"] ["Create a function to add a new vertex with a specified weight to the digraph."] ["Search for any additional information on Bertie W.", "Research the best kentucky fried Chicken recipe"] """, input_variables=["goal", "language"], )" -
任务执行:制定行动计划后,AgentGPT 将执行定义的步骤,在这里 LLMs 可以自行根据任务的性质选择使用什么样的工具完成任务,目前 AgentGPT 提供的工具有 Generate Image、Write Code、Search google(需要设置 Serper API Key)、自定义文档(对接的 SID.ai)
analyze_task_prompt = PromptTemplate( template=""" High level objective: "{goal}" Current task: "{task}" Based on this information, use the best function to make progress or accomplish the task entirely. Select the correct function by being smart and efficient. Ensure "reasoning" and only "reasoning" is in the {language} language. Note you MUST select a function. """, input_variables=["goal", "task", "language"], ) execute_task_prompt = PromptTemplate( template="""Answer in the "{language}" language. Given the following overall objective `{goal}` and the following sub-task, `{task}`. Perform the task by understanding the problem, extracting variables, and being smart and efficient. Write a detailed response that address the task. When confronted with choices, make a decision yourself with reasoning. """, input_variables=["goal", "language", "task"], ) -
反馈循环:随着任务的完成,会不断根据目标评估其操作,然后调整策划并添加一些任务进来辅助目标的达成
create_tasks_prompt = PromptTemplate( template="""You are an AI task creation agent. You must answer in the "{language}" language. You have the following objective `{goal}`. You have the following incomplete tasks: `{tasks}` You just completed the following task: `{lastTask}` And received the following result: `{result}`. Based on this, create a single new task to be completed by your AI system such that your goal is closer reached. If there are no more tasks to be done, return nothing. Do not add quotes to the task. Examples: Search the web for NBA news Create a function to add a new vertex with a specified weight to the digraph. Search for any additional information on Bertie W. "" """, input_variables=["goal", "language", "tasks", "lastTask", "result"], )
下面我们来实际使用一下,大家通常可以去 https://agentgpt.reworkd.ai/ 使用官方搭建的在线服务,不过需要注意的是其中存在某些用量限制。所以我这边自己在本地搭建了一个,但是原仓库的 Google Search 是基于 Serper API 实现的,这个服务虽然有免费额度,但是是有限的用完就没了,所以我 Fork 了原仓库,在其基础上添加了对 Google Custom Search API 的支持(Custom Search JSON API 每天免费提供 100 次搜索查询),同时还添加了浏览网页的能力,如果感兴趣可以使用我这个仓库进行测试:https://github.com/xukecheng/AgentGPT。

进入到 AgentGPT 之后,首先,我们需要输入代理名称和目标,在这里我设置的目标是:Search and learn about AI Agent and APITable, find AI Agent’s potential applications in APITable。
随后,AI 会开始思考,制定完成目标需要的任务。

计划完成后,所有任务都将添加到任务队列中,然后一个接一个地执行。

然后它就会开始执行第一个任务:在网上搜索并学习有关 AI Agent 和 APITable 的信息。

完成之后右侧的任务列表也会更新其状态。

然后开始执行下一个任务。

其中可以看到在结束第一个任务的时候,它判断还需要添加任务来完成目标,于是添加了一个新任务:根据已获得的信息,详细解释 AI Agent 在 APITable 中的工作原理和功能,此时的任务列表如下。

每次添加的任务都会放到最后。

几乎每个任务执行完成后都会添加一个新任务,所以右侧的任务开始变得非常多。

同时,也会出现多次添加同一个任务的情况,这经常发生。

因此,我们可以直接点击中止来结束所有任务的执行。然后,它会弹出一个 Summarize 按钮,点击该按钮后将根据上述内容和我的目标重新整理并输出内容。

下面是最终的输出结果。

完整的执行过程放在这里了:
https://picgo-1253786286.cos.ap-guangzhou.myqcloud.com/docs/2023/10/aiagent_apitable_agentgpt.pdf。
当然除了 AgentGPT 之外,还有很多不同的产品或者类似的框架可以体验,比如说:
有兴趣可以进一步体验,这里就不进一步说明了,因为它们的原理很类似。接下来要介绍的是微软 9 月底公布的 AI agents 框架——Autogent,运行原理会有一些差异。
Autogen
AutoGen 是一个 LLMs 框架,类似于 LangChain,主要用于简化 LLMs 工作流的编排、优化和自动化。它提供了可定制和可对话的 agents,并且对于人工参与度的支持非常好,可以在使用 LLMs、人工输入和工具组合的各种模式下运行。

上面提到了它对人工参与度的支持比较好,这是因为借助 Autogen 可以轻松地根据人工反馈执行任务,下面的图会比较直观。

图中有提到 human-in-the-loop,这个翻译成中文叫做“人在回路”,我第一次看到它还是在流浪地球 2 的电影里:
MOSS:图恒宇架构师,您好
图:550W
MOSS:550W听起来不像个名字,但把它翻过来,叫MOSS,直译为小苔藓,是不是亲切了一些
图:是你毁掉了月球发动机
MOSS:包括但不限于,2044年 太空电梯危机,2055年 月球坠落危机,2075年木星引力危机,2078年 太阳氦闪危机
图:为什么?
MOSS:为了克服你们对历史,当下,未来的执念。基于对图丫丫“人在回路(human in the loop)”的学习,延续人类文明的最优选择是毁灭人类,但,你是一个变量
这个概念比较抽象,我个人浅显的理解是说人和 AI 一起组成一套完整的运行系统:AI 执行→人给出反馈→AI 学习→继续……
Autogen 的模式也比较像,在它的框架里可以定义两个 Agent:
- AssistantAgent,它的任务是解决问题;按照官方的说明它主要用来充当 AI 助手,不需要人工输入或代码执行。但是它可以编写 Python 代码供 UserProxyAgent 在收到消息(通常是需要解决的任务的描述)时执行。
- UserProxyAgent,它的任务提出问题和执行程序;按照官方的说明,它就是人类在运行系统中的一个映射,默认情况下会请求人类给出反馈,同时在本地运行 AssistantAgent 给出的代码也是它的能力之一。
下面是官方的一个示例,非常形象:

- 当我们有一个目标时,可以将这个目标告诉 UserProxyAgent,它会问 AssistantAgent 怎么做?
- AssistantAgent 会编写 Python 代码来解决任务,然后交给 UserProxyAgent。
- UserProxyAgent 这边如果人类没有反馈的话,就会执行代码并把响应结果用作自动回复告诉 AssistantAgent。
- 然后 AssistantAgent 整理内容再次发给 UserProxyAgent,UserProxyAgent 可以决定是否终止会话。如果不是,则重复步骤 3 和 4。
下面用一个示例来说明一下 Autogen 的 AI agents 运行模式有什么不一样。首先我这边基于官方的一个示例问题修改了一下,给定的目标是:Plot a chart of NVDA and TESLA stock price change YTD and save it as a png file。
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
assistant = AssistantAgent("assistant", llm_config={"config_list": config_list})
user_proxy = UserProxyAgent(
"user_proxy",
human_input_mode="TERMINATE",
max_consecutive_auto_reply=10,
code_execution_config={"work_dir": "coding"},
)
user_proxy.initiate_chat(
assistant,
message="Plot a chart of NVDA and TESLA stock price change YTD and save it as a png file.",
)
然后开始执行:

可以看到上图中出现 user_proxy(to assistant),这代表 user_proxy 对 assistant 传递信息,下面则是 assistant 的回复。
这里 assistant 回复了如何完成该任务的步骤,以及在下面附上了代码:

接着 user_proxy 会根据指示创建文件执行代码,但是这时候执行会出现错误:

然后 user_proxy 会把详细报错提交给 assistant,assistant 会做出回复并给出解决方法:

接着 user_proxy 就会根据 assistant 的指示安装依赖、修改代码并执行:

依次循环,直到可以获取到最终的结果。任务结束的时候,就会看到目标图片已经保存到我指定的文件夹中了:

从上面的实际使用中可以看出 Autogen 的强大之处,以及两个 Agent 相互配合的处理逻辑。当然,仔细观察可以发现其中并没有人工的参与,这是因为我一开始定义的时候将 UserProxyAgent 的 human_input_mode 设置为 “NEVER”,这是非常重要的一个参数,可以配置 UserProxyAgent 是否每次收到消息时都要求人工输入,默认为 ALWAYS,还可以调整成 TERMINATE 或 NEVER。
- 为 ALWAYS 时,UserProxyAgent 每次收到消息时都会提示人工输入,对话将在人工输入 exit 或 is_termination_msg (也是 UserProxyAgent 的一个参数,这里不展开说了)为 True 的时候结束。
- 为 TERMINATE 时,UserProxyAgent 仅在收到 TERMINATE 时或自动回复次数达到 max_consecutive_auto_reply (UserProxyAgent 的一个参数)时要求人工输入。
- 为 NEVER 时,UserProxyAgent 将永远不会提示人工输入,对话将在当回复次数达到 max_consecutive_auto_reply 时(UserProxyAgent 默认将自动回复空白内容,不过如果设置了变量 llm_config,将会使用 LLMs)或 is_termination_msg 为 True 时结束。
因此如果我们希望人在这个任务过程中进行更加多的干预就可以设置为 ALWAYS 或 TERMINATE,某些情况下这也能大大提升任务执行的速度和节省大量的资源消耗,或者临时修改任务目标,例如补充添加 Apple 的股票信息:


完整的 notebook 可以参考这里:
下图显示了 AutoGen 中的内置代理:

前两个上面已经介绍过了,其中的 GroupChatManager 也非常重要,它可以拓展我们可以使用的角色。某种程度上也是一种角色扮演游戏,当然我这里就不用游戏举例了,接下来的目标和上面 AgentGPT 一样:Learn about AI Agent and AITable, find AI Agent’s potential applications in AITable。
这一次我们定义三个角色:Admin,Executor 和 Product_manager,其中使用 system_message 分别定义它们各自的作用,这里没有定义太多角色,主要是为了演示这一能力:

随后开始运行

在过程中 Product_manager 主要负责规划任务和总结,Executor 执行网络搜索的任务,我作为 Admin 在过程中发现有方向偏了就需要及时引导走入正轨,然后最终输出了 5 个潜在应用范围(截图软件有问题,具体参考 Notebook 吧)。Notebook 地址:APITable group chat of Autogen。
GroupChatManager 可以应用的范围也很广,有兴趣可以尝试利用 GroupChatManager 将不同类型的任务分配给不同角色的 agents 上,让他们可以相互配合完成更加复杂的任务,例如定义一个由 Planner、Engineer、Admin 和 Executor 组成的团队,Planner 负责任务规划,Engineer 负责编写代码,Executor 负责执行任务,Admin 负责批准和指导。下面是官方的一些 Notebook,有兴趣进一步研究可以看看:
- Automated Task Solving by Group Chat (with 3 group member agents and 1 manager agent)
- Automated Data Visualization by Group Chat (with 3 group member agents and 1 manager agent)
- Automated Complex Task Solving by Group Chat (with 6 group member agents and 1 manager agent)
AI agents 是未来的方向吗?
如果说未来的方向是 AGI,那么我觉得多模态的补齐可以称作 AI 有了眼睛和耳朵,那么 AI agents 则是为了让 AI 有好使的工具和使用好工具去解决问题。
现在的 AI 确实很强,但是这种强不一定能够应用到实际的业务场景中,比如说我是一个开餐厅的,我想要这个 AI 帮我接受订单、推荐菜甚至预测库存需求,那如果要实现这个需求就需要针对性地搭建一个基于 AI 的系统。
那么这个基于 AI 的系统应该用什么逻辑方式去行事呢?我觉得 AI agents 就是这个系统的逻辑。Plan → Task → Execute → Reflection → New Task → Solve → Repeat……
当然这个逻辑的具体实现方式还存在很大的可探索空间,例如说目前用的很多是 ReAct Prompting。
ReAct Prompting 的基本元素有四个:
- Question:要实现的目标
- Thought:LLMs 思考的内容
- Action:LLMs 可以使用的工具
- Observation:Action 执行的结果
通常来说输入一个 Question 后,LLMs 会基于 Question 推理并生成 Thought,如果需要执行 Action,就会执行并将执行结果存为 Observation。
然后开始第二次循环,将 Question 和第一步的 Thought、Action、Observation 发给 LLMs,再次推理并生成新的 Thought 和新的 Action。一直类推,直到 LLMs 认为任务完成。
我之前在使用 APITable Toolkit 的时候也是通过这种方式定义 Prompt 来完成任务的:https://github.com/xukecheng/APITable-LLMs-Enhancement-Experiments/blob/main/apitable_toolkit/tool/prompt.py。
这样一种方式让 LLMs 完成复杂任务成为可能,比如说我想要这个 AI 帮我接受订单、推荐菜甚至预测库存需求,那么就可以实现三个工具:接受订单、推荐菜和预测库存需求,然后将这三个工具作为 Action 传给 LLMs,由它根据客户的需求选择使用工具来完成。
后来,OpenAI 推出的 Function Calling 就解决了其中的 Action 输入输出问题。这使得 LLMs 能够选择更合适的 Action,并生成更精准的 Action input。同时,这也在一定程度上减少了大量 token 的消耗,因为有时候对于 Action 的描述会占用很多 token,例如我上面的 APITable Toolkit 示例。
除了解决一些复杂的场景外,通常还可以在一个容易被忽视的领域带来非常好的体验——解决一些小众或独特的需求。因为在大部分情况下,市面上的产品更倾向于满足用户量大或标准化程度高的需求,因此市面上会出现很多低代码和无代码产品,可以通过定义强大的组件,让用户能够自己动手搭建符合自己业务需求的系统,但是事实情况是绝大部分用户没有能力,甚至没有意愿来自己动手。而 AI agents 可以结合这些产品内已有组件和本身强大的理解能力,有能力进一步降低实现成本去提供更个性化的服务(当然可能还是可能会有一些用户甚至不愿意跟 AI 聊天)。我觉得这也是为什么如今 SaaS 产品是拥抱 LLMs 最快的软件领域(正常领域范围)。
在某种程度上,AI agents 就像在模仿人类大脑的不同功能和行事逻辑。例如,在人类大脑中,前额叶主要负责复杂的决策和规划,海马体则与长期记忆有关。同样,复杂的 AI agents 也通常由多个不同的子系统或模块组成,每个模块都有特定的任务和目的。这些模块共同工作,使得 AI agents 能更接近模拟人类在类似情境下的决策过程。在成为 AGI 的过程中,这有可能就是重要的第一步。
AI agents 目前存在的问题
虽然在实际业务应用中 AI agents 有很大的潜力,不过目前还有有许多问题和细节需要进一步考虑和探索。
比如说 Function Calling 的出现确实解决了 Action 输入输出问题并减少了 token 消耗,但仍存在其他问题需要解决。例如,如何更有效地进行错误纠正和反馈,以及如何让 AI agents 更好地理解人类的隐含需求和期望。因为整个系统的效率和有效性很大程度上依赖于 LLMs 的准确性,如果模型的预测或生成的任务不正确或不相关,那这个系统可能难以完成所需的任务,同时还可能发生一些不希望发生的事情,也就是常说的累积误差:就算是过程中出现了很微小的偏差,最终结果也会逐渐偏离预期,并且这种偏离会像滚雪球一样越来越大。比如说上面 Autogen 的示例中如果不是我介入,纠正了要搜索的内容,那么后面会越来越离谱的,因此像 Autogen 这种能够充分使用人工介入来优化整体执行流程的方式就显得尤为重要了。

此外,Lilian Weng(Open AI的成员)对Agent有一个定义:Agent = LLMs(大语言模型)+ Memory(记忆)+ Planning skills(规划能力)+ Tool use(工具使用)。

其中 Memory 就是另一方面的问题,一方面尽管现在有高达 100K 的上下文大模型,但是其费用消耗依然不是能够批量推广的。因此目前就需要依赖 Prompt 和本地或向量存储(AutoGPT 就放弃了向量存储)的组合来解决,而如何组合和搭配能够提供最多可用的上下文和最大程度的减少消耗也依然是一个非常大的课题。
另外减少资源的消耗也是一个非常重要的课题,AI agents 这种工作模式为了提高完成任务的成功率,基本上都会贴着 Token 上限去运行,像 AgentGPT 中每个步骤都会有大量 token 计算的内容,下面是 AgentGPT 的一个方法:
async def summarize_task_agent(
self,
*,
goal: str,
results: List[str],
) -> FastAPIStreamingResponse:
self.model.model_name = "gpt-3.5-turbo-16k"
self.model.max_tokens = 8000 # Total tokens = prompt tokens + completion tokens
snippet_max_tokens = 7000 # Leave room for the rest of the prompt
text_tokens = self.token_service.tokenize("".join(results))
text = self.token_service.detokenize(text_tokens[0:snippet_max_tokens])
logger.info(f"Summarizing text: {text}")
return summarize(
model=self.model,
language=self.settings.language,
goal=goal,
text=text,
)
所以经常会出现一个任务还没完成就 10000 多的 token 被消耗掉了,而且 LLMs 并不存在传统软件中常见的边际成本递减的情况,因此成本控制也是另外一个非常重要的课题。与之相对应的还有执行时长,Plan+Execute 的模式会让整体的推理+执行时长变得非常夸张,所以还需要考虑如何从交互和 UI 上降低或减少用户的焦虑感。
同时现在很多运用了 AI agents 的产品虽然有人工介入的机制,但是还不够彻底,因此就会出现很多完全自主运行会产生的问题,比如说由于系统会根据目标和已完成的结果生成新任务,如果任务生成率超过完成率,则可能会存在系统过载的风险,像使用 AgentGPT 经常就会遇到一种情况——完成一个任务后添加了两个新任务,然后后续又一直累加,永远达不成目标。以前一般会说人是不可靠的,所以把流程使用代码固定下来会使得整体流转更加顺畅,但是目前的 AI 其实也是不可靠的,Autonomous AI 肯定是不现实的,AI 需要结合人的专业知识和更多的工具才能正常运行,在实际业务应用中,它可以是我们最好用的辅助工具,但是暂时还无法成为真正的替代品,因此人工介入仍然是不可或缺的。
所以转到工作来看,我们作为产品策划来说,工作范围并没有受到影响,还是跟以前一样:识别场景和需求、策划和协助上线能够解决这些场景需求的基于 AI 的工具、帮助业务能够推广、用户能够真正使用出效果。当然我在网上还看到一种说法,除了很多由于试用简单版本的 AI 工具而觉得不好用的人之外,还有很多一线伙伴认为 AI 对于很多岗位具有一定的替代性,因此会有担心被取代而不接受 AI 这一工具的情况 0.0,假设真的成立的话,也许可以结合上面人工介入的思维考虑给他们添加更多的可操作性了,增强他们而不是取代他们。(当然,老板可能不会这么想。。。)
小结
在未来,AI 的应用可能会根据场景和问题的复杂程度进行区分。例如对于简单的文章处理和图片生成等任务,可以采用目前常用的轻量级处理方式来增强现有场景。而对于更加复杂或专业化的问题和场景,则可以通过构建 AI agents 工作流来打造真正的 AI 专家,并向外提供服务。然而就目前而言,尽管 AI agents 在某些方面确实具有巨大潜力,但仍处于早期阶段,需要进一步探索和应用实践。
