返回

AutoGen消息转发:register_reply用法详解及多Agent协作方案

Ai

AutoGen 中如何将消息转发给另一个 Agent? (register_reply 的使用)

在开发多智能体系统时,常常需要一个智能体将对话转发给另一个智能体。像你遇到的情况:需要项目经理先制定计划,然后用户审核,审核通过后再把消息转发给一组其他智能体。你尝试使用 register_reply,但似乎没起作用。别担心,咱来一起捋一捋。

问题根源:对 register_reply 的误解

从你的代码和看, 你对register_reply的功能和用法可能有些偏差. register_reply 确实用于注册一个回复函数,但其主要目的是允许一个 agent 基于 其他 agent 的回复, 或环境(如工具函数的调用等),触发 自身 的回复逻辑 ,而不是直接将消息“转发”到另一个 agent. 在你这儿 project_manager.register_reply(user_proxy,add_data_reply) 会把user_proxy 的答复传给 project_manager触发 add_data_reply , 然而并不会执行 comedian.generate_reply. comedian.generate_reply需要的 messages也并不是原先你想的.

咱们需要更灵活的方式来控制对话流程,实现“转发”的效果。

解决方案:多种姿势搞定消息转发

下面,我将提供几种可行的方案,帮你解决这个问题。各有优缺点,你可以根据自己的实际需求选择。

方案一:直接调用,简单粗暴

最简单的方法是在用户审核通过后,直接调用目标 agent 的 sendreceive 方法。

原理:

  • 在用户代理 (UserProxyAgent) 确认计划后, 不使用register_reply, 直接让它主动给执行 agent 发送消息
  • 触发 comedian Agent, 使用 initiate_chat or send & receive.

代码示例:

import autogen

config_list = autogen.config_list_from_json(
    "OAI_CONFIG_LIST",
    filter_dict={
        "model": ["gpt-4"],
    },
)

llm_config = {
    "config_list": config_list,
    "cache_seed": 42,
    "request_timeout":600
}

project_manager = autogen.AssistantAgent(
    name="project_manager",
    system_message="""You are responsible for coming up with a plan to estimate the cost.""",
    llm_config=llm_config,
)

comedian = autogen.AssistantAgent(
    name= "comedian",
    system_message="""Your job is to make a joke about the plan shared.
    """,
    llm_config=llm_config,)

user_proxy = autogen.UserProxyAgent(
   name="User_proxy",
   system_message="A human admin.",
   code_execution_config={"last_n_messages": 2, "work_dir": "groupchat"},
   human_input_mode="ALWAYS"
)

# 第一次对话:项目经理制定计划并等待用户确认
user_proxy.initiate_chat(
    project_manager,
    message="""I would like you to comeup with a plan to build a model rocket""",
)

# 获取用户对计划的反馈。 假设这是来自用户界面或某种输入机制
user_feedback = input("Do you approve the plan? (yes/no): ")

if user_feedback.lower() == 'yes':
    # 获取 project_manager 的最后一条消息(即计划)
    plan_message = project_manager.last_message()["content"]
     # 将计划作为消息发送给 comedian, 可以开始新的对话,或这把消息转发给另一个group
    user_proxy.send(
        recipient=comedian,
        message=plan_message
        )

    user_proxy.receive(
        sender=comedian,
    )

说明:

  1. user_proxy.initiate_chat 启动与 project_manager 的对话,制定计划。
  2. 通过 input() 模拟用户审核 (实际应用中, 可能是前端界面的操作)。
  3. 如果用户批准,通过 project_manager.last_message() 获取计划内容。
  4. user_proxy.senduser_proxy.receive 用于实现 user_proxycomedian 交流.
  5. 可以进一步拓展, 把comedian 换成group chat manager, 开始群聊.

方案二:使用 GroupChat,灵活可控

如果后续涉及多个智能体的交互,使用 GroupChat 会更方便管理。

原理:

  1. 创建一个包含 project_managercomedian 和其他需要参与的智能体的 GroupChat
  2. project_manager先跟user_proxy制定计划, 计划获得批准后。
  3. 创建一个新的 GroupChat 对象,用于启动新的讨论. 将原先对话加入新的GroupChat。

代码示例:

import autogen

config_list = autogen.config_list_from_json(
    "OAI_CONFIG_LIST",
    filter_dict={
        "model": ["gpt-4"],
    },
)

llm_config = {
    "config_list": config_list,
    "cache_seed": 42,
    "request_timeout":600
}

project_manager = autogen.AssistantAgent(
    name="project_manager",
    system_message="""You are responsible for coming up with a plan to estimate the cost.""",
    llm_config=llm_config,
)

comedian = autogen.AssistantAgent(
    name= "comedian",
    system_message="""Your job is to make a joke about the plan shared.
    """,
    llm_config=llm_config,)
    
engineer = autogen.AssistantAgent(
    name="engineer",
    system_message="""Your job is to review the plan, and provide constructive feedback.
    """,
    llm_config=llm_config,
)

user_proxy = autogen.UserProxyAgent(
   name="User_proxy",
   system_message="A human admin.",
   code_execution_config={"last_n_messages": 2, "work_dir": "groupchat"},
   human_input_mode="ALWAYS"
)
# 第一次对话:项目经理制定计划并等待用户确认
user_proxy.initiate_chat(
    project_manager,
    message="""I would like you to comeup with a plan to build a model rocket""",
)

# 获取用户对计划的反馈。 假设这是来自用户界面或某种输入机制
user_feedback = input("Do you approve the plan? (yes/no): ")

if user_feedback.lower() == 'yes':

    # 获取 project_manager 的最后一条消息(即计划)
    plan_message = project_manager.last_message()

    groupchat = autogen.GroupChat(agents=[user_proxy, comedian, engineer], messages=[], max_round=12)
    manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)

    user_proxy.send(
        recipient=manager,
        message=plan_message["content"] #把上一个对话的内容总结发给下一个groupchat
        )


说明:

  1. 前期准备工作与方案一致。
  2. 当计划审核通过后,用新的agents创建GroupChat
  3. 注意: 使用 plan_message["content"], 或者更好的做法是,在project_manager完成计划时就要求其总结内容, 并把内容发送到下一个GroupChat

方案三:自定义 register_reply,精细控制(进阶)

如果你坚持使用 register_reply,想实现更复杂的逻辑(例如,根据用户反馈的不同,转发给不同的 agent),可以这样改进。

原理:

  • 定义一个更通用、灵活的回复函数。
  • 在这个函数里,根据具体情况(如用户输入、消息内容等)决定下一步操作。
  • 不依赖sender做消息转发。

代码示例:

import autogen

config_list = autogen.config_list_from_json(
    "OAI_CONFIG_LIST",
    filter_dict={
        "model": ["gpt-4"],
    },
)

llm_config = {
    "config_list": config_list,
    "cache_seed": 42,
    "request_timeout":600
}

project_manager = autogen.AssistantAgent(
    name="project_manager",
    system_message="""You are responsible for coming up with a plan to estimate the cost.""",
    llm_config=llm_config,
)

comedian = autogen.AssistantAgent(
    name= "comedian",
    system_message="""Your job is to make a joke about the plan shared.
    """,
    llm_config=llm_config,)

user_proxy = autogen.UserProxyAgent(
   name="User_proxy",
   system_message="A human admin.",
   code_execution_config={"last_n_messages": 2, "work_dir": "groupchat"},
   human_input_mode="ALWAYS",
)

async def custom_reply(
    recipient,
    messages,
    sender,
    config,
):

    if messages is None or len(messages) == 0:
        return False, None

    last_message = messages[-1]
    if "APPROVED" in last_message["content"].upper():

        plan = [msg for msg in reversed(messages) if msg["role"] == "assistant"][0]["content"]

        user_proxy.send(recipient=comedian, message=plan)

        return True, None #stop on this turn

    return False, None

# 让 user_proxy 触发事件
user_proxy.register_reply(
    trigger=autogen.Agent, #监听任何agent
    reply_func=custom_reply,
    config=None,
)

# 启动与 project_manager 的对话
user_proxy.initiate_chat(
    project_manager,
    message="""I would like you to comeup with a plan to build a model rocket""",
)

# 模拟用户批准
user_proxy.send(project_manager, "APPROVED")
user_proxy.receive(comedian) #user_proxy 会先触发 register_reply 的function.

说明:

  1. custom_reply 接收参数的意义和之前的不同. messages 指的是触发agent之前的对话, 包括触发Agent所发出的.
  2. 内部逻辑:判断 messages, 如果有 “APPROVED”,则提取之前的计划, 再转发消息给 comedian
  3. 使用 user_proxy.register_reply 将其注册到 user_proxy 上, 触发任何 Agent都可以 (包括project_manager).
  4. user_proxy.send(project_manager, "APPROVED") 模拟用户的批准操作(实际中应根据实际用户输入来决定)。
  5. 通过返回 (True, None) 终止默认的循环.
    这种写法避免了直接转发, 更清晰.

总结和建议

选择哪种方案取决于你的具体需求:

  • 如果只是简单的转发,方案一最直接。
  • 如果后续交互复杂,方案二更易于管理。
  • 如果需要根据用户反馈做更精细的控制,方案三更灵活, 但是有一定上手难度。

记住,register_reply 的核心是基于其他人的回复触发自身的逻辑 ,而不是直接的消息转发。掌握了这一点,你就能更好地运用 AutoGen 构建复杂的多智能体系统了!