You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

app_team_user_proxy.py 5.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. from typing import List, cast
  2. import chainlit as cl
  3. import yaml
  4. from autogen_agentchat.agents import AssistantAgent, UserProxyAgent
  5. from autogen_agentchat.base import TaskResult
  6. from autogen_agentchat.conditions import TextMentionTermination
  7. from autogen_agentchat.messages import ModelClientStreamingChunkEvent, TextMessage
  8. from autogen_agentchat.teams import RoundRobinGroupChat
  9. from autogen_core import CancellationToken
  10. from autogen_core.models import ChatCompletionClient
  11. async def user_input_func(prompt: str, cancellation_token: CancellationToken | None = None) -> str:
  12. """Get user input from the UI for the user proxy agent."""
  13. try:
  14. response = await cl.AskUserMessage(content=prompt).send()
  15. except TimeoutError:
  16. return "User did not provide any input within the time limit."
  17. if response:
  18. return response["output"] # type: ignore
  19. else:
  20. return "User did not provide any input."
  21. async def user_action_func(prompt: str, cancellation_token: CancellationToken | None = None) -> str:
  22. """Get user action from the UI for the user proxy agent."""
  23. try:
  24. response = await cl.AskActionMessage(
  25. content="Pick an action",
  26. actions=[
  27. cl.Action(name="approve", label="Approve", payload={"value": "approve"}),
  28. cl.Action(name="reject", label="Reject", payload={"value": "reject"}),
  29. ],
  30. ).send()
  31. except TimeoutError:
  32. return "User did not provide any input within the time limit."
  33. if response and response.get("payload"): # type: ignore
  34. if response.get("payload").get("value") == "approve": # type: ignore
  35. return "APPROVE." # This is the termination condition.
  36. else:
  37. return "REJECT."
  38. else:
  39. return "User did not provide any input."
  40. @cl.on_chat_start # type: ignore
  41. async def start_chat() -> None:
  42. # Load model configuration and create the model client.
  43. with open("model_config.yaml", "r") as f:
  44. model_config = yaml.safe_load(f)
  45. model_client = ChatCompletionClient.load_component(model_config)
  46. # Create the assistant agent.
  47. assistant = AssistantAgent(
  48. name="assistant",
  49. model_client=model_client,
  50. system_message="You are a helpful assistant.",
  51. model_client_stream=True, # Enable model client streaming.
  52. )
  53. # Create the critic agent.
  54. critic = AssistantAgent(
  55. name="critic",
  56. model_client=model_client,
  57. system_message="You are a critic. Provide constructive feedback. "
  58. "Respond with 'APPROVE' if your feedback has been addressed.",
  59. model_client_stream=True, # Enable model client streaming.
  60. )
  61. # Create the user proxy agent.
  62. user = UserProxyAgent(
  63. name="user",
  64. # input_func=user_input_func, # Uncomment this line to use user input as text.
  65. input_func=user_action_func, # Uncomment this line to use user input as action.
  66. )
  67. # Termination condition.
  68. termination = TextMentionTermination("APPROVE", sources=["user"])
  69. # Chain the assistant, critic and user agents using RoundRobinGroupChat.
  70. group_chat = RoundRobinGroupChat([assistant, critic, user], termination_condition=termination)
  71. # Set the assistant agent in the user session.
  72. cl.user_session.set("prompt_history", "") # type: ignore
  73. cl.user_session.set("team", group_chat) # type: ignore
  74. @cl.set_starters # type: ignore
  75. async def set_starts() -> List[cl.Starter]:
  76. return [
  77. cl.Starter(
  78. label="Poem Writing",
  79. message="Write a poem about the ocean.",
  80. ),
  81. cl.Starter(
  82. label="Story Writing",
  83. message="Write a story about a detective solving a mystery.",
  84. ),
  85. cl.Starter(
  86. label="Write Code",
  87. message="Write a function that merge two list of numbers into single sorted list.",
  88. ),
  89. ]
  90. @cl.on_message # type: ignore
  91. async def chat(message: cl.Message) -> None:
  92. # Get the team from the user session.
  93. team = cast(RoundRobinGroupChat, cl.user_session.get("team")) # type: ignore
  94. # Streaming response message.
  95. streaming_response: cl.Message | None = None
  96. # Stream the messages from the team.
  97. async for msg in team.run_stream(
  98. task=[TextMessage(content=message.content, source="user")],
  99. cancellation_token=CancellationToken(),
  100. ):
  101. if isinstance(msg, ModelClientStreamingChunkEvent):
  102. # Stream the model client response to the user.
  103. if streaming_response is None:
  104. # Start a new streaming response.
  105. streaming_response = cl.Message(content="", author=msg.source)
  106. await streaming_response.stream_token(msg.content)
  107. elif streaming_response is not None:
  108. # Done streaming the model client response.
  109. # We can skip the current message as it is just the complete message
  110. # of the streaming response.
  111. await streaming_response.send()
  112. # Reset the streaming response so we won't enter this block again
  113. # until the next streaming response is complete.
  114. streaming_response = None
  115. elif isinstance(msg, TaskResult):
  116. # Send the task termination message.
  117. final_message = "Task terminated. "
  118. if msg.stop_reason:
  119. final_message += msg.stop_reason
  120. await cl.Message(content=final_message).send()
  121. else:
  122. # Skip all other message types.
  123. pass