import os
from dotenv import load_dotenv
load_dotenv()
True

人机交互

在上一节“团队”中,我们了解了如何创建、观察和控制代理团队。本节将重点介绍如何在应用程序中与团队进行交互,并向团队提供人工反馈。

您可以通过两种主要方式从您的应用程序与团队进行互动:

在团队运行run()或执行期间run_stream(),通过提供反馈UserProxyAgent。

一旦运行终止,通过输入向下一次调用run()或提供反馈run_stream()。

我们将在本节介绍这两种方法。

要直接跳转到与 Web 和 UI 框架集成的代码示例,请参阅以下链接:

  • AgentChat + FastAPI
  • AgentChat + ChainLit
  • AgentChat + Streamlit

运行期间提供反馈

这UserProxyAgent是一个特殊的内置代理,可以作为用户的代理向团队提供反馈。

要使用UserProxyAgent,您可以在运行团队之前创建它的实例并将其包含在团队中。团队将决定何时调用UserProxyAgent 来征求用户的反馈。

例如,在RoundRobinGroupChat团队中,UserProxyAgent按照传递给团队的顺序调用,而在SelectorGroupChat 团队中,选择器提示或选择器函数决定何时调用 UserProxyAgent。

下图说明了如何 UserProxyAgent 在团队运行期间获取用户的反馈:在这里插入图片描述

粗体箭头表示团队运行期间的控制流:当团队调用时UserProxyAgent,它将控制权转移给应用程序/用户,并等待反馈;一旦提供反馈,控制权就会转移回团队,团队继续执行。

在运行过程中调用时UserProxyAgent,它会阻止团队的执行,直到用户提供反馈或错误信息。这将阻碍团队的进度,并使团队处于无法保存或恢复的不稳定状态。

由于此方法的阻塞特性,建议仅将其用于需要用户立即反馈的短暂交互,例如通过单击按钮请求批准或不批准,或需要立即注意的警报,否则任务失败。

以下是如何使用UserProxyAgent 进行RoundRobinGroupChat诗歌生成任务的示例:

from autogen_agentchat.agents import AssistantAgent, UserProxyAgent  # 导入助手代理和用户代理
from autogen_agentchat.conditions import TextMentionTermination  # 导入文本关键词终止条件
from autogen_agentchat.teams import RoundRobinGroupChat  # 导入轮询团队对话机制
from autogen_agentchat.ui import Console  # 控制台工具,用于输出对话消息流
from autogen_ext.models.openai import OpenAIChatCompletionClient  # 导入 OpenAI 模型客户端# 创建模型客户端,使用 gpt-4o-mini 模型
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")# 创建一个助手代理,负责自动生成内容
assistant = AssistantAgent("assistant", model_client=model_client)# 创建一个用户代理,使用 input() 从控制台获取用户输入
user_proxy = UserProxyAgent("user_proxy", input_func=input)# 创建终止条件:当用户输入 "APPROVE" 时终止对话
termination = TextMentionTermination("APPROVE")# 创建一个团队,包含助手代理和用户代理,使用上述终止条件
team = RoundRobinGroupChat([assistant, user_proxy],termination_condition=termination,
)# 启动对话流程,以流式方式运行任务,并将输出打印到控制台
stream = team.run_stream(task="写一首关于海洋的四行诗。")# 如果你在脚本中运行,请使用 asyncio.run(...) 调用 Console
await Console(stream)  # 将对话内容流式输出到终端,支持用户实时参与# 关闭模型客户端,释放资源
await model_client.close()
---------- TextMessage (user) ----------
写一首关于海洋的四行诗。
---------- TextMessage (assistant) ----------
深蓝海洋浩瀚无垠,  
波涛涌动如心潮涌现。  
阳光洒落银光闪烁,  
渔舟唱晚愿随风行。  
TERMINATEEnter your response:  a---------- TextMessage (user_proxy) ----------
a
---------- TextMessage (assistant) ----------
请您提供更多信息或明确的问题,我会尽力帮助您。TERMINATEEnter your response:  写一个甘肃的古诗---------- TextMessage (user_proxy) ----------
写一个甘肃的古诗
---------- TextMessage (assistant) ----------
祁连山下草如茵,  
甘泉流逸润心田。  
古道西风吹客醉,  
月明孤影共此仙。  
TERMINATEEnter your response:  approve---------- TextMessage (user_proxy) ----------
approve
---------- TextMessage (assistant) ----------
如果您需要进一步的帮助或有其他请求,请告诉我!TERMINATEEnter your response:  APPROVE---------- TextMessage (user_proxy) ----------
APPROVE

从控制台输出中,您可以看到团队征求用户的反馈以user_proxy批准生成的诗歌。

您可以提供自己的输入函数来自定义反馈流程。例如,当团队以 Web 服务形式运行时,您可以使用自定义输入函数来等待来自 Web 套接字连接的消息。以下代码片段展示了使用FastAPIUserProxyAgent Web 框架时自定义输入函数的示例:

为下次运行提供反馈

通常,应用程序或用户会与代理团队进行交互循环:团队运行直至终止,应用程序或用户提供反馈,然后团队根据反馈再次运行。

这种方法在团队与应用程序/用户之间进行异步通信的持久会话中很有用:一旦团队完成运行,应用程序就会保存团队的状态,将其放入持久存储中,并在反馈到达时恢复团队。

有关如何保存和加载团队状态,请参阅管理状态。本节将重点介绍反馈机制。

下图说明了此方法中的控制流程:

实现此方法有两种方式:

  • 设置最大转弯次数,以便团队始终在指定的转弯次数后停止。
  • 使用终止条件(例如TextMentionTermination)HandoffTermination允许团队根据团队的内部状态决定何时停止并交还控制权。

您可以同时使用这两种方法来实现所需的行为。

使用最大转弯次数

此方法允许您通过设置最大轮次来暂停团队以等待用户输入。例如,您可以设置max_turns为 1,让团队在第一个客服人员响应后停止。这在需要持续用户参与的场景中尤其有用,例如在聊天机器人中。

为了实现这一点,请max_turns在RoundRobinGroupChat()构造函数中设置参数。

# team = RoundRobinGroupChat([...], max_turns=1)

团队停止后,回合计数将被重置。恢复团队后,回合计数将重新从 0 开始。但是,团队的内部状态将被保留,例如,团队RoundRobinGroupChat将从列表中具有相同对话历史记录的下一个客服人员开始恢复。

max_turn特定于团队类,目前仅受 RoundRobinGroupChat、SelectorGroupChat和 的支持Swarm。与终止条件一起使用时,只要满足任一条件,团队就会停止。

以下是如何使用最多 1 次的诗歌生成任务max_turns的示例:RoundRobinGroupChat

from autogen_agentchat.agents import AssistantAgent  # 导入助手代理
from autogen_agentchat.teams import RoundRobinGroupChat  # 导入轮询式团队对话类
from autogen_agentchat.ui import Console  # 控制台输出工具
from autogen_ext.models.openai import OpenAIChatCompletionClient  # 导入 OpenAI 模型客户端# 创建模型客户端,指定使用 gpt-4o-mini 模型
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")# 创建助手代理,负责生成内容
assistant = AssistantAgent("assistant", model_client=model_client)# 创建对话团队,这里设置最大轮数为 1(每次只进行一轮对话)
team = RoundRobinGroupChat([assistant], max_turns=1)# 初始任务:生成一首关于海洋的四行诗
task = "写一首关于海洋的四行诗。"# 进入循环,持续与助手交互,直到用户主动退出
while True:# 执行任务并将对话消息流实时输出到控制台stream = team.run_stream(task=task)# 如果是在脚本中运行,请使用 asyncio.run(...) 调用 Consoleawait Console(stream)  # 显示 AI 响应内容# 获取用户输入的新任务或反馈task = input("请输入你的反馈(输入 'exit' 可退出):")# 如果用户输入 exit,则退出循环if task.lower().strip() == "exit":break# 关闭模型客户端,释放资源
await model_client.close()
---------- TextMessage (user) ----------
写一首关于海洋的四行诗。
---------- TextMessage (assistant) ----------
浩瀚海洋波涛涌,  
蓝色深处藏奇梦。  
船只扬帆逐浪行,  
心随海风共自由。  TERMINATE请输入你的反馈(输入 'exit' 可退出): 来一个宋词---------- TextMessage (user) ----------
来一个宋词
---------- TextMessage (assistant) ----------
《清平乐·村居》绿树阴浓夏日长,  
楼台倒影入池塘。  
水面清圆一一笑,  
天空霹雳一声响。天边晚霞红似火,  
渔舟唱晚逐波行。  
停船暂借问渔翁,  
笑指波心荡涟漪。  TERMINATE请输入你的反馈(输入 'exit' 可退出): exit

您可以看到,在一名代理做出响应后,团队立即停止了。

使用终止条件

在前面几节中,我们已经看到了几个终止条件的例子。在本节中,我们将重点讨论HandoffTermination 当代理发送HandoffMessage消息时,哪些条件会终止团队。

让我们创建一个AssistantAgent具有交接设置的单个代理的团队,并使用需要用户额外输入的任务来运行该团队,因为代理没有相关工具来继续处理该任务。

所使用的模型AssistantAgent必须支持工具调用才能使用切换功能。

from autogen_agentchat.agents import AssistantAgent  # 导入助手代理类
from autogen_agentchat.base import Handoff  # 导入交接逻辑(用于将任务转移给其他代理)
from autogen_agentchat.conditions import HandoffTermination, TextMentionTermination  # 导入终止条件
from autogen_agentchat.teams import RoundRobinGroupChat  # 导入轮询式团队聊天机制
from autogen_agentchat.ui import Console  # 控制台工具,用于输出对话内容
from autogen_ext.models.openai import OpenAIChatCompletionClient  # OpenAI 模型客户端# 创建 OpenAI 模型客户端(默认使用环境变量中的 API 密钥)
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini",  # 使用 gpt-4o-mini 模型# api_key="sk-..."  # 可选:若设置了 OPENAI_API_KEY 环境变量,则可省略
)# 创建一个“懒惰”的助手代理:始终将任务交接给用户
lazy_agent = AssistantAgent("lazy_assistant",  # 代理名称model_client=model_client,  # 使用的模型客户端handoffs=[Handoff(target="user", message="转移给用户。")],  # 定义交接行为:将任务移交给“user”system_message="如果无法完成任务,则转交给用户。否则,完成后,响应“TERMINATE”。",# 系统提示词:如果无法完成任务就交接给用户;否则,任务完成后回复 'TERMINATE'
)# 定义一个终止条件:当代理执行交接到用户时终止
handoff_termination = HandoffTermination(target="user")# 定义另一个终止条件:当文本中出现 终止 "TERMINATE" 字样时终止
text_termination = TextMentionTermination("TERMINATE")# 创建一个仅包含该懒惰代理的团队,同时设置两个终止条件
lazy_agent_team = RoundRobinGroupChat([lazy_agent],  # 团队成员termination_condition=handoff_termination | text_termination  # 任意一个终止条件满足即结束
)# 执行任务并将对话过程流式输出到控制台
task = "北京现在的天气如何?"
await Console(lazy_agent_team.run_stream(task=task),  # 执行任务并以流方式返回output_stats=True  # 输出额外的统计信息,例如 token 使用量等
)
---------- TextMessage (user) ----------
北京现在的天气如何?
---------- ToolCallRequestEvent (lazy_assistant) ----------
[FunctionCall(id='call_KGGGBV8lQb2dHW0Yst702D4k', arguments='{}', name='transfer_to_user')]
[Prompt tokens: 65, Completion tokens: 11]
---------- ToolCallExecutionEvent (lazy_assistant) ----------
[FunctionExecutionResult(content='转移给用户。', name='transfer_to_user', call_id='call_KGGGBV8lQb2dHW0Yst702D4k', is_error=False)]
---------- HandoffMessage (lazy_assistant) ----------
转移给用户。
---------- Summary ----------
Number of messages: 4
Finish reason: Handoff to user from lazy_assistant detected.
Total prompt tokens: 65
Total completion tokens: 11
Duration: 1.12 secondsTaskResult(messages=[TextMessage(source='user', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 11, 298603, tzinfo=datetime.timezone.utc), content='北京现在的天气如何?', type='TextMessage'), ToolCallRequestEvent(source='lazy_assistant', models_usage=RequestUsage(prompt_tokens=65, completion_tokens=11), metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 12, 406768, tzinfo=datetime.timezone.utc), content=[FunctionCall(id='call_KGGGBV8lQb2dHW0Yst702D4k', arguments='{}', name='transfer_to_user')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='lazy_assistant', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 12, 408012, tzinfo=datetime.timezone.utc), content=[FunctionExecutionResult(content='转移给用户。', name='transfer_to_user', call_id='call_KGGGBV8lQb2dHW0Yst702D4k', is_error=False)], type='ToolCallExecutionEvent'), HandoffMessage(source='lazy_assistant', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 12, 408220, tzinfo=datetime.timezone.utc), content='转移给用户。', target='user', context=[], type='HandoffMessage')], stop_reason='Handoff to user from lazy_assistant detected.')

您可以看到,由于检测到了切换消息,团队已停止。让我们通过提供代理所需的信息来继续团队工作。

# 执行任务:“The weather in New York is sunny.”,以流式方式运行代理团队,并将结果实时输出到控制台
await Console(lazy_agent_team.run_stream(task="北京天气晴朗。"))
---------- TextMessage (user) ----------
北京天气晴朗。
---------- TextMessage (lazy_assistant) ----------
TERMINATETaskResult(messages=[TextMessage(source='user', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 21, 39779, tzinfo=datetime.timezone.utc), content='北京天气晴朗。', type='TextMessage'), TextMessage(source='lazy_assistant', models_usage=RequestUsage(prompt_tokens=100, completion_tokens=4), metadata={}, created_at=datetime.datetime(2025, 6, 30, 11, 57, 22, 59815, tzinfo=datetime.timezone.utc), content='TERMINATE', type='TextMessage')], stop_reason="Text 'TERMINATE' mentioned")

您可以看到用户提供信息后团队继续进行。

如果您正在使用以目标用户Swarm为目标的团队 HandoffTermination,要恢复团队,您需要将 设置task为 ,HandoffMessage 并将target设置为要运行的下一个代理。有关更多详细信息,请参阅Swarm 。


终止

在上一节中,我们探讨了如何定义代理,并将它们组织成能够解决任务的团队。然而,运行可能会永远持续下去,在很多情况下,我们需要知道何时停止它们。这就是终止条件的作用。

AgentChat 通过提供一个基TerminationCondition类和从其继承的几个实现来支持几种终止条件。

终止条件是一个可调用函数,它接受自上次调用该条件以来BaseAgentEvent的或BaseChatMessage对象序列,如果对话应该终止则返回 ,否则返回。一旦达到终止条件,必须通过调用 重置它才能再次使用。StopMessageNonereset()

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

  • 它们是有状态的,但每次运行(run()或run_stream())完成后都会自动重置。
  • 它们可以使用 AND 和 OR 运算符进行组合。

对于群聊团队(例如RoundRobinGroupChat、 SelectorGroupChat和Swarm),终止条件在每个代理响应后调用。虽然响应可能包含多条内部消息,但团队只会针对单个响应中的所有消息调用一次终止条件。因此,该条件的调用方式是使用自上次调用以来的消息“增量序列”。

内置终止条件:

  • MaxMessageTermination:生成指定数量的消息(包括代理和任务消息)后停止。
  • TextMentionTermination:当消息中提到特定文本或字符串时停止(例如“TERMINATE”)。
  • TokenUsageTermination:当使用一定数量的提示或完成令牌时停止。这要求代理在其消息中报告令牌使用情况。
  • TimeoutTermination:在指定的秒数后停止。
  • HandoffTermination:当请求切换到特定目标时停止。切换消息可用于构建诸如 之类的模式Swarm。当您希望暂停运行并允许应用程序或用户在代理切换至他们时提供输入时,这非常有用。
  • SourceMatchTermination:特定代理响应后停止。
  • ExternalTermination:允许从运行外部以编程方式控制终止。这对于 UI 集成非常有用(例如,聊天界面中的“停止”按钮)。
  • StopMessageTerminationStopMessage:当代理产生时停止。
  • TextMessageTerminationTextMessage:当代理产生时停止。
  • FunctionCallTermination:当代理生成ToolCallExecutionEvent包含具有匹配名称的时停止。FunctionExecutionResult
  • FunctionalTermination:当函数表达式True在最后一个增量消息序列上求值时停止。这对于快速创建内置终止条件未涵盖的自定义终止条件非常有用。

基本用法

为了展示终止条件的特点,我们将创建一个由两个代理组成的团队:负责文本生成的主要代理和审查并对生成的文本提供反馈的评论代理。

from autogen_agentchat.agents import AssistantAgent  # 导入助手代理类
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination  # 导入最大消息数终止条件和关键词终止条件
from autogen_agentchat.teams import RoundRobinGroupChat  # 导入轮询式团队对话类
from autogen_agentchat.ui import Console  # 控制台工具,用于输出消息
from autogen_ext.models.openai import OpenAIChatCompletionClient  # OpenAI 模型客户端# 创建 OpenAI 模型客户端,使用 gpt-4o-mini 模型
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini",  # 指定使用 gpt-4o-mini 模型temperature=1,   # 设置模型输出的随机性(temperature 越高,输出越多样化)# api_key="sk-..."  # 可选:如果设置了 OPENAI_API_KEY 环境变量,可以省略此项
)# 创建主要助手代理(primary_agent),负责主要任务生成
primary_agent = AssistantAgent("primary",  # 代理名称model_client=model_client,  # 使用的模型客户端system_message="你是一个有用的人工智能助手。",  
)# 创建评论代理(critic_agent),用于对主代理的输出进行反馈
critic_agent = AssistantAgent("critic",  # 代理名称model_client=model_client,  # 使用相同的模型客户端system_message="为每条消息提供建设性反馈。当您的反馈得到处理后,请回复批准“APPROVE”。",# 系统提示词:为每条消息提供建设性反馈;当反馈被采纳后,请回复 "APPROVE" 表示认可
)

让我们来探讨一下终止条件如何在每次通话后自动重置run,run_stream从而允许团队从中断的地方继续对话。

# 定义一个最大消息数终止条件:对话达到 3 条消息后自动结束
max_msg_termination = MaxMessageTermination(max_messages=3)# 创建一个轮询团队,包含 primary_agent 和 critic_agent,使用最大消息数作为终止条件
round_robin_team = RoundRobinGroupChat([primary_agent, critic_agent],termination_condition=max_msg_termination
)# 如果你是在脚本中运行,请使用 asyncio.run(...) 包裹此语句
# 运行团队任务,并将消息流式输出到控制台
await Console(round_robin_team.run_stream(task="写一首关于北京天气的独特俳句") 
)
---------- TextMessage (user) ----------
写一首关于北京天气的独特俳句
---------- TextMessage (primary) ----------
冬日寒风起,  
红墙映衬黄昏,  
雪落静无声。
---------- TextMessage (critic) ----------
这首关于北京天气的俳句非常优美,以下是我的反馈:1. **意境深远**:首句“冬日寒风起”便营造出一种清冷、凛冽的氛围,让读者瞬间感受到冬季的特点。2. **视觉与听觉结合**:第二句“红墙映衬黄昏”很好地描绘了北京的传统建筑与景致,营造出温暖而又沉静的画面。第三句“雪落静无声”则增添了冬日的宁静感,令人心旷神怡。3. **情感共鸣**:整首俳句传达出了一种对季节变换的敏感与思考,展现了对北京冬日的独特情感。简单的语言中却蕴含丰富的情感和美感。建议方面,可以考虑在“红墙映衬黄昏”中添加一些更具体的细节,例如描绘黄昏的色彩,以增强画面的层次感和动感。总的来说,这是一首很成功的俳句,展现了北京冬日的宁静与美丽。审批:APPROVETaskResult(messages=[TextMessage(source='user', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 41, 28, 539043, tzinfo=datetime.timezone.utc), content='写一首关于北京天气的独特俳句', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=186, completion_tokens=23), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 41, 35, 428626, tzinfo=datetime.timezone.utc), content='冬日寒风起,  \n红墙映衬黄昏,  \n雪落静无声。', type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=746, completion_tokens=273), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 41, 40, 956230, tzinfo=datetime.timezone.utc), content='这首关于北京天气的俳句非常优美,以下是我的反馈:\n\n1. **意境深远**:首句“冬日寒风起”便营造出一种清冷、凛冽的氛围,让读者瞬间感受到冬季的特点。\n\n2. **视觉与听觉结合**:第二句“红墙映衬黄昏”很好地描绘了北京的传统建筑与景致,营造出温暖而又沉静的画面。第三句“雪落静无声”则增添了冬日的宁静感,令人心旷神怡。\n\n3. **情感共鸣**:整首俳句传达出了一种对季节变换的敏感与思考,展现了对北京冬日的独特情感。简单的语言中却蕴含丰富的情感和美感。\n\n建议方面,可以考虑在“红墙映衬黄昏”中添加一些更具体的细节,例如描绘黄昏的色彩,以增强画面的层次感和动感。\n\n总的来说,这是一首很成功的俳句,展现了北京冬日的宁静与美丽。\n\n审批:APPROVE', type='TextMessage')], stop_reason='Maximum number of messages 3 reached, current message count: 3')

# 如果你是在独立脚本中运行此代码,请使用 asyncio.run(...) 包裹此调用
await Console(round_robin_team.run_stream())  # 运行轮询团队对话任务,并将对话过程实时输出到控制台
---------- TextMessage (primary) ----------
非常感谢您的详细反馈与赞赏!我很高兴您喜欢这首俳句,并对其中的意境和情感进行了深入分析。您的建议也很有建设性,如果在“红墙映衬黄昏”中更具体地融入一些色彩细节,会让画面更加生动。我会谨记这一点,继续探索更加丰富的表达方式。若您还有其他想法或需要诗歌创作的主题,请随时告诉我!
---------- TextMessage (critic) ----------
非常高兴看到您对反馈的积极态度,以及愿意继续探索更丰富表达方式的决心!您的写作潜力很大,我期待看到您在未来创作中融入更多细节和情感。 如果您有其他主题想要尝试,或希望进一步探讨写作技巧,请随时告诉我!无论是继续写诗、探讨风格,还是其他文学形式,我都会很乐意提供帮助。继续加油,期待您的更多作品! 审批:APPROVE
---------- TextMessage (primary) ----------
非常感谢您的鼓励与支持!您的反馈让我倍感动力,也让我意识到细节和情感在创作中的重要性。我会继续努力,尝试在我的作品中融入更多的细节与深度。如果有其他主题或者风格您希望我尝试,或者有任何写作技巧想要探讨,随时告诉我,我很乐意与您一起交流和创作!期待在未来的作品中展示更多的创造力。再次感谢您的支持!TaskResult(messages=[TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=492, completion_tokens=105), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 43, 51, 716987, tzinfo=datetime.timezone.utc), content='非常感谢您的详细反馈与赞赏!我很高兴您喜欢这首俳句,并对其中的意境和情感进行了深入分析。您的建议也很有建设性,如果在“红墙映衬黄昏”中更具体地融入一些色彩细节,会让画面更加生动。我会谨记这一点,继续探索更加丰富的表达方式。若您还有其他想法或需要诗歌创作的主题,请随时告诉我!', type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=1134, completion_tokens=113), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 43, 54, 217188, tzinfo=datetime.timezone.utc), content='非常高兴看到您对反馈的积极态度,以及愿意继续探索更丰富表达方式的决心!您的写作潜力很大,我期待看到您在未来创作中融入更多细节和情感。 \n\n如果您有其他主题想要尝试,或希望进一步探讨写作技巧,请随时告诉我!无论是继续写诗、探讨风格,还是其他文学形式,我都会很乐意提供帮助。\n\n继续加油,期待您的更多作品! \n\n审批:APPROVE', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=720, completion_tokens=107), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 43, 57, 558103, tzinfo=datetime.timezone.utc), content='非常感谢您的鼓励与支持!您的反馈让我倍感动力,也让我意识到细节和情感在创作中的重要性。我会继续努力,尝试在我的作品中融入更多的细节与深度。\n\n如果有其他主题或者风格您希望我尝试,或者有任何写作技巧想要探讨,随时告诉我,我很乐意与您一起交流和创作!期待在未来的作品中展示更多的创造力。再次感谢您的支持!', type='TextMessage')], stop_reason='Maximum number of messages 3 reached, current message count: 3')

团队从中断的地方继续工作,让主要代理对反馈做出回应。

组合终止条件

  • & 让我们展示如何使用 AND ( ) 和 OR ( ) 运算符组合终止条件;
  • | 以创建更复杂的终止逻辑。例如,我们将创建一个团队,该团队在生成 10 条消息后或评论员代理批准一条消息后停止。
# 定义最大消息数终止条件:当消息总数达到 10 条时自动终止
max_msg_termination = MaxMessageTermination(max_messages=10)# 定义文本关键词终止条件:当某条消息中包含 "APPROVE"(如评论代理表示认可)时终止
text_termination = TextMentionTermination("APPROVE")# 组合多个终止条件:任一条件满足时就结束对话(使用按位或运算符 |)
combined_termination = max_msg_termination | text_termination# 创建轮询式团队,包含主代理和评论代理,并设置终止条件为组合条件
round_robin_team = RoundRobinGroupChat([primary_agent, critic_agent],termination_condition=combined_termination
)# 如果你是在独立 .py 脚本中运行,请使用 asyncio.run(...) 来运行该异步任务
# 运行对话任务并将对话消息流式输出到控制台
await Console(round_robin_team.run_stream(task="写一首独特的关于北京天气的俳句") 
)
---------- TextMessage (user) ----------
写一首独特的关于北京天气的俳句
---------- TextMessage (primary) ----------
春风轻拂柳,  
杏花点缀街头,  
阳光暖心间。  
---------- TextMessage (critic) ----------
这首关于北京天气的俳句非常优美,以下是我的反馈:1. **意象清新**:首句“春风轻拂柳”引入了春天的生机,展现了自然的温柔,立即让人感受到春季的气息。2. **细节生动**:第二句“杏花点缀街头”生动地描绘出春天的景象,杏花作为春季的象征,可以让人联想到北京街头的浪漫与美丽。3. **情感温暖**:最后一句“阳光暖心间”则将春天的温暖与情感结合起来,营造出一种温馨与幸福感,让人心生向往。整体上,俳句简单而富有层次,情感真挚,意象生动,成功地传达了北京春天的温暖与美丽。建议方面,可以考虑在“杏花点缀街头”中加入一些形容词,比如“盛开的杏花”或“芬芳的杏花”,这样能更深刻地表现花的美丽与香气。总的来说,这是一首非常成功的俳句,展现了春天在北京的独特魅力。审批:APPROVETaskResult(messages=[TextMessage(source='user', models_usage=None, metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 47, 4, 409935, tzinfo=datetime.timezone.utc), content='写一首独特的关于北京天气的俳句', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=849, completion_tokens=24), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 47, 6, 591966, tzinfo=datetime.timezone.utc), content='春风轻拂柳,  \n杏花点缀街头,  \n阳光暖心间。  ', type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=1299, completion_tokens=287), metadata={}, created_at=datetime.datetime(2025, 6, 30, 12, 47, 11, 572637, tzinfo=datetime.timezone.utc), content='这首关于北京天气的俳句非常优美,以下是我的反馈:\n\n1. **意象清新**:首句“春风轻拂柳”引入了春天的生机,展现了自然的温柔,立即让人感受到春季的气息。\n\n2. **细节生动**:第二句“杏花点缀街头”生动地描绘出春天的景象,杏花作为春季的象征,可以让人联想到北京街头的浪漫与美丽。\n\n3. **情感温暖**:最后一句“阳光暖心间”则将春天的温暖与情感结合起来,营造出一种温馨与幸福感,让人心生向往。\n\n整体上,俳句简单而富有层次,情感真挚,意象生动,成功地传达了北京春天的温暖与美丽。\n\n建议方面,可以考虑在“杏花点缀街头”中加入一些形容词,比如“盛开的杏花”或“芬芳的杏花”,这样能更深刻地表现花的美丽与香气。\n\n总的来说,这是一首非常成功的俳句,展现了春天在北京的独特魅力。\n\n审批:APPROVE', type='TextMessage')], stop_reason="Text 'APPROVE' mentioned")

评论员代理批准该消息后,对话就会停止,但如果生成了 10 条消息,对话也会停止。

或者,如果我们只想在两个条件都满足时停止运行,我们可以使用 AND ( &) 运算符。

# combined_termination = max_msg_termination & text_termination

自定义终止条件

内置的终止条件足以满足大多数用例的需求。但是,在某些情况下,您可能需要实现与现有终止条件不相符的自定义终止条件。您可以通过创建该类的TerminationCondition子类来实现。

在这个例子中,我们创建了一个自定义终止条件,当进行特定的函数调用时,对话就会停止。

from typing import Sequencefrom autogen_agentchat.base import TerminatedException, TerminationCondition  # 引入终止异常和终止条件基类
from autogen_agentchat.messages import (BaseAgentEvent,BaseChatMessage,StopMessage,ToolCallExecutionEvent,
)  # 引入对话消息相关类
from autogen_core import Component  # 引入组件基类,用于可配置组件
from pydantic import BaseModel  # 用于定义结构化配置模型
from typing_extensions import Self  # 引入 Self 类型,用于类型提示返回当前类实例class FunctionCallTerminationConfig(BaseModel):"""用于序列化和反序列化的终止条件配置类"""function_name: str  # 指定需要检测的函数名class FunctionCallTermination(TerminationCondition, Component[FunctionCallTerminationConfig]):"""当检测到指定名称的函数执行结果(FunctionExecutionResult)时终止对话"""component_config_schema = FunctionCallTerminationConfig  # 组件配置模式component_provider_override = "autogen_agentchat.conditions.FunctionCallTermination""""组件提供者路径,用于动态加载和配置"""def __init__(self, function_name: str) -> None:# 初始化状态为未终止,保存指定函数名self._terminated = Falseself._function_name = function_name@propertydef terminated(self) -> bool:"""返回是否已经触发终止条件"""return self._terminatedasync def __call__(self, messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> StopMessage | None:"""每轮对话调用,用于检查是否触发终止条件"""if self._terminated:raise TerminatedException("Termination condition has already been reached")  # 已终止则抛出异常for message in messages:# 检查是否为工具调用结果事件(函数执行结果)if isinstance(message, ToolCallExecutionEvent):for execution in message.content:# 如果函数名称与指定函数名匹配,触发终止if execution.name == self._function_name:self._terminated = Truereturn StopMessage(content=f"Function '{self._function_name}' was executed.",  # 返回终止说明source="FunctionCallTermination",  # 指定终止源标识)return None  # 若未满足终止条件,返回 Noneasync def reset(self) -> None:"""重置终止状态,用于重新开始对话"""self._terminated = Falsedef _to_config(self) -> FunctionCallTerminationConfig:"""将当前实例序列化为配置对象"""return FunctionCallTerminationConfig(function_name=self._function_name,)@classmethoddef _from_config(cls, config: FunctionCallTerminationConfig) -> Self:"""从配置对象反序列化创建终止条件实例"""return cls(function_name=config.function_name,)

当评论家代理使用函数调用批准消息时,让我们使用这个新的终止条件来停止对话approve。

首先,我们创建一个简单的函数,当评论家代理批准一条消息时,该函数将被调用。

def approve() -> None:"""Approve the message when all feedbacks have been addressed."""pass

然后我们创建代理。评论家代理配备了该approve工具。

from autogen_agentchat.agents import AssistantAgent  # 导入助手代理类
from autogen_agentchat.teams import RoundRobinGroupChat  # 导入轮询团队类
from autogen_agentchat.ui import Console  # 导入控制台输出工具
from autogen_ext.models.openai import OpenAIChatCompletionClient  # 导入 OpenAI 模型客户端# 创建 OpenAI 模型客户端,使用 gpt-4o 模型,设置温度参数控制生成随机性
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini",  # 指定使用 gpt-4o-mini 模型temperature=1,   # 设置输出的多样性(temperature 越高越随机)# api_key="sk-...",  # 可选:若设置了 OPENAI_API_KEY 环境变量,可以省略此项
)# 创建主代理(primary),用于执行主要任务(如写作、生成回答等)
primary_agent = AssistantAgent("primary",  # 代理名称model_client=model_client,  # 指定所用模型客户端system_message="你是一个有用的人工智能助手。",  # 系统提示词:设定角色为乐于助人的 AI 助手
)# 创建评论代理(critic),并注册 approve 函数作为工具
critic_agent = AssistantAgent("critic",  # 代理名称model_client=model_client,  # 使用相同的模型客户端tools=[approve],  # 注册工具:approve(通常是一个函数,例如批准任务通过)system_message="提供建设性反馈。所有反馈意见均已处理完毕后,请使用批准工具进行批准。",# 系统提示词:提供建设性反馈;当所有反馈问题已解决时,使用 approve 工具批准结果
)
# 创建一个函数调用终止条件,当调用名为 "approve" 的函数时终止对话
function_call_termination = FunctionCallTermination(function_name="approve")# 创建一个轮询对话团队,包含 primary 和 critic 两个代理,使用函数调用终止条件
round_robin_team = RoundRobinGroupChat([primary_agent, critic_agent],termination_condition=function_call_termination  # 当调用 approve 工具时自动终止对话
)# 如果你是在 .py 脚本中运行,请使用 asyncio.run(...) 包裹本语句
# 执行对话任务,并将代理的消息流式输出到控制台
await Console(round_robin_team.run_stream(task="写一首独特的关于北京天气的俳句")  
)# 对话完成后,关闭模型客户端以释放资源
await model_client.close()
---------- TextMessage (user) ----------
写一首独特的关于北京天气的俳句
---------- TextMessage (primary) ----------
秋风送爽来,  
白云浮问晴雨,  
故宫静待雪。  
---------- TextMessage (critic) ----------
这首俳句很有意境,描绘了北京秋冬季节的天气变化和古老文化的气息。以下是一些建设性反馈:1. **视觉细节**:可以考虑加入一些用于描绘天气的具体细节,比如温度、湿度等,让读者更能感受到北京的天气特征。2. **情感表达**:可以通过加入主人公的感受来增强情感表达。例如,对秋风的感慨或初雪的期待,增加主题的深度。3. **节奏感**:可以考虑在某些地方增加停顿或改变节奏,使得朗读时更具韵律感和节奏感。可以尝试改进这些方面,使得诗句更加丰富。
---------- TextMessage (primary) ----------
非常感谢你的反馈!我会根据你的建议进行改进。以下是修改后的版本:初冬寒风吹,  
银霜轻覆古巷,  
心随云行走。希望这个版本能更好地传达北京天气的细腻感受与情感!
---------- TextMessage (critic) ----------
这个修改后的版本非常出色!你成功地将视觉细节与情感表达结合起来,给读者带来了更深的共鸣。以下是一些具体的反馈:1. **意象丰富**:使用“银霜轻覆古巷”生动地展现了冬天的特色,古巷的形象也增添了文化底蕴。2. **情感共鸣**:句尾的“心随云行走”传达了一种自由与随性的情感,令人感受到天气对心情的影响,这提升了诗的深度。3. **节奏感**:整首俳句在节奏上顺畅自然,朗读时很流畅,使得整首诗更具韵律感。这个版本已经很棒了,能够很有效地传达出北京的天气与情感。继续保持这样的创作状态!如果没有其他修改的地方,我将会为这首诗进行批准。请确认是否可行。
---------- TextMessage (primary) ----------
非常感谢你的肯定与鼓励!我很高兴你喜欢这个版本,并且认为它成功地达到了预期的效果。如果没有其他的修改建议,我也很乐意将这首诗定稿。再次感谢你的指导和支持!
---------- ToolCallRequestEvent (critic) ----------
[FunctionCall(id='call_vUi2MIWn73LPGmfPVT0ODpHu', arguments='{}', name='approve')]
---------- ToolCallExecutionEvent (critic) ----------
[FunctionExecutionResult(content='None', name='approve', call_id='call_vUi2MIWn73LPGmfPVT0ODpHu', is_error=False)]
---------- ToolCallSummaryMessage (critic) ----------
None

您可以看到,当评论家代理使用函数调用批准该消息时,对话停止了approve。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90361.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90361.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90361.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink Db2 CDC 环境配置与验证

一、DB2 数据库核心配置 1. 启用数据库日志记录与CDC支持 -- 以DB2管理员身份连接数据库 CONNECT TO mydb USER db2inst1 USING password;-- 启用数据库归档日志模式(CDC依赖) UPDATE DATABASE CONFIGURATION USING LOGARCHMETH1 DISK:/db2log/archive…

初识单例模式

文章目录场景通点定义实现思路六种 Java 实现饿汉式懒汉式synchronized 方法双重检查锁 Double Check Lock Volatile静态内部类 Singleton Holder枚举单例单例运用场景破解单例模式参考场景通点 资源昂贵:数据库连接池、线程池、日志组件,只需要一份全…

音乐抢单源码(连单卡单/叠加组规则/打针/多语言)

简介: 测试环境:Nginx、PHP7.2、MySQL5.6,运行目录设置为public,伪静态thinkphp,建议开启SSL 测试语言:11种 不知道谁给我的一套,说是买来的,我看了一下功能感觉也一般&#…

分类树查询性能优化:从 2 秒到 0.1 秒的技术蜕变之路

在电商系统中,分类树查询是一个基础且高频的功能,然而这个看似简单的功能背后却隐藏着不小的性能挑战。本文将分享我们在实际项目中对分类树查询功能进行五次优化的全过程,看如何将查询耗时从 2 秒缩短至 0.1 秒,为用户提供更流畅…

Ansible 介绍及安装

简介 Ansible 是一款开源的自动化工具,广泛应用于配置管理、应用部署、任务自动化以及多节点管理等领域。它由 Michael DeHaan 于 2012 年创建,ansible 目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手…

超光谱相机的原理和应用场景

超光谱相机是光谱成像技术的尖端形态,具备亚纳米级光谱分辨率与超千波段连续覆盖能力,通过“图谱合一”的三维数据立方体实现物质的精准识别与分析。其核心技术架构、应用场景及发展趋势如下:一、核心技术原理1、‌分光机制‌‌干涉分光‌&am…

掌握MySQL函数:高效数据处理指南

​ 在 MySQL 数据库管理系统中,函数扮演着极为重要的角色。它们就像是数据库操作的得力助手,能够帮助开发者高效地完成各种数据处理任务。本文将深入探讨 MySQL 函数的方方面面,从其基本概念到实际应用,帮助读者全面掌握这一强大的…

10.SpringBoot的统一异常处理详解

文章目录1. 异常处理基础概念1.1 什么是异常处理1.2 为什么需要统一异常处理1.3 Spring异常处理机制2. SpringBoot默认异常处理2.1 默认错误页面2.2 自定义错误页面3. 全局异常处理器3.1 基础全局异常处理器3.2 统一响应格式3.3 使用统一响应格式的异常处理器4. 自定义异常4.1 …

No Hack No CTF 2025Web部分个人WP

No Hack No CTF 2025 Next Song is 春日影 hint:NextJS Vulnerability at /adminCVE-2025-29927Next.js 中间件权限绕过漏洞 访问admin路由发现跳转利用CVE: curl -i \-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:m…

STM32第十八天 ESP8266-01S和电脑实现串口通信

一: ESP和电脑实现串口通信1. 配置 WiFi 模式 ATCWMODE3 // softAPstation mode 响应 : OK 2. 连接路路由器器 ATCWJAP"SSID","password" // SSID and password of router 响应 : OK 3. 查询 ESP8266 设备的 IP 地址 ATCIFSR 响应 : CIFSR:APIP…

STM32第十七天ESP8266-01Swifi模块

ESP8266-01S wifi模块1:ESP8266是实现wifi通讯的一个模块种类,有很多分类包含esp8266-12、esp8266-12E、ESP8266-01S、esp32等等。esp8266-01S由一颗esp8266作为主控再由一块flash作为存储芯片组成,带有板载芯片供电采用3.3V电压使用串口进行…

ProCCD复古相机:捕捉复古瞬间

在数字摄影盛行的今天,复古胶片相机的独特质感和怀旧风格依然吸引着众多摄影爱好者。ProCCD复古相机APP正是这样一款能够满足用户对复古摄影需求的应用程序。它通过模拟复古CCD数码相机的效果,让用户在手机上也能轻松拍出具有千禧年风格的照片和视频。无…

Spring Boot 应用启动时,端口 8080 已被其他进程占用,怎么办

1、修改application.yml配置文件,将端口号更改为未被占用的端口(例如9090)2、以管理员身份运行命令提示符在命令提示符窗口中输入命令netstat -ano | findstr :8080”输出结果可能如下:“TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING xx…

使用Jenkins完成springboot项目快速更新

✨重磅!盹猫的个人小站正式上线啦~诚邀各位技术大佬前来探秘!✨ 这里有: 硬核技术干货:编程技巧、开发经验、踩坑指南,带你解锁技术新姿势!趣味开发日常:代码背后的脑洞故事、工具…

HDLBits刷题笔记和一些拓展知识(九)

文章目录HDLBits刷题笔记CircuitsFsm1Fsm1sFsm2Fsm3onehotExams/ece241 2013 q4Lemmings1Lemmings2Lemmings3Lemmings4Fsm onehotFsm ps2Fsm ps2dataFsm serialFsm serialdataFsm serialdpFsm hdlc未完待续HDLBits刷题笔记 以下是在做HDLBits时的一些刷题笔记,截取一…

CD46.【C++ Dev】list的模拟实现(1)

目录 1.STL库的list 2.模拟实现 节点结构体 list类 无参构造函数 尾插函数 迭代器★ begin() operator 前置 后置 operator-- 前置-- 后置-- operator! operator end() operator* const修饰的迭代器的设计 1.STL库的list 模拟实现list之前,先看看STL库里的…

数据结构——二叉树的基本介绍

————————————本文旨在讨论与学习计算机知识,欢迎交流————————————上一章,我们讲解了树结构的综述导论,那么,现在我们来深入了解一下树结构中最常用研究的结构——二叉树结构(上一章的扩展——…

英伟达发布 Llama Nemotron Nano 4B:专为边缘 AI 和科研任务优化的高效开源推理模型

英伟达推出了 Llama Nem)otron Nano 4B,这是一款专为在科学任务、编程、符号运算、函数调用和指令执行方面提供强大性能与效率而设计的开源推理模型,其紧凑程度足以支持边缘部署。该模型仅包含 40 亿参数,却在内部基准测试中实现了比其他多达…

论文阅读笔记——Autoregressive Image Generation without Vector Quantization

MAR 论文 基于 VQ(向量量化)的图像生成方法具有显著优势,它通过离散化压缩将原始图像映射到有限的 codebook 空间,从而缩小学习范围、降低建模难度,同时这种离散表示更易于与自回归(AG)生成方式…

【科普】关于C 语言日志系统实战:如何同时输出到终端和文件?

1.概述 c语言没有现成的日志库,如果要记录日志,需要自己封装一个日志库。如果要实现日志级别和参数打印,还是比较麻烦的,正好在github找到了一个c语言开源日志库,可以实现日志级别打印,参数打印&#xff0…