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

Ability to add MessageTransforms to the GroupChat's Select Speaker nested chat (speaker_selection_method='auto') #2

Merged
merged 19 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions autogen/agentchat/contrib/capabilities/transform_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
import copy
from typing import Dict, List

from autogen import ConversableAgent

from ....formatting_utils import colored
from ...conversable_agent import ConversableAgent
from .transforms import MessageTransform


Expand Down
21 changes: 21 additions & 0 deletions autogen/agentchat/groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from ..runtime_logging import log_new_agent, logging_enabled
from .agent import Agent
from .chat import ChatResult
from .contrib.capabilities import transform_messages
from .conversable_agent import ConversableAgent

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -82,6 +83,8 @@ def custom_speaker_selection_func(
of times until a single agent is returned or it exhausts the maximum attempts.
Applies only to "auto" speaker selection method.
Default is 2.
- select_speaker_transform_messages: (optional) the message transformations to apply to the nested select speaker agent-to-agent chat messages.
Takes a TransformMessages object, defaults to None and is only utilised when the speaker selection method is "auto".
- select_speaker_auto_verbose: whether to output the select speaker responses and selections
If set to True, the outputs from the two agents in the nested select speaker chat will be output, along with
whether the responses were successful, or not, in selecting an agent
Expand Down Expand Up @@ -138,6 +141,7 @@ def custom_speaker_selection_func(
The names are case-sensitive and should not be abbreviated or changed.
The only names that are accepted are {agentlist}.
Respond with ONLY the name of the speaker and DO NOT provide a reason."""
select_speaker_transform_messages: Optional[transform_messages.TransformMessages] = None
select_speaker_auto_verbose: Optional[bool] = False
role_for_select_speaker_messages: Optional[str] = "system"

Expand Down Expand Up @@ -255,6 +259,15 @@ def __post_init__(self):
elif self.max_retries_for_selecting_speaker < 0:
raise ValueError("max_retries_for_selecting_speaker must be greater than or equal to zero")

# Load message transforms here (load once for the Group Chat so we don't have to re-initiate it and it maintains the cache across subsequent select speaker calls)
if self.select_speaker_transform_messages is not None:
if isinstance(self.select_speaker_transform_messages, transform_messages.TransformMessages):
self._speaker_selection_transforms = self.select_speaker_transform_messages
else:
raise ValueError("select_speaker_transform_messages must be None or MessageTransforms.")
else:
self._speaker_selection_transforms = None

# Validate select_speaker_auto_verbose
if self.select_speaker_auto_verbose is None or not isinstance(self.select_speaker_auto_verbose, bool):
raise ValueError("select_speaker_auto_verbose cannot be None or non-bool")
Expand Down Expand Up @@ -661,6 +674,10 @@ def validate_speaker_name(recipient, messages, sender, config) -> Tuple[bool, Un
else:
start_message = messages[-1]

# Add the message transforms, if any, to the speaker selection agent
if self._speaker_selection_transforms is not None:
self._speaker_selection_transforms.add_to_agent(speaker_selection_agent)

# Run the speaker selection chat
result = checking_agent.initiate_chat(
speaker_selection_agent,
Expand Down Expand Up @@ -755,6 +772,10 @@ def validate_speaker_name(recipient, messages, sender, config) -> Tuple[bool, Un
else:
start_message = messages[-1]

# Add the message transforms, if any, to the speaker selection agent
if self._speaker_selection_transforms is not None:
self._speaker_selection_transforms.add_to_agent(speaker_selection_agent)

# Run the speaker selection chat
result = await checking_agent.a_initiate_chat(
speaker_selection_agent,
Expand Down
55 changes: 55 additions & 0 deletions ms_code/test_groupchat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from typing import Any, Dict, List, Optional

import pytest

from autogen import Agent, AssistantAgent, GroupChat, GroupChatManager
from autogen.agentchat.contrib.capabilities import transform_messages, transforms


def test_select_speaker_transform_messages():
"""Tests adding transform messages to a GroupChat for speaker selection when in 'auto' mode"""

# Test adding a TransformMessages to a group chat
test_add_transforms = transform_messages.TransformMessages(
transforms=[
transforms.MessageHistoryLimiter(max_messages=10),
transforms.MessageTokenLimiter(max_tokens=3000, max_tokens_per_message=500, min_tokens=300),
]
)

print(GroupChat.__module__) # Prints the module where GroupChat is defined
import inspect

# Get the file where GroupChat is defined
print(inspect.getfile(GroupChat))

coder = AssistantAgent(name="Coder", llm_config=None)
groupchat = GroupChat(messages=[], agents=[coder], select_speaker_transform_messages=test_add_transforms)

# Ensure the transform have been added to the GroupChat
assert groupchat._speaker_selection_transforms == test_add_transforms

# Attempt to add a non MessageTransforms object, such as a list of transforms
with pytest.raises(ValueError, match="select_speaker_transform_messages must be None or MessageTransforms."):
groupchat = GroupChat(
messages=[],
agents=[coder],
select_speaker_transform_messages=List[transforms.MessageHistoryLimiter(max_messages=10)],
)

# Ensure if we don't pass any transforms in, none are on the GroupChat
groupchat_missing = GroupChat(messages=[], agents=[coder])

assert groupchat_missing._speaker_selection_transforms is None

# Ensure we can pass in None
groupchat_none = GroupChat(
messages=[],
agents=[coder],
select_speaker_transform_messages=None,
)

assert groupchat_none._speaker_selection_transforms is None


test_select_speaker_transform_messages()
42 changes: 42 additions & 0 deletions test/agentchat/test_groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import autogen
from autogen import Agent, AssistantAgent, GroupChat, GroupChatManager
from autogen.agentchat.contrib.capabilities import transform_messages, transforms
from autogen.exception_utils import AgentNameConflict, UndefinedNextAgent


Expand Down Expand Up @@ -2067,6 +2068,46 @@ def test_manager_resume_messages():
return_agent, return_message = manager.resume(messages="Let's get this conversation started.")


def test_select_speaker_transform_messages():
"""Tests adding transform messages to a GroupChat for speaker selection when in 'auto' mode"""

# Test adding a TransformMessages to a group chat
test_add_transforms = transform_messages.TransformMessages(
transforms=[
transforms.MessageHistoryLimiter(max_messages=10),
transforms.MessageTokenLimiter(max_tokens=3000, max_tokens_per_message=500, min_tokens=300),
]
)

coder = AssistantAgent(name="Coder", llm_config=None)
groupchat = GroupChat(messages=[], agents=[coder], select_speaker_transform_messages=test_add_transforms)

# Ensure the transform have been added to the GroupChat
assert groupchat._speaker_selection_transforms == test_add_transforms

# Attempt to add a non MessageTransforms object, such as a list of transforms
with pytest.raises(ValueError, match="select_speaker_transform_messages must be None or MessageTransforms."):
groupchat = GroupChat(
messages=[],
agents=[coder],
select_speaker_transform_messages=[transforms.MessageHistoryLimiter(max_messages=10)],
)

# Ensure if we don't pass any transforms in, none are on the GroupChat
groupchat_missing = GroupChat(messages=[], agents=[coder])

assert groupchat_missing._speaker_selection_transforms is None

# Ensure we can pass in None
groupchat_none = GroupChat(
messages=[],
agents=[coder],
select_speaker_transform_messages=None,
)

assert groupchat_none._speaker_selection_transforms is None


def test_manager_resume_message_assignment():
"""Tests that the messages passed in are assigned to agents correctly"""

Expand Down Expand Up @@ -2140,5 +2181,6 @@ def test_manager_resume_message_assignment():
# test_manager_resume_functions()
# test_manager_resume_returns()
# test_manager_resume_messages()
# test_select_speaker_transform_messages()
test_manager_resume_message_assignment()
pass
Loading
Loading