Skip to content

Commit

Permalink
improve validation of llm_config (#1946)
Browse files Browse the repository at this point in the history
* improve validation of llm_config

* fixed test_register_for_llm_without_LLM

* docstr about llm_config=None

* Make None a sentinel

* pop tools

---------

Co-authored-by: Davor Runje <[email protected]>
  • Loading branch information
sonichi and davorrunje authored Mar 11, 2024
1 parent ce71d85 commit 5235818
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 27 deletions.
34 changes: 18 additions & 16 deletions autogen/agentchat/conversable_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ConversableAgent(LLMAgent):
`run_code`, and `execute_function` methods respectively.
"""

DEFAULT_CONFIG = {} # An empty configuration
DEFAULT_CONFIG = False # False or dict, the default config for llm inference
MAX_CONSECUTIVE_AUTO_REPLY = 100 # maximum number of consecutive auto replies (subject to future change)

DEFAULT_SUMMARY_PROMPT = "Summarize the takeaway from the conversation. Do not add any introductory phrases."
Expand Down Expand Up @@ -123,7 +123,9 @@ def __init__(
llm_config (dict or False or None): llm inference configuration.
Please refer to [OpenAIWrapper.create](/docs/reference/oai/client#create)
for available options.
When using OpenAI or Azure OpenAI endpoints, please specify a non-empty 'model' either in `llm_config` or in each config of 'config_list' in `llm_config`.
To disable llm-based auto reply, set to False.
When set to None, will use self.DEFAULT_CONFIG, which defaults to False.
default_auto_reply (str or dict): default auto reply when no code execution or llm-based reply is generated.
description (str): a short description of the agent. This description is used by other agents
(e.g. the GroupChatManager) to decide when to call upon this agent. (Default: system_message)
Expand All @@ -139,21 +141,7 @@ def __init__(
else (lambda x: content_str(x.get("content")) == "TERMINATE")
)

if llm_config is False:
self.llm_config = False
self.client = None
else:
self.llm_config = self.DEFAULT_CONFIG.copy()
if isinstance(llm_config, dict):
self.llm_config.update(llm_config)
if "model" not in self.llm_config and (
not self.llm_config.get("config_list")
or any(not config.get("model") for config in self.llm_config["config_list"])
):
raise ValueError(
"Please either set llm_config to False, or specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'."
)
self.client = OpenAIWrapper(**self.llm_config)
self._validate_llm_config(llm_config)

if logging_enabled():
log_new_agent(self, locals())
Expand Down Expand Up @@ -246,6 +234,20 @@ def __init__(
"process_message_before_send": [],
}

def _validate_llm_config(self, llm_config):
assert llm_config in (None, False) or isinstance(
llm_config, dict
), "llm_config must be a dict or False or None."
if llm_config is None:
llm_config = self.DEFAULT_CONFIG
self.llm_config = self.DEFAULT_CONFIG if llm_config is None else llm_config
# TODO: more complete validity check
if self.llm_config in [{}, {"config_list": []}, {"config_list": [{"model": ""}]}]:
raise ValueError(
"When using OpenAI or Azure OpenAI endpoints, specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'."
)
self.client = None if self.llm_config is False else OpenAIWrapper(**self.llm_config)

@property
def name(self) -> str:
"""Get the name of the agent."""
Expand Down
6 changes: 5 additions & 1 deletion autogen/agentchat/groupchat.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,11 @@ def __init__(
system_message: Optional[Union[str, List]] = "Group chat manager.",
**kwargs,
):
if kwargs.get("llm_config") and (kwargs["llm_config"].get("functions") or kwargs["llm_config"].get("tools")):
if (
kwargs.get("llm_config")
and isinstance(kwargs["llm_config"], dict)
and (kwargs["llm_config"].get("functions") or kwargs["llm_config"].get("tools"))
):
raise ValueError(
"GroupChatManager is not allowed to make function/tool calls. Please remove the 'functions' or 'tools' config in 'llm_config' you passed in."
)
Expand Down
5 changes: 3 additions & 2 deletions autogen/agentchat/user_proxy_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,11 @@ def __init__(
- timeout (Optional, int): The maximum execution time in seconds.
- last_n_messages (Experimental, Optional, int): The number of messages to look back for code execution. Default to 1.
default_auto_reply (str or dict or None): the default auto reply message when no code execution or llm based reply is generated.
llm_config (dict or False): llm inference configuration.
llm_config (dict or False or None): llm inference configuration.
Please refer to [OpenAIWrapper.create](/docs/reference/oai/client#create)
for available options.
Default to false, which disables llm-based auto reply.
Default to False, which disables llm-based auto reply.
When set to None, will use self.DEFAULT_CONFIG, which defaults to False.
system_message (str or List): system message for ChatCompletion inference.
Only used when llm_config is not False. Use it to reprogram the agent.
description (str): a short description of the agent. This description is used by other agents
Expand Down
1 change: 1 addition & 0 deletions autogen/oai/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ def __init__(self, *, config_list: Optional[List[Dict[str, Any]]] = None, **base
base_config: base config. It can contain both keyword arguments for openai client
and additional kwargs.
When using OpenAI or Azure OpenAI endpoints, please specify a non-empty 'model' either in `base_config` or in each config of `config_list`.
"""

if logging_enabled():
Expand Down
2 changes: 1 addition & 1 deletion autogen/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.17"
__version__ = "0.2.18"
9 changes: 7 additions & 2 deletions notebook/agentchat_function_call_async.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@
"\n",
"llm_config_manager = llm_config.copy()\n",
"llm_config_manager.pop(\"functions\", None)\n",
"llm_config_manager.pop(\"tools\", None)\n",
"\n",
"manager = autogen.GroupChatManager(\n",
" groupchat=groupchat,\n",
Expand Down Expand Up @@ -361,8 +362,12 @@
],
"metadata": {
"front_matter": {
"tags": ["code generation", "function call", "async"],
"description": "Learn how to implement both synchronous and asynchronous function calls using AssistantAgent and UserProxyAgent in AutoGen, with examples of their application in individual and group chat settings for task execution with language models."
"description": "Learn how to implement both synchronous and asynchronous function calls using AssistantAgent and UserProxyAgent in AutoGen, with examples of their application in individual and group chat settings for task execution with language models.",
"tags": [
"code generation",
"function call",
"async"
]
},
"kernelspec": {
"display_name": "flaml_dev",
Expand Down
14 changes: 9 additions & 5 deletions test/agentchat/test_conversable_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,25 +817,29 @@ def exec_python(cell: Annotated[str, "Valid Python cell to execute."]) -> str:


def test_register_for_llm_without_LLM():
agent = ConversableAgent(name="agent", llm_config=None)
with pytest.raises(
ValueError,
match="Please either set llm_config to False, or specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'.",
AssertionError,
match="To update a tool signature, agent must have an llm_config",
):
ConversableAgent(name="agent", llm_config=None)

@agent.register_for_llm(description="do things.")
def do_stuff(s: str) -> str:
return f"{s} done"


def test_register_for_llm_without_configuration():
with pytest.raises(
ValueError,
match="Please either set llm_config to False, or specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'.",
match="When using OpenAI or Azure OpenAI endpoints, specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'.",
):
ConversableAgent(name="agent", llm_config={"config_list": []})


def test_register_for_llm_without_model_name():
with pytest.raises(
ValueError,
match="Please either set llm_config to False, or specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'.",
match="When using OpenAI or Azure OpenAI endpoints, specify a non-empty 'model' either in 'llm_config' or in each config of 'config_list'.",
):
ConversableAgent(name="agent", llm_config={"config_list": [{"model": ""}]})

Expand Down

0 comments on commit 5235818

Please sign in to comment.