Skip to content

Commit

Permalink
Adding register_nested_chats to make nested chat easier (microsoft#…
Browse files Browse the repository at this point in the history
…1753)

* add util

* add notebook

* SoM notebook

* doc

* update notebook

* SoM

* optiguide

* rename

* add implementation

* update notebook

* update notebook

* update notebook

* summary method

* initiate_chats enhancements

* callable summary_method

* summary method

* summary method default

* docstr

* add timeout to slient pip install test

* consolidate_chat_info

* a_initiate_chat

* AssertionError tests

* AssertionError test

* update tests

* update test

* remove redudant file

* kwargs

* update notebook

* update notebook

* nested

* update SoM

* update notebook

* max_turns

* add notebook

* updatenotebook

* add notebooks

* update notebook and test

* add links to the example page

* annotations

* documentation

* default values

* Expanded details about the purpose of each cell

* update default value

* default value for reply_func_from_nested_chats

* default reply func name

* update notebook

* update optiGuide

* upload fig

* optiGuide notebook

* doc

* update notebook

* update notebook

* notebook format

* update optiguide notebook

* raise value error

* update notebook

* Improve language

---------

Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
Co-authored-by: signalprime <15487280+signalprime@users.noreply.github.com>
Co-authored-by: gagb <gagb@users.noreply.github.com>
  • Loading branch information
4 people authored Feb 27, 2024
1 parent 3b8a12c commit 1eaf77a
Show file tree
Hide file tree
Showing 8 changed files with 2,912 additions and 3 deletions.
75 changes: 75 additions & 0 deletions autogen/agentchat/conversable_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging
import re
from collections import defaultdict
from functools import partial
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Type, TypeVar, Union
import warnings
from openai import BadRequestError
Expand Down Expand Up @@ -325,6 +326,80 @@ def reply_func(
if ignore_async_in_sync_chat and inspect.iscoroutinefunction(reply_func):
self._ignore_async_func_in_sync_chat_list.append(reply_func)

@staticmethod
def _summary_from_nested_chats(
chat_queue: List[Dict[str, Any]], recipient: Agent, messages: Union[str, Callable], sender: Agent, config: Any
) -> Tuple[bool, str]:
"""A simple chat reply function.
This function initiate one or a sequence of chats between the "recipient" and the agents in the
chat_queue.
It extracts and returns a summary from the nested chat based on the "summary_method" in each chat in chat_queue.
Returns:
Tuple[bool, str]: A tuple where the first element indicates the completion of the chat, and the second element contains the summary of the last chat if any chats were initiated.
"""
last_msg = messages[-1].get("content")
chat_to_run = []
for i, c in enumerate(chat_queue):
current_c = c.copy()
message = current_c.get("message")
# If message is not provided in chat_queue, we by default use the last message from the original chat history as the first message in this nested chat (for the first chat in the chat queue).
# NOTE: This setting is prone to change.
if message is None and i == 0:
message = last_msg
if callable(message):
message = message(recipient, messages, sender, config)
# We only run chat that has a valid message. NOTE: This is prone to change dependin on applications.
if message:
current_c["message"] = message
chat_to_run.append(current_c)
if not chat_to_run:
return True, None
res = recipient.initiate_chats(chat_to_run)
return True, res[-1].summary

def register_nested_chats(
self,
chat_queue: List[Dict[str, Any]],
trigger: Union[Type[Agent], str, Agent, Callable[[Agent], bool], List] = [Agent, None],
reply_func_from_nested_chats: Union[str, Callable] = "summary_from_nested_chats",
position: int = 2,
**kwargs,
) -> None:
"""Register a nested chat reply function.
Args:
chat_queue (list): a list of chat objects to be initiated.
trigger (Agent class, str, Agent instance, callable, or list): Default to [Agent, None]. Ref to `register_reply` for details.
reply_func_from_nested_chats (Callable, str): the reply function for the nested chat.
The function takes a chat_queue for nested chat, recipient agent, a list of messages, a sender agent and a config as input and returns a reply message.
Default to "summary_from_nested_chats", which corresponds to a built-in reply function that get summary from the nested chat_queue.
```python
def reply_func_from_nested_chats(
chat_queue: List[Dict],
recipient: ConversableAgent,
messages: Optional[List[Dict]] = None,
sender: Optional[Agent] = None,
config: Optional[Any] = None,
) -> Tuple[bool, Union[str, Dict, None]]:
```
position (int): Ref to `register_reply` for details. Default to 2. It means we first check the termination and human reply, then check the registered nested chat reply.
kwargs: Ref to `register_reply` for details.
"""
if reply_func_from_nested_chats == "summary_from_nested_chats":
reply_func_from_nested_chats = self._summary_from_nested_chats
if not callable(reply_func_from_nested_chats):
raise ValueError("reply_func_from_nested_chats must be a callable")
reply_func = partial(reply_func_from_nested_chats, chat_queue)
self.register_reply(
trigger,
reply_func,
position,
kwargs.get("config"),
kwargs.get("reset_config"),
ignore_async_in_sync_chat=kwargs.get("ignore_async_in_sync_chat"),
)

@property
def system_message(self) -> str:
"""Return the system message."""
Expand Down
Loading

0 comments on commit 1eaf77a

Please sign in to comment.