Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AgentChat task message type and group chat state validation for Swarm #4230

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

ekzhu
Copy link
Collaborator

@ekzhu ekzhu commented Nov 16, 2024

Resolves #4199

  1. task can be ChatMessage type
  2. Add group chat state validation step,and address swarm state valiation
  3. Change handling of start and reset to RPC and capture any error from running without affecting the group chat runtime state.
  4. Misc fixes for docs

Example of Swarm + HandoffTermination:

import asyncio
from autogen_ext.models import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import Swarm
from autogen_agentchat.task import HandoffTermination, Console, MaxMessageTermination
from autogen_agentchat.messages import HandoffMessage


async def main() -> None:
    model_client = OpenAIChatCompletionClient(model="gpt-4o")

    agent = AssistantAgent(
        "Alice",
        model_client=model_client,
        handoffs=["user"],
        system_message="You are Alice and you only answer questions about yourself, ask the user for help if needed.",
    )
    termination = HandoffTermination(target="user") | MaxMessageTermination(3)
    team = Swarm([agent], termination_condition=termination)

    # Start the conversation.
    await Console(team.run_stream(task="What is bob's birthday?"))

    # Resume with user feedback.
    await Console(team.run_stream(task=HandoffMessage(source="user", target="Alice", content="Bob's birthday is on 1st January.")))


asyncio.run(main())
---------- user ----------
What is bob's birthday?
---------- Alice ----------
I can only answer questions about myself. If you need information about Bob's birthday, you might need to ask directly or consult someone who knows him.
[Prompt tokens: 63, Completion tokens: 31]
---------- Alice ----------
[FunctionCall(id='call_5mA1B4MigcfS7Ebpz2al1Q5X', arguments='{}', name='transfer_to_user')]
[Prompt tokens: 99, Completion tokens: 11]
---------- Alice ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_5mA1B4MigcfS7Ebpz2al1Q5X')]
---------- Alice ----------
Transferred to user, adopting the role of user immediately.
---------- Summary ----------
Number of messages: 5
Finish reason: Handoff to user from Alice detected., Maximum number of messages 3 reached, current message count: 5
Total prompt tokens: 162
Total completion tokens: 42
Duration: 1.26 seconds
---------- user ----------
Bob's birthday is on 1st January.
---------- Alice ----------
Thank you for providing that information! If you have any questions about me, feel free to ask.
[Prompt tokens: 147, Completion tokens: 21]
---------- Alice ----------
Do you have any questions about me, Alice?
[Prompt tokens: 173, Completion tokens: 11]
---------- Summary ----------
Number of messages: 3
Finish reason: Maximum number of messages 3 reached, current message count: 3
Total prompt tokens: 320
Total completion tokens: 32
Duration: 1.00 seconds

Example of getting error if the resuming message is not a handoff message:

# same as above until resume

# Resume with a wrong message type.
await Console(team.run_stream(task="Bob's birthday is on 1st January."))
---------- user ----------
What is bob's birthday?
---------- Alice ----------
[FunctionCall(id='call_WtpRq2NKtRh9EqYtqAKpS9vm', arguments='{}', name='transfer_to_user')]
[Prompt tokens: 63, Completion tokens: 11]
---------- Alice ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_WtpRq2NKtRh9EqYtqAKpS9vm')]
---------- Alice ----------
Transferred to user, adopting the role of user immediately.
---------- Summary ----------
Number of messages: 4
Finish reason: Handoff to user from Alice detected., Maximum number of messages 3 reached, current message count: 4
Total prompt tokens: 63
Total completion tokens: 11
Duration: 0.56 seconds
Traceback (most recent call last):
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/test.py", line 28, in <module>
    asyncio.run(main())
  File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/test.py", line 25, in main
    await Console(team.run_stream(task="Bob's birthday is on 1st January."))
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/task/_console.py", line 33, in Console
    async for message in stream:
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat.py", line 288, in run_stream
    await self._runtime.send_message(
  File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/application/_single_threaded_agent_runtime.py", line 233, in send_message
    return await future
           ^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/application/_single_threaded_agent_runtime.py", line 315, in _process_send
    response = await recipient_agent.on_message(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_sequential_routed_agent.py", line 49, in on_message
    return await super().on_message(message, ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/components/_routed_agent.py", line 468, in on_message
    return await h(self, message, ctx)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/components/_routed_agent.py", line 388, in wrapper
    return_value = await func(self, message, ctx)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat_manager.py", line 74, in handle_start
    await self.validate_group_state(message.message)
  File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_swarm_group_chat.py", line 49, in validate_group_state
    raise ValueError(
ValueError: The existing handoff target user is not one of the participants ['Alice']. If you are resuming Swarm with a new task make sure to include in your task a HandoffMessage with a valid participant as the target. For example, if you are resuming from a HandoffTermination, make sure the new task is a HandoffMessage with a valid participant as the target.

…dress swarm state valiation; change handling of start and reset to RPC to capture any error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Swarm work with HandoffTermination
1 participant