Skip to content

Commit

Permalink
chore: minor fix and update (#1188)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wendong-Fan authored Nov 17, 2024
1 parent a9963e2 commit db1d9ef
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 47 deletions.
3 changes: 2 additions & 1 deletion camel/models/samba_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ def run( # type: ignore[misc]
`ChatCompletion` in the non-stream mode, or
`Stream[ChatCompletionChunk]` in the stream mode.
"""

if "tools" in self.model_config_dict:
del self.model_config_dict["tools"]
if self.model_config_dict.get("stream") is True:
return self._run_streaming(messages)
else:
Expand Down
6 changes: 3 additions & 3 deletions camel/societies/workforce/workforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
)
from camel.societies.workforce.worker import Worker
from camel.tasks.task import Task, TaskState
from camel.toolkits import SEARCH_FUNCS, WEATHER_FUNCS, GoogleMapsToolkit
from camel.toolkits import GoogleMapsToolkit, SearchToolkit, WeatherToolkit
from camel.types import ModelPlatformType, ModelType

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -353,8 +353,8 @@ def _create_new_agent(self, role: str, sys_msg: str) -> ChatAgent:

# Default tools for a new agent
function_list = [
*SEARCH_FUNCS,
*WEATHER_FUNCS,
*SearchToolkit().get_tools(),
*WeatherToolkit().get_tools(),
*GoogleMapsToolkit().get_tools(),
]

Expand Down
16 changes: 5 additions & 11 deletions camel/toolkits/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
)
from .open_api_specs.security_config import openapi_security_config

from .math_toolkit import MathToolkit, MATH_FUNCS
from .search_toolkit import SearchToolkit, SEARCH_FUNCS
from .weather_toolkit import WeatherToolkit, WEATHER_FUNCS
from .dalle_toolkit import DalleToolkit, DALLE_FUNCS
from .math_toolkit import MathToolkit
from .search_toolkit import SearchToolkit
from .weather_toolkit import WeatherToolkit
from .dalle_toolkit import DalleToolkit
from .ask_news_toolkit import AskNewsToolkit, AsyncAskNewsToolkit

from .linkedin_toolkit import LinkedInToolkit
from .reddit_toolkit import RedditToolkit
from .base import BaseToolkit
Expand All @@ -35,7 +34,7 @@
from .google_scholar_toolkit import GoogleScholarToolkit
from .arxiv_toolkit import ArxivToolkit
from .slack_toolkit import SlackToolkit
from .twitter_toolkit import TwitterToolkit, TWITTER_FUNCS
from .twitter_toolkit import TwitterToolkit
from .open_api_toolkit import OpenAPIToolkit
from .retrieval_toolkit import RetrievalToolkit
from .notion_toolkit import NotionToolkit
Expand Down Expand Up @@ -65,9 +64,4 @@
'GoogleScholarToolkit',
'NotionToolkit',
'ArxivToolkit',
'MATH_FUNCS',
'SEARCH_FUNCS',
'WEATHER_FUNCS',
'DALLE_FUNCS',
'TWITTER_FUNCS',
]
3 changes: 0 additions & 3 deletions camel/toolkits/dalle_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,3 @@ def get_tools(self) -> List[FunctionTool]:
representing the functions in the toolkit.
"""
return [FunctionTool(self.get_dalle_img)]


DALLE_FUNCS: List[FunctionTool] = DalleToolkit().get_tools()
31 changes: 29 additions & 2 deletions camel/toolkits/function_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,31 @@ def _remove_a_key(d: Dict, remove_key: Any) -> None:
_remove_a_key(d[key], remove_key)


def _remove_title_recursively(data, parent_key=None):
r"""Recursively removes the 'title' key from all levels of a nested
dictionary, except when 'title' is an argument name in the schema.
"""
if isinstance(data, dict):
# Only remove 'title' if it's not an argument name
if parent_key not in [
"properties",
"$defs",
"items",
"allOf",
"oneOf",
"anyOf",
]:
data.pop("title", None)

# Recursively process each key-value pair
for key, value in data.items():
_remove_title_recursively(value, parent_key=key)
elif isinstance(data, list):
# Recursively process each element in the list
for item in data:
_remove_title_recursively(item, parent_key=parent_key)


def get_openai_function_schema(func: Callable) -> Dict[str, Any]:
r"""Generates a schema dict for an OpenAI function based on its signature.
Expand Down Expand Up @@ -120,9 +145,11 @@ def _create_mol(name, field):

model = _create_mol(to_pascal(func.__name__), fields)
parameters_dict = get_pydantic_object_schema(model)

# The `"title"` is generated by `model.model_json_schema()`
# but is useless for openai json schema
_remove_a_key(parameters_dict, "title")
# but is useless for openai json schema, remove generated 'title' from
# parameters_dict
_remove_title_recursively(parameters_dict)

docstring = parse(func.__doc__ or "")
for param in docstring.params:
Expand Down
3 changes: 0 additions & 3 deletions camel/toolkits/math_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,3 @@ def get_tools(self) -> List[FunctionTool]:
FunctionTool(self.sub),
FunctionTool(self.mul),
]


MATH_FUNCS: List[FunctionTool] = MathToolkit().get_tools()
3 changes: 0 additions & 3 deletions camel/toolkits/search_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,3 @@ def get_tools(self) -> List[FunctionTool]:
FunctionTool(self.query_wolfram_alpha),
FunctionTool(self.tavily_search),
]


SEARCH_FUNCS: List[FunctionTool] = SearchToolkit().get_tools()
15 changes: 6 additions & 9 deletions camel/toolkits/twitter_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,6 @@ def _handle_http_error(response: requests.Response) -> str:
return "Unexpected Exception"


TWITTER_FUNCS = [
FunctionTool(create_tweet),
FunctionTool(delete_tweet),
FunctionTool(get_my_user_profile),
FunctionTool(get_user_by_username),
]


class TwitterToolkit(BaseToolkit):
r"""A class representing a toolkit for Twitter operations.
Expand Down Expand Up @@ -442,4 +434,9 @@ def get_tools(self) -> List[FunctionTool]:
List[FunctionTool]: A list of FunctionTool objects
representing the functions in the toolkit.
"""
return TWITTER_FUNCS
return [
FunctionTool(create_tweet),
FunctionTool(delete_tweet),
FunctionTool(get_my_user_profile),
FunctionTool(get_user_by_username),
]
3 changes: 0 additions & 3 deletions camel/toolkits/weather_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,3 @@ def get_tools(self) -> List[FunctionTool]:
return [
FunctionTool(self.get_weather_data),
]


WEATHER_FUNCS: List[FunctionTool] = WeatherToolkit().get_tools()
36 changes: 34 additions & 2 deletions docs/key_modules/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ In CAMEL, a tool is an `FunctionTool` that LLMs can call.

### 2.1 How to Define Your Own Tool?

Developers can create custom tools tailored to their agent’s specific needs:
Developers can create custom tools tailored to their agent’s specific needs with ease. Here's how you can define and use a custom tool:

**Example: Adding Two Numbers**

First, define your function and wrap it using the `FunctionTool`

```python
from camel.toolkits import FunctionTool
Expand All @@ -37,10 +41,17 @@ def add(a: int, b: int) -> int:
integer: The sum of the two numbers.
"""
return a + b


# Wrap the function with FunctionTool
add_tool = FunctionTool(add)
```

**Accessing Tool Properties**

Once your tool is defined, you can inspect its properties using built-in methods:

Retrieve the function's name:

```python
print(add_tool.get_function_name())
```
Expand All @@ -49,6 +60,8 @@ print(add_tool.get_function_name())
>>> add
```

Get the description of what the function does:

```python
print(add_tool.get_function_description())
```
Expand All @@ -57,6 +70,8 @@ print(add_tool.get_function_description())
>>> Adds two numbers.
```

Fetch the schema representation for OpenAI functions:

```python
print(add_tool.get_openai_function_schema())
```
Expand All @@ -72,6 +87,8 @@ print(add_tool.get_openai_function_schema())
'type': 'object'}}
```

Retrieve the tool schema, compatible with OpenAI's structure:

```python
print(add_tool.get_openai_tool_schema())
```
Expand Down Expand Up @@ -111,6 +128,21 @@ google_tool = FunctionTool(SearchToolkit().search_google)
wiki_tool = FunctionTool(SearchToolkit().search_wiki)
```

### 2.3 Passing Tools to `ChatAgent`
Enhance the functionality of a ChatAgent by passing custom tools during initialization. Here's how you can do it:

```python
from camel.agents import ChatAgent

# Initialize a ChatAgent with your custom tools
tool_agent = ChatAgent(
tools=tools,
)

# Interact with the agent
response = tool_agent.step("A query related to the tool you added")
```

Here is a list of the available CAMEL tools and their descriptions:

| Toolkit | Description |
Expand Down
8 changes: 6 additions & 2 deletions examples/toolkits/post_weather_on_twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from camel.agents import ChatAgent
from camel.messages import BaseMessage
from camel.toolkits import SEARCH_FUNCS, TWITTER_FUNCS, WEATHER_FUNCS
from camel.toolkits import SearchToolkit, TwitterToolkit, WeatherToolkit
from camel.utils import print_text_animated


Expand All @@ -38,7 +38,11 @@ def main():

agent = ChatAgent(
system_message=sys_msg,
tools=[*TWITTER_FUNCS, *WEATHER_FUNCS, *SEARCH_FUNCS],
tools=[
*TwitterToolkit().get_tools(),
*WeatherToolkit().get_tools(),
*SearchToolkit().get_tools(),
],
)

usr_msg = BaseMessage.make_user_message(
Expand Down
4 changes: 2 additions & 2 deletions examples/workforce/multiple_single_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
from camel.societies.workforce import Workforce
from camel.tasks.task import Task
from camel.toolkits import (
WEATHER_FUNCS,
FunctionTool,
GoogleMapsToolkit,
SearchToolkit,
WeatherToolkit,
)
from camel.types import ModelPlatformType, ModelType

Expand All @@ -44,7 +44,7 @@ def main():
content="You can search online for information",
),
model=search_agent_model,
tools=[*search_tools, *WEATHER_FUNCS],
tools=[*search_tools, *WeatherToolkit().get_tools()],
)

# Set up tour guide agent
Expand Down
6 changes: 3 additions & 3 deletions examples/workforce/role_playing_with_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from camel.models import ModelFactory
from camel.societies.workforce import Workforce
from camel.tasks.task import Task
from camel.toolkits import SEARCH_FUNCS, WEATHER_FUNCS, GoogleMapsToolkit
from camel.toolkits import GoogleMapsToolkit, SearchToolkit, WeatherToolkit
from camel.types import ModelPlatformType, ModelType


Expand All @@ -36,8 +36,8 @@ def main():
planner_agent = ChatAgent(planner_sysmsg)

function_list = [
*SEARCH_FUNCS,
*WEATHER_FUNCS,
*SearchToolkit().get_tools(),
*WeatherToolkit().get_tools(),
*GoogleMapsToolkit().get_tools(),
]

Expand Down

0 comments on commit db1d9ef

Please sign in to comment.