本系列博文在掘金同步发布, 更多优质文章,请关注本人掘金账号:
人肉推土机的掘金账号
AutoGen系列一:基础介绍与入门教程
AutoGen系列二:深入自定义智能体
AutoGen系列三:内置智能体的应用与实战
AutoGen系列四:自定义智能体的高级技巧
AutoGen系列五: 智能体团队协作的深度剖析与实践
AutoGen 技术博客系列 (六):SelectorGroupChat 的原理与实践
AutoGen 技术博客系列 (七):状态管理与组件序列化解析
AutoGen 技术博客系列 八:深入剖析 Swarm—— 智能体协作的新范式
AutoGen 技术博客系列 九:从 v0.2 到 v0.4 的迁移指南
这是一份为 autogen-agentchat
v0.2.*
版本用户提供的迁移指南,旨在帮助用户升级到 v0.4
版本,该版本引入了一组新的 API 和功能。v0.4
版本包含重大变更,请仔细阅读本指南。我们仍在 0.2
分支中维护 v0.2
版本,但强烈建议您升级到 v0.4
版本。
注意: v0.4
不再拥有 pyautogen
PyPI 包的管理员权限,自 0.2.34 版本起,该包的发布不再来自微软。如需继续使用 v0.2
版本的 AutoGen,请使用 autogen-agentchat~=0.2
进行安装。请阅读我们关于分支的澄清声明。
什么是 v0.4?
自 2023 年 AutoGen 发布以来,我们积极倾听社区以及来自小型初创公司和大型企业用户的反馈,并基于这些反馈构建了 AutoGen v0.4
。这是一个从头开始重写的版本,采用异步、事件驱动架构,旨在解决可观测性、灵活性、交互控制和扩展性等问题。
v0.4
API 是分层的:核心 API 是基础层,提供了一个可扩展的、事件驱动的参与者框架,用于创建智能体工作流;AgentChat API 构建在核心 API 之上,提供了一个任务驱动的高级框架,用于构建交互式智能体应用程序,它是 AutoGen v0.2
的替代品。
本指南主要关注 v0.4
的 AgentChat API,但您也可以仅使用核心 API 构建自己的高级框架。
新用户:直接跳转到 AgentChat 教程开始使用 v0.4
。
本指南内容
我们提供了一份详细指南,说明如何将现有代码库从 v0.2
迁移到 v0.4
。有关如何迁移的详细信息,请参阅以下每个功能。
- 模型客户端
- 与 OpenAI 兼容的 API 的模型客户端
- 模型客户端缓存
- 助手智能体
- 多模态智能体
- 用户代理
- 可对话智能体和注册回复
- 保存和加载智能体状态
- 双智能体聊天
- 工具使用
- 聊天结果
- v0.2 和 v0.4 消息之间的转换
- 群聊
- 恢复群聊
- 保存和加载群聊状态
- 带工具使用的群聊
- 带自定义选择器(Stateflow)的群聊
- 嵌套聊天
- 顺序聊天
- GPTAssistantAgent
- 长上下文处理
- 可观测性和控制
- 代码执行器
以下 v0.2
中的功能将在未来的 v0.4.*
版本中提供:
- 模型客户端成本 #4835
- 可教学智能体
- RAG 智能体
当缺失的功能可用时,我们将更新本指南。
模型客户端
在 v0.2
中,您可以按如下方式配置模型客户端并创建 OpenAIWrapper
对象:
from autogen.oai import OpenAIWrapperconfig_list = [{"model": "gpt-4o", "api_key": "sk-xxx"},{"model": "gpt-4o-mini", "api_key": "sk-xxx"},
]
model_client = OpenAIWrapper(config_list=config_list)
注意:在 AutoGen 0.2 中,OpenAI 客户端会尝试列表中的配置,直到找到一个可用的。而 0.4 版本需要选择特定的模型配置。
在 v0.4
中,我们提供了两种创建模型客户端的方法。
使用组件配置
AutoGen 0.4 有一个通用的组件配置系统,模型客户端是其一个很好的应用场景。以下是创建 OpenAI 聊天完成客户端的示例:
from autogen_core.models import ChatCompletionClientconfig = {"provider": "OpenAIChatCompletionClient","config": {"model": "gpt-4o","api_key": "sk-xxx" # 也可以使用 os.environ["..."]}
}
model_client = ChatCompletionClient.load_component(config)
直接使用模型客户端类
- Open AI:
from autogen_ext.models.openai import OpenAIChatCompletionClient
model_client = OpenAIChatCompletionClient(model="gpt-4o", api_key="sk-xxx")
- Azure OpenAI:
from autogen_ext.models.openai import AzureOpenAIChatCompletionClient
model_client = AzureOpenAIChatCompletionClient(azure_deployment="gpt-4o",azure_endpoint="https://<your-endpoint>.openai.azure.com/",model="gpt-4o",api_version="2024-09-01-preview",api_key="sk-xxx",
)
与 OpenAI 兼容的 API 的模型客户端
您可以使用 OpenAIChatCompletionClient
连接到与 OpenAI 兼容的 API,但需要指定 base_url
和 model_info
:
from autogen_ext.models.openai import OpenAIChatCompletionClientcustom_model_client = OpenAIChatCompletionClient(model="custom-model-name",base_url="https://custom-model.com/reset/of/the/path",api_key="placeholder",model_info={"vision": True,"function_calling": True,"json_output": True,"family": "unknown",},
)
注意:我们并未测试所有与 OpenAI 兼容的 API,其中许多 API 与 OpenAI API 的工作方式不同,尽管它们可能声称支持 OpenAI API。在使用之前,请务必进行测试。
未来将添加对其他托管模型的支持。
模型客户端缓存
在 v0.2
中,您可以通过 LLM 配置中的 cache_seed
参数设置缓存种子,缓存默认启用。
llm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,"cache_seed": 42,
}
在 v0.4
中,缓存默认未启用,要使用缓存,需要在模型客户端周围使用 ChatCompletionCache
包装器。
您可以使用 DiskCacheStore
或 RedisStore
来存储缓存。
pip install -U "autogen-ext[openai, diskcache, redis]"
以下是使用 diskcache
进行本地缓存的示例:
import asyncio
import tempfile
from autogen_core.models import UserMessage
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.models.cache import ChatCompletionCache, CHAT_CACHE_VALUE_TYPE
from autogen_ext.cache_store.diskcache import DiskCacheStore
from diskcache import Cacheasync def main():with tempfile.TemporaryDirectory() as tmpdirname:# 初始化原始客户端openai_model_client = OpenAIChatCompletionClient(model="gpt-4o")# 然后初始化 CacheStore,这里使用 diskcache.Cache# 您也可以使用 redis,如下所示:# from autogen_ext.cache_store.redis import RedisStore# import redis# redis_instance = redis.Redis()# cache_store = RedisCacheStore[CHAT_CACHE_VALUE_TYPE](redis_instance)cache_store = DiskCacheStore[CHAT_CACHE_VALUE_TYPE](Cache(tmpdirname))cache_client = ChatCompletionCache(openai_model_client, cache_store)response = await cache_client.create([UserMessage(content="Hello, how are you?", source="user")])print(response) # 应打印来自 OpenAI 的响应response = await cache_client.create([UserMessage(content="Hello, how are you?", source="user")])print(response) # 应打印缓存的响应asyncio.run(main())
助手智能体
在 v0.2
中,您可以按如下方式创建助手智能体:
from autogen.agentchat import AssistantAgentllm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,
}
assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",llm_config=llm_config,
)
在 v0.4
中,创建方式类似,但需要指定 model_client
而不是 llm_config
:
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClientmodel_client = OpenAIChatCompletionClient(model="gpt-4o", api_key="sk-xxx", seed=42, temperature=0)
assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client,
)
然而,使用方式有所不同。在 v0.4
中,不再调用 assistant.send
,而是调用 assistant.on_messages
或 assistant.on_messages_stream
来处理传入消息。此外,on_messages
和 on_messages_stream
方法是异步的,后者返回一个异步生成器,用于流式传输智能体的内部思考过程。
以下是在 v0.4
中直接调用助手智能体的示例,延续上述代码:
import asyncio
from autogen_agentchat.messages import TextMessage
from autogen_agentchat.agents import AssistantAgent
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client,)cancellation_token = CancellationToken()response = await assistant.on_messages([TextMessage(content="Hello!", source="user")], cancellation_token)print(response)asyncio.run(main())
CancellationToken
可用于在调用 cancellation_token.cancel()
时异步取消请求,这将导致 on_messages
调用的 await
引发 CancelledError
。
多模态智能体
v0.4
中的 AssistantAgent
如果模型客户端支持,则支持多模态输入。模型客户端的 vision
能力用于确定智能体是否支持多模态输入。
import asyncio
from pathlib import Path
from autogen_agentchat.messages import MultiModalMessage
from autogen_agentchat.agents import AssistantAgent
from autogen_core import CancellationToken, Image
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client,)cancellation_token = CancellationToken()message = MultiModalMessage(content=["Here is an image:", Image.from_file(Path("test.png"))],source="user",)response = await assistant.on_messages([message], cancellation_token)print(response)asyncio.run(main())
用户代理
在 v0.2
中,您可以按如下方式创建用户代理:
from autogen.agentchat import UserProxyAgentuser_proxy = UserProxyAgent(name="user_proxy",human_input_mode="NEVER",max_consecutive_auto_reply=10,code_execution_config=False,llm_config=False,
)
此用户代理将通过控制台接收用户输入,如果传入消息以 “TERMINATE” 结尾,则会终止。
在 v0.4
中,用户代理只是一个仅接收用户输入的智能体,无需其他特殊配置。您可以按如下方式创建用户代理:
from autogen_agentchat.agents import UserProxyAgentuser_proxy = UserProxyAgent("user_proxy")
有关更多详细信息以及如何使用超时自定义输入函数,请参阅 UserProxyAgent
。
可对话智能体和注册回复
在 v0.2
中,您可以按如下方式创建可对话智能体并注册回复函数:
from typing import Any, Dict, List, Optional, Tuple, Union
from autogen.agentchat import ConversableAgentllm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,
}
conversable_agent = ConversableAgent(name="conversable_agent",system_message="You are a helpful assistant.",llm_config=llm_config,code_execution_config={"work_dir": "coding"},human_input_mode="NEVER",max_consecutive_auto_reply=10,
)def reply_func(recipient: ConversableAgent,messages: Optional[List[Dict]] = None,sender: Optional[Agent] = None,config: Optional[Any] = None,
) -> Tuple[bool, Union[str, Dict, None]]:# 自定义回复逻辑return True, "Custom reply"# 注册回复函数
conversable_agent.register_reply([ConversableAgent], reply_func, position=0)
# 注意:异步回复函数仅在使用异步发送时调用
在 v0.4
中,我们可以简单地创建一个自定义智能体,并实现 on_messages
、on_reset
和 produced_message_types
方法,而无需猜测 reply_func
的功能、其参数以及 position
的值。
from typing import Sequence
from autogen_core import CancellationToken
from autogen_agentchat.agents import BaseChatAgent
from autogen_agentchat.messages import TextMessage, ChatMessage
from autogen_agentchat.base import Responseclass CustomAgent(BaseChatAgent):async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken) -> Response:return Response(chat_message=TextMessage(content="Custom reply", source=self.name))async def on_reset(self, cancellation_token: CancellationToken) -> None:pass@propertydef produced_message_types(self) -> Sequence[type[ChatMessage]]:return (TextMessage,)
然后,您可以像使用 AssistantAgent
一样使用自定义智能体。有关更多详细信息,请参阅自定义智能体教程。
保存和加载智能体状态
在 v0.2
中,没有内置方法来保存和加载智能体的状态,您需要自己实现,通过导出 ConversableAgent
的 chat_messages
属性,并通过 chat_messages
参数重新导入。
在 v0.4
中,您可以在智能体上调用 save_state
和 load_state
方法来保存和加载其状态。
import asyncio
import json
from autogen_agentchat.messages import TextMessage
from autogen_agentchat.agents import AssistantAgent
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client,)cancellation_token = CancellationToken()response = await assistant.on_messages([TextMessage(content="Hello!", source="user")], cancellation_token)print(response)# 保存状态state = await assistant.save_state()# (可选)将状态写入磁盘with open("assistant_state.json", "w") as f:json.dump(state, f)# (可选)从磁盘加载状态with open("assistant_state.json", "r") as f:state = json.load(f)print(state) # 检查状态,其中包含聊天历史# 继续聊天response = await assistant.on_messages([TextMessage(content="Tell me a joke.", source="user")], cancellation_token)print(response)# 加载状态,使智能体恢复到最后一条消息之前的状态await assistant.load_state(state)# 再次进行相同的聊天response = await assistant.on_messages([TextMessage(content="Tell me a joke.", source="user")], cancellation_token)asyncio.run(main())
您也可以在任何团队(如 RoundRobinGroupChat
)上调用 save_state
和 load_state
来保存和加载整个团队的状态。
双智能体聊天
在 v0.2
中,您可以按如下方式创建用于代码执行的双智能体聊天:
from autogen.coding import LocalCommandLineCodeExecutor
from autogen.agentchat import AssistantAgent, UserProxyAgentllm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,
}assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant. Write all code in python. Reply only 'TERMINATE' if the task is done.",llm_config=llm_config,is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
)user_proxy = UserProxyAgent(name="user_proxy",human_input_mode="NEVER",max_consecutive_auto_reply=10,code_execution_config={"code_executor": LocalCommandLineCodeExecutor(work_dir="coding")},llm_config=False,is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
)chat_result = user_proxy.initiate_chat(assistant, message="Write a python script to print 'Hello, world!'")
# Intermediate messages are printed to the console directly.
print(chat_result)
在 v0.4
中,您可以按如下方式创建用于代码执行的双智能体聊天:
import asyncio
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination, MaxMessageTermination
from autogen_agentchat.ui import Console
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant. Write all code in python. Reply only 'TERMINATE' if the task is done.",model_client=model_client,)code_executor = CodeExecutorAgent(name="code_executor",code_executor=LocalCommandLineCodeExecutor(work_dir="coding"),)# The termination condition is a combination of text termination and max message termination, either of which will cause the chat to terminate.termination = TextMentionTermination("TERMINATE") | MaxMessageTermination(10)# The group chat will alternate between the assistant and the code executor.group_chat = RoundRobinGroupChat([assistant, code_executor], termination_condition=termination)# `run_stream` returns an async generator to stream the intermediate messages.stream = group_chat.run_stream(task="Write a python script to print 'Hello, world!'")# `Console` is a simple UI to display the stream.await Console(stream)asyncio.run(main())
工具使用
在 v0.2
中,要创建一个使用工具的聊天机器人,必须有两个智能体,一个用于调用工具,一个用于执行工具。对于每个用户请求,都需要发起一个双智能体聊天。
from autogen.agentchat import AssistantAgent, UserProxyAgent, register_functionllm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,
}tool_caller = AssistantAgent(name="tool_caller",system_message="You are a helpful assistant. You can call tools to help user.",llm_config=llm_config,max_consecutive_auto_reply=1, # 设置为 1,以便在每个助手回复后返回应用程序,因为我们正在构建一个聊天机器人
)tool_executor = UserProxyAgent(name="tool_executor",human_input_mode="NEVER",code_execution_config=False,llm_config=False,
)def get_weather(city: str) -> str:return f"The weather in {city} is 72 degree and sunny."# 将工具函数注册到工具调用者和执行者
register_function(get_weather, caller=tool_caller, executor=tool_executor)while True:user_input = input("User: ")if user_input == "exit":breakchat_result = tool_executor.initiate_chat(tool_caller,message=user_input,summary_method="reflection_with_llm", # 让模型反思工具使用,设置为 "last_msg" 可直接返回工具调用结果)print("Assistant:", chat_result.summary)
在 v0.4
中,实际上只需要一个智能体 ——AssistantAgent
—— 来处理工具调用和工具执行。
import asynciofrom autogen_core import CancellationTokenfrom autogen_ext.models.openai import OpenAIChatCompletionClientfrom autogen_agentchat.agents import AssistantAgentfrom autogen_agentchat.messages import TextMessagedef get_weather(city: str) -> str: # 也可以是异步工具return f"The weather in {city} is 72 degree and sunny."async def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant. You can call tools to help user.",model_client=model_client,tools=[get_weather],reflect_on_tool_use=True, # 设置为 True 让模型反思工具使用,设置为 False 可直接返回工具调用结果)while True:user_input = input("User: ")if user_input == "exit":breakresponse = await assistant.on_messages([TextMessage(content=user_input, source="user")], CancellationToken())print("Assistant:", response.chat_message.content)asyncio.run(main())
在诸如 RoundRobinGroupChat
这样的群聊中使用配备工具的智能体时,只需像上面那样将工具添加到智能体中,并创建一个包含这些智能体的群聊即可。
聊天结果
在 v0.2
中,您可以从 initiate_chat
方法获取一个 ChatResult
对象。例如:
chat_result = tool_executor.initiate_chat(tool_caller,message=user_input,summary_method="reflection_with_llm",
)print(chat_result.summary) # 获取聊天的 LLM 反思总结
print(chat_result.chat_history) # 获取聊天历史
print(chat_result.cost) # 获取聊天成本
print(chat_result.human_input) # 获取聊天请求的人工输入
有关更多详细信息,请参阅 ChatResult
文档。
在 v0.4
中,您可以从 run
或 run_stream
方法获取一个 TaskResult
对象。TaskResult
对象包含 messages
,它是聊天的消息历史,包括智能体的私有(工具调用等)和公共消息。
TaskResult
和 ChatResult
之间有一些显著差异:
TaskResult
中的messages
列表使用与ChatResult.chat_history
列表不同的消息格式。- 没有
summary
字段。应用程序需要决定如何使用messages
列表总结聊天。 TaskResult
对象中不提供human_input
,因为可以通过使用source
字段过滤从messages
列表中提取用户输入。TaskResult
对象中不提供cost
,但是您可以根据令牌使用情况计算成本。添加成本计算将是一个很好的社区扩展。有关社区扩展,请参阅。
v0.2 和 v0.4 消息之间的转换
您可以使用以下转换函数在 autogen_agentchat.base.TaskResult.messages
中的 v0.4
消息和 ChatResult.chat_history
中的 v0.2
消息之间进行转换。
from typing import Any, Dict, List, Literalfrom autogen_agentchat.messages import (AgentEvent,ChatMessage,HandoffMessage,MultiModalMessage,StopMessage,TextMessage,ToolCallExecutionEvent,ToolCallRequestEvent,ToolCallSummaryMessage,
)from autogen_core import FunctionCall, Imagefrom autogen_core.models import FunctionExecutionResultdef convert_to_v02_message(message: AgentEvent | ChatMessage,role: Literal["assistant", "user", "tool"],image_detail: Literal["auto", "high", "low"] = "auto",
) -> Dict[str, Any]:"""将 v0.4 AgentChat 消息转换为 v0.2 消息。Args:message (AgentEvent | ChatMessage): 要转换的消息。role (Literal["assistant", "user", "tool"]): 消息的角色。image_detail (Literal["auto", "high", "low"], 可选): 多模态消息中图像内容的详细级别。默认为 "auto"。Returns:Dict[str, Any]: 转换后的 AutoGen v0.2 消息。"""v02_message: Dict[str, Any] = {}if isinstance(message, TextMessage | StopMessage | HandoffMessage | ToolCallSummaryMessage):v02_message = {"content": message.content, "role": role, "name": message.source}elif isinstance(message, MultiModalMessage):v02_message = {"content": [], "role": role, "name": message.source}for modal in message.content:if isinstance(modal, str):v02_message["content"].append({"type": "text", "text": modal})elif isinstance(modal, Image):v02_message["content"].append(modal.to_openai_format(detail=image_detail))else:raise ValueError(f"无效的多模态消息内容: {modal}")elif isinstance(message, ToolCallRequestEvent):v02_message = {"tool_calls": [], "role": "assistant", "content": None, "name": message.source}for tool_call in message.content:v02_message["tool_calls"].append({"id": tool_call.id,"type": "function","function": {"name": tool_call.name, "args": tool_call.arguments},})elif isinstance(message, ToolCallExecutionEvent):tool_responses: List[Dict[str, str]] = []for tool_result in message.content:tool_responses.append({"tool_call_id": tool_result.call_id,"role": "tool","content": tool_result.content,})content = "\n\n".join([response["content"] for response in tool_responses])v02_message = {"tool_responses": tool_responses, "role": "tool", "content": content}else:raise ValueError(f"无效的消息类型: {type(message)}")return v02_messagedef convert_to_v04_message(message: Dict[str, Any]) -> AgentEvent | ChatMessage:"""将 v0.2 消息转换为 v0.4 AgentChat 消息。"""if "tool_calls" in message:tool_calls: List[FunctionCall] = []for tool_call in message["tool_calls"]:tool_calls.append(FunctionCall(id=tool_call["id"],name=tool_call["function"]["name"],arguments=tool_call["function"]["args"],))return ToolCallRequestEvent(source=message["name"], content=tool_calls)elif "tool_responses" in message:tool_results: List[FunctionExecutionResult] = []for tool_response in message["tool_responses"]:tool_results.append(FunctionExecutionResult(call_id=tool_response["tool_call_id"],content=tool_response["content"],))return ToolCallExecutionEvent(source="tools", content=tool_results)elif isinstance(message["content"], list):content: List[str | Image] = []for modal in message["content"]: # type: ignoreif modal["type"] == "text": # type: ignorecontent.append(modal["text"]) # type: ignoreelse:content.append(Image.from_uri(modal["image_url"]["url"])) # type: ignorereturn MultiModalMessage(content=content, source=message["name"])elif isinstance(message["content"], str):return TextMessage(content=message["content"], source=message["name"])else:raise ValueError(f"无法转换消息: {message}")
群聊
在 v0.2
中,您需要创建一个 GroupChat
类并将其传递给 GroupChatManager
,并且需要有一个用户代理作为参与者来发起聊天。对于一个简单的作家和评论家场景,您可以如下操作:
from autogen.agentchat import AssistantAgent, GroupChat, GroupChatManagerllm_config = {"config_list": [{"model": "gpt-4o", "api_key": "sk-xxx"}],"seed": 42,"temperature": 0,
}writer = AssistantAgent(name="writer",description="A writer.",system_message="You are a writer.",llm_config=llm_config,is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("APPROVE"),
)critic = AssistantAgent(name="critic",description="A critic.",system_message="You are a critic, provide feedback on the writing. Reply only 'APPROVE' if the task is done.",llm_config=llm_config,
)# 创建一个包含作家和评论家的群聊
groupchat = GroupChat(agents=[writer, critic], messages=[], max_round=12)# 创建一个群聊管理器来管理群聊,使用轮询选择方法
manager = GroupChatManager(groupchat=groupchat, llm_config=llm_config, speaker_selection_method="round_robin")# 与编辑者发起聊天,中间消息将直接打印到控制台
result = editor.initiate_chat(manager,message="Write a short story about a robot that discovers it has feelings.",
)print(result.summary)
在 v0.4
中,您可以使用 RoundRobinGroupChat
来实现相同的行为。
import asynciofrom autogen_agentchat.agents import AssistantAgentfrom autogen_agentchat.teams import RoundRobinGroupChatfrom autogen_agentchat.conditions import TextMentionTerminationfrom autogen_agentchat.ui import Consolefrom autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)writer = AssistantAgent(name="writer",description="A writer.",system_message="You are a writer.",model_client=model_client,)critic = AssistantAgent(name="critic",description="A critic.",system_message="You are a critic, provide feedback on the writing. Reply only 'APPROVE' if the task is done.",model_client=model_client,)# 终止条件是文本终止,当收到 "APPROVE" 文本时聊天将终止termination = TextMentionTermination("APPROVE")# 群聊将在作家和评论家之间交替group_chat = RoundRobinGroupChat([writer, critic], termination_condition=termination, max_turns=12)# `run_stream` 返回一个异步生成器来流式传输中间消息stream = group_chat.run_stream(task="Write a short story about a robot that discovers it has feelings.")# `Console` 是一个简单的 UI 来显示流await Console(stream)asyncio.run(main())
对于基于 LLM 的发言者选择,您可以使用 SelectorGroupChat
代替。有关更多详细信息,请参阅 Selector Group Chat
教程和 SelectorGroupChat
。
注意:在 v0.4
中,在群聊中使用工具时不需要在用户代理上注册函数。您可以像在工具使用部分所示的那样将工具函数传递给 AssistantAgent
。智能体将在需要时自动调用工具。如果您的工具输出格式不正确,您可以使用 reflect_on_tool_use
参数让模型反思工具使用。
恢复群聊
在 v0.2
中,恢复群聊有点复杂。您需要显式地保存群聊消息,并在想要恢复聊天时重新加载它们。有关更多详细信息,请参阅 v0.2
中的恢复群聊。
在 v0.4
中,您可以简单地再次使用相同的群聊对象调用 run
或 run_stream
来恢复聊天。要导出和加载状态,您可以使用 save_state
和 load_state
方法。
import asyncio
import jsonfrom autogen_agentchat.agents import AssistantAgentfrom autogen_agentchat.teams import RoundRobinGroupChatfrom autogen_agentchat.conditions import TextMentionTerminationfrom autogen_agentchat.ui import Consolefrom autogen_ext.models.openai import OpenAIChatCompletionClientdef create_team() -> RoundRobinGroupChat:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)writer = AssistantAgent(name="writer",description="A writer.",system_message="You are a writer.",model_client=model_client,)critic = AssistantAgent(name="critic",description="A critic.",system_message="You are a critic, provide feedback on the writing. Reply only 'APPROVE' if the task is done.",model_client=model_client,)# 终止条件是文本终止,当收到 "APPROVE" 文本时聊天将终止termination = TextMentionTermination("APPROVE")# 群聊将在作家和评论家之间交替group_chat = RoundRobinGroupChat([writer, critic], termination_condition=termination)return group_chatasync def main() -> None:# 创建团队group_chat = create_team()# `run_stream` 返回一个异步生成器来流式传输中间消息stream = group_chat.run_stream(task="Write a short story about a robot that discovers it has feelings.")# `Console` 是一个简单的 UI 来显示流await Console(stream)# 保存群聊和所有参与者的状态state = await group_chat.save_state()with open("group_chat_state.json", "w") as f:json.dump(state, f)# 创建一个具有相同参与者配置的新团队group_chat = create_team()# 加载群聊和所有参与者的状态with open("group_chat_state.json", "r") as f:state = json.load(f)await group_chat.load_state(state)# 恢复聊天stream = group_chat.run_stream(task="Translate the story into Chinese.")await Console(stream)asyncio.run(main())
带工具使用的群聊
在 v0.2
的群聊中,若要使用工具,需在用户代理上注册工具函数,并将用户代理纳入群聊。如此,其他智能体发出的工具调用会被路由至用户代理执行。但我们发现这种方式存在诸多问题,比如工具调用路由可能无法按预期工作,且不支持函数调用的模型无法接收工具调用请求与结果。
在 v0.4
中,无需在用户代理上注册工具函数。因为在 v0.4
里,智能体能够直接调用工具,只要在创建 AssistantAgent
时将工具函数作为参数传入即可。例如,在群聊场景下,若有多个智能体,每个智能体都可按如下方式配置工具:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClientdef get_weather(city: str) -> str:return f"The weather in {city} is 72 degree and sunny."async def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)agent1 = AssistantAgent(name="agent1",system_message="You can use the get_weather tool to answer user questions.",model_client=model_client,tools=[get_weather])agent2 = AssistantAgent(name="agent2",system_message="You are another agent in the group chat.",model_client=model_client)termination = TextMentionTermination("END")group_chat = RoundRobinGroupChat([agent1, agent2], termination_condition=termination)stream = group_chat.run_stream(task="Ask about the weather in New York")await Console(stream)asyncio.run(main())
在上述示例中,agent1
被配置为可使用 get_weather
工具。当群聊运行时,若 agent1
认为需要,便会调用该工具。
带自定义选择器(Stateflow)的群聊
在 v0.2
中,没有直接支持带自定义选择器(如 Stateflow)的群聊功能。
在 v0.4
中,SelectorGroupChat
类提供了基于自定义逻辑选择发言者的功能。通过自定义选择器函数,可以实现类似 Stateflow 的复杂状态流转逻辑。例如,根据消息内容、智能体状态等因素决定下一个发言的智能体。以下是一个简单示例:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import SelectorGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClientdef custom_selector(team, messages):# 简单示例:总是选择第一个智能体发言return team.agents[0]async def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)agent1 = AssistantAgent(name="agent1",system_message="Agent 1 in the group.",model_client=model_client)agent2 = AssistantAgent(name="agent2",system_message="Agent 2 in the group.",model_client=model_client)termination = TextMentionTermination("END")group_chat = SelectorGroupChat([agent1, agent2], termination_condition=termination, selector=custom_selector)stream = group_chat.run_stream(task="Start the group chat")await Console(stream)asyncio.run(main())
在这个示例中,custom_selector
函数简单地选择第一个智能体发言。实际应用中,可以根据更复杂的逻辑来选择发言者,实现类似 Stateflow 的功能。
嵌套聊天
在 v0.2
中,实现嵌套聊天较为复杂,需要手动管理不同智能体之间的交互以及消息传递,并且难以跟踪和管理嵌套层次。
在 v0.4
中,由于其事件驱动和分层的架构,嵌套聊天变得更加直观和易于管理。例如,可以在一个群聊中,让某个智能体发起一个子聊天,而无需复杂的手动管理。以下是一个简单的概念示例:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)parent_agent1 = AssistantAgent(name="parent_agent1",system_message="Parent agent 1.",model_client=model_client)parent_agent2 = AssistantAgent(name="parent_agent2",system_message="Parent agent 2.",model_client=model_client)child_agent1 = AssistantAgent(name="child_agent1",system_message="Child agent 1 for nested chat.",model_client=model_client)child_agent2 = AssistantAgent(name="child_agent2",system_message="Child agent 2 for nested chat.",model_client=model_client)child_termination = TextMentionTermination("CHILD_END")child_group_chat = RoundRobinGroupChat([child_agent1, child_agent2], termination_condition=child_termination)def nested_chat_handler(parent_messages):async def run_nested_chat():task = "Some task for nested chat based on parent messages"stream = child_group_chat.run_stream(task)async for message in stream:# 可以在这里处理子聊天的消息,例如发送回父聊天passasyncio.create_task(run_nested_chat())parent_agent1.register_event_handler("on_message", nested_chat_handler)parent_termination = TextMentionTermination("PARENT_END")parent_group_chat = RoundRobinGroupChat([parent_agent1, parent_agent2], termination_condition=parent_termination)stream = parent_group_chat.run_stream(task="Start the parent chat")await Console(stream)asyncio.run(main())
在上述示例中,parent_agent1
注册了一个事件处理程序,当收到消息时,会发起一个子群聊 child_group_chat
。
顺序聊天
在 v0.2
中,实现顺序聊天需要手动控制智能体之间的消息传递顺序,并且难以动态调整顺序。
在 v0.4
中,可以通过自定义团队类或者利用现有的团队类(如 RoundRobinGroupChat
并结合自定义逻辑)来实现顺序聊天。例如,创建一个新的团队类,按照预定义的顺序依次让智能体发言:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import BaseGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClientclass SequentialChatGroup(BaseGroupChat):def __init__(self, agents, termination_condition):super().__init__(agents, termination_condition)self.current_agent_index = 0async def _select_next_speaker(self, messages):speaker = self.agents[self.current_agent_index]self.current_agent_index = (self.current_agent_index + 1) % len(self.agents)return speakerasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)agent1 = AssistantAgent(name="agent1",system_message="First agent in sequential chat.",model_client=model_client)agent2 = AssistantAgent(name="agent2",system_message="Second agent in sequential chat.",model_client=model_client)termination = TextMentionTermination("END")sequential_group_chat = SequentialChatGroup([agent1, agent2], termination_condition=termination)stream = sequential_group_chat.run_stream(task="Start sequential chat")await Console(stream)asyncio.run(main())
在上述示例中,SequentialChatGroup
类继承自 BaseGroupChat
,并自定义了 _select_next_speaker
方法,按照顺序选择智能体发言。
GPTAssistantAgent
在 v0.2
中,没有专门的 GPTAssistantAgent
类。
在 v0.4
中,GPTAssistantAgent
是 AssistantAgent
的一个变体,专门用于与 OpenAI 的 GPT Assistant API 进行交互。使用 GPTAssistantAgent
时,需要提供 assistant_id
,它代表在 OpenAI 平台上创建的特定助手。例如:
import asyncio
from autogen_agentchat.agents import GPTAssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", api_key="sk-xxx")assistant = GPTAssistantAgent(name="gpt_assistant",assistant_id="your_assistant_id",model_client=model_client)cancellation_token = CancellationToken()response = await assistant.on_messages([TextMessage(content="Hello!", source="user")], cancellation_token)print(response)asyncio.run(main())
GPTAssistantAgent
允许用户利用在 OpenAI 平台上预先配置好的助手功能,例如自定义工具、知识库等。
长上下文处理
在 v0.2
中,长上下文处理较为困难,因为没有内置的机制来有效管理和总结长对话历史。用户需要手动处理上下文,例如截断消息历史或者使用外部工具进行总结。
在 v0.4
中,通过引入智能体状态管理和更灵活的消息处理机制,长上下文处理得到了显著改善。例如,AssistantAgent
类提供了 summary
方法,可以在需要时对对话历史进行总结。此外,v0.4
的架构允许更方便地集成外部总结工具或者自定义总结逻辑。以下是一个简单示例,展示如何在对话过程中进行总结:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClientasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client)cancellation_token = CancellationToken()messages = [TextMessage(content="First message", source="user"),TextMessage(content="Second message", source="user")]for message in messages:response = await assistant.on_messages([message], cancellation_token)summary = await assistant.summary()print("Summary:", summary)asyncio.run(main())
在这个示例中,随着对话消息的积累,调用 assistant.summary()
方法可以获取对话的总结,有助于管理长上下文。
可观测性和控制
在 v0.2
中,可观测性和控制能力有限。例如,很难实时监控智能体之间的交互,并且对智能体行为的控制大多依赖于手动配置参数。
在 v0.4
中,由于其事件驱动的架构,提供了更好的可观测性和控制能力。可以通过注册事件处理程序来监控智能体的各种事件,如消息接收、发送、工具调用等。例如,以下代码展示如何监控智能体发送消息的事件:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClientdef message_sent_handler(event):print(f"Message sent: {event.chat_message.content}")async def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)assistant = AssistantAgent(name="assistant",system_message="You are a helpful assistant.",model_client=model_client)assistant.register_event_handler("on_message_sent", message_sent_handler)cancellation_token = CancellationToken()response = await assistant.on_messages([TextMessage(content="Hello!", source="user")], cancellation_token)asyncio.run(main())
此外,通过 CancellationToken
可以在运行时取消智能体的操作,实现对智能体行为的动态控制。
代码执行器
在 v0.2
中,代码执行器主要通过 CodeExecutor
类及其子类(如 LocalCodeExecutor
和 RemoteCodeExecutor
)实现。例如,使用 LocalCommandLineCodeExecutor
来在本地执行代码:
from autogen.coding import LocalCommandLineCodeExecutorcode_executor = LocalCommandLineCodeExecutor()
result = code_executor.run("print('Hello, World!')")
print(result)
在 v0.4
中,代码执行器的功能得到了进一步整合和改进。CodeExecutor
类得到了增强,并且可以更方便地与智能体集成。例如,在 AssistantAgent
中,可以直接配置代码执行器,使得智能体在需要时能够执行代码。以下是一个示例:
import asyncio
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_core import CancellationToken
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_agentchat.code_execution import LocalCodeExecutorasync def main() -> None:model_client = OpenAIChatCompletionClient(model="gpt-4o", seed=42, temperature=0)code_executor = LocalCodeExecutor()assistant = AssistantAgent(name="assistant",system_message="You can execute code when needed.",model_client=model_client,code_executor=code_executor)cancellation_token = CancellationToken()response = await assistant.on_messages([TextMessage(content="Execute print('Hello, World!')", source="user")], cancellation_token)print(response)asyncio.run(main())
在这个示例中,AssistantAgent
配置了 LocalCodeExecutor
,当收到需要执行代码的消息时,智能体可以调用代码执行器来执行代码。