有限状态机(FSM)群聊允许用户约束代理的转换。
TL;DR
最近,FSM群聊功能发布,允许用户输入一个转换图来约束代理的转换。随着代理数量的增加,这非常有用,因为转换对的数量(N选2的组合)呈指数增长,增加了次优转换的风险,从而导致令牌的浪费和/或不良结果。
过渡图可能的使用场景
- 一次性工作流程,即我们希望每个代理只在问题上进行一次传递,代理 A -> B -> C。
- 决策树流程,就像一个决策树,我们从根节点(代理)开始,沿着决策树向下流动,代理作为节点。例如,如果查询是SQL查询,交给SQL代理,否则如果查询是RAG查询,交给RAG代理。
- 顺序团队操作。假设我们有一个由3个开发者代理组成的团队,每个代理负责一个不同的GitHub仓库。我们还有一个业务分析师团队,他们讨论并辩论用户的总体目标。我们可以让开发者团队的管理代理与业务分析团队的管理代理进行交流。这样,讨论会更加集中在团队层面,可以预期产生更好的结果。
请注意,我们并没有强制要求使用有向无环图;用户可以指定图为无环的,但是循环的工作流程也可能对迭代解决问题和在解决方案上添加额外的分析层非常有用。
使用指南
我们添加了两个参数allowed_or_disallowed_speaker_transitions
和speaker_transitions_type
。
allowed_or_disallowed_speaker_transitions
:是一个字典,类型期望为{Agent: [Agent]}
。键指的是源代理,而列表中的值指的是目标代理。如果未指定,则假定为完全连接图。speaker_transitions_type
: 是一个字符串类型的参数,具体取值为["allowed", "disallowed"]。我们希望用户能够提供一个允许或禁止的转换字典,以提高易用性。在代码库中,我们会将禁止的转换反转为一个允许的转换字典allowed_speaker_transitions_dict
。
有限状态机(FSM)特性的应用
一个快速演示,展示了如何在AutoGen
框架中启动基于有限状态机的GroupChat
。在这个演示中,如果我们将每个代理视为一个状态,并且每个代理根据某些条件发言。例如,User总是首先启动任务,紧接着Planner创建计划。然后Engineer和Executor交替工作,当必要时Critic介入,并且在Critic之后,只有Planner应该修订额外的计划。每个状态只能在一段时间内存在,并且状态之间存在转换条件。因此,GroupChat可以很好地抽象为有限状态机(FSM)。
用法
- 先决条件
pip install autogen[graph]
-
导入依赖项
from autogen.agentchat import GroupChat, AssistantAgent, UserProxyAgent, GroupChatManager
from autogen.oai.openai_utils import config_list_from_dotenv -
Configure LLM parameters
# Please feel free to change it as you wish
config_list = config_list_from_dotenv(
dotenv_file_path='.env',
model_api_key_map={'gpt-4-1106-preview':'OPENAI_API_KEY'},
filter_dict={
"model": {
"gpt-4-1106-preview"
}
}
)
gpt_config = {
"cache_seed": None,
"temperature": 0,
"config_list": config_list,
"timeout": 100,
} -
定义任务
# 描述任务
task = """Add 1 to the number output by the previous role. If the previous number is 20, output "TERMINATE".""" -
定义代理
# agents configuration
engineer = AssistantAgent(
name="Engineer",
llm_config=gpt_config,
system_message=task,
description="""I am **ONLY** allowed to speak **immediately** after `Planner`, `Critic` and `Executor`.
If the last number mentioned by `Critic` is not a multiple of 5, the next speaker must be `Engineer`.
"""
)
planner = AssistantAgent(
name="Planner",
system_message=task,
llm_config=gpt_config,
description="""I am **ONLY** allowed to speak **immediately** after `User` or `Critic`.
If the last number mentioned by `Critic` is a multiple of 5, the next speaker must be `Planner`.
"""
)
executor = AssistantAgent(
name="Executor",
system_message=task,
is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("FINISH"),
llm_config=gpt_config,
description="""I am **ONLY** allowed to speak **immediately** after `Engineer`.
If the last number mentioned by `Engineer` is a multiple of 3, the next speaker can only be `Executor`.
"""
)
critic = AssistantAgent(
name="Critic",
system_message=task,
llm_config=gpt_config,
description="""I am **ONLY** allowed to speak **immediately** after `Engineer`.
If the last number mentioned by `Engineer` is not a multiple of 3, the next speaker can only be `Critic`.
"""
)
user_proxy = UserProxyAgent(
name="User",
system_message=task,
code_execution_config=False,
human_input_mode="NEVER",
llm_config=False,
description="""
Never select me as a speaker.
"""
)- 在这里,我将
system_messages
配置为"task",因为每个代理都应该知道它需要做什么。在这个例子中,每个代理都有相同的任务,即按顺序计数。 - 最重要的一点是
description
参数,在这里我使用自然语言描述了FSM的转换条件。因为管理者根据图的约束知道接下来哪些代理是可用的,所以在每个候选代理的description
字段中,我描述了它何时可以说话,从而有效地描述了FSM中的转换条件。
- 在这里,我将
-
定义图表
graph_dict = {}
graph_dict[user_proxy] = [planner]
graph_dict[planner] = [engineer]
graph_dict[engineer] = [critic, executor]
graph_dict[critic] = [engineer, planner]
graph_dict[executor] = [engineer]- 这里的图和上面提到的转换条件共同构成了一个完整的FSM。两者都是必不可少的,不能缺失。
- 您可以根据自己的意愿进行可视化,如下所示
-
Define a
GroupChat
and aGroupChatManager
agents = [user_proxy, engineer, planner, executor, critic]
# create the groupchat
group_chat = GroupChat(agents=agents, messages=[], max_round=25, allowed_or_disallowed_speaker_transitions=graph_dict, allow_repeat_speaker=None, speaker_transitions_type="allowed")
# create the manager
manager = GroupChatManager(
groupchat=group_chat,
llm_config=gpt_config,
is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),
code_execution_config=False,
) -
启动聊天
# 启动任务
user_proxy.initiate_chat(
manager,
message="1",
clear_history=True
) -
You may get the following output(I deleted the ignorable warning):
1
--------------------------------------------------------------------------------
2
--------------------------------------------------------------------------------
3
--------------------------------------------------------------------------------
4
--------------------------------------------------------------------------------
5
--------------------------------------------------------------------------------
6
--------------------------------------------------------------------------------
7
--------------------------------------------------------------------------------
8
--------------------------------------------------------------------------------
9
--------------------------------------------------------------------------------
10
--------------------------------------------------------------------------------
11
--------------------------------------------------------------------------------
12
--------------------------------------------------------------------------------
13
--------------------------------------------------------------------------------
14
--------------------------------------------------------------------------------
15
--------------------------------------------------------------------------------
16
--------------------------------------------------------------------------------
17
--------------------------------------------------------------------------------
18
--------------------------------------------------------------------------------
19
--------------------------------------------------------------------------------
20
--------------------------------------------------------------------------------
TERMINATE
笔记本示例
更多的例子可以在notebook中找到。该笔记本包含了更多可能的转换路径示例,例如(1)中心辐射型,(2)顺序团队操作,以及(3)大声思考和辩论。它还使用了autogen.graph_utils
中的函数visualize_speaker_transitions_dict
来可视化各种图形。