{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 团队\n\n在本节中,您将学习如何使用AutoGen创建_多智能体团队_(简称团队)。团队是一组共同协作以实现共同目标的智能体。\n\n我们将首先展示如何创建和运行一个团队。然后解释如何观察团队行为(这对调试和理解团队性能至关重要),以及控制团队行为的常见操作。\n\n\nAgentChat支持多种团队预设:\n\n- {py:class}`~autogen_agentchat.teams.RoundRobinGroupChat`: 以轮转方式让参与者轮流发言的群聊团队(本页介绍)。[教程](#creating-a-team)\n- {py:class}`~autogen_agentchat.teams.SelectorGroupChat`: 在每条消息后使用ChatCompletion模型选择下一位发言者的团队。[教程](../selector-group-chat.ipynb)\n- {py:class}`~autogen_agentchat.teams.MagenticOneGroupChat`: 用于解决跨领域开放式网页和文件任务的通用多智能体系统。[教程](../magentic-one.md)\n- {py:class}`~autogen_agentchat.teams.Swarm`: 使用{py:class}`~autogen_agentchat.messages.HandoffMessage`信号在智能体间切换的团队。[教程](../swarm.ipynb)\n\n```{note}\n\n**何时应该使用团队?**\n\n团队适用于需要协作和多样化专业知识的复杂任务。\n但与单个智能体相比,它们需要更多的框架来引导。\n虽然AutoGen简化了团队协作流程,但对于简单任务建议从单个智能体开始,\n当单个智能体无法胜任时再过渡到多智能体团队。\n在采用团队方法前,请确保已用适当的工具和指令优化过您的单个智能体。\n```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 创建团队\n\n{py:class}`~autogen_agentchat.teams.RoundRobinGroupChat`是一种简单而有效的团队配置,所有智能体共享相同上下文并按轮转方式依次响应。每个智能体在轮到自己时,会将其响应广播给所有其他智能体,确保整个团队保持一致的上下文。\n\n我们将从创建一个包含两个{py:class}`~autogen_agentchat.agents.AssistantAgent`的团队开始,并设置一个{py:class}`~autogen_agentchat.conditions.TextMentionTermination`条件,当在智能体响应中检测到特定单词时停止团队。\n\n这个双智能体团队实现了_反思_模式,这是一种多智能体设计模式,其中评论者智能体会评估主智能体的响应。通过[核心API](../../core-user-guide/design-patterns/reflection.ipynb)了解更多关于反思模式的内容。\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "\n", "from autogen_agentchat.agents import AssistantAgent\n", "from autogen_agentchat.base import TaskResult\n", "from autogen_agentchat.conditions import ExternalTermination, TextMentionTermination\n", "from autogen_agentchat.teams import RoundRobinGroupChat\n", "from autogen_agentchat.ui import Console\n", "from autogen_core import CancellationToken\n", "from autogen_ext.models.openai import OpenAIChatCompletionClient\n", "\n", "# 创建OpenAI模型客户端。\n", "model_client = OpenAIChatCompletionClient(\n", " model=\"gpt-4o-2024-08-06\",\n", " # api_key=\"sk-...\", # 如果已设置OPENAI_API_KEY环境变量则可选\n", ")\n", "\n", "# 创建主智能体。\n", "primary_agent = AssistantAgent(\n", " \"primary\",\n", " model_client=model_client,\n", " system_message=\"You are a helpful AI assistant.\",\n", ")\n", "\n", "# 创建评论家代理。\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", "# 定义一个终止条件,当评论家批准时停止任务。\n", "text_termination = TextMentionTermination(\"APPROVE\")\n", "\n", "# 创建一个包含主要代理和评论家代理的团队。\n", "team = RoundRobinGroupChat([primary_agent, critic_agent], termination_condition=text_termination)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 运行团队\n\n我们将调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run` 方法\n来启动团队并执行任务。\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TaskResult(messages=[TextMessage(source='user', models_usage=None, content='Write a short poem about the fall season.', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=28, completion_tokens=109), content=\"Leaves of amber, gold, and rust, \\nDance upon the gentle gust. \\nCrisp air whispers tales of old, \\nAs daylight wanes, the night grows bold. \\n\\nPumpkin patch and apple treats, \\nLaughter in the street repeats. \\nSweaters warm and fires aglow, \\nIt's time for nature's vibrant show. \\n\\nThe harvest moon ascends the sky, \\nWhile geese in formation start to fly. \\nAutumn speaks in colors bright, \\nA fleeting grace, a pure delight. \", type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=154, completion_tokens=200), content='Your poem beautifully captures the essence of the fall season with vivid imagery and a rhythmic flow. The use of descriptive language like \"amber, gold, and rust\" effectively paints a visual picture of the changing leaves. Phrases such as \"crisp air whispers tales of old\" and \"daylight wanes, the night grows bold\" add a poetic touch by incorporating seasonal characteristics.\\n\\nHowever, you might consider exploring other sensory details to deepen the reader\\'s immersion. For example, mentioning the sound of crunching leaves underfoot or the scent of cinnamon and spices in the air could enhance the sensory experience.\\n\\nAdditionally, while the mention of \"pumpkin patch and apple treats\" is evocative of fall, expanding on these elements or including more personal experiences or emotions associated with the season might make the poem more relatable and engaging.\\n\\nOverall, you\\'ve crafted a lovely poem that celebrates the beauty and traditions of autumn with grace and warmth. A few tweaks to include multisensory details could elevate it even further.', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=347, completion_tokens=178), content=\"Thank you for the thoughtful feedback. Here's a revised version of the poem with additional sensory details:\\n\\nLeaves of amber, gold, and rust, \\nDance upon the gentle gust. \\nCrisp air whispers tales of old, \\nAs daylight wanes, the night grows bold. \\n\\nCrunch beneath the wandering feet, \\nA melody of autumn's beat. \\nCinnamon and spices blend, \\nIn every breeze, nostalgia sends. \\n\\nPumpkin patch and apple treats, \\nLaughter in the street repeats. \\nSweaters warm and fires aglow, \\nIt's time for nature's vibrant show. \\n\\nThe harvest moon ascends the sky, \\nWhile geese in formation start to fly. \\nAutumn speaks in colors bright, \\nA fleeting grace, a pure delight. \\n\\nI hope this version resonates even more with the spirit of fall. Thank you again for your suggestions!\", type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=542, completion_tokens=3), content='APPROVE', type='TextMessage')], stop_reason=\"Text 'APPROVE' mentioned\")\n" ] } ], "source": [ "# 在脚本中运行时使用 `asyncio.run(...)`。\n", "result = await team.run(task=\"Write a short poem about the fall season.\")\n", "print(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "团队持续运行代理,直到满足终止条件。\n在本例中,团队按照轮询顺序运行代理,直到在代理响应中检测到\"APPROVE\"一词时满足终止条件。\n当团队停止时,它会返回一个包含团队中所有代理生成消息的{py:class}`~autogen_agentchat.base.TaskResult`对象。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 观察团队运行\n\n与代理的{py:meth}`~autogen_agentchat.agents.BaseChatAgent.on_messages_stream`方法类似,您可以通过调用{py:meth}`~autogen_agentchat.teams.BaseGroupChat.run_stream`方法在团队运行时流式传输其消息。该方法返回一个生成器,随着消息的产生,它会逐个生成团队中代理产生的消息,最后一项是{py:class}`~autogen_agentchat.base.TaskResult`对象。\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "source='user' models_usage=None content='Write a short poem about the fall season.' type='TextMessage'\n", "source='primary' models_usage=RequestUsage(prompt_tokens=28, completion_tokens=105) content=\"Leaves descend in golden dance, \\nWhispering secrets as they fall, \\nCrisp air brings a gentle trance, \\nHeralding Autumn's call. \\n\\nPumpkins glow with orange light, \\nFields wear a cloak of amber hue, \\nDays retreat to longer night, \\nSkies shift to deeper blue. \\n\\nWinds carry scents of earth and pine, \\nSweaters wrap us, warm and tight, \\nNature's canvas, bold design, \\nIn Fall's embrace, we find delight. \" type='TextMessage'\n", "source='critic' models_usage=RequestUsage(prompt_tokens=150, completion_tokens=226) content='Your poem beautifully captures the essence of fall with vivid imagery and a soothing rhythm. The imagery of leaves descending, pumpkins glowing, and fields cloaked in amber hues effectively paints a picture of the autumn season. The use of contrasting elements like \"Days retreat to longer night\" and \"Sweaters wrap us, warm and tight\" provides a nice balance between the cold and warmth associated with the season. Additionally, the personification of autumn through phrases like \"Autumn\\'s call\" and \"Nature\\'s canvas, bold design\" adds depth to the depiction of fall.\\n\\nTo enhance the poem further, you might consider focusing on the soundscape of fall, such as the rustling of leaves or the distant call of migrating birds, to engage readers\\' auditory senses. Also, varying the line lengths slightly could add a dynamic flow to the reading experience.\\n\\nOverall, your poem is engaging and effectively encapsulates the beauty and transition of fall. With a few adjustments to explore other sensory details, it could become even more immersive. \\n\\nIf you incorporate some of these suggestions or find another way to expand the sensory experience, please share your update!' type='TextMessage'\n", "source='primary' models_usage=RequestUsage(prompt_tokens=369, completion_tokens=143) content=\"Thank you for the thoughtful critique and suggestions. Here's a revised version of the poem with added attention to auditory senses and varied line lengths:\\n\\nLeaves descend in golden dance, \\nWhisper secrets in their fall, \\nBreezes hum a gentle trance, \\nHeralding Autumn's call. \\n\\nPumpkins glow with orange light, \\nAmber fields beneath wide skies, \\nDays retreat to longer night, \\nChill winds and distant cries. \\n\\nRustling whispers of the trees, \\nSweaters wrap us, snug and tight, \\nNature's canvas, bold and free, \\nIn Fall's embrace, pure delight. \\n\\nI appreciate your feedback and hope this version better captures the sensory richness of the season!\" type='TextMessage'\n", "source='critic' models_usage=RequestUsage(prompt_tokens=529, completion_tokens=160) content='Your revised poem is a beautiful enhancement of the original. By incorporating auditory elements such as \"Breezes hum\" and \"Rustling whispers of the trees,\" you\\'ve added an engaging soundscape that draws the reader deeper into the experience of fall. The varied line lengths work well to create a more dynamic rhythm throughout the poem, adding interest and variety to each stanza.\\n\\nThe succinct, yet vivid, lines of \"Chill winds and distant cries\" wonderfully evoke the atmosphere of the season, adding a touch of mystery and depth. The final stanza wraps up the poem nicely, celebrating the complete sensory embrace of fall with lines like \"Nature\\'s canvas, bold and free.\"\\n\\nYou\\'ve successfully infused more sensory richness into the poem, enhancing its overall emotional and atmospheric impact. Great job on the revisions!\\n\\nAPPROVE' type='TextMessage'\n", "Stop Reason: Text 'APPROVE' mentioned\n" ] } ], "source": [ "# 在脚本内部运行时,请使用异步主函数并通过`asyncio.run(...)`调用它。\n", "await team.reset() # 重置团队以执行新任务。\n", "async for message in team.run_stream(task=\"Write a short poem about the fall season.\"): # type: ignore\n", " if isinstance(message, TaskResult):\n", " print(\"Stop Reason:\", message.stop_reason)\n", " else:\n", " print(message)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如上述示例所示,您可以通过检查 {py:attr}`~autogen_agentchat.base.TaskResult.stop_reason` 属性来确定团队停止的原因。\n\n{py:meth}`~autogen_agentchat.ui.Console` 方法提供了一种便捷的方式,可将消息以适当格式打印到控制台。\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "Write a short poem about the fall season.\n", "---------- primary ----------\n", "Golden leaves in crisp air dance, \n", "Whispering tales as they prance. \n", "Amber hues paint the ground, \n", "Nature's symphony all around. \n", "\n", "Sweaters hug with tender grace, \n", "While pumpkins smile, a warm embrace. \n", "Chill winds hum through towering trees, \n", "A vibrant tapestry in the breeze. \n", "\n", "Harvest moons in twilight glow, \n", "Casting magic on fields below. \n", "Fall's embrace, a gentle call, \n", "To savor beauty before snowfalls. \n", "[Prompt tokens: 28, Completion tokens: 99]\n", "---------- critic ----------\n", "Your poem beautifully captures the essence of the fall season, creating a vivid and cozy atmosphere. The imagery of golden leaves and amber hues paints a picturesque scene that many can easily relate to. I particularly appreciate the personification of pumpkins and the gentle embrace of sweaters, which adds warmth to your verses. \n", "\n", "To enhance the poem further, you might consider adding more sensory details to make the reader feel even more immersed in the experience. For example, including specific sounds, scents, or textures could deepen the connection to autumn's ambiance. Additionally, you could explore the emotional transitions as the season prepares for winter to provide a reflective element to the piece.\n", "\n", "Overall, it's a lovely and evocative depiction of fall, evoking feelings of comfort and appreciation for nature's changing beauty. Great work!\n", "[Prompt tokens: 144, Completion tokens: 157]\n", "---------- primary ----------\n", "Thank you for your thoughtful feedback! I'm glad you enjoyed the imagery and warmth in the poem. To enhance the sensory experience and emotional depth, here's a revised version incorporating your suggestions:\n", "\n", "---\n", "\n", "Golden leaves in crisp air dance, \n", "Whispering tales as they prance. \n", "Amber hues paint the crunchy ground, \n", "Nature's symphony all around. \n", "\n", "Sweaters hug with tender grace, \n", "While pumpkins grin, a warm embrace. \n", "Chill winds hum through towering trees, \n", "Crackling fires warm the breeze. \n", "\n", "Apples in the orchard's glow, \n", "Sweet cider scents that overflow. \n", "Crunch of paths beneath our feet, \n", "Cinnamon spice and toasty heat. \n", "\n", "Harvest moons in twilight's glow, \n", "Casting magic on fields below. \n", "Fall's embrace, a gentle call, \n", "Reflects on life's inevitable thaw. \n", "\n", "--- \n", "\n", "I hope this version enhances the sensory and emotional elements of the season. Thank you again for your insights!\n", "[Prompt tokens: 294, Completion tokens: 195]\n", "---------- critic ----------\n", "APPROVE\n", "[Prompt tokens: 506, Completion tokens: 4]\n", "---------- Summary ----------\n", "Number of messages: 5\n", "Finish reason: Text 'APPROVE' mentioned\n", "Total prompt tokens: 972\n", "Total completion tokens: 455\n", "Duration: 11.78 seconds\n" ] }, { "data": { "text/plain": [ "TaskResult(messages=[TextMessage(source='user', models_usage=None, content='Write a short poem about the fall season.', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=28, completion_tokens=99), content=\"Golden leaves in crisp air dance, \\nWhispering tales as they prance. \\nAmber hues paint the ground, \\nNature's symphony all around. \\n\\nSweaters hug with tender grace, \\nWhile pumpkins smile, a warm embrace. \\nChill winds hum through towering trees, \\nA vibrant tapestry in the breeze. \\n\\nHarvest moons in twilight glow, \\nCasting magic on fields below. \\nFall's embrace, a gentle call, \\nTo savor beauty before snowfalls. \", type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=144, completion_tokens=157), content=\"Your poem beautifully captures the essence of the fall season, creating a vivid and cozy atmosphere. The imagery of golden leaves and amber hues paints a picturesque scene that many can easily relate to. I particularly appreciate the personification of pumpkins and the gentle embrace of sweaters, which adds warmth to your verses. \\n\\nTo enhance the poem further, you might consider adding more sensory details to make the reader feel even more immersed in the experience. For example, including specific sounds, scents, or textures could deepen the connection to autumn's ambiance. Additionally, you could explore the emotional transitions as the season prepares for winter to provide a reflective element to the piece.\\n\\nOverall, it's a lovely and evocative depiction of fall, evoking feelings of comfort and appreciation for nature's changing beauty. Great work!\", type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=294, completion_tokens=195), content=\"Thank you for your thoughtful feedback! I'm glad you enjoyed the imagery and warmth in the poem. To enhance the sensory experience and emotional depth, here's a revised version incorporating your suggestions:\\n\\n---\\n\\nGolden leaves in crisp air dance, \\nWhispering tales as they prance. \\nAmber hues paint the crunchy ground, \\nNature's symphony all around. \\n\\nSweaters hug with tender grace, \\nWhile pumpkins grin, a warm embrace. \\nChill winds hum through towering trees, \\nCrackling fires warm the breeze. \\n\\nApples in the orchard's glow, \\nSweet cider scents that overflow. \\nCrunch of paths beneath our feet, \\nCinnamon spice and toasty heat. \\n\\nHarvest moons in twilight's glow, \\nCasting magic on fields below. \\nFall's embrace, a gentle call, \\nReflects on life's inevitable thaw. \\n\\n--- \\n\\nI hope this version enhances the sensory and emotional elements of the season. Thank you again for your insights!\", type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=506, completion_tokens=4), content='APPROVE', type='TextMessage')], stop_reason=\"Text 'APPROVE' mentioned\")" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await team.reset() # 重置团队以执行新任务。\n", "await Console(team.run_stream(task=\"Write a short poem about the fall season.\")) # 将消息流式传输到控制台。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 重置团队\n\n您可以通过调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.reset` 方法来重置团队。该方法将清除团队状态,包括所有代理。\n它将调用每个代理的 {py:meth}`~autogen_agentchat.base.ChatAgent.on_reset` 方法来清除代理状态。\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "await team.reset() # 为下一次运行重置团队。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果下一个任务与上一个任务无关,通常最好重置团队。\n但如果下一个任务与上一个任务相关,则无需重置,可以继续使用该团队。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 停止团队\n\n除了像 {py:class}`~autogen_agentchat.conditions.TextMentionTermination` 这样基于团队内部状态自动终止的条件外,\n你也可以通过 {py:class}`~autogen_agentchat.conditions.ExternalTermination` 从外部停止团队。\n\n调用 {py:meth}`~autogen_agentchat.conditions.ExternalTermination.set` \n在 {py:class}`~autogen_agentchat.conditions.ExternalTermination` 上会在当前代理回合结束时停止团队。\n因此,团队可能不会立即停止。\n这允许当前代理完成其回合并在团队停止前向团队广播最终消息,保持团队状态一致。\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "Write a short poem about the fall season.\n", "---------- primary ----------\n", "Leaves of amber, gold, and red, \n", "Gently drifting from trees overhead. \n", "Whispers of wind through the crisp, cool air, \n", "Nature's canvas painted with care. \n", "\n", "Harvest moons and evenings that chill, \n", "Fields of plenty on every hill. \n", "Sweaters wrapped tight as twilight nears, \n", "Fall's charming embrace, as warm as it appears. \n", "\n", "Pumpkins aglow with autumn's light, \n", "Harvest feasts and stars so bright. \n", "In every leaf and breeze that calls, \n", "We find the magic of glorious fall. \n", "[Prompt tokens: 28, Completion tokens: 114]\n", "---------- Summary ----------\n", "Number of messages: 2\n", "Finish reason: External termination requested\n", "Total prompt tokens: 28\n", "Total completion tokens: 114\n", "Duration: 1.71 seconds\n" ] }, { "data": { "text/plain": [ "TaskResult(messages=[TextMessage(source='user', models_usage=None, content='Write a short poem about the fall season.', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=28, completion_tokens=114), content=\"Leaves of amber, gold, and red, \\nGently drifting from trees overhead. \\nWhispers of wind through the crisp, cool air, \\nNature's canvas painted with care. \\n\\nHarvest moons and evenings that chill, \\nFields of plenty on every hill. \\nSweaters wrapped tight as twilight nears, \\nFall's charming embrace, as warm as it appears. \\n\\nPumpkins aglow with autumn's light, \\nHarvest feasts and stars so bright. \\nIn every leaf and breeze that calls, \\nWe find the magic of glorious fall. \", type='TextMessage')], stop_reason='External termination requested')" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 创建一个带有外部终止条件的新团队。\n", "external_termination = ExternalTermination()\n", "team = RoundRobinGroupChat(\n", " [primary_agent, critic_agent],\n", " termination_condition=external_termination | text_termination, # 使用按位或运算符组合条件。\n", ")\n", "\n", "# 在后台任务中运行团队。\n", "run = asyncio.create_task(Console(team.run_stream(task=\"Write a short poem about the fall season.\")))\n", "\n", "# 等待一段时间。\n", "await asyncio.sleep(0.1)\n", "\n", "# 停止团队。\n", "external_termination.set()\n", "\n", "# 等待团队完成。\n", "await run" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "从上面的输出可以看出,团队停止是因为满足了外部终止条件,\n但发言代理在团队停止前完成了它的回合。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 恢复团队\n\n团队是有状态的,除非你重置团队,否则每次运行后都会保留对话历史和上下文。\n\n你可以通过再次调用 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run` 或 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run_stream` 方法(无需新任务)\n来恢复团队,从上次中断的地方继续。\n{py:class}`~autogen_agentchat.teams.RoundRobinGroupChat` 会从轮询顺序中的下一个代理继续执行。\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- critic ----------\n", "This poem beautifully captures the essence of the fall season with vivid imagery and a soothing rhythm. The descriptions of the changing leaves, cool air, and various autumn traditions make it easy for readers to envision and feel the charm of fall. Here are a few suggestions to enhance its impact:\n", "\n", "1. **Structure Variation**: Consider breaking some lines with a hyphen or ellipsis for dramatic effect or emphasis. For instance, “Sweaters wrapped tight as twilight nears— / Fall’s charming embrace, as warm as it appears.\"\n", "\n", "2. **Sensory Details**: While the poem already evokes visual and tactile senses, incorporating other senses such as sound or smell could deepen the immersion. For example, include the scent of wood smoke or the crunch of leaves underfoot.\n", "\n", "3. **Metaphorical Language**: Adding metaphors or similes can further enrich the imagery. For example, you might compare the leaves falling to a golden rain or the chill in the air to a gentle whisper.\n", "\n", "Overall, it’s a lovely depiction of fall. These suggestions are minor tweaks that might elevate the reader's experience even further. Nice work!\n", "\n", "Let me know if these feedbacks are addressed.\n", "[Prompt tokens: 159, Completion tokens: 237]\n", "---------- primary ----------\n", "Thank you for the thoughtful feedback! Here’s a revised version, incorporating your suggestions: \n", "\n", "Leaves of amber, gold—drifting like dreams, \n", "A golden rain from trees’ canopies. \n", "Whispers of wind—a gentle breath, \n", "Nature’s scented tapestry embracing earth. \n", "\n", "Harvest moons rise as evenings chill, \n", "Fields of plenty paint every hill. \n", "Sweaters wrapped tight as twilight nears— \n", "Fall’s embrace, warm as whispered years. \n", "\n", "Pumpkins aglow with autumn’s light, \n", "Crackling leaves underfoot in flight. \n", "In every leaf and breeze that calls, \n", "We find the magic of glorious fall. \n", "\n", "I hope these changes enhance the imagery and sensory experience. Thank you again for your feedback!\n", "[Prompt tokens: 389, Completion tokens: 150]\n", "---------- critic ----------\n", "Your revisions have made the poem even more evocative and immersive. The use of sensory details, such as \"whispers of wind\" and \"crackling leaves,\" beautifully enriches the poem, engaging multiple senses. The metaphorical language, like \"a golden rain from trees’ canopies\" and \"Fall’s embrace, warm as whispered years,\" adds depth and enhances the emotional warmth of the poem. The structural variation with the inclusion of dashes effectively adds emphasis and flow. \n", "\n", "Overall, these changes bring greater vibrancy and life to the poem, allowing readers to truly experience the wonders of fall. Excellent work on the revisions!\n", "\n", "APPROVE\n", "[Prompt tokens: 556, Completion tokens: 132]\n", "---------- Summary ----------\n", "Number of messages: 3\n", "Finish reason: Text 'APPROVE' mentioned\n", "Total prompt tokens: 1104\n", "Total completion tokens: 519\n", "Duration: 9.79 seconds\n" ] }, { "data": { "text/plain": [ "TaskResult(messages=[TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=159, completion_tokens=237), content='This poem beautifully captures the essence of the fall season with vivid imagery and a soothing rhythm. The descriptions of the changing leaves, cool air, and various autumn traditions make it easy for readers to envision and feel the charm of fall. Here are a few suggestions to enhance its impact:\\n\\n1. **Structure Variation**: Consider breaking some lines with a hyphen or ellipsis for dramatic effect or emphasis. For instance, “Sweaters wrapped tight as twilight nears— / Fall’s charming embrace, as warm as it appears.\"\\n\\n2. **Sensory Details**: While the poem already evokes visual and tactile senses, incorporating other senses such as sound or smell could deepen the immersion. For example, include the scent of wood smoke or the crunch of leaves underfoot.\\n\\n3. **Metaphorical Language**: Adding metaphors or similes can further enrich the imagery. For example, you might compare the leaves falling to a golden rain or the chill in the air to a gentle whisper.\\n\\nOverall, it’s a lovely depiction of fall. These suggestions are minor tweaks that might elevate the reader\\'s experience even further. Nice work!\\n\\nLet me know if these feedbacks are addressed.', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=389, completion_tokens=150), content='Thank you for the thoughtful feedback! Here’s a revised version, incorporating your suggestions: \\n\\nLeaves of amber, gold—drifting like dreams, \\nA golden rain from trees’ canopies. \\nWhispers of wind—a gentle breath, \\nNature’s scented tapestry embracing earth. \\n\\nHarvest moons rise as evenings chill, \\nFields of plenty paint every hill. \\nSweaters wrapped tight as twilight nears— \\nFall’s embrace, warm as whispered years. \\n\\nPumpkins aglow with autumn’s light, \\nCrackling leaves underfoot in flight. \\nIn every leaf and breeze that calls, \\nWe find the magic of glorious fall. \\n\\nI hope these changes enhance the imagery and sensory experience. Thank you again for your feedback!', type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=556, completion_tokens=132), content='Your revisions have made the poem even more evocative and immersive. The use of sensory details, such as \"whispers of wind\" and \"crackling leaves,\" beautifully enriches the poem, engaging multiple senses. The metaphorical language, like \"a golden rain from trees’ canopies\" and \"Fall’s embrace, warm as whispered years,\" adds depth and enhances the emotional warmth of the poem. The structural variation with the inclusion of dashes effectively adds emphasis and flow. \\n\\nOverall, these changes bring greater vibrancy and life to the poem, allowing readers to truly experience the wonders of fall. Excellent work on the revisions!\\n\\nAPPROVE', type='TextMessage')], stop_reason=\"Text 'APPROVE' mentioned\")" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await Console(team.run_stream()) # 恢复团队以继续上次的任务。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "你可以在上面的输出中看到团队从上次中断的地方恢复,\n第一条消息来自团队停止前最后发言的下一个代理。\n\n让我们在保留前一个任务上下文的同时,用新任务再次恢复团队。\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "---------- user ----------\n", "将这首诗用中文唐诗风格写一遍。\n", "---------- primary ----------\n", "朔风轻拂叶飘金, \n", "枝上斜阳染秋林。 \n", "满山丰收人欢喜, \n", "月明归途衣渐紧。 \n", "\n", "南瓜影映灯火中, \n", "落叶沙沙伴归程。 \n", "片片秋意随风起, \n", "秋韵悠悠心自明。 \n", "[Prompt tokens: 700, Completion tokens: 77]\n", "---------- critic ----------\n", "这首改编的唐诗风格诗作成功地保留了原诗的意境与情感,体现出秋季特有的氛围和美感。通过“朔风轻拂叶飘金”、“枝上斜阳染秋林”等意象,生动地描绘出了秋天的景色,与唐诗中的自然意境相呼应。且“月明归途衣渐紧”、“落叶沙沙伴归程”让人感受到秋天的安宁与温暖。\n", "\n", "通过这些诗句,读者能够感受到秋天的惬意与宁静,勾起丰收与团圆的画面,是一次成功的翻译改编。\n", "\n", "APPROVE\n", "[Prompt tokens: 794, Completion tokens: 161]\n", "---------- Summary ----------\n", "Number of messages: 3\n", "Finish reason: Text 'APPROVE' mentioned\n", "Total prompt tokens: 1494\n", "Total completion tokens: 238\n", "Duration: 3.89 seconds\n" ] }, { "data": { "text/plain": [ "TaskResult(messages=[TextMessage(source='user', models_usage=None, content='将这首诗用中文唐诗风格写一遍。', type='TextMessage'), TextMessage(source='primary', models_usage=RequestUsage(prompt_tokens=700, completion_tokens=77), content='朔风轻拂叶飘金, \\n枝上斜阳染秋林。 \\n满山丰收人欢喜, \\n月明归途衣渐紧。 \\n\\n南瓜影映灯火中, \\n落叶沙沙伴归程。 \\n片片秋意随风起, \\n秋韵悠悠心自明。 ', type='TextMessage'), TextMessage(source='critic', models_usage=RequestUsage(prompt_tokens=794, completion_tokens=161), content='这首改编的唐诗风格诗作成功地保留了原诗的意境与情感,体现出秋季特有的氛围和美感。通过“朔风轻拂叶飘金”、“枝上斜阳染秋林”等意象,生动地描绘出了秋天的景色,与唐诗中的自然意境相呼应。且“月明归途衣渐紧”、“落叶沙沙伴归程”让人感受到秋天的安宁与温暖。\\n\\n通过这些诗句,读者能够感受到秋天的惬意与宁静,勾起丰收与团圆的画面,是一次成功的翻译改编。\\n\\nAPPROVE', type='TextMessage')], stop_reason=\"Text 'APPROVE' mentioned\")" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 新任务是将同一首诗翻译成中文唐诗风格。\n", "await Console(team.run_stream(task=\"将这首诗用中文唐诗风格写一遍。\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 中止团队\n\n你可以通过设置传递给 `cancellation_token` 参数的 {py:class}`~autogen_core.CancellationToken`,\n在执行过程中中止对 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run` 或 {py:meth}`~autogen_agentchat.teams.BaseGroupChat.run_stream` 的调用。\n\n与停止团队不同,中止团队会立即停止团队并抛出 {py:class}`~asyncio.CancelledError` 异常。\n\n```{note}\n当团队被中止时,调用者会收到 {py:class}`~asyncio.CancelledError` 异常。\n```\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Task was cancelled.\n" ] } ], "source": [ "# 创建一个取消令牌。\n", "cancellation_token = CancellationToken()\n", "\n", "# 使用另一个协程来运行团队。\n", "run = asyncio.create_task(\n", " team.run(\n", " task=\"Translate the poem to Spanish.\",\n", " cancellation_token=cancellation_token,\n", " )\n", ")\n", "\n", "# 取消运行。\n", "cancellation_token.cancel()\n", "\n", "try:\n", " result = await run # 这将引发一个 CancelledError 错误。\n", "except asyncio.CancelledError:\n", " print(\"Task was cancelled.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 单智能体团队\n\n通常,您可能希望在团队配置中运行单个智能体。\n这对于在循环中运行 {py:class}`~autogen_agentchat.agents.AssistantAgent` 非常有用,\n直到满足终止条件。\n\n这与使用 {py:meth}`~autogen_agentchat.agents.BaseChatAgent.run` 或 {py:meth}`~autogen_agentchat.agents.BaseChatAgent.run_stream` 方法\n运行 {py:class}`~autogen_agentchat.agents.AssistantAgent` 不同,\n后者只运行智能体一步并返回结果。\n有关单步运行的更多详情,请参阅 {py:class}`~autogen_agentchat.agents.AssistantAgent`。\n\n以下是在 {py:class}`~autogen_agentchat.teams.RoundRobinGroupChat` 团队配置中运行单个智能体的示例,\n使用 {py:class}`~autogen_agentchat.conditions.TextMessageTermination` 条件。\n任务是通过工具递增数字直到达到10。\n智能体将持续调用该工具直到数字达到10,\n然后返回最终的 {py:class}`~autogen_agentchat.messages.TextMessage`\n这将停止运行。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "TextMessage source='user' models_usage=None metadata={} content='Increment the number 5 to 10.' type='TextMessage'\n", "ToolCallRequestEvent source='looped_assistant' models_usage=RequestUsage(prompt_tokens=75, completion_tokens=15) metadata={} content=[FunctionCall(id='call_qTDXSouN3MtGDqa8l0DM1ciD', arguments='{\"number\":5}', name='increment_number')] type='ToolCallRequestEvent'\n", "ToolCallExecutionEvent source='looped_assistant' models_usage=None metadata={} content=[FunctionExecutionResult(content='6', name='increment_number', call_id='call_qTDXSouN3MtGDqa8l0DM1ciD', is_error=False)] type='ToolCallExecutionEvent'\n", "ToolCallSummaryMessage source='looped_assistant' models_usage=None metadata={} content='6' type='ToolCallSummaryMessage'\n", "ToolCallRequestEvent source='looped_assistant' models_usage=RequestUsage(prompt_tokens=103, completion_tokens=15) metadata={} content=[FunctionCall(id='call_VGZPlsFVVdyxutR63Yr087pt', arguments='{\"number\":6}', name='increment_number')] type='ToolCallRequestEvent'\n", "ToolCallExecutionEvent source='looped_assistant' models_usage=None metadata={} content=[FunctionExecutionResult(content='7', name='increment_number', call_id='call_VGZPlsFVVdyxutR63Yr087pt', is_error=False)] type='ToolCallExecutionEvent'\n", "ToolCallSummaryMessage source='looped_assistant' models_usage=None metadata={} content='7' type='ToolCallSummaryMessage'\n", "ToolCallRequestEvent source='looped_assistant' models_usage=RequestUsage(prompt_tokens=131, completion_tokens=15) metadata={} content=[FunctionCall(id='call_VRKGPqPM9AHoef2g2kgsKwZe', arguments='{\"number\":7}', name='increment_number')] type='ToolCallRequestEvent'\n", "ToolCallExecutionEvent source='looped_assistant' models_usage=None metadata={} content=[FunctionExecutionResult(content='8', name='increment_number', call_id='call_VRKGPqPM9AHoef2g2kgsKwZe', is_error=False)] type='ToolCallExecutionEvent'\n", "ToolCallSummaryMessage source='looped_assistant' models_usage=None metadata={} content='8' type='ToolCallSummaryMessage'\n", "ToolCallRequestEvent source='looped_assistant' models_usage=RequestUsage(prompt_tokens=159, completion_tokens=15) metadata={} content=[FunctionCall(id='call_TOUMjSCG2kVdFcw2CMeb5DYX', arguments='{\"number\":8}', name='increment_number')] type='ToolCallRequestEvent'\n", "ToolCallExecutionEvent source='looped_assistant' models_usage=None metadata={} content=[FunctionExecutionResult(content='9', name='increment_number', call_id='call_TOUMjSCG2kVdFcw2CMeb5DYX', is_error=False)] type='ToolCallExecutionEvent'\n", "ToolCallSummaryMessage source='looped_assistant' models_usage=None metadata={} content='9' type='ToolCallSummaryMessage'\n", "ToolCallRequestEvent source='looped_assistant' models_usage=RequestUsage(prompt_tokens=187, completion_tokens=15) metadata={} content=[FunctionCall(id='call_wjq7OO9Kf5YYurWGc5lsqttJ', arguments='{\"number\":9}', name='increment_number')] type='ToolCallRequestEvent'\n", "ToolCallExecutionEvent source='looped_assistant' models_usage=None metadata={} content=[FunctionExecutionResult(content='10', name='increment_number', call_id='call_wjq7OO9Kf5YYurWGc5lsqttJ', is_error=False)] type='ToolCallExecutionEvent'\n", "ToolCallSummaryMessage source='looped_assistant' models_usage=None metadata={} content='10' type='ToolCallSummaryMessage'\n", "TextMessage source='looped_assistant' models_usage=RequestUsage(prompt_tokens=215, completion_tokens=15) metadata={} content='The number 5 incremented to 10 is 10.' type='TextMessage'\n", "TaskResult TaskResult(messages=[TextMessage(source='user', models_usage=None, metadata={}, content='Increment the number 5 to 10.', type='TextMessage'), ToolCallRequestEvent(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=75, completion_tokens=15), metadata={}, content=[FunctionCall(id='call_qTDXSouN3MtGDqa8l0DM1ciD', arguments='{\"number\":5}', name='increment_number')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='looped_assistant', models_usage=None, metadata={}, content=[FunctionExecutionResult(content='6', name='increment_number', call_id='call_qTDXSouN3MtGDqa8l0DM1ciD', is_error=False)], type='ToolCallExecutionEvent'), ToolCallSummaryMessage(source='looped_assistant', models_usage=None, metadata={}, content='6', type='ToolCallSummaryMessage'), ToolCallRequestEvent(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=103, completion_tokens=15), metadata={}, content=[FunctionCall(id='call_VGZPlsFVVdyxutR63Yr087pt', arguments='{\"number\":6}', name='increment_number')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='looped_assistant', models_usage=None, metadata={}, content=[FunctionExecutionResult(content='7', name='increment_number', call_id='call_VGZPlsFVVdyxutR63Yr087pt', is_error=False)], type='ToolCallExecutionEvent'), ToolCallSummaryMessage(source='looped_assistant', models_usage=None, metadata={}, content='7', type='ToolCallSummaryMessage'), ToolCallRequestEvent(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=131, completion_tokens=15), metadata={}, content=[FunctionCall(id='call_VRKGPqPM9AHoef2g2kgsKwZe', arguments='{\"number\":7}', name='increment_number')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='looped_assistant', models_usage=None, metadata={}, content=[FunctionExecutionResult(content='8', name='increment_number', call_id='call_VRKGPqPM9AHoef2g2kgsKwZe', is_error=False)], type='ToolCallExecutionEvent'), ToolCallSummaryMessage(source='looped_assistant', models_usage=None, metadata={}, content='8', type='ToolCallSummaryMessage'), ToolCallRequestEvent(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=159, completion_tokens=15), metadata={}, content=[FunctionCall(id='call_TOUMjSCG2kVdFcw2CMeb5DYX', arguments='{\"number\":8}', name='increment_number')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='looped_assistant', models_usage=None, metadata={}, content=[FunctionExecutionResult(content='9', name='increment_number', call_id='call_TOUMjSCG2kVdFcw2CMeb5DYX', is_error=False)], type='ToolCallExecutionEvent'), ToolCallSummaryMessage(source='looped_assistant', models_usage=None, metadata={}, content='9', type='ToolCallSummaryMessage'), ToolCallRequestEvent(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=187, completion_tokens=15), metadata={}, content=[FunctionCall(id='call_wjq7OO9Kf5YYurWGc5lsqttJ', arguments='{\"number\":9}', name='increment_number')], type='ToolCallRequestEvent'), ToolCallExecutionEvent(source='looped_assistant', models_usage=None, metadata={}, content=[FunctionExecutionResult(content='10', name='increment_number', call_id='call_wjq7OO9Kf5YYurWGc5lsqttJ', is_error=False)], type='ToolCallExecutionEvent'), ToolCallSummaryMessage(source='looped_assistant', models_usage=None, metadata={}, content='10', type='ToolCallSummaryMessage'), TextMessage(source='looped_assistant', models_usage=RequestUsage(prompt_tokens=215, completion_tokens=15), metadata={}, content='The number 5 incremented to 10 is 10.', type='TextMessage')], stop_reason=\"Text message received from 'looped_assistant'\")\n" ] } ], "source": [ "from autogen_agentchat.agents import AssistantAgent\n", "from autogen_agentchat.conditions import TextMessageTermination\n", "from autogen_agentchat.teams import RoundRobinGroupChat\n", "from autogen_agentchat.ui import Console\n", "from autogen_ext.models.openai import OpenAIChatCompletionClient\n", "\n", "model_client = OpenAIChatCompletionClient(\n", " model=\"gpt-4o\",\n", " # api_key=\"sk-...\", # 可选,\n", " # 如果您设置了 OPENAI_API_KEY 环境变量。 为本示例禁用并行工具调用。\n", " parallel_tool_calls=False, # type: ignore\n", ")\n", "\n", "\n", "# 创建一个用于递增数字的工具。\n", "def increment_number(number: int) -> int:\n", " \"\"\"Increment a number by 1.\"\"\"\n", " return number + 1\n", "\n", "\n", "# 创建一个使用 increment_number 函数的工具代理。\n", "looped_assistant = AssistantAgent(\n", " \"looped_assistant\",\n", " model_client=model_client,\n", " tools=[increment_number], # 注册该工具。\n", " system_message=\"You are a helpful AI assistant, use the tool to increment the number.\",\n", ")\n", "\n", "# 终止条件:如果代理返回文本消息则停止任务。\n", "termination_condition = TextMessageTermination(\"looped_assistant\")\n", "\n", "# 创建一个包含循环助手代理和终止条件的团队。\n", "team = RoundRobinGroupChat(\n", " [looped_assistant],\n", " termination_condition=termination_condition,\n", ")\n", "\n", "# 运行团队执行任务并将消息打印到控制台。\n", "async for message in team.run_stream(task=\"Increment the number 5 to 10.\"): # type: ignore\n", " print(type(message).__name__, message)\n", "\n", "await model_client.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "关键在于关注终止条件。\n在这个示例中,我们使用 {py:class}`~autogen_agentchat.conditions.TextMessageTermination` 条件\n当代理停止生成 {py:class}`~autogen_agentchat.messages.ToolCallSummaryMessage` 时终止团队运行。\n团队将持续运行,直到代理生成包含最终结果的 {py:class}`~autogen_agentchat.messages.TextMessage`。\n\n你也可以使用其他终止条件来控制代理。\n更多详情请参阅[终止条件](./termination.ipynb)。\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 }