终止条件#

在前一节中,我们探讨了如何定义代理,并将它们组织成可以通过通信(对话)解决任务的团队。然而,对话可能永远持续下去,在许多情况下,我们需要知道_何时_停止它们。这就是终止条件的作用。

AgentChat 通过提供基础 TerminationCondition 类和几个继承自它的实现来支持多种终止条件。

终止条件是一个可调用对象,它接收自上次调用该条件以来的 ChatMessage 对象序列,如果对话应该终止则返回 StopMessage,否则返回 None。一旦达到终止条件,必须在再次使用之前重置它。

关于终止条件的一些重要注意事项:

  • 它们是有状态的,必须在再次使用之前重置。

  • 它们可以使用 AND 和 OR 运算符组合。

  • 它们由团队实现/执行,而不是由代理执行。代理可以通过发送 StopMessage 来发出或请求终止,但团队负责执行它。

首先,让我们定义一个只有一个代理的简单团队,然后探索如何应用多个终止条件来指导结果行为。

import logging

from autogen_agentchat import EVENT_LOGGER_NAME
from autogen_agentchat.agents import CodingAssistantAgent
from autogen_agentchat.logging import ConsoleLogHandler
from autogen_agentchat.task import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_core.components.models import OpenAIChatCompletionClient

logger = logging.getLogger(EVENT_LOGGER_NAME)
logger.addHandler(ConsoleLogHandler())
logger.setLevel(logging.INFO)

model_client = OpenAIChatCompletionClient(
    model="gpt-4o",
    temperature=1,
    api_key="sk-", # Optional if you have an OPENAI_API_KEY env variable set.
)

writing_assistant_agent = CodingAssistantAgent(
    name="writing_assistant_agent",
    system_message="You are a helpful assistant that solve tasks by generating text responses and code.",
    model_client=model_client,
)
/tmp/ipykernel_326523/3735405718.py:21: DeprecationWarning: CodingAssistantAgent is deprecated. Use AssistantAgent instead.
  writing_assistant_agent = CodingAssistantAgent(

MaxMessageTermination#

最简单的终止条件是 MaxMessageTermination 条件,它在固定数量的消息后终止对话。

max_msg_termination = MaxMessageTermination(max_messages=3)
round_robin_team = RoundRobinGroupChat([writing_assistant_agent], termination_condition=max_msg_termination)
round_robin_team_result = await round_robin_team.run(task="Write a unique, Haiku about the weather in Paris")
{"timestamp": "2024-12-06T17:57:10.104944", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:10.104944", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:10.104944", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.015792", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 38,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.015792", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 38,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.015792", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 38,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.737698", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 66,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.737698", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 66,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.737698", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 66,\n    \"completion_tokens\": 19\n  },\n  \"content\": \"Rain whispers softly,  \\nEiffel towers through the mist\u2014  \\nCity wrapped in gray.  \"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:57:11.738580", "message": "{\n  \"source\": \"MaxMessageTermination\",\n  \"models_usage\": null,\n  \"content\": \"Maximum number of messages 3 reached, current message count: 3\"\n}", "type": "StopMessage"}
{"timestamp": "2024-12-06T17:57:11.738580", "message": "{\n  \"source\": \"MaxMessageTermination\",\n  \"models_usage\": null,\n  \"content\": \"Maximum number of messages 3 reached, current message count: 3\"\n}", "type": "StopMessage"}
{"timestamp": "2024-12-06T17:57:11.738580", "message": "{\n  \"source\": \"MaxMessageTermination\",\n  \"models_usage\": null,\n  \"content\": \"Maximum number of messages 3 reached, current message count: 3\"\n}", "type": "StopMessage"}

我们看到对话在代理发送指定数量的消息后终止。

StopMessageTermination#

在这种情况下,如果任何代理发送 StopMessage,团队就会终止对话。那么,代理什么时候会发送 StopMessage 呢?通常,这是在代理的 on_message 方法中实现的,代理可以检查传入的消息,并根据某些条件决定发送 StopMessage

这里一个常见的模式是提示代理(或参与对话的某个代理)在其响应中发出特定的文本字符串,这可以用来触发终止条件。

事实上,如果你查看 AgentChat 提供的默认 CodingAssistantAgent 类的代码实现,你会发现两件事:

  • 默认的 system_message 指示代理在认为任务完成时以"terminate"一词结束其响应

  • on_message 方法中,代理检查传入的消息是否包含文本"terminate",如果包含则返回 StopMessage

writing_assistant_agent = CodingAssistantAgent(
    name="writing_assistant_agent",
    system_message="You are a helpful assistant that solve tasks by generating text responses and code. Respond with TERMINATE when the task is done.",
    model_client=model_client,
)

text_termination = TextMentionTermination("TERMINATE")
round_robin_team = RoundRobinGroupChat([writing_assistant_agent], termination_condition=text_termination)

round_robin_team_result = await round_robin_team.run(task="Write a unique, Haiku about the weather in Paris")
/tmp/ipykernel_326523/3843252945.py:1: DeprecationWarning: CodingAssistantAgent is deprecated. Use AssistantAgent instead.
  writing_assistant_agent = CodingAssistantAgent(
{"timestamp": "2024-12-06T17:58:44.631351", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:44.631351", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:44.631351", "message": "{\n  \"source\": \"user\",\n  \"models_usage\": null,\n  \"content\": \"Write a unique, Haiku about the weather in Paris\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:45.489890", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 48,\n    \"completion_tokens\": 25\n  },\n  \"content\": \"Cobblestones glisten,  \\nParis whispers in the rain\u2014  \\nClouds dance with the Seine.  \\n\\nTERMINATE\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:45.489890", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 48,\n    \"completion_tokens\": 25\n  },\n  \"content\": \"Cobblestones glisten,  \\nParis whispers in the rain\u2014  \\nClouds dance with the Seine.  \\n\\nTERMINATE\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:45.489890", "message": "{\n  \"source\": \"writing_assistant_agent\",\n  \"models_usage\": {\n    \"prompt_tokens\": 48,\n    \"completion_tokens\": 25\n  },\n  \"content\": \"Cobblestones glisten,  \\nParis whispers in the rain\u2014  \\nClouds dance with the Seine.  \\n\\nTERMINATE\"\n}", "type": "TextMessage"}
{"timestamp": "2024-12-06T17:58:45.490716", "message": "{\n  \"source\": \"TextMentionTermination\",\n  \"models_usage\": null,\n  \"content\": \"Text 'TERMINATE' mentioned\"\n}", "type": "StopMessage"}
{"timestamp": "2024-12-06T17:58:45.490716", "message": "{\n  \"source\": \"TextMentionTermination\",\n  \"models_usage\": null,\n  \"content\": \"Text 'TERMINATE' mentioned\"\n}", "type": "StopMessage"}
{"timestamp": "2024-12-06T17:58:45.490716", "message": "{\n  \"source\": \"TextMentionTermination\",\n  \"models_usage\": null,\n  \"content\": \"Text 'TERMINATE' mentioned\"\n}", "type": "StopMessage"}