AutoGen-AgentChat-3-人机交互

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) ----------
深蓝海洋浩瀚无垠,  
波涛涌动如心潮涌现。  
阳光洒落银光闪烁,  
渔舟唱晚愿随风行。  
TERMINATE


Enter your response:  a


---------- TextMessage (user_proxy) ----------
a
---------- TextMessage (assistant) ----------
请您提供更多信息或明确的问题,我会尽力帮助您。TERMINATE


Enter your response:  写一个甘肃的古诗


---------- TextMessage (user_proxy) ----------
写一个甘肃的古诗
---------- TextMessage (assistant) ----------
祁连山下草如茵,  
甘泉流逸润心田。  
古道西风吹客醉,  
月明孤影共此仙。  
TERMINATE


Enter your response:  approve


---------- TextMessage (user_proxy) ----------
approve
---------- TextMessage (assistant) ----------
如果您需要进一步的帮助或有其他请求,请告诉我!TERMINATE


Enter 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(...) 调用 Console
    await 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 seconds





TaskResult(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) ----------
TERMINATE





TaskResult(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. **情感共鸣**:整首俳句传达出了一种对季节变换的敏感与思考,展现了对北京冬日的独特情感。简单的语言中却蕴含丰富的情感和美感。

建议方面,可以考虑在“红墙映衬黄昏”中添加一些更具体的细节,例如描绘黄昏的色彩,以增强画面的层次感和动感。

总的来说,这是一首很成功的俳句,展现了北京冬日的宁静与美丽。

审批:APPROVE





TaskResult(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. **情感温暖**:最后一句“阳光暖心间”则将春天的温暖与情感结合起来,营造出一种温馨与幸福感,让人心生向往。

整体上,俳句简单而富有层次,情感真挚,意象生动,成功地传达了北京春天的温暖与美丽。

建议方面,可以考虑在“杏花点缀街头”中加入一些形容词,比如“盛开的杏花”或“芬芳的杏花”,这样能更深刻地表现花的美丽与香气。

总的来说,这是一首非常成功的俳句,展现了春天在北京的独特魅力。

审批:APPROVE





TaskResult(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 Sequence

from 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 = False
        self._function_name = function_name

    @property
    def terminated(self) -> bool:
        """返回是否已经触发终止条件"""
        return self._terminated

    async 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 = True
                        return StopMessage(
                            content=f"Function '{self._function_name}' was executed.",  # 返回终止说明
                            source="FunctionCallTermination",  # 指定终止源标识
                        )
        return None  # 若未满足终止条件,返回 None

    async def reset(self) -> None:
        """重置终止状态,用于重新开始对话"""
        self._terminated = False

    def _to_config(self) -> FunctionCallTerminationConfig:
        """将当前实例序列化为配置对象"""
        return FunctionCallTerminationConfig(
            function_name=self._function_name,
        )

    @classmethod
    def _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。

内容概要:本书《Deep Reinforcement Learning with Guaranteed Performance》探讨了基于李雅普诺夫方法的深度强化学习及其在非线性系统最优控制中的应用。书中提出了一种近似最优自适应控制方法,结合泰勒展开、神经网络、估计器设计及滑模控制思想,解决了不同场景下的跟踪控制问题。该方法不仅保证了性能指标的渐近收敛,还确保了跟踪误差的渐近收敛至零。此外,书中还涉及了执行器饱和、冗余解析等问题,并提出了新的冗余解析方法,验证了所提方法的有效性和优越性。 适合人群:研究生及以上学历的研究人员,特别是从事自适应/最优控制、机器人学和动态神经网络领域的学术界和工业界研究人员。 使用场景及目标:①研究非线性系统的最优控制问题,特别是在存在输入约束和系统动力学的情况下;②解决带有参数不确定性的线性和非线性系统的跟踪控制问题;③探索基于李雅普诺夫方法的深度强化学习在非线性系统控制中的应用;④设计和验证针对冗余机械臂的新型冗余解析方法。 其他说明:本书分为七章,每章内容相对独立,便于读者理解。书中不仅提供了理论分析,还通过实际应用(如欠驱动船舶、冗余机械臂)验证了所提方法的有效性。此外,作者鼓励读者通过仿真和实验进一步验证书中提出的理论和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值