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。