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

Unable to use the input function with run_stream #5041

Open
vincent-herlemont opened this issue Jan 14, 2025 · 4 comments
Open

Unable to use the input function with run_stream #5041

vincent-herlemont opened this issue Jan 14, 2025 · 4 comments
Labels
documentation Improvements or additions to documentation proj-agentchat
Milestone

Comments

@vincent-herlemont
Copy link

vincent-herlemont commented Jan 14, 2025

What happened?

The input() function does not work with run_stream. The input() function returns immediately without waiting.

Run: test-autogen/src/e4/swarm.py#L32-L68

Ouput
---------- user ----------
I need to refund my flight
---------- travel_agent ----------
[FunctionCall(id='call_gc43qnq4xA6Xo0OyQBSUAVfr', arguments='{}', name='transfer_to_refund_agent')]
---------- travel_agent ----------
[FunctionExecutionResult(content='Transferred to refund_agent, adopting the role of refund_agent immediately.', call_id='call_gc43qnq4xA6Xo0OyQBSUAVfr')]
---------- travel_agent ----------
Transferred to refund_agent, adopting the role of refund_agent immediately.
---------- refund_agent ----------
To assist you with the refund, I'll need your flight reference number. Could you please provide that information?
---------- refund_agent ----------
[FunctionCall(id='call_E76uUOGQs1XJD5KP6LH6c1QX', arguments='{}', name='transfer_to_user')]
---------- refund_agent ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_E76uUOGQs1XJD5KP6LH6c1QX')]
---------- refund_agent ----------
Transferred to user, adopting the role of user immediately.

User (type 'exit' to quit): 
Waiting for user input...
User: 
Chat interrupted by user.

Chat session ended.

What did you expect to happen?

I can use the input() function as in the example from the documentation https://microsoft.github.io/autogen/stable/user-guide/agentchat-user-guide/swarm.html

async def run_team_stream() -> None:
    task_result = await Console(team.run_stream(task=task))
    last_message = task_result.messages[-1]

    while isinstance(last_message, HandoffMessage) and last_message.target == "user":
        user_message = input("User: ")

        task_result = await Console(
            team.run_stream(task=HandoffMessage(source="user", target=last_message.source, content=user_message))
        )
        last_message = task_result.messages[-1]


await run_team_stream()

See my similar test code here: test-autogen/src/e4/swarm.py#L32-L68

How can we reproduce it (as minimally and precisely as possible)?

You will find all the code to reproduce the problem in the repository test-autogen.

AutoGen version

0.4.1

Which package was this bug in

Core

Model used

gpt4-o

Python version

3.12

Operating system

Ubuntu 20.04.1

Any additional info you think would be helpful for fixing this bug

No response

@SudhakarPunniyakotti
Copy link
Contributor

SudhakarPunniyakotti commented Jan 14, 2025

I too face the same issue.

AutoGen version
0.4.0 and 0.4.1

Which package was this bug in
Core

Model used
gpt4-o

Python version
3.10.12

Operating system
MacOS Sonoma 14.6.1

@ekzhu
Copy link
Collaborator

ekzhu commented Jan 14, 2025

Adding the complete script here for debugging, removing the code that catches exceptions:

import asyncio

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.conditions import HandoffTermination, TextMentionTermination
from autogen_agentchat.messages import HandoffMessage
from autogen_agentchat.teams import Swarm
from autogen_agentchat.ui import Console
from autogen_ext.models.openai import OpenAIChatCompletionClient


def refund_flight(flight_id: str) -> str:
    """Simulate refunding a flight."""
    return f"Flight {flight_id} refunded successfully"


def check_flight_status(flight_id: str) -> str:
    """Simulate checking flight status."""
    return f"Flight {flight_id} is scheduled and on time"


def create_model_client(model: str = "gpt-4o") -> OpenAIChatCompletionClient:
    """Create a model client with the specified model."""
    return OpenAIChatCompletionClient(model=model)


def create_travel_agent(model_client: OpenAIChatCompletionClient) -> AssistantAgent:
    """Create the travel agent that handles general inquiries."""
    return AssistantAgent(
        "travel_agent",
        model_client=model_client,
        handoffs=["refund_agent", "user"],
        system_message="""You are a travel agent.
        The refund_agent is in charge of processing flight refunds.
        If you need information from the user, first send your message, then handoff to the user.
        Use TERMINATE when the travel planning is complete.""",
    )


def create_refund_agent(model_client: OpenAIChatCompletionClient) -> AssistantAgent:
    """Create the refund agent that handles refund processing."""
    return AssistantAgent(
        "refund_agent",
        model_client=model_client,
        handoffs=["travel_agent", "user"],
        tools=[refund_flight, check_flight_status],
        system_message="""You are an agent specialized in refunding flights.
        You need flight reference numbers to refund a flight.
        You can refund flights using the refund_flight tool.
        You can check flight status using the check_flight_status tool.
        If you need information from the user, first send your message, then handoff to the user.
        When the transaction is complete, handoff to the travel agent to finalize.""",
    )


async def run_customer_support(task: str, model: str = "gpt-4o") -> None:
    """Run the customer support swarm with the given task."""
    # Create model client
    model_client = create_model_client(model)

    # Create agents
    travel_agent = create_travel_agent(model_client)
    refund_agent = create_refund_agent(model_client)

    # Create team
    termination = HandoffTermination(target="user") | TextMentionTermination("TERMINATE")
    team = Swarm(participants=[travel_agent, refund_agent], termination_condition=termination)

    print("\nStarting customer support chat. Type 'exit' to quit or Ctrl+C to interrupt.\n")

    # Run initial task
    task_result = await Console(team.run_stream(task=task))
    last_message = task_result.messages[-1]

    # Handle user interactions
    while isinstance(last_message, HandoffMessage) and last_message.target == "user":
        print("\nUser (type 'exit' to quit): ")
        print("Waiting for user input...")  # Debug print
        user_message = input("User: ")

        if not user_message or user_message.lower() == "exit":
            print("\nChat ended by user.")
            break

        task_result = await Console(
            team.run_stream(task=HandoffMessage(source="user", target=last_message.source, content=user_message))
        )
        last_message = task_result.messages[-1]


def run_customer_support_sync(task: str, model: str = "gpt-4o") -> None:
    """Synchronous wrapper for run_customer_support."""
    asyncio.run(run_customer_support(task=task, model=model))


task = "I need to refund my flight"
asyncio.run(run_customer_support(task))
(python) ekzhu@TheWagyu:~/autogen/python$ python test.py

Starting customer support chat. Type 'exit' to quit or Ctrl+C to interrupt.

---------- user ----------
I need to refund my flight
---------- travel_agent ----------
[FunctionCall(id='call_sxLBESxX3SgiMk1WDnuMKPuV', arguments='{}', name='transfer_to_refund_agent'), FunctionCall(id='call_ySlHGksNarSFVtubZt7twjIe', arguments='{}', name='transfer_to_user')]
/home/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_chat_agent_container.py:53: UserWarning: Multiple handoffs detected only the first is executed: ['transfer_to_refund_agent', 'transfer_to_user']
  async for msg in self._agent.on_messages_stream(self._message_buffer, ctx.cancellation_token):
---------- travel_agent ----------
[FunctionExecutionResult(content='Transferred to refund_agent, adopting the role of refund_agent immediately.', call_id='call_sxLBESxX3SgiMk1WDnuMKPuV'), FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_ySlHGksNarSFVtubZt7twjIe')]
---------- travel_agent ----------
Transferred to refund_agent, adopting the role of refund_agent immediately.
---------- refund_agent ----------
I can help you with that. Could you please provide me with your flight reference number?
---------- refund_agent ----------
[FunctionCall(id='call_i8c8URTzTMLFgUcoQEogQl4c', arguments='{}', name='transfer_to_user')]
---------- refund_agent ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_i8c8URTzTMLFgUcoQEogQl4c')]
---------- refund_agent ----------
Transferred to user, adopting the role of user immediately.

User (type 'exit' to quit): 
Waiting for user input...
User: Traceback (most recent call last):
  File "/home/ekzhu/autogen/python/test.py", line 96, in <module>
    asyncio.run(run_customer_support(task))
  File "/home/ekzhu/.local/share/uv/python/cpython-3.12.7-linux-x86_64-gnu/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/home/ekzhu/.local/share/uv/python/cpython-3.12.7-linux-x86_64-gnu/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ekzhu/.local/share/uv/python/cpython-3.12.7-linux-x86_64-gnu/lib/python3.12/asyncio/base_events.py", line 687, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/home/ekzhu/autogen/python/test.py", line 78, in run_customer_support
    user_message = input("User: ")
                   ^^^^^^^^^^^^^^^
EOFError

@ekzhu
Copy link
Collaborator

ekzhu commented Jan 14, 2025

Use aioconsole instead:

import aioconsole

user_message = await aioconsole.ainput("User: ")
# user_message = input("User: ")

@ekzhu ekzhu added this to the 0.4.2 milestone Jan 14, 2025
@ekzhu
Copy link
Collaborator

ekzhu commented Jan 14, 2025

@jackgerrits we need to update all usage of input across documentation to use aioconsole or running in asyncio loop.

@ekzhu ekzhu added proj-agentchat documentation Improvements or additions to documentation labels Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation proj-agentchat
Projects
None yet
Development

No branches or pull requests

3 participants