允许人类对代理进行反馈
在前两章中,我们介绍了 ConversableAgent
类,并展示了如何使用它创建可以完成任务的自主(human_input_mode=NEVER
)代理。我们还展示了如何正确终止代 理之间的对话。
但是,许多应用程序可能需要将人类与代理放在一个循环中。例如,允许人类反馈来引导代理朝正确的方向发展、指定目标等。在本章中,我们将展示 AutoGen 如何支持人类干预。
在 AutoGen 的 ConversableAgent
中,人类循环组件位于自动回复组件之前。它可以拦截传入的消息,并决定是将其传递给自动回复组件还是提供人类反馈。下图展示了该设计。
人类循环组件可以通过 human_input_mode
参数进行自定义。我们将在下面的章节中向您展示如何使用它。
人类输入模式
目前,AutoGen 支持三种人类输入模式。模式是通过 ConversableAgent
的 human_input_mode
参数指定的。这三种模式分别是:
NEVER
:从不请求人类输入。TERMINATE
(默认):仅在满足终止条件时请求人类输入。请注意,在此模式下,如果人类选择拦截并回复,对话将继续进行,并且max_consecutive_auto_reply
使用的计数器将被重置。ALWAYS
:始终请求人类输入,人类可以选择跳过并触发自动回复,拦截并提供反馈,或终止对话。请注意,在此模式下,基于max_consecutive_auto_reply
的终止将被忽略。
前面的章节已经展示了许多 human_input_mode
为 NEVER
的情况的示例。下面我们再次展示一个这种情况的示例,并展示当将此 模式设置为 ALWAYS
和 NEVER
时的区别。
人类输入模式 = NEVER
在此模式下,从不请求人类输入,并使用终止条件来终止对话。当您希望代理完全自主地行动时,此模式非常有用。
以下是使用此模式运行简单的猜数字游戏的示例,其中两个代理参与,终止消息设置为检查是否猜对了数字。
import os
from autogen import ConversableAgent
# 创建一个名为 agent_with_number 的 ConversableAgent 对象
agent_with_number = ConversableAgent(
"agent_with_number",
system_message="你正在玩一个猜数字的游戏。你心里想的数字是53,我会尝试猜出来。如果我猜得太高,请说'太高';如果我猜得太低,请说'太低'。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
is_termination_msg=lambda msg: "53" in msg["content"], # 如果对方猜中了数字,终止对话
human_input_mode="NEVER", # 不需要人类输入
)
# 创建一个名为 agent_guess_number 的 ConversableAgent 对象
agent_guess_number = ConversableAgent(
"agent_guess_number",
system_message="我心里有一个数字,你要猜出来。如果我说'太高',你应该猜一个更小的数字。如果我说'太低',你应该猜一个更大的数字。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
human_input_mode="NEVER",
)
# agent_with_number 发起对话,并将 agent_guess_number 作为对话对象
result = agent_with_number.initiate_chat(
agent_guess_number,
message="我心里有一个1到100之间的数字。猜猜看吧!",
)
agent_with_number (对 agent_guess_number 说):
我心里有一个数字,范围在1到100之间。猜一下吧!
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是50吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太低了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是75吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太高了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是63吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太高了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是57吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太高了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是54吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太高了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是52吗?
--------------------------------------------------------------------------------
agent_with_number (对 agent_guess_number 说):
太低了。
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number 说):
是53吗?
--------------------------------------------------------------------------------
太棒了!游戏结束了。猜测的代理使用了二分查找,非常高效!你可以看到,在猜测的代理说出正确的数字后,对话被终止了,这触发了基于消息的终止条件。
人类输入模式 = ALWAYS
在这种模式下,总是要求人类输入,人类可以选择跳过、拦截或终止对话。让我们通过与之前的代理一起玩同样的游戏,以人类的身份参与游戏,我们将成为猜测数字的代理,并与之前的代理进行对战。
human_proxy = ConversableAgent(
"human_proxy",
llm_config=False, # 人类代理不使用LLM
human_input_mode="ALWAYS", # 总是要求人类输入
)
# 与之前的代理开始对话,初始猜测为10。
result = human_proxy.initiate_chat(
agent_with_number, # 这是之前的代理,拥有一个数字
message="10",
)
10
--------------------------------------------------------------------------------
太小了。
--------------------------------------------------------------------------------
79
--------------------------------------------------------------------------------
太大了。
--------------------------------------------------------------------------------
76
--------------------------------------------------------------------------------
太大了。
--------------------------------------------------------------------------------
我放弃了。
--------------------------------------------------------------------------------
没关系!我想的数字是53。
--------------------------------------------------------------------------------
如果你运行上面的代码,每次轮到你说话时都会提示你输入回答。你可以看到,人类在猜测数字方面并不是很好...但是嘿,代理最终还是很好心地给出了数字。
人类输入模式 = TERMINATE
在这种模式下,只有在满足终止条件时才会要求人类输入。如果人类选择拦截并回复,计数器将被重置;如果人类选择跳过,将使用自动回复机制;如果人类选择终止,对话将被终止。
让我们再次玩同样的游戏,但这次猜测的代理只有两次机会猜测数字,如果失败,将要求人类提供反馈,并且对话将被终止。 猜数字的代理获得了两次猜测的机会。如果最终猜对了数字,对话将终止。
agent_with_number = ConversableAgent(
"agent_with_number",
system_message="你正在玩一个猜数字的游戏。在第一局中,你心里想的数字是53,我会试着猜出来。如果我猜得太高,请说'太高',如果我猜得太低,请说'太低'。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
max_consecutive_auto_reply=1, # 在要求人类输入之前,连续自动回复的最大次数
is_termination_msg=lambda msg: "53" in msg["content"], # 如果其他代理猜对了数字,终止对话
human_input_mode="TERMINATE", # 直到游戏终止前一直要求人类输入
)
agent_guess_number = ConversableAgent(
"agent_guess_number",
system_message="我心里有一个数 字,你要试着猜出来。如果我说'太高',你应该猜一个更小的数字。如果我说'太低',你应该猜一个更大的数字。",
llm_config={"config_list": [{"model": "gpt-4", "api_key": os.environ["OPENAI_API_KEY"]}]},
human_input_mode="NEVER",
)
result = agent_with_number.initiate_chat(
agent_guess_number,
message="我心里有一个1到100之间的数字。猜猜看吧!",
)
agent_with_number (对 agent_guess_number):
我有一个介于1和100之间的数字。猜猜看吧!
--------------------------------------------------------------------------------
agent_guess_number (对 agent_with_number):