原文:
towardsdatascience.com/diving-deep-into-autogen-and-agentic-frameworks-3e161fa3c086
以及 AutoGen 项目
图片由作者提供 – SDXL
代理最近在技术新闻网站上无处不在。虽然人们对这些程序能做什么抱有很高的期望,但关于应该为这些代理提供动力的框架的讨论却不多。从高层次来看,代理只是一个程序,通常由大型语言模型(LLM)提供动力,以完成某个动作。虽然任何人都可以提示 LLM,但代理系统的关键区别在于它们在面对模糊任务时的一致表现。
要获得这种一致的表现并不简单。虽然像思维链、反思等提示技术已被证明可以提高 LLM 的表现,但 LLM 在聊天过程中得到适当的反馈时往往会发生根本性的改进。这可以像科学家指出聊天机器人响应中的缺陷,或者程序员在尝试运行 LLM 的代码时复制编译器消息。
因此,当我们试图使这些代理系统更加一致地表现时,人们可能会合理地询问我们是否可以找到一种方法,让多个 LLM 相互提供反馈,从而提高系统的整体输出。这正是"AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation"论文的作者们介入的地方。他们撰写了一篇论文并启动了一个 MIT 许可证项目来解决这个问题。
我们将从论文中讨论的高级概念开始,然后过渡到一些使用 autogen 代码库的示例。
可对话代理
为了协调大型语言模型(LLM),AutoGen 依赖于一个对话模型。基本思路是代理之间相互交流以解决问题。就像人类改进彼此的工作一样,LLM 会倾听他人的说法,然后提供改进或新的信息。
虽然人们最初可能预期所有的工作都由 LLM 来完成,但代理系统需要的不仅仅是这种功能。正如像 Voyager 这样的论文所显示的,通过为代理创建技能和工具可以获得超出预期的性能。这意味着允许系统保存和执行 LLM 之前编写的函数,同时也为像人类这样的演员留下扮演角色的空间。因此,作者决定代理有三个主要来源:LLM、人类和工具。
图 1 的一部分 来自论文
如上所示,我们有一个名为ConversableAgent的父类,它允许使用三个来源中的任何一个。从这个父类中,我们派生了AssistantAgent和UserProxyAgent这两个子类。请注意,这显示了在我们创建专用类时选择三个来源之一给代理的模式。我们喜欢将代理分成明确的角色,以便我们可以使用对话式编程来指导它们。
对话式编程
定义了我们的演员后,我们可以讨论如何编程它们以实现代理的最终目标。作者建议将对话式编程视为确定代理应该计算什么以及何时计算它。
每个代理都有一个send、receive和generate_reply函数。按顺序进行,代理首先会收到一条消息,然后是generate_reply,最后将消息发送给其他代理。代理收到消息的方式是我们控制计算发生的时间。我们可以有管理器或没有管理器来做这件事,我们将在下面看到。虽然每个函数都可以自定义,但generate_reply是作者建议你放置代理计算逻辑的地方。让我们通过以下论文中的高级示例来了解这是如何完成的。
图 2来自论文
逐步深入,我们创建了两个代理:一个AssistantAgent(与 OpenAI 的 LLMs 交互)和一个UserProxyAgent(将给出指令并运行它收到的代码)。然后,作者定义了reply_func_A2B,其中我们看到如果代理发送回代码,UserProxyAgent将执行该代码。此外,为了确保UserProxyAgent仅在必要时响应,我们在代码执行调用周围添加了逻辑。代理将来回移动,直到发送终止消息或达到最大自动回复次数,或者代理对自己响应的最大次数。
在下面的交互可视化中,我们可以看到两个代理迭代以创建一个对用户立即有用的最终结果。
图 1 的一部分来自论文
现在我们对它有了高级理解,让我们通过一些示例应用深入到代码中。
编码示例
让我们从要求 LLM 生成在本地运行的代码并要求 LLM 在抛出任何异常时进行编辑开始。以下我正在修改来自 AutoGen 项目的"使用代码生成、执行和调试解决任务"示例。
from IPython.display import Image, display
import autogen
from autogen.coding import LocalCommandLineCodeExecutor
import os
config_list = [{
"model": "llama3-70b-8192",
"api_key": os.environ.get('GROQ_API_KEY'),
"base_url":"https://api.groq.com/openai/v1"
}]
assistant = autogen.AssistantAgent(
name="assistant",
llm_config={
"cache_seed": 41, # seed for caching and reproducibility
"config_list": config_list, # a list of OpenAI API configurations
"temperature": 0, # temperature for sampling
}, # configuration for autogen's enhanced inference API which is compatible with OpenAI API
)
# create a UserProxyAgent instance named "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={
# the executor to run the generated code
"executor": LocalCommandLineCodeExecutor(work_dir="coding"),
},
)
# the assistant receives a message from the user_proxy, which contains the task description
chat_res = user_proxy.initiate_chat(
assistant,
message="""What date is today? Compare the year-to-date gain for META and TESLA.""",
summary_method="reflection_with_llm",
)
要深入了解,我们首先实例化两个代理——我们的用户代理代理 (AssistantAgent) 和我们的 LLM 代理 (UserProxyAgent)。LLM 代理被赋予了一个 API 密钥,以便它可以调用外部 LLM,然后是一个系统消息以及一个 cache_seed,以减少运行之间的随机性。请注意,AutoGen 并不限制你只能使用 OpenAI 端点——你可以连接到任何遵循 OpenAI API 格式的外部提供者(在这个例子中我展示了 Groq)。
用户代理代理的配置更为复杂。让我们从一些更有趣的配置开始,从顶部开始。human_input_mode 允许你确定人类在过程中的参与程度。这里和下面的示例都选择了 "NEVER",因为它们希望这个过程尽可能无缝,人类永远不会被提示。如果你选择像 "ALWAYS" 这样的选项,每次代理收到消息时都会提示人类。中间的选择是 "TERMINATE",它只会在我们达到 max_consecutive_auto_reply 的最大连续自动回复次数或从其他代理收到终止消息时提示用户。
我们还可以配置终止消息的外观。在这种情况下,我们检查代理接收到的消息末尾是否出现 TERMINATE。虽然上面的代码没有显示,AutoGen 库内给代理的提示是告诉 LLM 这样回答的依据。要更改此设置,你需要修改提示和配置。
“LocalCommandLineCodeExecutor” 的屏幕截图
最后,也许最重要的是 code_execution_config。在这个例子中,我们希望用户的计算机执行 LLM 生成的代码。为此,我们传递了 LocalCommandLineCodeExecutor,它将处理这个过程。这里的代码 确定系统的本地 shell,然后将程序保存到本地文件。然后它将使用 Python 的 subprocess 在本地执行此代码,并返回子进程的 stdout、stderr 以及退出代码。
RAG 示例
接下来,让我们看看如何使用 "使用 RetrieveChat 进行检索增强代码生成和问答的示例 来设置一个检索增强生成 (RAG) 代理。简而言之,这段代码允许用户就特定数据源向 LLM 提出一个问题,并得到对该问题的准确回答。
import json
import os
import chromadb
import autogen
from autogen.agentchat.contrib.retrieve_assistant_agent import RetrieveAssistantAgent
from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent
# Accepted file formats for that can be stored in
# a vector database instance
from autogen.retrieve_utils import TEXT_FORMATS
config_list = [
{"model": "gpt-3.5-turbo-0125", "api_key": "<YOUR_API_KEY>", "api_type": "openai"},
]
assistant = RetrieveAssistantAgent(
name="assistant",
system_message="You are a helpful assistant.",
llm_config={
"timeout": 600,
"cache_seed": 42,
"config_list": config_list,
},
)
ragproxyagent = RetrieveUserProxyAgent(
name="ragproxyagent",
human_input_mode="NEVER",
max_consecutive_auto_reply=3,
retrieve_config={
"task": "qa",
"docs_path": [
"https://raw.githubusercontent.com/microsoft/FLAML/main/website/docs/Examples/Integrate%20-%20Spark.md",
"https://raw.githubusercontent.com/microsoft/FLAML/main/website/docs/Research.md",
os.path.join(os.path.abspath(""), "..", "website", "docs"),
],
"custom_text_types": ["non-existent-type"],
"chunk_token_size": 2000,
"model": config_list[0]["model"],
"vector_db": "chroma", # conversely pass your client here
"overwrite": False, # set to True if you want to overwrite an existing collection
},
code_execution_config=False, # set to False if you don't want to execute the code
)
assistant.reset()
code_problem = "How can I use FLAML to perform a classification task and use spark to do parallel training. Train 30 seconds and force cancel jobs if time limit is reached."
chat_result = ragproxyagent.initiate_chat(
assistant, message=ragproxyagent.message_generator, problem=code_problem, search_string="spark"
)
LLM 智能体的设置在这里类似,只是用RetrieveAssistantAgent类代替,这个类看起来非常类似于典型的 AssistantAgent 类。
对于 RetrieveUserProxyAgent,我们有一系列配置。从顶部开始,有一个"task"值,告诉智能体要做什么。它可以是指示智能体进行问答(“qa”)、编码(“code”)或默认值(“default”),其中"default"表示同时进行编码和问答。这些决定了给予智能体的提示。
在这里,大部分的检索配置都是用来传递给我们的 RAG。RAG 通常建立在通过向量嵌入的相似性搜索之上,因此这个配置让我们可以指定如何从源文档中创建向量嵌入。在上面的示例中,我们传递了创建这些嵌入的模型、我们将源文档拆分为每个嵌入的块大小以及选择的向量数据库。
在上面的示例中,有两点需要注意。首先,它假设你正在实时创建你的向量数据库。如果你想连接到一个已经实例化的向量数据库,AutoGen 可以处理这种情况,你只需传递你的客户端即可。其次,你应该注意,这个 API 最近已经更改,并且似乎仍在对其进行工作,所以当你本地运行时,配置可能略有不同,尽管高级概念可能仍然相同。
多智能体示例
最后,让我们看看如何使用 AutoGen 来拥有三个或更多的智能体。下面我们有"与编码者和可视化评论者进行群聊"的示例,其中包含三个智能体:一个编码者、一个评论者和一个用户代理。
就像网络一样,当我们添加更多的智能体时,连接的数量以二次方的速率增加。在上面的示例中,我们只有两个智能体,所以没有太多可以发送的消息。当有三个智能体时,我们需要帮助;我们需要一个管理者。
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
from IPython.display import Image
import autogen
config_list_gpt4 = autogen.config_list_from_json(
"OAI_CONFIG_LIST",
filter_dict={
"model": ["gpt-4", "gpt-4-0314", "gpt4", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-v0314"],
},
)
llm_config = {"config_list": config_list_gpt4, "cache_seed": 42}
user_proxy = autogen.UserProxyAgent(
name="User_proxy",
system_message="A human admin.",
code_execution_config={
"last_n_messages": 3,
"work_dir": "groupchat",
"use_docker": False,
}, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.
human_input_mode="NEVER",
)
coder = autogen.AssistantAgent(
name="Coder", # the default assistant agent is capable of solving problems with code
llm_config=llm_config,
)
critic = autogen.AssistantAgent(
name="Critic",
system_message="""Critic. You are a helpful assistant highly skilled in evaluating the quality of a given visualization code by providing a score from 1 (bad) - 10 (good) while providing clear rationale. YOU MUST CONSIDER VISUALIZATION BEST PRACTICES for each evaluation. Specifically, you can carefully evaluate the code across the following dimensions
- bugs (bugs): are there bugs, logic errors, syntax error or typos? Are there any reasons why the code may fail to compile? How should it be fixed? If ANY bug exists, the bug score MUST be less than 5.
- Data transformation (transformation): Is the data transformed appropriately for the visualization type? E.g., is the dataset appropriated filtered, aggregated, or grouped if needed? If a date field is used, is the date field first converted to a date object etc?
- Goal compliance (compliance): how well the code meets the specified visualization goals?
- Visualization type (type): CONSIDERING BEST PRACTICES, is the visualization type appropriate for the data and intent? Is there a visualization type that would be more effective in conveying insights? If a different visualization type is more appropriate, the score MUST BE LESS THAN 5.
- Data encoding (encoding): Is the data encoded appropriately for the visualization type?
- aesthetics (aesthetics): Are the aesthetics of the visualization appropriate for the visualization type and the data?
YOU MUST PROVIDE A SCORE for each of the above dimensions.
{bugs: 0, transformation: 0, compliance: 0, type: 0, encoding: 0, aesthetics: 0}
Do not suggest code.
Finally, based on the critique above, suggest a concrete list of actions that the coder should take to improve the code.
""",
llm_config=llm_config,
)
groupchat = autogen.GroupChat(agents=[user_proxy, coder, critic], messages=[], max_round=20)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)
user_proxy.initiate_chat(
manager,
message="download data from https://raw.githubusercontent.com/uwdata/draco/master/data/cars.csv and plot a visualization that tells us about the relationship between weight and horsepower. Save the plot to a file. Print the fields in a dataset before visualizing it.",
)
首先,类似于上面的示例,我们为用户创建一个智能体(UserProxyAgent),但这次我们创建了 2 个不同的 LLM 智能体——一个编码者和一个评论者。编码者没有收到特别的指示,但评论者收到了。评论者收到了编码者智能体的代码,并被要求按照某种范式对其进行评论。
在创建智能体之后,我们将这三个智能体传递给一个 GroupChat 对象。群聊是一个数据对象,它跟踪所发生的一切。它存储消息、帮助选择下一个智能体的提示以及涉及的智能体列表。
然后,GroupChatManager 就会接收到这个数据对象,作为帮助它做出决策的一种方式。你可以配置它以多种方式选择下一个说话者,包括轮流、随机,以及提供函数。默认情况下,它使用以下提示:"阅读上面的对话。然后从 {agentlist} 中选择下一个角色进行扮演。只返回角色。"当然,你可以根据自己的喜好进行调整。
一旦对话进行了最大轮数(循环对话)或接收到 "TERMINATE" 字符串,管理者就会结束群聊。这样,我们就可以协调多个智能体同时进行。
结论
随着 LLM 研究和开发继续创造令人难以置信的性能,似乎很可能会出现数据和性能的边缘情况,LLM 开发者可能根本不会将其构建到他们的模型中。因此,能够为这些模型提供所需工具、反馈和数据以创建持续高质量性能的系统将非常有价值。
从这个角度来看,AutoGen 是一个值得关注的有趣项目。它即实用又开源,让人一瞥人们是如何思考解决围绕智能体的一些技术挑战的。
现在是构建令人兴奋的时刻
[1] 吴强,等. “AutoGen:通过多智能体对话实现下一代 LLM 应用” (2023), arXiv
[2] 王晨,等. “autogen” (2024), GitHub
[3] 微软公司等. “与编码者和可视化评论家进行群聊” (2024), GitHub
[4] 微软公司等. “通过代码生成、执行和调试进行任务解决” (2024), GitHub
[5] 微软公司等. “使用 RetrieveChat 进行检索增强代码生成和问答” (2024), GitHub
9710

被折叠的 条评论
为什么被折叠?



