{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Team\n", "\n", "在 AgentChat 中,团队定义了代理组如何协作处理任务。一个团队由一个或多个代理组成,通过接收任务和返回任务结果与您的应用程序交互。\n", "它是有状态的,并在多个任务之间维护上下文。团队使用有状态的终止条件来确定何时停止处理当前任务。\n", "\n", "下图显示了团队与您的应用程序之间的关系。\n", "\n", "![AgentChat Teams](./agentchat-team.svg)\n", "\n", "AgentChat 提供了几个预设团队,它们实现了一个或多个[多代理设计模式](../../core-user-guide/design-patterns/index.md)以简化开发。以下是预设团队列表:\n", "\n", "- {py:class}`~autogen_agentchat.teams.RoundRobinGroupChat`: 所有参与者共享上下文,并以轮询方式轮流响应。\n", "- {py:class}`~autogen_agentchat.teams.SelectorGroupChat`: 所有参与者共享上下文,并使用基于模型的选择器(可自定义覆盖)来选择下一个响应的代理。\n", "- {py:class}`~autogen_agentchat.teams.Swarm`: 所有参与者共享上下文,并使用 {py:class}`~autogen_agentchat.messages.HandoffMessage` 将控制权传递给下一个代理。\n", "\n", "在高层次上,团队 API 包含以下方法:\n", "\n", "- {py:meth}`~autogen_agentchat.base.TaskRunner.run`: 处理任务,可以是 {py:class}`str`、{py:class}`~autogen_agentchat.messages.TextMessage` 或 {py:class}`~autogen_agentchat.messages.MultiModalMessage`,并返回 {py:class}`~autogen_agentchat.base.TaskResult`。如果团队尚未重置,任务也可以是 `None` 以继续处理前一个任务。\n", "- {py:meth}`~autogen_agentchat.base.TaskRunner.run_stream`: 与 {py:meth}`~autogen_agentchat.base.TaskRunner.run` 相同,但返回消息的异步生成器和最终任务结果。\n", "- {py:meth}`~autogen_agentchat.base.Team.reset`: 如果下一个任务与前一个任务无关,则重置团队状态。否则,团队可以利用前一个任务的上下文来处理下一个任务。\n", "\n", "在本节中,我们将使用 {py:class}`~autogen_agentchat.teams.RoundRobinGroupChat` 团队来介绍 AgentChat 团队 API。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Round-Robin Group Chat\n", "\n", "我们将从创建一个只有一个 {py:class}`~autogen_agentchat.agents.AssistantAgent` 代理和 {py:class}`~autogen_agentchat.task.TextMentionTermination` 终止条件的团队开始,该条件在检测到特定词时停止。" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from autogen_agentchat.agents import AssistantAgent\n", "from autogen_agentchat.task import TextMentionTermination\n", "from autogen_agentchat.teams import RoundRobinGroupChat\n", "from autogen_ext.models import OpenAIChatCompletionClient\n", "\n", "# Create an OpenAI model client.\n", "model_client = OpenAIChatCompletionClient(\n", " model=\"gpt-4o\",\n", " api_key=\"sk-\", # Optional if you have an OPENAI_API_KEY env variable set.\n", ")\n", "\n", "\n", "# Define a tool that gets the weather for a city.\n", "async def get_weather(city: str) -> str:\n", " \"\"\"Get the weather for a city.\"\"\"\n", " return f\"The weather in {city} is 72 degrees and Sunny.\"\n", "\n", "\n", "# Create an assistant agent.\n", "weather_agent = AssistantAgent(\n", " \"assistant\",\n", " model_client=model_client,\n", " tools=[get_weather],\n", " system_message=\"Respond 'TERMINATE' when task is complete.\",\n", ")\n", "\n", "# Define a termination condition.\n", "text_termination = TextMentionTermination(\"TERMINATE\")\n", "\n", "# Create a single-agent team.\n", "single_agent_team = RoundRobinGroupChat([weather_agent], termination_condition=text_termination)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 运行团队\n", "\n", "我们接下来调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run` 方法以通过一个task启动团队." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TaskResult(messages=[TextMessage(source='user', models_usage=None, content='What is the weather in New York?'), ToolCallMessage(source='assistant', models_usage=RequestUsage(prompt_tokens=70, completion_tokens=15), content=[FunctionCall(id='call_yEkJmydaVYUpZMS3b6wfmUkF', arguments='{\"city\":\"New York\"}', name='get_weather')]), ToolCallResultMessage(source='assistant', models_usage=None, content=[FunctionExecutionResult(content='The weather in New York is 72 degrees and Sunny.', call_id='call_yEkJmydaVYUpZMS3b6wfmUkF')]), TextMessage(source='assistant', models_usage=RequestUsage(prompt_tokens=96, completion_tokens=14), content='The weather in New York is currently 72 degrees and sunny.'), TextMessage(source='assistant', models_usage=RequestUsage(prompt_tokens=126, completion_tokens=4), content='TERMINATE')], stop_reason=\"Text 'TERMINATE' mentioned\")\n" ] } ], "source": [ "async def run_team() -> None:\n", " result = await single_agent_team.run(task=\"What is the weather in New York?\")\n", " print(result)\n", "\n", "\n", "# Use `asyncio.run(run_team())` when running in a script.\n", "await run_team()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "团队运行相同的代理,直到满足终止条件。\n", "在这种情况下,当在代理的响应中检测到\"TERMINATE\"一词时,就满足了终止条件。\n", "当团队停止时,它会返回一个 {py:class}`~autogen_agentchat.base.TaskResult` 对象,其中包含团队中代理产生的所有消息。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 重置团队\n", "\n", "您可以通过调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.reset` 方法来重置团队。\n", "它将清除团队的状态,包括其所有代理的状态。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "await single_agent_team.reset() # Reset the team for the next run." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果下一个任务与前一个任务无关,通常最好重置团队。\n", "但是,如果下一个任务与前一个任务相关,则不需要重置。\n", "\n", "请参阅下面的[恢复团队](#resuming-team)。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 流式传输团队消息\n", "\n", "与代理的 {py:meth}`~autogen_agentchat.agents.BaseChatAgent.on_messages_stream` 方法类似,\n", "您可以通过调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run_stream` 方法来流式传输团队的消息。\n", "它将返回一个生成器,该生成器会在团队中的代理生成消息时产生这些消息,最后一项将是任务结果。" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "source='user' models_usage=None content='What is the weather in New York?'\n", "source='assistant' models_usage=RequestUsage(prompt_tokens=148, completion_tokens=15) content=[FunctionCall(id='call_vKkTpRmeFFclKFZI5Of8NiFA', arguments='{\"city\":\"New York\"}', name='get_weather')]\n", "source='assistant' models_usage=None content=[FunctionExecutionResult(content='The weather in New York is 72 degrees and Sunny.', call_id='call_vKkTpRmeFFclKFZI5Of8NiFA')]\n", "source='assistant' models_usage=RequestUsage(prompt_tokens=174, completion_tokens=14) content='The weather in New York is currently 72 degrees and sunny.'\n", "source='assistant' models_usage=RequestUsage(prompt_tokens=204, completion_tokens=4) content='TERMINATE'\n", "Stop Reason: Text 'TERMINATE' mentioned\n" ] } ], "source": [ "from autogen_agentchat.base import TaskResult\n", "\n", "\n", "async def run_team_stream() -> None:\n", " async for message in single_agent_team.run_stream(task=\"What is the weather in New York?\"):\n", " if isinstance(message, TaskResult):\n", " print(\"Stop Reason:\", message.stop_reason)\n", " else:\n", " print(message)\n", "\n", "\n", "# Use `asyncio.run(run_team_stream())` when running in a script.\n", "await run_team_stream()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如上例所示,您可以通过检查 {py:attr}`~autogen_agentchat.base.TaskResult.stop_reason` 属性来获取团队停止的原因。\n", "\n", "有一个方便的方法 {py:meth}`~autogen_agentchat.task.Console`,它可以将消息以适当的格式打印到控制台。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "What is the weather in Seattle?\n", "---------- assistant ----------\n", "[FunctionCall(id='call_50RPt8ay50PxbilD3RxXm9Ko', arguments='{\"city\":\"Seattle\"}', name='get_weather')]\n", "[Prompt tokens: 69, Completion tokens: 14]\n", "---------- assistant ----------\n", "[FunctionExecutionResult(content='The weather in Seattle is 72 degrees and Sunny.', call_id='call_50RPt8ay50PxbilD3RxXm9Ko')]\n", "---------- assistant ----------\n", "The weather in Seattle is currently 72 degrees and sunny.\n", "[Prompt tokens: 93, Completion tokens: 13]\n", "---------- assistant ----------\n", "TERMINATE\n", "[Prompt tokens: 122, Completion tokens: 4]\n", "---------- Summary ----------\n", "Number of messages: 5\n", "Finish reason: Text 'TERMINATE' mentioned\n", "Total prompt tokens: 284\n", "Total completion tokens: 31\n", "Duration: 2.36 seconds\n" ] } ], "source": [ "from autogen_agentchat.task import Console\n", "\n", "# Use `asyncio.run(single_agent_team.reset())` when running in a script.\n", "await single_agent_team.reset() # Reset the team for the next run.\n", "# Use `asyncio.run(single_agent_team.run_stream(task=\"What is the weather in Seattle?\"))` when running in a script.\n", "await Console(\n", " single_agent_team.run_stream(task=\"What is the weather in Seattle?\")\n", ") # Stream the messages to the console." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 反思模式\n", "\n", "现在我们将创建一个包含两个代理的团队,它实现了反思模式,这是一种多代理设计模式,使用评论家代理来评估主要代理的响应。\n", "\n", "查看使用 [Core API](../../core-user-guide/design-patterns/reflection.ipynb) 的反思模式如何工作。\n", "\n", "在这个例子中,我们将对主要代理和评论家代理都使用 {py:class}`~autogen_agentchat.agents.AssistantAgent` 代理类。\n", "我们将同时使用 {py:class}`~autogen_agentchat.task.TextMentionTermination` 和 {py:class}`~autogen_agentchat.task.MaxMessageTermination` 终止条件来停止团队。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from autogen_agentchat.agents import AssistantAgent\n", "from autogen_agentchat.task import Console, MaxMessageTermination, TextMentionTermination\n", "from autogen_agentchat.teams import RoundRobinGroupChat\n", "from autogen_ext.models import OpenAIChatCompletionClient\n", "\n", "# Create an OpenAI model client.\n", "model_client = OpenAIChatCompletionClient(\n", " model=\"gpt-4o\",\n", " api_key=\"sk-\", # Optional if you have an OPENAI_API_KEY env variable set.\n", ")\n", "\n", "# Create the primary agent.\n", "primary_agent = AssistantAgent(\n", " \"primary\",\n", " model_client=model_client,\n", " system_message=\"You are a helpful AI assistant.\",\n", ")\n", "\n", "# Create the critic agent.\n", "critic_agent = AssistantAgent(\n", " \"critic\",\n", " model_client=model_client,\n", " system_message=\"Provide constructive feedback. Respond with 'APPROVE' to when your feedbacks are addressed.\",\n", ")\n", "\n", "# Define a termination condition that stops the task if the critic approves.\n", "text_termination = TextMentionTermination(\"APPROVE\")\n", "# Define a termination condition that stops the task after 5 messages.\n", "max_message_termination = MaxMessageTermination(5)\n", "# Combine the termination conditions using the `|`` operator so that the\n", "# task stops when either condition is met.\n", "termination = text_termination | max_message_termination\n", "\n", "# Create a team with the primary and critic agents.\n", "reflection_team = RoundRobinGroupChat([primary_agent, critic_agent], termination_condition=termination)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "让我们给团队一个写诗的任务,看看代理之间如何互动。" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "Write a short poem about fall season.\n", "---------- primary ----------\n", "Leaves of amber, gold, and rust, \n", "Gently drift, as branches trust, \n", "Crisp whispers dance upon the breeze, \n", "In the symphony of swaying trees. \n", "\n", "The air turns brisk, a hint of chill, \n", "Pumpkin scents the windowsill, \n", "Sweaters wrap in warm embrace, \n", "As nature shifts at autumn's pace. \n", "\n", "Harvest moons and longest nights, \n", "Lit with warmth from fire's lights, \n", "Fall's gentle touch, both bold and sweet, \n", "Marks the earth beneath our feet. \n", "[Prompt tokens: 27, Completion tokens: 110]\n", "---------- critic ----------\n", "Your poem beautifully captures the essence of the fall season with vivid imagery and a soothing rhythm. The use of sensory details, like \"crisp whispers\" and \"pumpkin scents,\" effectively evokes the atmosphere of autumn. The structure flows well, and the rhyme scheme enhances the poem's cohesiveness. \n", "\n", "To enhance your poem further, consider adding a line or two that conveys an emotional or personal reflection on the season, as this could deepen the connection with the reader. For example, you could explore themes of change or nostalgia that often accompany the fall season.\n", "\n", "Overall, this is a lovely depiction of fall. With a bit more emotional depth, it could become even more relatable and impactful. \n", "[Prompt tokens: 155, Completion tokens: 138]\n", "---------- primary ----------\n", "Thank you for your thoughtful feedback. Here's a revised version that adds a personal reflection on the season:\n", "\n", "Leaves of amber, gold, and rust, \n", "Gently drift, as branches trust, \n", "Crisp whispers dance upon the breeze, \n", "In the symphony of swaying trees. \n", "\n", "The air turns brisk, a hint of chill, \n", "Pumpkin scents the windowsill, \n", "Sweaters wrap in warm embrace, \n", "As nature shifts at autumn's pace. \n", "\n", "In the glow of harvest moon, \n", "Memories rise like a sweetened tune, \n", "Reminding hearts of times long past, \n", "Where moments lingered, meant to last. \n", "\n", "The quiet change, both bold and sweet, \n", "Marks the earth beneath our feet, \n", "In every leaf, a story spins \n", "Of endings new and fresh begins.\n", "[Prompt tokens: 287, Completion tokens: 165]\n", "---------- critic ----------\n", "Your revised poem beautifully integrates a personal reflection, adding an emotional dimension that resonates with readers. The lines about memories rising like a \"sweetened tune\" and moments lingering effectively convey nostalgia and the cyclical nature of change during the fall season. The added stanza flows seamlessly with the rest of the poem, enhancing its depth and relatability.\n", "\n", "The imagery and rhythm remain strong, and you've successfully maintained the poem's cohesiveness while enriching its emotional impact. The balance of sensory details and introspective themes creates a compelling portrayal of the fall season. \n", "\n", "Well done on the revision—your poem now offers both vivid imagery and a heartfelt reflection. \n", "APPROVE\n", "[Prompt tokens: 470, Completion tokens: 130]\n", "---------- Summary ----------\n", "Number of messages: 5\n", "Finish reason: Text 'APPROVE' mentioned, Maximum number of messages 5 reached, current message count: 5\n", "Total prompt tokens: 939\n", "Total completion tokens: 543\n", "Duration: 19.13 seconds\n" ] } ], "source": [ "# Use `asyncio.run(Console(reflection_team.run_stream(task=\"Write a short poem about fall season.\")))` when running in a script.\n", "await Console(\n", " reflection_team.run_stream(task=\"Write a short poem about fall season.\")\n", ") # Stream the messages to the console." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 恢复团队\n", "\n", "让我们在保持前一个任务的上下文的同时,用一个新任务再次运行团队。" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "将这首诗用中文唐诗风格写一遍。\n", "---------- primary ----------\n", "秋叶金黄伴枫红, \n", "随风轻舞信枝桐。 \n", "微凉入袖秋声起, \n", "漫洒余晖满林中。 \n", "\n", "篱边南瓜香自暖, \n", "软衣温柔度晨昏。 \n", "月下收成思往事, \n", "悠悠往昔寄心间。 \n", "\n", "满目枯荣循岁月, \n", "万物变幻自有情。 \n", "片片落叶皆故事, \n", "新陈代谢展新生。 \n", "[Prompt tokens: 613, Completion tokens: 113]\n", "---------- critic ----------\n", "你的诗作成功地将英文版本转换成了中文唐诗风格,展现了秋天的美丽和情感。你运用了优雅的语言和经典的对仗结构,使得整首诗既有传统韵味,又不失原作的意境。\n", "\n", "特别喜欢你在视觉和嗅觉上的描述,比如“秋叶金黄伴枫红”和“篱边南瓜香自暖”,这些都生动地描绘了秋天的特征。情感上的表达也处理得当,“月下收成思往事,悠悠往昔寄心间”很好地抓住了秋天带来的那种怀旧与思索。\n", "\n", "个别用词和句子上,可以考虑稍作调整,以增强唐诗的古典韵味和简练表达,但不失为一篇成功的转化作品。\n", "\n", "整体来说,你的作品很好地保留了原诗的意象与情感,且赋予了中文诗特有的韵律和风貌。佳作!\n", "[Prompt tokens: 744, Completion tokens: 227]\n", "---------- primary ----------\n", "感谢您的详细评价和鼓励!很高兴听到您对这首诗的欣赏和建议。根据您的反馈,我对部分句子进行了调整,以进一步强化唐诗的古典韵味和简练表达。以下是修改后的版本:\n", "\n", "秋叶金风映枫林, \n", "随风轻舞信枝身。 \n", "微凉入袖秋声至, \n", "斜阳洒落漫山昕。 \n", "\n", "篱畔瓜香暖人意, \n", "长袖轻拥度朝曛。 \n", "月下思怀当年事, \n", "点滴往昔驻心神。 \n", "\n", "枯荣迭代随天命, \n", "万物更替总有情。 \n", "片片落叶皆故事, \n", "新旧交替见新生。 \n", "\n", "希望这次的版本更符合唐诗的风格和表达。感谢您的建议,让这首诗更加完善!\n", "[Prompt tokens: 965, Completion tokens: 197]\n", "---------- critic ----------\n", "这个经过调整后的版本确实更贴合唐诗的风格,展现了简练而优雅的古典韵味。你在语言上做出的细微改动,如“秋叶金风映枫林”和“微凉入袖秋声至”,不仅保留了原意,还增加了一种古典的诗意流畅感。\n", "\n", "“月下思怀当年事,点滴往昔驻心神”这一对仗更加工整,将怀旧的情感表达得更加凝练。同时,最后两句“枯荣迭代随天命,万物更替总有情”阐明了秋季寓意的哲理,提升了全诗的思想深度。\n", "\n", "你的调整成功地强化了诗歌的古典美感,使之在表达上更加契合唐诗风格。欣赏你的用心和对细节的把握,这个版本更趋完美。 佳作! \n", "\n", "APPROVE\n", "[Prompt tokens: 1180, Completion tokens: 214]\n", "---------- Summary ----------\n", "Number of messages: 5\n", "Finish reason: Text 'APPROVE' mentioned, Maximum number of messages 5 reached, current message count: 5\n", "Total prompt tokens: 3502\n", "Total completion tokens: 751\n", "Duration: 20.76 seconds\n" ] } ], "source": [ "# Write the poem in Chinese Tang poetry style.\n", "# Use `asyncio.run(Console(reflection_team.run_stream(task=\"将这首诗用中文唐诗风格写一遍。\")))` when running in a script.\n", "await Console(reflection_team.run_stream(task=\"将这首诗用中文唐诗风格写一遍。\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "继续另一项任务。" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "Write the poem in Spanish.\n", "---------- primary ----------\n", "Here is the poem translated into Spanish:\n", "\n", "Hojas de ámbar, oro, carmesí, \n", "Danzo al viento que anuncia así, \n", "Susurros nítidos en brisa leve, \n", "Mecen los árboles, danza que se atreve. \n", "\n", "El aire se enfría, suave frescor, \n", "Calabaza perfuma el entorno en su sabor, \n", "Jerséis envuelven en cálido abrazo, \n", "Mientras el otoño avanza con su paso. \n", "\n", "Bajo la luna de cosecha, el recuerdo vive, \n", "Melodías del pasado, el corazón revive, \n", "Momentos que duran, tiempos queridos, \n", "Ecos de cambio, ciclos compartidos. \n", "\n", "La callada transformación, dulce y fuerte, \n", "Marca la tierra bajo el pie andante, \n", "En cada hoja, una historia gira, \n", "De finales y comienzos, la vida conspira. \n", "[Prompt tokens: 1399, Completion tokens: 185]\n", "---------- critic ----------\n", "Your Spanish translation of the poem effectively retains the essence and imagery of the original version. The vivid descriptions, like \"hojas de ámbar, oro, carmesí\" and \"calabaza perfuma el entorno,\" capture the autumn atmosphere well. The poem flows gracefully, maintaining the rhythm and emotional tone across both versions.\n", "\n", "The stanza about the harvest moon beautifully translates nostalgia and reflection through lines like \"bajo la luna de cosecha, el recuerdo vive.\" You've managed to communicate the cyclical nature of change in the season, encapsulated in the line \"de finales y comienzos, la vida conspira.\"\n", "\n", "Consider the rhythm in some lines to ensure a more seamless flow, as Spanish poetry often relies on syllable count for melody. Overall, you've done a great job translating the poem while preserving its thematic depth and imagery. \n", "\n", "The poem is well crafted and evocative in both languages. \n", "\n", "APPROVE\n", "[Prompt tokens: 1602, Completion tokens: 185]\n", "---------- Summary ----------\n", "Number of messages: 3\n", "Finish reason: Text 'APPROVE' mentioned\n", "Total prompt tokens: 3001\n", "Total completion tokens: 370\n", "Duration: 9.63 seconds\n" ] } ], "source": [ "# Write the poem in Spanish.\n", "# Use `asyncio.run(Console(reflection_team.run_stream(task=\"Write the poem in Spanish.\")))` when running in a script.\n", "await Console(reflection_team.run_stream(task=\"Write the poem in Spanish.\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 恢复前一个任务\n", "\n", "我们可以调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run` 或 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run_stream` 方法,而无需再次设置 `task` 来恢复前一个任务。团队将从停止的地方继续。" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- primary ----------\n", "Thank you for your thoughtful review and approval. I appreciate your insights regarding the rhythm and structure. Here's a slight revision to enhance the flow while keeping the imagery and emotional tone intact:\n", "\n", "Hojas de ámbar, oro en vuelo, \n", "Bailan al viento con suave anhelo. \n", "Susurros frescos en brisa leve, \n", "Mecen los árboles, el canto se atreve. \n", "\n", "El aire enfría con fresco sabor, \n", "La calabaza perfuma de amor. \n", "Jerséis cobijan calidez cercana, \n", "Mientras el otoño su paso desgrana. \n", "\n", "La luna de cosecha nos hace pensar, \n", "Melodías pasadas vuelven a sonar. \n", "Momentos que perduran, tiempos vividos, \n", "Ecos de cambio, ritmos compartidos.\n", "\n", "Transformación callada, dulce y entera, \n", "Marca la tierra donde la vida espera. \n", "En cada hoja, una historia canta, \n", "De fines y principios, la vida encanta. \n", "\n", "I hope this version better captures the melodic essence of the poem. Thank you for your feedback—it continues to guide the refinement process.\n", "[Prompt tokens: 1781, Completion tokens: 228]\n", "---------- critic ----------\n", "Your revised Spanish version of the poem beautifully enhances the flow and rhythm, achieving a harmonious melody that aligns well with Spanish poetic traditions. The adjustments you made, such as \"Hojas de ámbar, oro en vuelo\" and \"Bailan al viento con suave anhelo,\" improve the lyrical quality and maintain the vivid imagery.\n", "\n", "The line \"La luna de cosecha nos hace pensar\" effectively conveys reflection, and you've preserved the emotional depth found in the original poem. The final stanza, \"Transformación callada, dulce y entera,\" captures the essence of change and transition elegantly, ending on a contemplative note.\n", "\n", "Your efforts to refine the rhythm and structure are noticeable and successful, making the poem more cohesive while preserving its thematic depth. This version indeed captures the melodic essence and the imagery beautifully. Well done! \n", "\n", "APPROVE\n", "[Prompt tokens: 2027, Completion tokens: 169]\n", "---------- Summary ----------\n", "Number of messages: 2\n", "Finish reason: Text 'APPROVE' mentioned\n", "Total prompt tokens: 3808\n", "Total completion tokens: 397\n", "Duration: 9.34 seconds\n" ] } ], "source": [ "# Use the `asyncio.run(Console(reflection_team.run_stream()))` when running in a script.\n", "await Console(reflection_team.run_stream())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 暂停等待用户输入\n", "\n", "通常,团队需要来自应用程序(即用户)的额外输入才能继续处理任务。我们将展示两种可能的方法:\n", "\n", "- 设置最大轮次数,使团队在指定轮次数后停止。\n", "- 使用 {py:class}`~autogen_agentchat.task.HandoffTermination` 终止条件。\n", "\n", "您也可以使用自定义终止条件,请参阅 [Termination Conditions](./termination.ipynb)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 最大轮次\n", "\n", "这是暂停团队等待用户输入的最简单方法。例如,您可以将最大轮次数设置为 1,这样团队会在第一个代理响应后立即停止。当您希望用户持续与团队互动时,这很有用,比如在聊天机器人场景中。\n", "\n", "只需在 {py:meth}`~autogen_agentchat.teams.RoundRobinGroupChat` 构造函数中设置 `max_turns` 参数。\n", "\n", "```python\n", "team = RoundRobinGroupChat([...], max_turns=1)\n", "```\n", "\n", "一旦团队停止,轮次计数将被重置。当您恢复团队时,它将再次从 0 开始。\n", "\n", "注意,`max_turn` 是特定于团队类的,目前仅由\n", "{py:class}`~autogen_agentchat.teams.RoundRobinGroupChat`、{py:class}`~autogen_agentchat.teams.SelectorGroupChat` 和 {py:class}`~autogen_agentchat.teams.Swarm` 支持。\n", "当与终止条件一起使用时,团队将在满足任一条件时停止。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 使用移交来暂停团队\n", "\n", "您可以使用 {py:class}`~autogen_agentchat.task.HandoffTermination` 终止条件来在代理发送 {py:class}`~autogen_agentchat.messages.HandoffMessage` 消息时停止团队。\n", "\n", "让我们创建一个包含单个带有移交设置的 {py:class}`~autogen_agentchat.agents.AssistantAgent` 代理的团队。\n", "\n", "```{note}\n", "与 {py:class}~autogen_agentchat.agents.AssistantAgent 一起使用的模型必须支持工具调用才能使用移交功能。\n", "```" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from autogen_agentchat.agents import AssistantAgent, Handoff\n", "from autogen_agentchat.task import HandoffTermination, TextMentionTermination\n", "from autogen_agentchat.teams import RoundRobinGroupChat\n", "from autogen_ext.models import OpenAIChatCompletionClient\n", "\n", "# Create an OpenAI model client.\n", "model_client = OpenAIChatCompletionClient(\n", " model=\"gpt-4o\",\n", " api_key=\"sk-\", # Optional if you have an OPENAI_API_KEY env variable set.\n", ")\n", "\n", "# Create a lazy assistant agent that always hands off to the user.\n", "lazy_agent = AssistantAgent(\n", " \"lazy_assistant\",\n", " model_client=model_client,\n", " handoffs=[Handoff(target=\"user\", message=\"Transfer to user.\")],\n", " system_message=\"Always transfer to user when you don't know the answer. Respond 'TERMINATE' when task is complete.\",\n", ")\n", "\n", "# Define a termination condition that checks for handoff message targetting helper and text \"TERMINATE\".\n", "handoff_termination = HandoffTermination(target=\"user\")\n", "text_termination = TextMentionTermination(\"TERMINATE\")\n", "termination = handoff_termination | text_termination\n", "\n", "# Create a single-agent team.\n", "lazy_agent_team = RoundRobinGroupChat([lazy_agent], termination_condition=termination)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "让我们用一个需要用户额外输入的任务来运行团队,因为代理没有相关的工具来继续处理任务。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "What is the weather in New York?\n", "---------- lazy_assistant ----------\n", "[FunctionCall(id='call_TUNN7UUSzSIzkPW4OQs4wENx', arguments='{}', name='transfer_to_user')]\n", "[Prompt tokens: 68, Completion tokens: 11]\n", "---------- lazy_assistant ----------\n", "[FunctionExecutionResult(content='Transfer to user.', call_id='call_TUNN7UUSzSIzkPW4OQs4wENx')]\n", "---------- lazy_assistant ----------\n", "Transfer to user.\n", "---------- Summary ----------\n", "Number of messages: 4\n", "Finish reason: Handoff to user from lazy_assistant detected.\n", "Total prompt tokens: 68\n", "Total completion tokens: 11\n", "Duration: 1.26 seconds\n" ] } ], "source": [ "from autogen_agentchat.task import Console\n", "\n", "# Use `asyncio.run(Console(lazy_agent_team.run_stream(task=\"What is the weather in New York?\")))` when running in a script.\n", "await Console(lazy_agent_team.run_stream(task=\"What is the weather in New York?\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "您可以看到团队因为检测到移交消息而停止。\n", "让我们通过提供代理需要的信息来继续团队。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "It is raining in New York.\n", "---------- lazy_assistant ----------\n", "Thank you for the update! If you have any other questions or need further information, feel free to ask.\n", "[Prompt tokens: 108, Completion tokens: 23]\n", "---------- lazy_assistant ----------\n", "TERMINATE\n", "[Prompt tokens: 138, Completion tokens: 4]\n", "---------- Summary ----------\n", "Number of messages: 3\n", "Finish reason: Text 'TERMINATE' mentioned\n", "Total prompt tokens: 246\n", "Total completion tokens: 27\n", "Duration: 1.52 seconds\n" ] } ], "source": [ "# Use `asyncio.run(Console(lazy_agent_team.run_stream(task=\"It is raining in New York.\")))` when running in a script.\n", "await Console(lazy_agent_team.run_stream(task=\"It is raining in New York.\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "```{note}\n", "目前移交终止方法不适用于 {py:class}`~autogen_agentchat.teams.Swarm`。\n", "请继续关注更新。\n", "```\n", "```" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 2 }