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

functionality of manual history cleaning by user proxy added #1230

Merged
merged 34 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
56b5fe5
functionality of manual history cleaning by admin added
Grigorij-Dudnik Jan 13, 2024
42cb928
formatting improved
Grigorij-Dudnik Jan 13, 2024
f1a9187
formatting improved 2
Grigorij-Dudnik Jan 13, 2024
1f40a73
formatting improved 3
Grigorij-Dudnik Jan 13, 2024
4df97a3
Merge branch 'main' into manual_history_cleaning
Grigorij-Dudnik Jan 13, 2024
4671d70
Merge branch 'main' into manual_history_cleaning
davorrunje Jan 15, 2024
4083ad4
Merge branch 'main' into manual_history_cleaning
Grigorij-Dudnik Jan 16, 2024
0d4f77d
test function added
Grigorij-Dudnik Jan 17, 2024
ef0cafb
test code formatting
Grigorij-Dudnik Jan 17, 2024
62ca13e
test code formatting 2
Grigorij-Dudnik Jan 17, 2024
aa73fcf
more advanced logging. Now user can see nr of messages to preserve as…
Grigorij-Dudnik Jan 18, 2024
8d02c30
Merge branch 'main' into manual_history_cleaning
davorrunje Jan 18, 2024
e2958c9
test_invalid_allow_repeat_speaker uncommented
Grigorij-Dudnik Jan 19, 2024
4400c32
Merge branch 'manual_history_cleaning' of https://github.com/GregorD1…
Grigorij-Dudnik Jan 19, 2024
f28d7c1
Merge branch 'main' into manual_history_cleaning
davorrunje Jan 19, 2024
822fbf9
warning when providing recepient agent and nr messages to preserve ad…
Grigorij-Dudnik Jan 20, 2024
d67562e
Merge branch 'manual_history_cleaning' of https://github.com/GregorD1…
Grigorij-Dudnik Jan 20, 2024
a520d54
code formatting
Grigorij-Dudnik Jan 20, 2024
6ce9e97
code formatting
Grigorij-Dudnik Jan 20, 2024
403e6e6
code formatting
Grigorij-Dudnik Jan 20, 2024
db46def
Merge branch 'main' into manual_history_cleaning
Grigorij-Dudnik Jan 22, 2024
2fc78ab
added 'enable_clear_history' variable to GroupChat
Grigorij-Dudnik Jan 22, 2024
fca28ab
Merge branch 'manual_history_cleaning' of https://github.com/GregorD1…
Grigorij-Dudnik Jan 22, 2024
4a76e91
'enable_clear_history' added, better descripted
Grigorij-Dudnik Jan 23, 2024
6488d82
clearing groupchat history added
Grigorij-Dudnik Jan 23, 2024
ac58b55
clearing groupchat history added
Grigorij-Dudnik Jan 23, 2024
b0b42a7
two ifs merged into one, formatting improved
Grigorij-Dudnik Jan 24, 2024
f27400f
two ifs merged into one, formatting improved
Grigorij-Dudnik Jan 24, 2024
11dbee3
two ifs merged into one, formatting improved
Grigorij-Dudnik Jan 24, 2024
e9706b7
formatting
Grigorij-Dudnik Jan 24, 2024
ea1bc05
formatting
Grigorij-Dudnik Jan 24, 2024
dce124c
Merge branch 'main' into manual_history_cleaning
sonichi Jan 24, 2024
25f3432
Merge branch 'main' into manual_history_cleaning
Grigorij-Dudnik Jan 25, 2024
fe813da
Merge branch 'main' into manual_history_cleaning
sonichi Jan 26, 2024
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
24 changes: 19 additions & 5 deletions autogen/agentchat/conversable_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,16 +759,30 @@ def reset_consecutive_auto_reply_counter(self, sender: Optional[Agent] = None):
else:
self._consecutive_auto_reply_counter[sender] = 0

def clear_history(self, agent: Optional[Agent] = None):
def clear_history(self, recipient: Optional[Agent] = None, nr_messages_to_preserve: Optional[int] = None):
"""Clear the chat history of the agent.

Args:
agent: the agent with whom the chat history to clear. If None, clear the chat history with all agents.
recipient: the agent with whom the chat history to clear. If None, clear the chat history with all agents.
nr_messages_to_preserve: the number of newest messages to preserve in the chat history.
"""
if agent is None:
self._oai_messages.clear()
if recipient is None:
if nr_messages_to_preserve:
for key in self._oai_messages:
# Remove messages from history except last `nr_messages_to_preserve` messages.
self._oai_messages[key] = self._oai_messages[key][-nr_messages_to_preserve:]
else:
self._oai_messages.clear()
else:
self._oai_messages[agent].clear()
self._oai_messages[recipient].clear()
if nr_messages_to_preserve:
print(
colored(
"WARNING: `nr_preserved_messages` is ignored when clearing chat history with a specific agent.",
"yellow",
),
flush=True,
)

def generate_oai_reply(
self,
Expand Down
58 changes: 58 additions & 0 deletions autogen/agentchat/groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,12 @@ def run_chat(
raise
if reply is None:
break

# check for "clear history" phrase in reply and activate clear history function if found
sonichi marked this conversation as resolved.
Show resolved Hide resolved
if type(reply) is dict and reply["role"] == "user":
sonichi marked this conversation as resolved.
Show resolved Hide resolved
if "CLEAR HISTORY" in reply["content"].upper():
reply["content"] = self.clear_agents_history(reply["content"], groupchat)

# The speaker sends the message without requesting a reply
speaker.send(reply, self, request_reply=False)
message = self.last_message(speaker)
Expand Down Expand Up @@ -464,3 +470,55 @@ def _raise_exception_on_async_reply_functions(self) -> None:

for agent in self._groupchat.agents:
agent._raise_exception_on_async_reply_functions()

def clear_agents_history(self, reply: str, groupchat: GroupChat) -> str:
"""Clears history of messages for all agents or selected one. Can preserve selected number of last messages.

Args:
reply (str): Admin reply to analyse.
sonichi marked this conversation as resolved.
Show resolved Hide resolved
groupchat (GroupChat): GroupChat object.
"""
# Split the reply into words
words = reply.split()
# Find the position of "clear" to determine where to start processing
clear_word_index = next(i for i in reversed(range(len(words))) if words[i].upper() == "CLEAR")
# Extract potential agent name and steps
words_to_check = words[clear_word_index + 2 : clear_word_index + 4]
nr_messages_to_preserve = None
agent_to_memory_clear = None

for word in words_to_check:
if word.isdigit():
nr_messages_to_preserve = int(word)
elif word[:-1].isdigit(): # for the case when number of messages is followed by dot or other sign
nr_messages_to_preserve = int(word[:-1])
else:
for agent in groupchat.agents:
if agent.name == word:
agent_to_memory_clear = agent
break
elif agent.name == word[:-1]: # for the case when agent name is followed by dot or other sign
agent_to_memory_clear = agent
break
# clear history
if agent_to_memory_clear:
if nr_messages_to_preserve:
print(
f"Clearing history for {agent_to_memory_clear.name} except last {nr_messages_to_preserve} messages."
)
else:
print(f"Clearing history for {agent_to_memory_clear.name}.")
agent_to_memory_clear.clear_history(nr_messages_to_preserve=nr_messages_to_preserve)
else:
if nr_messages_to_preserve:
print(f"Clearing history for all agents except last {nr_messages_to_preserve} messages.")
else:
print("Clearing history for all agents.")
for agent in groupchat.agents:
agent.clear_history(nr_messages_to_preserve=nr_messages_to_preserve)

# Reconstruct the reply without the "clear history" command and parameters
skip_words_number = 2 + int(bool(agent_to_memory_clear)) + int(bool(nr_messages_to_preserve))
reply = " ".join(words[:clear_word_index] + words[clear_word_index + skip_words_number :])

return reply
75 changes: 75 additions & 0 deletions test/agentchat/test_groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,80 @@ def test_selection_helpers():
groupchat.manual_select_speaker()


def test_clear_agents_history():
agent1 = autogen.ConversableAgent(
"alice",
max_consecutive_auto_reply=10,
human_input_mode="NEVER",
llm_config=False,
default_auto_reply="This is alice speaking.",
)
agent2 = autogen.ConversableAgent(
"bob",
max_consecutive_auto_reply=10,
human_input_mode="NEVER",
llm_config=False,
default_auto_reply="This is bob speaking.",
)
agent3 = autogen.ConversableAgent(
"sam",
max_consecutive_auto_reply=10,
human_input_mode="ALWAYS",
llm_config=False,
)
groupchat = autogen.GroupChat(agents=[agent1, agent2, agent3], messages=[], max_round=3)
group_chat_manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=False)

# testing pure "clear history" statement
with mock.patch.object(builtins, "input", lambda _: "clear history. How you doing?"):
agent1.initiate_chat(group_chat_manager, message="hello")
agent1_history = list(agent1._oai_messages.values())[0]
agent2_history = list(agent2._oai_messages.values())[0]
assert agent1_history == [{"content": "How you doing?", "name": "sam", "role": "user"}]
assert agent2_history == [{"content": "How you doing?", "name": "sam", "role": "user"}]

# testing clear history for defined agent
with mock.patch.object(builtins, "input", lambda _: "clear history bob. How you doing?"):
agent1.initiate_chat(group_chat_manager, message="hello")
agent1_history = list(agent1._oai_messages.values())[0]
agent2_history = list(agent2._oai_messages.values())[0]
assert agent1_history == [
{"content": "hello", "role": "assistant"},
{"content": "This is bob speaking.", "name": "bob", "role": "user"},
{"content": "How you doing?", "name": "sam", "role": "user"},
]
assert agent2_history == [{"content": "How you doing?", "name": "sam", "role": "user"}]

# testing clear history with defined nr of messages to preserve
with mock.patch.object(builtins, "input", lambda _: "clear history 1. How you doing?"):
agent1.initiate_chat(group_chat_manager, message="hello")
agent1_history = list(agent1._oai_messages.values())[0]
agent2_history = list(agent2._oai_messages.values())[0]
assert agent1_history == [
{"content": "This is bob speaking.", "name": "bob", "role": "user"},
{"content": "How you doing?", "name": "sam", "role": "user"},
]
assert agent2_history == [
{"content": "This is bob speaking.", "role": "assistant"},
{"content": "How you doing?", "name": "sam", "role": "user"},
]

# testing clear history with defined agent and nr of messages to preserve
with mock.patch.object(builtins, "input", lambda _: "clear history bob 1. How you doing?"):
agent1.initiate_chat(group_chat_manager, message="hello")
agent1_history = list(agent1._oai_messages.values())[0]
agent2_history = list(agent2._oai_messages.values())[0]
assert agent1_history == [
{"content": "hello", "role": "assistant"},
{"content": "This is bob speaking.", "name": "bob", "role": "user"},
{"content": "How you doing?", "name": "sam", "role": "user"},
]
assert agent2_history == [
{"content": "This is bob speaking.", "role": "assistant"},
{"content": "How you doing?", "name": "sam", "role": "user"},
]


if __name__ == "__main__":
# test_func_call_groupchat()
# test_broadcast()
Expand All @@ -515,3 +589,4 @@ def test_selection_helpers():
# test_termination()
# test_next_agent()
test_invalid_allow_repeat_speaker()
test_clear_agents_history()
Loading