AutoGen 是一个支持使用多个代理来开发大型语言模型(LLM) 应用程序的框架,这些代理采样相互对话的方式来解决人类交给的任务。AutoGen 代理是可定制的、可对话的,并且无缝地允许人类参与。他们采用LLM、人类输入和各种工具组合的各种运作模式。
AutoGen 提供了可对话的 LLM 代理比如用户代理、助理代理等,还可用于通过人工或自动反馈解决各种任务,包括那些需要通过写代码才能完成的任务。下面我们来演示AutoGen通过代理之间的对话来完成人类交给的任务,并且代理们会在对话过程中完成生成代码,执行代码,观察代码结果,调试代码等迭代过程,直至最后完成任务。
以下demo建议在linux或者macos上测试成功!不建议在windows上执行,因为window环境容易产生莫名其妙的错误!
安装autogen
请新建一个python虚拟环境,并在命令行中执行以下安装命令:
pip install pyautogen
任务1:计算股票价格收益率
在下面的示例中,让我们看看如何使用AutoGen中的代理来编写python脚本并执行该脚本。这个过程包括构造一个充当助手的AssistantAgent,以及一个充当人类用户代理的UserProxyAgent。首先我们需要配置模型和api_key, 这里我们选择的模型为:“gpt-4”, 这也是autogo官方推荐的模型。
import autogenconfig_list = [{'model': 'gpt-4','api_key': 'your_api_key',#输入用户自己的api_key}
]
接下来我们需要创建2个代理分别是assistant和user_proxy,其中user_proxy代表人类,主要的职能是向assistant交代人类的任务,并执行assistant生成的代码,然后将代码执行结果反馈给assistant, 而assistant的主要职能是接受user_proxy交代的人类任务,然后向告知user_proxy完成任务所需要的步骤和代码,并观察user_proxy反馈的代码执行结果以此来判断任务是否完成,如果未能完成任务则需要进一步修改代码后再让user_proxy执行代码直至最后完成。整个完成任务的过程就是assistant和user_proxy一问一答的迭代过程,常规情况下退出迭代的条件就是assistant从user_proxy反馈中判断出任务已经完成并返回给user_proxy一个“TERMINATE”标记。如下图所示:
下面我们需要创建UserProxyAgent和AssistantAgent两个代理,我们在创建UserProxyAgent时,我们设置参数human_input_mode为“NEVER”,它表示UserProxyAgent将不会征求人类用户的反馈。当达到max_consecutive_auto_reply定义的限制时,或者当is_termination_msg()对接收到的消息返回true时,接下来我们来创建这两个代理:
# 创建"assistant" 代理
assistant = autogen.AssistantAgent(name="assistant",llm_config={"cache_seed": 42, # seed 用户缓存中间结果"config_list": config_list, "temperature": 0, },
)
# 创建"user_proxy"代理
user_proxy = autogen.UserProxyAgent(name="user_proxy",human_input_mode="NEVER",max_consecutive_auto_reply=10,is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),code_execution_config={"work_dir": "coding","use_docker": False, },
)
这里我们根据官方文档的说明来介绍一些两个代理的参数的含义:
AssistantAgent是ConversableAgent的一个子类,它配置了一个默认的系统消息。默认的系统消息是用来用LLM解决任务的,包括建议python代码块和调试。 human_input_mode
默认为“NEVER”并且code_execution_config
默认为 False。默认情况下,该代理不执行代码,而是期望用户执行代码。
UserProxyAgent 是ConversableAgent 的子类,它可以执行代码并向其他代理提供反馈 ,参数human_input_mode
默认设置为“ALWAYS” 和llm_config
默认设置为“False”。默认情况下,代理将在每次收到消息时提示人工输入。而在本例中我们将human_input_mode
默认设置为“NEVER”即无需人工参与。
接下来我们就任务交给user_proxy ,让它和assistant 一起合作来完成任务:
# 助手从user_proxy接收一条消息,其中包含任务描述
user_proxy.initiate_chat(assistant,message="""What date is today? Compare the year-to-date gain for META and TESLA.""",
)
我们的问题是:“What date is today? Compare the year-to-date gain for META and TESLA.” 中文意思为:“今天是几号?比较一下META和特斯拉今年的收益”。 要完成这个任务是需要查询meta和tesla这两支股票的年初和年末的价格来实现的,下面我们看看这两个代理是如何完成这个任务的:
以上是user_proxy 和assistant之间一部分对话内容的,这里我们可以看到,user_proxy向assistant交代任务后,assistant便回复了user_proxy 完成任务的所有步骤:firs, next..., 以及所需要的代码,而user_proxy 则去执行这些代码,在执行代码过程中可能会出现异常,user_proxy 会将代码执行的异常情况再反馈给assistant,assistant再修改代码,user_proxy再次执行代码,这样迭代循环,直至最后完成任务:
最后我们看到所有代码中的bug被解决以后,user_proxy执行代码后计算出了META和TESLA的年度收益率并将结果反馈给了assistant,assistant最后回复用户user_proxy时在末尾加上了 “TERMINATE”标记表示任务已经完成。上面的例子涉及代码执行。
在AutoGen中,当UserProxyAgent(用户代理)在接收到的消息中检测到可执行代码块并且没有提供人工用户输入时,它会自动触发代码执行。这个过程在指定的工作目录中进行,默认使用Docker容器。除非指定了特定的目录,比如在本例中我们在用户代理的参数code_execution_config中指定了work_dir为“coding”也就是说autogen会在我们的工作目录下创建一个coding文件夹,所有的工作都会在coding文件夹内完成,否则AutoGen默认为extensions目录。在构造UserProxyAgent的新实例时,用户可以通过设置work_dir参数来指定不同的工作目录。
任务2:绘图
接下来我们在任务1的基础上画出这两个股票的收益率趋势图,同样我们只需要告诉用户代理我们的要求即可:
# 上一个问题的后续
user_proxy.send(recipient=assistant,message="""Plot a chart of their stock price change YTD and save to stock_price_ytd.png.""",
)
这里我们完成了任务2,并在工作目录的“coding”文件夹内创建了一个股票收益率的图片,下面我们来打开这个图片:
from IPython.display import ImageImage(filename='coding/stock_price_ytd.png')
总结
今天我们学习了AutoGen的基本原理以及基础参数的设置,并通过两个简单的例子轻松实现了原本需要使用复杂逻辑才能完成的任务。任务的复杂逻辑并没有发生变化,只是实现这些逻辑的主体由人变成了AI,我们模拟出两个由AI担任的人物角色,他们通过相互之间的对话一步一步的解决了人类交给它们的任务,你说神奇不神奇!😀。
参考资料
Getting Started | AutoGen