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.

_group_chat_utils.py 3.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. """Credit to the original authors: https://github.com/microsoft/autogen/blob/main/autogen/agentchat/groupchat.py"""
  2. import re
  3. from typing import Dict, List
  4. from agnext.components.memory import ChatMemory
  5. from agnext.components.models import ChatCompletionClient, SystemMessage
  6. from agnext.core import AgentProxy
  7. from ..types import Message, TextMessage
  8. async def select_speaker(memory: ChatMemory[Message], client: ChatCompletionClient, agents: List[AgentProxy]) -> int:
  9. """Selects the next speaker in a group chat using a ChatCompletion client."""
  10. # TODO: Handle multi-modal messages.
  11. # Construct formated current message history.
  12. history_messages: List[str] = []
  13. for msg in await memory.get_messages():
  14. assert isinstance(msg, TextMessage)
  15. history_messages.append(f"{msg.source}: {msg.content}")
  16. history = "\n".join(history_messages)
  17. # Construct agent roles.
  18. roles = "\n".join(
  19. [f"{(await agent.metadata)['type']}: {(await agent.metadata)['description']}".strip() for agent in agents]
  20. )
  21. # Construct agent list.
  22. participants = str([(await agent.metadata)["type"] for agent in agents])
  23. # Select the next speaker.
  24. select_speaker_prompt = f"""You are in a role play game. The following roles are available:
  25. {roles}.
  26. Read the following conversation. Then select the next role from {participants} to play. Only return the role.
  27. {history}
  28. Read the above conversation. Then select the next role from {participants} to play. Only return the role.
  29. """
  30. select_speaker_messages = [SystemMessage(select_speaker_prompt)]
  31. response = await client.create(messages=select_speaker_messages)
  32. assert isinstance(response.content, str)
  33. mentions = await mentioned_agents(response.content, agents)
  34. if len(mentions) != 1:
  35. raise ValueError(f"Expected exactly one agent to be mentioned, but got {mentions}")
  36. agent_name = list(mentions.keys())[0]
  37. # Get the index of the selected agent by name
  38. agent_index = 0
  39. for i, agent in enumerate(agents):
  40. if (await agent.metadata)["type"] == agent_name:
  41. agent_index = i
  42. break
  43. assert agent_index is not None
  44. return agent_index
  45. async def mentioned_agents(message_content: str, agents: List[AgentProxy]) -> Dict[str, int]:
  46. """Counts the number of times each agent is mentioned in the provided message content.
  47. Agent names will match under any of the following conditions (all case-sensitive):
  48. - Exact name match
  49. - If the agent name has underscores it will match with spaces instead (e.g. 'Story_writer' == 'Story writer')
  50. - If the agent name has underscores it will match with '\\_' instead of '_' (e.g. 'Story_writer' == 'Story\\_writer')
  51. Args:
  52. message_content (Union[str, List]): The content of the message, either as a single string or a list of strings.
  53. agents (List[Agent]): A list of Agent objects, each having a 'name' attribute to be searched in the message content.
  54. Returns:
  55. Dict: a counter for mentioned agents.
  56. """
  57. mentions: Dict[str, int] = dict()
  58. for agent in agents:
  59. # Finds agent mentions, taking word boundaries into account,
  60. # accommodates escaping underscores and underscores as spaces
  61. name = (await agent.metadata)["type"]
  62. regex = (
  63. r"(?<=\W)("
  64. + re.escape(name)
  65. + r"|"
  66. + re.escape(name.replace("_", " "))
  67. + r"|"
  68. + re.escape(name.replace("_", r"\_"))
  69. + r")(?=\W)"
  70. )
  71. count = len(re.findall(regex, f" {message_content} ")) # Pad the message to help with matching
  72. if count > 0:
  73. mentions[name] = count
  74. return mentions