|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Group Chat\n",
- "\n",
- "Group chat is a design pattern where a group of agents share a common thread\n",
- "of messages: they all subscribe and publish to the same thread. Each participant\n",
- "agent is specialized for a particular task, such as writer, illustrator, and editor\n",
- "in a collaborative writing task.\n",
- "\n",
- "The order\n",
- "of converation is maintained by a Group Chat Manager agent, which selects\n",
- "the next agent to speak. The exact algorithm for selecting the next agent\n",
- "can vary based on your application requirements. Typicall, a round-robin\n",
- "algorithm or a selection by an LLM model is used.\n",
- "\n",
- "Group chat is useful for dynamically decomposing a complex task into smaller ones \n",
- "that can be handled by specialized agents with well-defined roles.\n",
- "\n",
- "In this example, we implement a simple group chat system with a round-robin\n",
- "Group Chat Manager to create content for a children's story book. \n",
- "We use three specialized agents: a writer, an illustrator, and an editor."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Message Protocol\n",
- "\n",
- "The message protocol for the group chat system is simple: user publishes\n",
- "a `GroupChatMessage` message to all participants.\n",
- "The group chat manager sends out a `RequestToSpeak` message to the next agent\n",
- "in the round-robin order, and the agent publishes `GroupChatMessage` messages,\n",
- "which are consumed by all participants.\n",
- "Once a conclusion is reached, in this case, the editor approves the draft,\n",
- "the group chat manager stops sending `RequestToSpeak` message, and\n",
- "the group chat ends."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "from dataclasses import dataclass\n",
- "\n",
- "from agnext.components import Image\n",
- "from agnext.components.models import LLMMessage\n",
- "\n",
- "\n",
- "@dataclass\n",
- "class GroupChatMessage:\n",
- " body: LLMMessage\n",
- "\n",
- "\n",
- "@dataclass\n",
- "class RequestToSpeak:\n",
- " pass"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Agents\n",
- "\n",
- "Let's first define the agents that only uses LLM models to generate text.\n",
- "The `WriterAgent` is responsible for writing a draft and create a description\n",
- "for the illustration.\n",
- "The `EditorAgent` is responsible for approving the draft which includes\n",
- "both the text written by the `WriterAgent` and the illustration\n",
- "created by the `IllustratorAgent`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [],
- "source": [
- "from typing import List\n",
- "\n",
- "from agnext.components import DefaultTopicId, RoutedAgent, message_handler\n",
- "from agnext.components.models import AssistantMessage, ChatCompletionClient, LLMMessage, SystemMessage, UserMessage\n",
- "from agnext.core import MessageContext\n",
- "\n",
- "\n",
- "class WriterAgent(RoutedAgent):\n",
- " def __init__(\n",
- " self,\n",
- " model_client: ChatCompletionClient,\n",
- " ) -> None:\n",
- " super().__init__(\"A writer\")\n",
- " self._model_client = model_client\n",
- " self._chat_history: List[LLMMessage] = [\n",
- " SystemMessage(\n",
- " \"You are a writer. Write a draft with a paragraph description of an illustration, starting the description paragraph with 'ILLUSTRATION'.\"\n",
- " )\n",
- " ]\n",
- "\n",
- " @message_handler\n",
- " async def handle_message(self, message: GroupChatMessage, ctx: MessageContext) -> None:\n",
- " self._chat_history.append(message.body)\n",
- "\n",
- " @message_handler\n",
- " async def handle_request_to_speak(self, message: RequestToSpeak, ctx: MessageContext) -> None:\n",
- " completion = await self._model_client.create(self._chat_history)\n",
- " assert isinstance(completion.content, str)\n",
- " self._chat_history.append(AssistantMessage(content=completion.content, source=\"Writer\"))\n",
- " print(f\"\\n{'-'*80}\\nWriter:\\n{completion.content}\")\n",
- " await self.publish_message(\n",
- " GroupChatMessage(body=UserMessage(content=completion.content, source=\"Writer\")), DefaultTopicId()\n",
- " )\n",
- "\n",
- "\n",
- "class EditorAgent(RoutedAgent):\n",
- " def __init__(\n",
- " self,\n",
- " model_client: ChatCompletionClient,\n",
- " ) -> None:\n",
- " super().__init__(\"An editor\")\n",
- " self._model_client = model_client\n",
- " self._chat_history: List[LLMMessage] = [\n",
- " SystemMessage(\"You are an editor. Reply with 'APPROVE' to approve the draft\")\n",
- " ]\n",
- "\n",
- " @message_handler\n",
- " async def handle_message(self, message: GroupChatMessage, ctx: MessageContext) -> None:\n",
- " self._chat_history.append(message.body)\n",
- "\n",
- " @message_handler\n",
- " async def handle_request_to_speak(self, message: RequestToSpeak, ctx: MessageContext) -> None:\n",
- " completion = await self._model_client.create(self._chat_history)\n",
- " assert isinstance(completion.content, str)\n",
- " self._chat_history.append(AssistantMessage(content=completion.content, source=\"Editor\"))\n",
- " print(f\"\\n{'-'*80}\\nEditor:\\n{completion.content}\")\n",
- " await self.publish_message(\n",
- " GroupChatMessage(body=UserMessage(content=completion.content, source=\"Editor\")), DefaultTopicId()\n",
- " )"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Now let's define the `IllustratorAgent` which uses a DALL-E model to generate\n",
- "an illustration based on the description provided by the `WriterAgent`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "import re\n",
- "\n",
- "import openai\n",
- "from IPython.display import display\n",
- "\n",
- "\n",
- "class IllustratorAgent(RoutedAgent):\n",
- " def __init__(self, image_client: openai.AsyncClient) -> None:\n",
- " super().__init__(\"An illustrator\")\n",
- " self._image_client = image_client\n",
- " self._chat_history: List[LLMMessage] = []\n",
- "\n",
- " @message_handler\n",
- " async def handle_message(self, message: GroupChatMessage, ctx: MessageContext) -> None:\n",
- " self._chat_history.append(message.body)\n",
- "\n",
- " @message_handler\n",
- " async def handle_request_to_speak(self, message: RequestToSpeak, ctx: MessageContext) -> None:\n",
- " # Generate an image using dall-e-2\n",
- " last_message_text = self._chat_history[-1].content\n",
- " assert isinstance(last_message_text, str)\n",
- " match = re.search(r\"ILLUSTRATION(.+)\\n\", last_message_text, re.DOTALL)\n",
- " print(f\"\\n{'-'*80}\\nIllustrator:\\n\")\n",
- " if match is None:\n",
- " print(\"No description found\")\n",
- " await self.publish_message(\n",
- " GroupChatMessage(UserMessage(content=\"No description found\", source=\"Illustrator\")), DefaultTopicId()\n",
- " )\n",
- " return\n",
- " description = match.group(1)[:500]\n",
- " print(description.strip())\n",
- " response = await self._image_client.images.generate(\n",
- " prompt=description.strip(), model=\"dall-e-2\", response_format=\"b64_json\", size=\"256x256\"\n",
- " )\n",
- " image = Image.from_base64(response.data[0].b64_json) # type: ignore\n",
- " display(image.image) # type: ignore\n",
- " await self.publish_message(\n",
- " GroupChatMessage(UserMessage(content=[image], source=\"Illustrator\")), DefaultTopicId()\n",
- " )"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Lastly, we define the `GroupChatManager` agent which manages the group chat\n",
- "and selects the next agent to speak in a round-robin fashion.\n",
- "The group chat manager checks if the editor has approved the draft by \n",
- "looking for the \"APPORVED\" keyword in the message. If the editor has approved\n",
- "the draft, the group chat manager stops selecting the next speaker, and the group chat ends."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [],
- "source": [
- "from agnext.core import AgentId\n",
- "\n",
- "\n",
- "class GroupChatManager(RoutedAgent):\n",
- " def __init__(self, participants: List[AgentId]) -> None:\n",
- " super().__init__(\"Group chat manager\")\n",
- " self._num_rounds = 0\n",
- " self._participants = participants\n",
- " self._chat_history: List[GroupChatMessage] = []\n",
- "\n",
- " @message_handler\n",
- " async def handle_message(self, message: GroupChatMessage, ctx: MessageContext) -> None:\n",
- " self._chat_history.append(message)\n",
- " assert isinstance(message.body, UserMessage)\n",
- " if message.body.source == \"Editor\" and \"APPROVE\" in message.body.content:\n",
- " return\n",
- " speaker = self._participants[self._num_rounds % len(self._participants)]\n",
- " self._num_rounds += 1\n",
- " await self.send_message(RequestToSpeak(), speaker)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Running the Group Chat\n",
- "\n",
- "To run the group chat, we create an {py:class}`~agnext.application.SingleThreadedAgentRuntime`\n",
- "and register the agents' factories and subscriptions.\n",
- "We then start the runtime and publish a `GroupChatMessage` to start the group chat."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "\n",
- "--------------------------------------------------------------------------------\n",
- "Writer:\n",
- "**ILLUSTRATION:**\n",
- "The illustration vividly captures the majestic essence of a dragon, its scales shimmering like a thousand emeralds under the moonlight. The dragon stands atop a rugged cliff, wings unfurled and casting a shadow over the ancient forest below. Its eyes, glowing with an otherworldly light, exude wisdom and power. Tendrils of smoke curl from its nostrils, blending into the mist that envelops the scene. The night sky is dotted with twinkling stars, and a full moon bathes the landscape in a silvery glow, accentuating the dragon's formidable presence. Below, the forest teems with life, unaware of the guardian watching over them from the heights above.\n",
- "\n",
- "**POEM:**\n",
- "\n",
- "In moonlit night, a dragon soared so high,\n",
- "Emerald scales 'neath a starlit sky.\n",
- "Upon a cliff, where whispers of ancients dwell,\n",
- "Its eyes of wisdom, tales untold, foretell.\n",
- "\n",
- "Wings unfurled, they whisper through the night,\n",
- "A guardian fierce, of forests bathed in light.\n",
- "Smoke tendrils dance, coiling in the mist,\n",
- "A silent sentinel, in nature's tryst.\n",
- "\n",
- "Stars above in silent hush adorn,\n",
- "The ageless dragon, by time unshorn.\n",
- "With power ancient and heart so deep,\n",
- "In moonlit realms, eternal vigil keep.\n",
- "\n",
- "--------------------------------------------------------------------------------\n",
- "Illustrator:\n",
- "\n",
- ":**\n",
- "The illustration vividly captures the majestic essence of a dragon, its scales shimmering like a thousand emeralds under the moonlight. The dragon stands atop a rugged cliff, wings unfurled and casting a shadow over the ancient forest below. Its eyes, glowing with an otherworldly light, exude wisdom and power. Tendrils of smoke curl from its nostrils, blending into the mist that envelops the scene. The night sky is dotted with twinkling stars, and a full moon bathes the landscape in a silver\n"
- ]
- },
- {
- "data": {
- "image/jpeg": "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",
|