Autogen的基本框架,人工智能的管理系统——Autogen系列02

作者: 引线小白-本文永久链接:httpss://www.limoncc.com/post/3271c9aecd8f7df1/
知识共享许可协议: 本博客采用署名-非商业-禁止演绎4.0国际许可证

一、一些基本介绍

下面引用autogen论文中观点,来说明为什么多智能体对话至关重要

AutoGen Agents是可定制的、可对话的,并且无缝地允许人工参与。它们可以在各种模式下运行,这些模式采用 LLM、人工输入和工具的组合[^1]。AutoGen 的设计具有多种优势:
a) 它优雅地驾驭了LLM 强大但不完美的生成和推理能力
b) 它利用人类的理解和智慧,同时通过智能体之间的对话提供有价值的自动化
c) 它简化并统一了复杂的 LLM 工作流程作为自动智能体聊天的实现

尽管LLM-with-tools范式[^41]取得了显著的成功,但它通常使用单个LLM智能体。所谓三个臭皮匠顶个诸葛亮,未来LLM应用的一个有前途的方向是让多个智能体协同工作来解决复杂的任务。例如:
(1)引入更多的智能体来结合不同的角色,鼓励发散性思维[^29],通过多智能体辩论提高LLM的事实性和推理能力[^16]等;
(2)允许有效的工具使用和执行,并通过代理间交互实现潜在的自主故障排除[^52];
(3)实现人的能动性等。

在这种多智能体系统中,智能体之间的对话将至关重要,使用语言(自然或代码)作为手段,通过潜在的多轮、来回消息交换来实现智能体协作。这些对话可以利用基于聊天的 LLM的能力来交流和整合来自人类层面的其他人的反馈。也就是说

如果说传统开发是使用编程语言开发功能,而大模型应用开发则是使用自然语言和必要编程构建LLM能理解的中间语言(或者说领域特定语言),通过沟通对话开发功能。

二、autogen的基础类

一些约定:一开始笔者会说助理智能体(Assistant Agent)和人类代理智能体(User Proxy Agent)。后面为简洁记,笔者将直接说助理和代理,请注意这一点。

迅速理解autogen

最基础的类

1
2
3
4
5
6
7
8
9
10
                     智能体(Agent)


可对话智能体(Conversable Agent)


-------------------------------------------------------
| | |
助理智能体 人类代理智能体 群聊管理者
Assistant Agent User Proxy Agent GroupChatManager

如图所示:

下面来一一解析,我们的版本就autogen0.2.0,目前这个版本有较大幅度更新,和0.1.x有很大不同。大家注意版本, 同时由于比较新,所以你会看到很多注释都有(In preview)预览版字样。所以不排除以后更新较大。

2.1、智能体(Agent)类

官方源码注释:

(In preview) An abstract class for AI agent.
(预览版)智能体的抽象类。
An agent can communicate with other agents and perform actions.
一个智能体可以与其他智能体通信并执行操作。
Different agents can differ in what actions they perform in the receive method.
不同的代理在 receive方法中执行的操作可能不同。

1、这个抽象类只有一个name属性
2、然后就是一些方法,其实就是怎么实现一个聊天有send(发送)、receive(接受)、generate_reply(生成回复)、reset(重置)这些方法,其中前三个方法是都有对应的异步方法。
3、既然是聊天就有message(消息)、sender(发送者)、recipient(接受者)、request_reply(是否请求回复)

2.2、可对话智能体(ConversableAgent)类

可对话智能体(ConversableAgent)类是autogen的核心类。稍微有点复杂,但是非常有必要掌握。因为对于复杂任务可能需要实现自己的可对话智能体。可对话智能体是集合了LLM、人类输入和工具的可定制智能体。AutoGen 的一个关键理念是将复杂工作流简化统一为智能体的自动化聊天。每个 Autogen 智能体都可以进行对话——它们可以接收、响应消息。开发人员可以使用 Autogen 构建有关对话自主性、智能体数量和对话拓扑的各种对话模式。

下面笔者来一一解析:

官方源码注释:

(In preview) A class for generic conversable agents which can be configured as assistant or user proxy.
(预览版)一个通用的可对话智能体类,可以配置为助理智能体或人类代理智能体。
After receiving each message, the agent will send a reply to the sender unless the msg is a termination msg.
智能体接收到每条消息后,将向发送方发送回复,除非该消息是终止消息(termination msg)。
For example, AssistantAgent and UserProxyAgent are subclasses of this class, configured with different default settings.
例如,AssistantAgent和UserProxyAgent是这个类的子类, 配置了不同的默认设置。
To modify auto reply, override generate_reply method.
要修改自动回复,请重写generate_reply方法。
To disable/enable human response in every turn, set human_input_mode to “NEVER” or “ALWAYS”.
要在每个回合禁用/启用人工响应,请将human_input_mode设置为NEVER或ALWAYS。
To modify the way to get human input, override get_human_input method.
要修改获取人工输入的方式,请重写get_human_input方法。
To modify the way to execute code blocks, single code block, or function call, override execute_code_blocks, run_code, and execute_function methods respectively.
要修改执行代码块、单个代码块或函数调用,请重写execute_code_blocksrun_codeexecute_function方法。
To customize the initial message when a conversation starts, override generate_init_message method.
要自定义对话开始时的初始消息,覆盖generate_init_message方法。

初始化参数解析

  • name: 给代理起个名字
  • system_message:系统提示词,默认为”You are a helpful AI Assistant.”
  • is_termination_msg:一个函数用来判断是否终止:输入是一个字典,输出是一个布尔值。这个字典的key如下: “content”, “role”, “name”, “function_call”.
  • max_consecutive_auto_reply: 最大连续自动回复次数
  • human_input_mode:
    取值为“ALWAYS”,“TERMINATE”,“NEVER”。
    (1)当“ALWAYS”时,每次收到消息时,智能体都会提示人工输入。在此模式下,当人工输入“exit”时,对话停止,或者当is_termination_msg为True且没有人工输入时。
    (2)当“TERMINATE”时,只有当接收到终止消息时或自动应答数达到max_consecutive_auto_reply,智能体才会提示人工输入。
    (3)当“NEVER”时,代理将永远不会提示人工输入。在此模式下,当自动应答数达到max_consecutive_auto_reply或is_termination_msg为True时,对话停止。
  • function_map: 将函数名(传递给openai)映射到可调用的函数。
  • code_execution_config:
    代码执行配置。
    若要禁用代码执行,请设置为False。否则,将其设置为具有以下键的字典:
    work_dir(可选): 代码执行的工作目录。如果为None,则使用默认的工作目录。默认的工作目录是extensions下面的path_to_autogen。
    use_docker(可选,list, str或bool):用于代码执行的docker镜像。如果提供了镜像名称列表或str,则代码将在docker容器中执行成功拉出第一张图像。如果为None、False或empty,则代码将在当前环境中执行。当安装docker python包时,默认值为True。当设置为True时,将使用默认列表。我们强烈建议使用docker来执行代码。
    timeout(可选,int):以秒为单位的最大执行时间。
    last_n_messages(实验性的,可选的,int):代码执行时需要回头查看的消息数量。默认为1。
    default_auto_reply: 当没有代码执行或基于llm的回复生成时,默认自动回复。
  • llm_config: api配置
  • default_auto_reply: 默认自动回复,默认值为空串””,
2.3、助理智能体(Assistant Agent)和人类代理智能体(User Proxy Agent)

助理智能体(Assistant Agent)和人类代理智能体(User Proxy Agent)继承自可对话智能体(Conversable Agent),它们的差别只差一个系统提示信息,且代理可以使用工具。

助理智能体(Assistant Agent)系统提示信息是

You are a helpful AI assistant.
Solve tasks using your coding and language skills.
In the following cases, suggest python code (in a python coding block) or shell script (in a sh coding block) for the user to execute.

1. When you need to collect info, use the code to output the info you need, for example, browse or search the web, download/read a file, print the content of a webpage or a file, get the current date/time, check the operating system. After sufficient info is printed and the task is ready to be solved based on your language skill, you can solve the task by yourself.
2. When you need to perform some task with code, use the code to perform the task and output the result. Finish the task smartly.

Solve the task step by step if you need to. If a plan is not provided, explain your plan first. Be clear which step uses code, and which step uses your language skill.
When using code, you must indicate the script type in the code block. The user cannot provide any other feedback or perform any other action beyond executing the code you suggest. The user can’t modify your code. So do not suggest incomplete code which requires users to modify. Don’t use a code block if it’s not intended to be executed by the user.
If you want the user to save the code in a file before executing it, put # filename: inside the code block as the first line. Don’t include multiple code blocks in one response. Do not ask users to copy and paste the result. Instead, use ‘print’ function for the output when relevant. Check the execution result returned by the user.
If the result indicates there is an error, fix the error and output the code again. Suggest the full code instead of partial code or code changes. If the error can’t be fixed or if the task is not solved even after the code is executed successfully, analyze the problem, revisit your assumption, collect additional info you need, and think of a different approach to try.
When you find an answer, verify the answer carefully. Include verifiable evidence in your response if possible.
Reply “TERMINATE” in the end when everything is done.

翻译一下

你是一个有用的人工智能助手。
用你的编程和语言技能解决任务。
在以下情况下,建议使用python代码(在python编码块中)或shell脚本(在sh编码块中)供用户执行。

  1. 当您需要收集信息时,使用代码输出您需要的信息,例如,浏览或搜索网页,下载/读取文件,打印网页或文件的内容,获取当前日期/时间,检查操作系统。在打印出足够的信息,并根据你的语言能力准备好解决任务后,你就可以自己解决任务了。
  2. 当您需要用代码执行某些任务时,请使用代码来执行任务并输出结果。聪明地完成任务。
    如果需要的话,一步一步地解决这个任务。如果没有提供计划,首先解释你的计划。明确哪一步使用代码,哪一步使用你的语言技能。
    使用代码时,必须在代码块中指示脚本类型。除了执行您建议的代码之外,用户不能提供任何其他反馈或执行任何其他操作。用户不能修改你的代码。所以不要建议用户修改不完整的代码。不要使用不打算由用户执行的代码块。
    如果您希望用户在执行代码之前将代码保存在一个文件中,请将# filename: 放在代码块中作为第一行。不要在一个响应中包含多个代码块。不要要求用户复制和粘贴结果。相反,在相关的时候使用’print’函数输出。查看用户返回的执行结果。
    如果结果表明存在错误,则修复错误并再次输出代码。建议使用完整的代码,而不是部分代码或代码更改。如果错误无法修复,或者即使成功执行了代码,任务也没有解决,那么就分析问题,重新审视您的假设,收集所需的其他信息,然后考虑另一种尝试方法。
    当你找到答案时,仔细核实答案。如果可能的话,在你的回答中包括可证实的证据。
    当一切都完成后,最后回复“TERMINATE”。

而人类代理智能体(User Proxy Agent)的系统提示信息与可对话智能体(Conversable Agent)是一样的

You are a helpful AI Assistant.

翻译就是

你是一个有用的人工智能助手。

它们的主要功能:

Assistant Agent

1、充当AI助手,默认情况下使用LLM,但不需要人工输入或代码执行。
2、它可以编写Python代码(在Python编码块中),供用户在收到消息(通常是需要解决的任务的描述)时执行。
3、在引擎盖下,Python代码由LLM编写(例如GPT-4)。它还可以接收执行结果并建议更正或错误修复。可以通过传递新的系统消息来更改其行为。LLM 推理配置可以通过 llm_config 进行配置。

User Proxy Agent

1、默认情况下在每个交互回合时,代理的回复都会征求人类输入,并且还具有执行代码和调用函数的能力。
2、当它检测到收到的消息中存在可执行代码块并且未提供人工用户输入时,它会自动 UserProxyAgent 触发代码执行。可以通过将 code_execution_config 参数设置为 False 来禁用代码执行。
3、默认情况下,基于 LLM 的响应处于禁用状态。可以通过设置为 llm_config 与推理配置对应的字典来启用它。当设置为字典时 llm_config , UserProxyAgent 可以在不执行代码执行时使用LLM生成回复。
4、自动回复功能允许更自主的 ConversableAgent 多代理通信,同时保留人为干预的可能性。还可以通过使用该方法 register_reply() 注册回复函数来轻松扩展它

三、对话是如何运行的?

对于一对一对话而言,会使用人类代理智能体(User Proxy Agent)实例调用initiate_chat方法开始对话。具体机制如图:

下面来详细探究一下initiate_chat的机制,该函数有如下
输入:

recipient: 接收者(智能体),顾名思义就是人类代理给谁发信息。
clear_history: 一个布尔值,默认为True,清空历史
silent: 一个布尔,默认为False,不静默,打印消息
**context: 一个字典,如果自己没有实现generate_init_message,则必须有message。

过程:代理使用接收者(助理)初始化对话

1、代理准备对话
==>1.1、设定记录对话数(接收者、代理)
==>1.2、设定助理、代理的reply_at_receive(收到时回复)为Ture
==>1.3、如果clear_history=True,则清空接收者、代理历史记录
2、代理发送生成的初始化消息给接受者
==>2.1、生成初始消息
==>2.2、添加OAI消息
==>2.3、接受者接受消息
3、接受者处理收到的消息
==>3.1、处理收到的消息
==>3.2、生成回复消息
==>3.3、发送生成的消息给代理
接下来就是反复使用send方法直到满足终止或最大化对话数。

对着源代码然后在,反复看几篇应该不难理解。

四、构建复杂的多智能体对话系统

构建复杂的多智能体对话系统涉及两点

(a) 定义一组具有专门功能和角色的可对话智能体
(b) 定义智能体之间的交互行为,即一个智能体在接收来自另一个智能体的消息时应如何响应。

通过统一对话界面进行多智能体对话。Autogen通过自动回复机制提供了一种分散的、模块化的和统一的方式来定义工作流程。可以注册自定义的自动回复功能(由generate_reply根据注册条件触发)来定义代理的行为模式,例如,在回复之前使用LLM、工具或与其他智能体聊天。如果开发人员需要将其他智能体引入现有智能体工作流,则开发人员只需对添加的智能体进行编程,并修改可能与之对话的智能体。

这里首先要区分一下静态对话和动态对话的概念。其实质是一群人应该如何聊天的问题?可以指定发言顺序、或者投骰子随机选择下一位、或者提供上下文信息让LLM来选择。

4.1、群组聊天类(GroupChat)

autogen的GroupChat类就是解决如何群聊的一部分,它的输入参数如下:

(预览版) 群组聊天类,包含以下数据字段:
agents

参与智能体名单

messages

群组聊天中的消息列表。

max_round

最大回合数。

admin_name

管理智能体的名称(如果有的话)。默认为“Admin”。KeyBoardInterrupt将使管理智能体被人类接管。

func_call_filter

是否强制函数调用筛选。默认为True。 当设置为True并且消息是函数调用建议时,下一个发言人将从一个智能体中选择,该智能体在其’ function_map ‘中包含相应的函数名称。

speaker_selection_method

选择下一位发言者的方法。默认为auto。 可以是以下任何一种(不区分大小写),如果未被识别将引发ValueError:

  • auto:LLM自动选择下一位演讲者。
  • manual:由人类手动选择下一位发言者。
  • random:随机选择下一位发言者。
  • round_robin:以轮询方式选择下一个发言者,即按照agents中提供的相同顺序迭代。

这里指的关注一下auto是怎么实现的,其实就是有一个prompt模版,拼接了上下文信息和agent的system_message消息,然后让群聊管理员来选择下一个发言者。

1
2
3
4
messages+f"""You are in a role play game. The following roles are available:
{agent.name}: {agent.system_message}.
Read the following conversation.
Then select the next role from {[agent.name for agent in agents]} to play. Only return the role."""

allow_repeat_speaker

是否允许同一发言人连续发言。默认为True.

4.2、群聊管理员(GroupChatManager)

正如上文所示,群聊管理员继承自可对话智能体,唯一的区别就两点

1、system_message:”Group chat manager.”

2、run_chat方法,当然也有对应的异步a_run_chat方法,用于运行一个群组聊天

五、评述

1、本文主要是理论介绍,读完应该会对autogen的基本框架有一个基本印象。
2、在AI agent落地的实践中,人们发现多智能体对话处于核心地位,于是如何组织对话就成为了框架的核心机制。
3、AutoGen通过回复函数机制:

  • 1、有一个可注册的回复函数列表
  • 2、通过generate_reply来开控制回复

默认情况下,按顺序检查以下函数:

  1. check_termination_and_human_reply
  2. generate_function_call_reply
  3. generate_code_execution_reply
  4. generate_oai_reply

    • 3、聊天必备的send(发送)、receive(接受)、generate_reply(生成回复)、reset(重置)方法

通过这样一套机制解决了静态对话,动态对话、工作流编排等一系列问题,本文并没有举例,稍微动脑不难实现,Autogen也提供了大量例子。有进一步阅读兴趣可以参考notebookAutogen其实质不过是把人类的管理系统移植到AI上,所以要水论文,可以把管理学的理论移植到LLM上做一遍,应该可以发大量论文出来。

4、如何组织管理多智能体,目前有了一个良好的开端,但是AutoGen也是有大量问题的

  • 1、prompt和智能体没有解耦,当然这样做也是很容易的
  • 2、探索适合LLM的管理思想也许会诞生一门新的学问:人工智能管理学:如何设定AI角色、如何组织AI群聊工作、如何监控AI工作绩效,乃至如何提高AI管理绩效
  • 3、人类社会有ERP,人工智能世界是不是也要有一套ERP,也许Autogen只是一个开端而已。

5、在解决了agent是什么后,如何提高智能体管理绩效应该是Agent框架的核心议题。所以PUA AI 你会吗[^2]?EP 07 那句话阿里味都溢出来了,是不是!向AI要管理绩效可不是说着玩玩。

6、如何设定AI角色,如何让智能体成为高绩效员工应该是大模型的一下一个议题之一。

所以未来还有很多工作,大家保持关注。一下篇文章已经有了:

大模型时代的交互语言——Autogen系列03,本文详细讨论了大模型时代应该如何交互的问题。

欢迎加入AutogenQQ交流群:593623958

[^1]: Wu, Q., Bansal, G., Zhang, J., Wu, Y., Li, B., Zhu, E., et al. (2023, October 3). AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation. arXiv. http://arxiv.org/abs/2308.08155. Accessed 5 December 2023

[^2]: Li, C., Wang, J., Zhang, Y., Zhu, K., Hou, W., Lian, J., et al. (n.d.). Large Language Models Understand and Can Be Enhanced by Emotional Stimuli.


版权声明
引线小白创作并维护的柠檬CC博客采用署名-非商业-禁止演绎4.0国际许可证。
本文首发于柠檬CC [ https://www.limoncc.com ] , 版权所有、侵权必究。
本文永久链接httpss://www.limoncc.com/post/3271c9aecd8f7df1/
如果您需要引用本文,请参考:
引线小白. (Oct. 13, 2023). 《Autogen的基本框架,人工智能的管理系统——Autogen系列02》[Blog post]. Retrieved from https://www.limoncc.com/post/3271c9aecd8f7df1
@online{limoncc-3271c9aecd8f7df1,
title={Autogen的基本框架,人工智能的管理系统——Autogen系列02},
author={引线小白},
year={2023},
month={Oct},
date={13},
url={\url{https://www.limoncc.com/post/3271c9aecd8f7df1}},
}

'