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

Feature/support conditional tool calling #1141

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
34511fa
fix: Make Google maps as optional
Wendong-Fan Sep 12, 2024
376f447
remove FUNCS and GPT35 Turbo in example
Wendong-Fan Sep 13, 2024
0ad7653
partial refactoring
WHALEEYE Sep 13, 2024
0420434
merge master
WHALEEYE Sep 24, 2024
88208f0
fix format
WHALEEYE Sep 24, 2024
c4df50c
refactor: add ToolManager
Sep 30, 2024
cde4c0a
update: Add several methods to ToolManager
Sep 30, 2024
785b37f
fix
Sep 30, 2024
3259cce
Refactor ToolManager and GithubToolkit classes
Oct 8, 2024
9220f15
Add toolkits manager example file
Oct 8, 2024
fa17d65
format toolkits manager example file
Oct 8, 2024
50ff7d9
Refactor toolkits manager file
Oct 12, 2024
42a1cf1
Refactor toolkits manager example file
Oct 12, 2024
9e01960
Refactor ToolManager to implement singleton pattern
Oct 12, 2024
187b7e5
Refactor ToolManager to support registering multiple toolkit function…
Oct 12, 2024
bab3c27
Fix comments
Oct 12, 2024
675ebab
Refactor toolkits manager example file
Oct 12, 2024
4b40cce
Refactor list_toolkit_classes
Oct 12, 2024
60a0435
fix bug
Oct 12, 2024
26434da
Merge branch 'master' into refactor/toolkits
Oct 12, 2024
9c4a163
feat: Refactor OpenAIFunction to FunctionTool (#966)
tom-doerr Oct 13, 2024
d15aacb
feat: make system_message as optional (#1038)
Wendong-Fan Oct 13, 2024
8af6911
Refactor search_toolkits method of ToolkitManager
Oct 14, 2024
ad2db6b
Refactor get_tools method in BaseToolkit
Oct 14, 2024
9092324
Format code
Oct 14, 2024
816cb01
Refactor FUNCS and the names of functional toolkits
Oct 14, 2024
9f5a62d
Refactor method loading in ToolkitManager
Oct 15, 2024
53e92a9
fix
Oct 15, 2024
0ee7215
Add get_toolkit_class method in ToolkitManager
Oct 15, 2024
c60d0ba
Refactor the way ToolkitManager reports errors and annotations.
Oct 15, 2024
d602e3e
bugfix
Oct 15, 2024
dd0e42c
Add Machine class and TaskManagerWithState class
Nov 1, 2024
0951bba
Refactor TaskManagerWithState to use FunctionToolState instead of str…
Nov 1, 2024
c206eca
Refactor imports in task.py
Nov 1, 2024
7cf305d
Refactor TaskManagerWithState to use FunctionToolState instead of str…
Nov 1, 2024
e3b8ac9
Add conditional_function_calling.py
Nov 1, 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
71 changes: 45 additions & 26 deletions camel/agents/chat_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
from openai import Stream

from camel.terminators import ResponseTerminator
from camel.toolkits import OpenAIFunction
from camel.toolkits import FunctionTool


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -115,7 +115,8 @@ class ChatAgent(BaseAgent):
r"""Class for managing conversations of CAMEL Chat Agents.

Args:
system_message (BaseMessage): The system message for the chat agent.
system_message (BaseMessage, optional): The system message for the
chat agent.
model (BaseModelBackend, optional): The model backend to use for
generating responses. (default: :obj:`OpenAIModel` with
`GPT_4O_MINI`)
Expand All @@ -131,10 +132,10 @@ class ChatAgent(BaseAgent):
(default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
tools (List[OpenAIFunction], optional): List of available
:obj:`OpenAIFunction`. (default: :obj:`None`)
external_tools (List[OpenAIFunction], optional): List of external tools
(:obj:`OpenAIFunction`) bind to one chat agent. When these tools
tools (List[FunctionTool], optional): List of available
:obj:`FunctionTool`. (default: :obj:`None`)
external_tools (List[FunctionTool], optional): List of external tools
(:obj:`FunctionTool`) bind to one chat agent. When these tools
are called, the agent will directly return the request instead of
processing it. (default: :obj:`None`)
response_terminators (List[ResponseTerminator], optional): List of
Expand All @@ -144,20 +145,24 @@ class ChatAgent(BaseAgent):

def __init__(
self,
system_message: BaseMessage,
system_message: Optional[BaseMessage] = None,
model: Optional[BaseModelBackend] = None,
memory: Optional[AgentMemory] = None,
message_window_size: Optional[int] = None,
token_limit: Optional[int] = None,
output_language: Optional[str] = None,
tools: Optional[List[OpenAIFunction]] = None,
external_tools: Optional[List[OpenAIFunction]] = None,
tools: Optional[List[FunctionTool]] = None,
external_tools: Optional[List[FunctionTool]] = None,
response_terminators: Optional[List[ResponseTerminator]] = None,
) -> None:
self.orig_sys_message: BaseMessage = system_message
self.system_message = system_message
self.role_name: str = system_message.role_name
self.role_type: RoleType = system_message.role_type
self.orig_sys_message: Optional[BaseMessage] = system_message
self._system_message: Optional[BaseMessage] = system_message
self.role_name: str = (
getattr(system_message, 'role_name', None) or "assistant"
)
self.role_type: RoleType = (
getattr(system_message, 'role_type', None) or RoleType.ASSISTANT
)
self.model_backend: BaseModelBackend = (
model
if model is not None
Expand Down Expand Up @@ -272,11 +277,12 @@ def reset(self):
terminator.reset()

@property
def system_message(self) -> BaseMessage:
def system_message(self) -> Optional[BaseMessage]:
r"""The getter method for the property :obj:`system_message`.

Returns:
BaseMessage: The system message of this agent.
Optional[BaseMessage]: The system message of this agent if set,
else :obj:`None`.
"""
return self._system_message

Expand Down Expand Up @@ -327,12 +333,22 @@ def set_output_language(self, output_language: str) -> BaseMessage:
BaseMessage: The updated system message object.
"""
self.output_language = output_language
content = self.orig_sys_message.content + (
language_prompt = (
"\nRegardless of the input language, "
f"you must output text in {output_language}."
)
self.system_message = self.system_message.create_new_instance(content)
return self.system_message
if self.orig_sys_message is not None:
content = self.orig_sys_message.content + language_prompt
self._system_message = self.orig_sys_message.create_new_instance(
content
)
return self._system_message
else:
self._system_message = BaseMessage.make_assistant_message(
role_name="Assistant",
content=language_prompt,
)
return self._system_message

def get_info(
self,
Expand Down Expand Up @@ -377,12 +393,15 @@ def init_messages(self) -> None:
r"""Initializes the stored messages list with the initial system
message.
"""
system_record = MemoryRecord(
message=self.system_message,
role_at_backend=OpenAIBackendRole.SYSTEM,
)
self.memory.clear()
self.memory.write_record(system_record)
if self.orig_sys_message is not None:
system_record = MemoryRecord(
message=self.orig_sys_message,
role_at_backend=OpenAIBackendRole.SYSTEM,
)
self.memory.clear()
self.memory.write_record(system_record)
else:
self.memory.clear()

def record_message(self, message: BaseMessage) -> None:
r"""Records the externally provided message into the agent memory as if
Expand Down Expand Up @@ -795,12 +814,12 @@ def _structure_output_with_function(
r"""Internal function of structuring the output of the agent based on
the given output schema.
"""
from camel.toolkits import OpenAIFunction
from camel.toolkits import FunctionTool

schema_json = get_pydantic_object_schema(output_schema)
func_str = json_to_function_code(schema_json)
func_callable = func_string_to_callable(func_str)
func = OpenAIFunction(func_callable)
func = FunctionTool(func_callable)

original_func_dict = self.func_dict
original_model_dict = self.model_backend.model_config_dict
Expand Down
12 changes: 6 additions & 6 deletions camel/configs/base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ class BaseConfig(ABC, BaseModel):
@classmethod
def fields_type_checking(cls, tools):
if tools is not None:
from camel.toolkits import OpenAIFunction
from camel.toolkits import FunctionTool

for tool in tools:
if not isinstance(tool, OpenAIFunction):
if not isinstance(tool, FunctionTool):
raise ValueError(
f"The tool {tool} should "
"be an instance of `OpenAIFunction`."
"be an instance of `FunctionTool`."
)
return tools

Expand All @@ -54,14 +54,14 @@ def as_dict(self) -> dict[str, Any]:

tools_schema = None
if self.tools:
from camel.toolkits import OpenAIFunction
from camel.toolkits import FunctionTool

tools_schema = []
for tool in self.tools:
if not isinstance(tool, OpenAIFunction):
if not isinstance(tool, FunctionTool):
raise ValueError(
f"The tool {tool} should "
"be an instance of `OpenAIFunction`."
"be an instance of `FunctionTool`."
)
tools_schema.append(tool.get_openai_tool_schema())
config_dict["tools"] = tools_schema
Expand Down
2 changes: 1 addition & 1 deletion camel/configs/groq_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class GroqConfig(BaseConfig):
user (str, optional): A unique identifier representing your end-user,
which can help OpenAI to monitor and detect abuse.
(default: :obj:`""`)
tools (list[OpenAIFunction], optional): A list of tools the model may
tools (list[FunctionTool], optional): A list of tools the model may
call. Currently, only functions are supported as a tool. Use this
to provide a list of functions the model may generate JSON inputs
for. A max of 128 functions are supported.
Expand Down
2 changes: 1 addition & 1 deletion camel/configs/openai_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class ChatGPTConfig(BaseConfig):
user (str, optional): A unique identifier representing your end-user,
which can help OpenAI to monitor and detect abuse.
(default: :obj:`""`)
tools (list[OpenAIFunction], optional): A list of tools the model may
tools (list[FunctionTool], optional): A list of tools the model may
call. Currently, only functions are supported as a tool. Use this
to provide a list of functions the model may generate JSON inputs
for. A max of 128 functions are supported.
Expand Down
2 changes: 1 addition & 1 deletion camel/configs/samba_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ class SambaCloudAPIConfig(BaseConfig):
user (str, optional): A unique identifier representing your end-user,
which can help OpenAI to monitor and detect abuse.
(default: :obj:`""`)
tools (list[OpenAIFunction], optional): A list of tools the model may
tools (list[FunctionTool], optional): A list of tools the model may
call. Currently, only functions are supported as a tool. Use this
to provide a list of functions the model may generate JSON inputs
for. A max of 128 functions are supported.
Expand Down
2 changes: 1 addition & 1 deletion camel/configs/zhipuai_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ZhipuAIConfig(BaseConfig):
in the chat completion. The total length of input tokens and
generated tokens is limited by the model's context length.
(default: :obj:`None`)
tools (list[OpenAIFunction], optional): A list of tools the model may
tools (list[FunctionTool], optional): A list of tools the model may
call. Currently, only functions are supported as a tool. Use this
to provide a list of functions the model may generate JSON inputs
for. A max of 128 functions are supported.
Expand Down
1 change: 1 addition & 0 deletions camel/messages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
'OpenAISystemMessage',
'OpenAIAssistantMessage',
'OpenAIUserMessage',
'OpenAIFunctionMessage',
'OpenAIMessage',
'BaseMessage',
'FunctionCallingMessage',
Expand Down
9 changes: 6 additions & 3 deletions camel/societies/babyagi_playing.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def __init__(
)

self.assistant_agent: ChatAgent
self.assistant_sys_msg: BaseMessage
self.assistant_sys_msg: Optional[BaseMessage]
self.task_creation_agent: TaskCreationAgent
self.task_prioritization_agent: TaskPrioritizationAgent
self.init_agents(
Expand Down Expand Up @@ -202,7 +202,8 @@ def init_agents(

self.task_creation_agent = TaskCreationAgent(
objective=self.specified_task_prompt,
role_name=self.assistant_sys_msg.role_name,
role_name=getattr(self.assistant_sys_msg, 'role_name', None)
or "assistant",
output_language=output_language,
message_window_size=message_window_size,
**(task_creation_agent_kwargs or {}),
Expand Down Expand Up @@ -238,7 +239,9 @@ def step(self) -> ChatAgentResponse:

task_name = self.subtasks.popleft()
assistant_msg_msg = BaseMessage.make_user_message(
role_name=self.assistant_sys_msg.role_name, content=f"{task_name}"
role_name=getattr(self.assistant_sys_msg, 'role_name', None)
or "assistant",
content=f"{task_name}",
)

assistant_response = self.assistant_agent.step(assistant_msg_msg)
Expand Down
8 changes: 5 additions & 3 deletions camel/societies/role_playing.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ def __init__(

self.assistant_agent: ChatAgent
self.user_agent: ChatAgent
self.assistant_sys_msg: BaseMessage
self.user_sys_msg: BaseMessage
self.assistant_sys_msg: Optional[BaseMessage]
self.user_sys_msg: Optional[BaseMessage]
self._init_agents(
init_assistant_sys_msg,
init_user_sys_msg,
Expand Down Expand Up @@ -454,9 +454,11 @@ def init_chat(self, init_msg_content: Optional[str] = None) -> BaseMessage:
)
if init_msg_content is None:
init_msg_content = default_init_msg_content

# Initialize a message sent by the assistant
init_msg = BaseMessage.make_assistant_message(
role_name=self.assistant_sys_msg.role_name,
role_name=getattr(self.assistant_sys_msg, 'role_name', None)
or "assistant",
content=init_msg_content,
)

Expand Down
Loading