camel-ai 0.2.37__py3-none-any.whl → 0.2.39__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/agents/chat_agent.py +4 -0
- camel/agents/repo_agent.py +2 -2
- camel/benchmarks/apibank.py +1 -1
- camel/benchmarks/apibench.py +1 -1
- camel/configs/__init__.py +3 -0
- camel/configs/modelscope_config.py +59 -0
- camel/datagen/evol_instruct/__init__.py +20 -0
- camel/datagen/evol_instruct/evol_instruct.py +424 -0
- camel/datagen/evol_instruct/scorer.py +166 -0
- camel/datagen/evol_instruct/templates.py +268 -0
- camel/datagen/self_improving_cot.py +1 -1
- camel/datasets/__init__.py +2 -0
- camel/datasets/base_generator.py +22 -9
- camel/datasets/few_shot_generator.py +2 -3
- camel/datasets/self_instruct_generator.py +415 -0
- camel/embeddings/openai_compatible_embedding.py +13 -5
- camel/environments/models.py +10 -4
- camel/environments/single_step.py +181 -41
- camel/interpreters/docker_interpreter.py +2 -2
- camel/interpreters/e2b_interpreter.py +1 -1
- camel/interpreters/internal_python_interpreter.py +1 -1
- camel/interpreters/subprocess_interpreter.py +1 -1
- camel/loaders/__init__.py +2 -2
- camel/loaders/{panda_reader.py → pandas_reader.py} +61 -30
- camel/loaders/unstructured_io.py +2 -1
- camel/memories/blocks/chat_history_block.py +1 -1
- camel/memories/context_creators/score_based.py +198 -67
- camel/models/__init__.py +2 -0
- camel/models/aiml_model.py +9 -3
- camel/models/anthropic_model.py +11 -3
- camel/models/azure_openai_model.py +9 -3
- camel/models/base_audio_model.py +6 -0
- camel/models/base_model.py +4 -0
- camel/models/deepseek_model.py +9 -3
- camel/models/gemini_model.py +9 -3
- camel/models/groq_model.py +9 -3
- camel/models/internlm_model.py +8 -2
- camel/models/model_factory.py +123 -0
- camel/models/modelscope_model.py +208 -0
- camel/models/moonshot_model.py +8 -2
- camel/models/nemotron_model.py +9 -3
- camel/models/nvidia_model.py +9 -3
- camel/models/ollama_model.py +9 -3
- camel/models/openai_audio_models.py +7 -5
- camel/models/openai_compatible_model.py +9 -3
- camel/models/openai_model.py +58 -5
- camel/models/openrouter_model.py +9 -3
- camel/models/qwen_model.py +9 -3
- camel/models/samba_model.py +9 -3
- camel/models/sglang_model.py +11 -4
- camel/models/siliconflow_model.py +8 -2
- camel/models/stub_model.py +2 -1
- camel/models/togetherai_model.py +11 -5
- camel/models/vllm_model.py +10 -4
- camel/models/yi_model.py +9 -3
- camel/models/zhipuai_model.py +11 -5
- camel/retrievers/auto_retriever.py +14 -0
- camel/retrievers/vector_retriever.py +1 -1
- camel/storages/__init__.py +2 -0
- camel/storages/graph_storages/neo4j_graph.py +1 -1
- camel/storages/vectordb_storages/__init__.py +2 -0
- camel/storages/vectordb_storages/base.py +2 -2
- camel/storages/vectordb_storages/milvus.py +2 -2
- camel/storages/vectordb_storages/qdrant.py +2 -2
- camel/storages/vectordb_storages/tidb.py +332 -0
- camel/tasks/task.py +2 -2
- camel/toolkits/__init__.py +9 -1
- camel/toolkits/arxiv_toolkit.py +2 -1
- camel/toolkits/ask_news_toolkit.py +11 -3
- camel/toolkits/audio_analysis_toolkit.py +2 -0
- camel/toolkits/base.py +3 -0
- camel/toolkits/browser_toolkit.py +84 -61
- camel/toolkits/code_execution.py +3 -1
- camel/toolkits/dappier_toolkit.py +2 -1
- camel/toolkits/data_commons_toolkit.py +2 -0
- camel/toolkits/excel_toolkit.py +2 -0
- camel/toolkits/file_write_toolkit.py +2 -0
- camel/toolkits/github_toolkit.py +6 -4
- camel/toolkits/google_scholar_toolkit.py +2 -0
- camel/toolkits/human_toolkit.py +17 -1
- camel/toolkits/image_analysis_toolkit.py +2 -0
- camel/toolkits/linkedin_toolkit.py +2 -1
- camel/toolkits/math_toolkit.py +2 -0
- camel/toolkits/mcp_toolkit.py +42 -52
- camel/toolkits/meshy_toolkit.py +20 -2
- camel/toolkits/networkx_toolkit.py +2 -0
- camel/toolkits/notion_toolkit.py +7 -0
- camel/toolkits/openai_agent_toolkit.py +131 -0
- camel/toolkits/openbb_toolkit.py +2 -1
- camel/toolkits/pubmed_toolkit.py +2 -0
- camel/toolkits/reddit_toolkit.py +2 -1
- camel/toolkits/retrieval_toolkit.py +2 -1
- camel/toolkits/search_toolkit.py +2 -1
- camel/toolkits/searxng_toolkit.py +207 -0
- camel/toolkits/semantic_scholar_toolkit.py +2 -0
- camel/toolkits/slack_toolkit.py +2 -0
- camel/toolkits/stripe_toolkit.py +2 -1
- camel/toolkits/sympy_toolkit.py +2 -0
- camel/toolkits/terminal_toolkit.py +2 -0
- camel/toolkits/thinking_toolkit.py +168 -12
- camel/toolkits/twitter_toolkit.py +2 -1
- camel/toolkits/video_analysis_toolkit.py +2 -1
- camel/toolkits/video_download_toolkit.py +2 -1
- camel/toolkits/weather_toolkit.py +2 -0
- camel/toolkits/whatsapp_toolkit.py +2 -1
- camel/toolkits/zapier_toolkit.py +2 -1
- camel/types/enums.py +66 -0
- camel/types/unified_model_type.py +5 -0
- camel/utils/__init__.py +2 -0
- camel/utils/chunker/code_chunker.py +9 -9
- camel/utils/commons.py +50 -30
- camel/utils/constants.py +2 -2
- camel/utils/mcp.py +79 -0
- camel/verifiers/__init__.py +2 -0
- camel/verifiers/base.py +15 -15
- camel/verifiers/math_verifier.py +182 -0
- camel/verifiers/python_verifier.py +28 -28
- {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/METADATA +54 -4
- {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/RECORD +122 -110
- {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.37.dist-info → camel_ai-0.2.39.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
# See the License for the specific language governing permissions and
|
|
12
|
+
# limitations under the License.
|
|
13
|
+
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
|
|
15
|
+
from typing import ClassVar, Dict, List, Optional, Union
|
|
16
|
+
from urllib.parse import urlparse
|
|
17
|
+
|
|
18
|
+
import requests
|
|
19
|
+
|
|
20
|
+
from camel.logger import get_logger
|
|
21
|
+
from camel.toolkits.base import BaseToolkit
|
|
22
|
+
from camel.toolkits.function_tool import FunctionTool
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SearxNGToolkit(BaseToolkit):
|
|
28
|
+
r"""A toolkit for performing web searches using SearxNG search engine.
|
|
29
|
+
|
|
30
|
+
This toolkit provides methods to search the web using SearxNG,
|
|
31
|
+
a privacy-respecting metasearch engine. It supports customizable
|
|
32
|
+
search parameters and safe search levels.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
searxng_host (str): The URL of the SearxNG instance to use for
|
|
36
|
+
searches. Must be a valid HTTP/HTTPS URL.
|
|
37
|
+
language (str, optional): Search language code for results.
|
|
38
|
+
(default: :obj:`"en"`)
|
|
39
|
+
categories (List[str], optional): List of search categories to use.
|
|
40
|
+
(default: :obj:`None`)
|
|
41
|
+
time_range (str, optional): Time range filter for search results.Valid
|
|
42
|
+
values are "day", "week", "month", "year". (default: :obj:`None`)
|
|
43
|
+
safe_search (int, optional): Safe search level (0: None, 1: Moderate,
|
|
44
|
+
2: Strict). (default: :obj:`1`)
|
|
45
|
+
|
|
46
|
+
Raises:
|
|
47
|
+
ValueError: If searxng_host is not a valid HTTP/HTTPS URL.
|
|
48
|
+
ValueError: If safe_search is not in the valid range [0, 2].
|
|
49
|
+
ValueError: If time_range is provided but not in valid options.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Constants for validation
|
|
53
|
+
_SAFE_SEARCH_LEVELS: ClassVar[Dict[int, str]] = {
|
|
54
|
+
0: "Disabled",
|
|
55
|
+
1: "Moderate",
|
|
56
|
+
2: "Strict",
|
|
57
|
+
}
|
|
58
|
+
_VALID_TIME_RANGES: ClassVar[List[str]] = ["day", "week", "month", "year"]
|
|
59
|
+
_DEFAULT_CATEGORY: ClassVar[str] = "general"
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
searxng_host: str,
|
|
64
|
+
language: str = "en",
|
|
65
|
+
categories: Optional[List[str]] = None,
|
|
66
|
+
time_range: Optional[str] = None,
|
|
67
|
+
safe_search: int = 1,
|
|
68
|
+
) -> None:
|
|
69
|
+
self._validate_searxng_host(searxng_host)
|
|
70
|
+
self._validate_safe_search(safe_search)
|
|
71
|
+
if time_range is not None:
|
|
72
|
+
self._validate_time_range(time_range)
|
|
73
|
+
|
|
74
|
+
self.searxng_host = searxng_host.rstrip('/')
|
|
75
|
+
self.language = language
|
|
76
|
+
self.categories = categories or [self._DEFAULT_CATEGORY]
|
|
77
|
+
self.time_range = time_range
|
|
78
|
+
self.safe_search = safe_search
|
|
79
|
+
|
|
80
|
+
logger.info(
|
|
81
|
+
f"Initialized SearxNG toolkit with host: {searxng_host}, "
|
|
82
|
+
f"safe_search: {self._SAFE_SEARCH_LEVELS[safe_search]}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def _validate_searxng_host(self, url: str) -> None:
|
|
86
|
+
r"""Validate if the given URL is a proper HTTP/HTTPS URL.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
url (str): The URL to validate.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
ValueError: If the URL is not valid.
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
result = urlparse(url)
|
|
96
|
+
is_valid = all(
|
|
97
|
+
[
|
|
98
|
+
result.scheme in ('http', 'https'),
|
|
99
|
+
result.netloc,
|
|
100
|
+
]
|
|
101
|
+
)
|
|
102
|
+
if not is_valid:
|
|
103
|
+
raise ValueError
|
|
104
|
+
except Exception:
|
|
105
|
+
raise ValueError(
|
|
106
|
+
"Invalid searxng_host URL. Must be a valid HTTP/HTTPS URL."
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def _validate_safe_search(self, level: int) -> None:
|
|
110
|
+
r"""Validate if the safe search level is valid.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
level (int): The safe search level to validate.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
ValueError: If the safe search level is not valid.
|
|
117
|
+
"""
|
|
118
|
+
if level not in self._SAFE_SEARCH_LEVELS:
|
|
119
|
+
raise ValueError(
|
|
120
|
+
f"Invalid safe_search level: {level}. Must be one of: "
|
|
121
|
+
f"{list(self._SAFE_SEARCH_LEVELS.keys())}"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def _validate_time_range(self, time_range: str) -> None:
|
|
125
|
+
r"""Validate if the time range is valid.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
time_range (str): The time range to validate.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
ValueError: If the time range is not valid.
|
|
132
|
+
"""
|
|
133
|
+
if time_range not in self._VALID_TIME_RANGES:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Invalid time_range: {time_range}. Must be one of: "
|
|
136
|
+
f"{self._VALID_TIME_RANGES}"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def search(
|
|
140
|
+
self,
|
|
141
|
+
query: str,
|
|
142
|
+
num_results: int = 10,
|
|
143
|
+
category: Optional[str] = None,
|
|
144
|
+
) -> List[Dict[str, str]]:
|
|
145
|
+
r"""Perform a web search using the configured SearxNG instance.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
query (str): The search query string to execute.
|
|
149
|
+
num_results (int, optional): Maximum number of results to return.
|
|
150
|
+
(default: :obj:`10`)
|
|
151
|
+
category (str, optional): Specific search category to use. If not
|
|
152
|
+
provided, uses the first category from self.categories.
|
|
153
|
+
(default: :obj:`None`)
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
List[Dict[str, str]]: List of search results, where each result is
|
|
157
|
+
dictionary containing 'title', 'link', and 'snippet' keys.
|
|
158
|
+
"""
|
|
159
|
+
params: Dict[str, Union[str, int]] = {
|
|
160
|
+
"q": query,
|
|
161
|
+
"format": "json",
|
|
162
|
+
"language": self.language,
|
|
163
|
+
"categories": category or self.categories[0],
|
|
164
|
+
"pageno": 1,
|
|
165
|
+
"safe": self.safe_search,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if self.time_range:
|
|
169
|
+
params["time_range"] = self.time_range
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
logger.debug(f"Sending search request with query: {query}")
|
|
173
|
+
response = requests.get(
|
|
174
|
+
f"{self.searxng_host}/search",
|
|
175
|
+
params=params, # type: ignore[arg-type]
|
|
176
|
+
headers={"User-Agent": "camel-ai/searxng-toolkit"},
|
|
177
|
+
)
|
|
178
|
+
response.raise_for_status()
|
|
179
|
+
results = response.json().get("results", [])
|
|
180
|
+
|
|
181
|
+
formatted_results = []
|
|
182
|
+
for result in results[:num_results]:
|
|
183
|
+
formatted_results.append(
|
|
184
|
+
{
|
|
185
|
+
"title": result.get("title", ""),
|
|
186
|
+
"link": result.get("url", ""),
|
|
187
|
+
"snippet": result.get("content", ""),
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
logger.debug(f"Retrieved {len(formatted_results)} results")
|
|
192
|
+
return formatted_results
|
|
193
|
+
|
|
194
|
+
except Exception as error:
|
|
195
|
+
logger.error(f"Search failed: {error!s}")
|
|
196
|
+
return []
|
|
197
|
+
|
|
198
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
199
|
+
r"""Get the list of available tools in the toolkit.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
List[FunctionTool]: A list of FunctionTool objects representing the
|
|
203
|
+
available functions in the toolkit.
|
|
204
|
+
"""
|
|
205
|
+
return [
|
|
206
|
+
FunctionTool(self.search),
|
|
207
|
+
]
|
|
@@ -19,8 +19,10 @@ import requests
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits import FunctionTool
|
|
21
21
|
from camel.toolkits.base import BaseToolkit
|
|
22
|
+
from camel.utils import MCPServer
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
@MCPServer()
|
|
24
26
|
class SemanticScholarToolkit(BaseToolkit):
|
|
25
27
|
r"""A toolkit for interacting with the Semantic Scholar
|
|
26
28
|
API to fetch paper and author data.
|
camel/toolkits/slack_toolkit.py
CHANGED
|
@@ -20,6 +20,7 @@ import os
|
|
|
20
20
|
from typing import TYPE_CHECKING, List, Optional
|
|
21
21
|
|
|
22
22
|
from camel.toolkits.base import BaseToolkit
|
|
23
|
+
from camel.utils import MCPServer
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
from ssl import SSLContext
|
|
@@ -31,6 +32,7 @@ from camel.toolkits import FunctionTool
|
|
|
31
32
|
logger = logging.getLogger(__name__)
|
|
32
33
|
|
|
33
34
|
|
|
35
|
+
@MCPServer()
|
|
34
36
|
class SlackToolkit(BaseToolkit):
|
|
35
37
|
r"""A class representing a toolkit for Slack operations.
|
|
36
38
|
|
camel/toolkits/stripe_toolkit.py
CHANGED
|
@@ -19,9 +19,10 @@ from typing import List, Optional
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits import FunctionTool
|
|
21
21
|
from camel.toolkits.base import BaseToolkit
|
|
22
|
-
from camel.utils import api_keys_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@MCPServer()
|
|
25
26
|
class StripeToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for Stripe operations.
|
|
27
28
|
|
camel/toolkits/sympy_toolkit.py
CHANGED
|
@@ -18,10 +18,12 @@ from typing import List, Optional
|
|
|
18
18
|
from camel.logger import get_logger
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
+
from camel.utils import MCPServer
|
|
21
22
|
|
|
22
23
|
logger = get_logger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@MCPServer()
|
|
25
27
|
class SymPyToolkit(BaseToolkit):
|
|
26
28
|
r"""A toolkit for performing symbolic computations using SymPy.
|
|
27
29
|
This includes methods for Algebraic manipulation calculus
|
|
@@ -19,10 +19,12 @@ from typing import Any, Dict, List, Optional
|
|
|
19
19
|
from camel.logger import get_logger
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
21
|
from camel.toolkits.function_tool import FunctionTool
|
|
22
|
+
from camel.utils import MCPServer
|
|
22
23
|
|
|
23
24
|
logger = get_logger(__name__)
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
@MCPServer()
|
|
26
28
|
class TerminalToolkit(BaseToolkit):
|
|
27
29
|
r"""A toolkit for terminal operations across multiple operating systems.
|
|
28
30
|
|
|
@@ -22,11 +22,7 @@ logger = get_logger(__name__)
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ThinkingToolkit(BaseToolkit):
|
|
25
|
-
r"""A toolkit for recording thoughts during reasoning processes.
|
|
26
|
-
|
|
27
|
-
Attributes:
|
|
28
|
-
thoughts (List[str]): A list to store the recorded thoughts.
|
|
29
|
-
"""
|
|
25
|
+
r"""A toolkit for recording thoughts during reasoning processes."""
|
|
30
26
|
|
|
31
27
|
def __init__(
|
|
32
28
|
self,
|
|
@@ -39,36 +35,196 @@ class ThinkingToolkit(BaseToolkit):
|
|
|
39
35
|
(default: :obj: `None`)
|
|
40
36
|
"""
|
|
41
37
|
super().__init__(timeout=timeout)
|
|
38
|
+
self.plans: List[str] = []
|
|
39
|
+
self.hypotheses: List[str] = []
|
|
42
40
|
self.thoughts: List[str] = []
|
|
41
|
+
self.contemplations: List[str] = []
|
|
42
|
+
self.critiques: List[str] = []
|
|
43
|
+
self.syntheses: List[str] = []
|
|
44
|
+
self.reflections: List[str] = []
|
|
45
|
+
|
|
46
|
+
def plan(self, plan: str) -> str:
|
|
47
|
+
r"""Use the tool to create a plan or strategy.
|
|
48
|
+
This tool is for outlining the approach or steps to be taken before
|
|
49
|
+
starting the actual thinking process.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
plan (str): A forward-looking plan or strategy.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
str: The recorded plan.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
logger.debug(f"Plan: {plan}")
|
|
59
|
+
self.plans.append(plan)
|
|
60
|
+
return f"Plan: {plan}"
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
error_msg = f"Error recording plan: {e}"
|
|
64
|
+
logger.error(error_msg)
|
|
65
|
+
return error_msg
|
|
66
|
+
|
|
67
|
+
def hypothesize(self, hypothesis: str) -> str:
|
|
68
|
+
r"""Use the tool to form a hypothesis or make a prediction.
|
|
69
|
+
This tool is for making educated guesses or predictions based on
|
|
70
|
+
the plan, before detailed thinking.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
hypothesis (str): A hypothesis or prediction to test.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
str: The recorded hypothesis.
|
|
77
|
+
"""
|
|
78
|
+
try:
|
|
79
|
+
logger.debug(f"Hypothesis: {hypothesis}")
|
|
80
|
+
if not self.plans:
|
|
81
|
+
return "Consider creating a plan before forming hypotheses."
|
|
82
|
+
self.hypotheses.append(hypothesis)
|
|
83
|
+
return f"Hypothesis: {hypothesis}"
|
|
84
|
+
|
|
85
|
+
except Exception as e:
|
|
86
|
+
error_msg = f"Error recording hypothesis: {e}"
|
|
87
|
+
logger.error(error_msg)
|
|
88
|
+
return error_msg
|
|
43
89
|
|
|
44
90
|
def think(self, thought: str) -> str:
|
|
45
91
|
r"""Use the tool to think about something.
|
|
46
92
|
It will not obtain new information or change the database, but just
|
|
47
|
-
append the thought to the log. Use it
|
|
48
|
-
|
|
93
|
+
append the thought to the log. Use it for initial thoughts and
|
|
94
|
+
observations during the execution of the plan.
|
|
49
95
|
|
|
50
96
|
Args:
|
|
51
97
|
thought (str): A thought to think about.
|
|
52
98
|
|
|
53
99
|
Returns:
|
|
54
|
-
str: The
|
|
100
|
+
str: The recorded thought.
|
|
55
101
|
"""
|
|
56
102
|
try:
|
|
57
103
|
logger.debug(f"Thought: {thought}")
|
|
104
|
+
if not self.plans:
|
|
105
|
+
return (
|
|
106
|
+
"Consider creating a plan before thinking "
|
|
107
|
+
"through the process."
|
|
108
|
+
)
|
|
58
109
|
self.thoughts.append(thought)
|
|
59
|
-
|
|
60
|
-
thoughts = "\n".join([f"- {t}" for t in self.thoughts])
|
|
61
|
-
return f"Thoughts:\n{thoughts}"
|
|
110
|
+
return f"Thought: {thought}"
|
|
62
111
|
|
|
63
112
|
except Exception as e:
|
|
64
113
|
error_msg = f"Error recording thought: {e}"
|
|
65
114
|
logger.error(error_msg)
|
|
66
115
|
return error_msg
|
|
67
116
|
|
|
117
|
+
def contemplate(self, contemplation: str) -> str:
|
|
118
|
+
r"""Use the tool to deeply contemplate an idea or concept.
|
|
119
|
+
This tool is for deeper, more thorough exploration of thoughts,
|
|
120
|
+
considering multiple perspectives and implications. It's more
|
|
121
|
+
comprehensive than basic thinking but more focused than reflection.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
contemplation (str): A deeper exploration of thoughts or concepts.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
str: The recorded contemplation.
|
|
128
|
+
"""
|
|
129
|
+
try:
|
|
130
|
+
logger.debug(f"Contemplation: {contemplation}")
|
|
131
|
+
if not self.thoughts:
|
|
132
|
+
return (
|
|
133
|
+
"Consider thinking about the topic before "
|
|
134
|
+
"deep contemplation."
|
|
135
|
+
)
|
|
136
|
+
self.contemplations.append(contemplation)
|
|
137
|
+
return f"Contemplation: {contemplation}"
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
error_msg = f"Error recording contemplation: {e}"
|
|
141
|
+
logger.error(error_msg)
|
|
142
|
+
return error_msg
|
|
143
|
+
|
|
144
|
+
def critique(self, critique: str) -> str:
|
|
145
|
+
r"""Use the tool to critically evaluate current thoughts.
|
|
146
|
+
This tool is for identifying potential flaws, biases, or
|
|
147
|
+
weaknesses in the current thinking process.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
critique (str): A critical evaluation of current thoughts.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
str: The recorded critique.
|
|
154
|
+
"""
|
|
155
|
+
try:
|
|
156
|
+
logger.debug(f"Critique: {critique}")
|
|
157
|
+
if not self.contemplations:
|
|
158
|
+
return "Consider contemplating deeply before critiquing."
|
|
159
|
+
self.critiques.append(critique)
|
|
160
|
+
return f"Critique: {critique}"
|
|
161
|
+
|
|
162
|
+
except Exception as e:
|
|
163
|
+
error_msg = f"Error recording critique: {e}"
|
|
164
|
+
logger.error(error_msg)
|
|
165
|
+
return error_msg
|
|
166
|
+
|
|
167
|
+
def synthesize(self, synthesis: str) -> str:
|
|
168
|
+
r"""Use the tool to combine and integrate various thoughts.
|
|
169
|
+
This tool is for bringing together different thoughts, contemplations,
|
|
170
|
+
and critiques into a coherent understanding.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
synthesis (str): An integration of multiple thoughts and insights.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
str: The recorded synthesis.
|
|
177
|
+
"""
|
|
178
|
+
try:
|
|
179
|
+
logger.debug(f"Synthesis: {synthesis}")
|
|
180
|
+
if not self.critiques:
|
|
181
|
+
return "Consider critiquing thoughts before synthesizing."
|
|
182
|
+
self.syntheses.append(synthesis)
|
|
183
|
+
return f"Synthesis: {synthesis}"
|
|
184
|
+
|
|
185
|
+
except Exception as e:
|
|
186
|
+
error_msg = f"Error recording synthesis: {e}"
|
|
187
|
+
logger.error(error_msg)
|
|
188
|
+
return error_msg
|
|
189
|
+
|
|
190
|
+
def reflect(self, reflection: str) -> str:
|
|
191
|
+
r"""Use the tool to reflect on the entire process.
|
|
192
|
+
This tool is for final evaluation of the entire thinking process,
|
|
193
|
+
including plans, hypotheses, thoughts, contemplations, critiques,
|
|
194
|
+
and syntheses.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
reflection (str): A comprehensive reflection on the process.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
str: The recorded reflection.
|
|
201
|
+
"""
|
|
202
|
+
try:
|
|
203
|
+
logger.debug(f"Reflection: {reflection}")
|
|
204
|
+
if not self.syntheses:
|
|
205
|
+
return (
|
|
206
|
+
"Consider synthesizing insights before final reflection."
|
|
207
|
+
)
|
|
208
|
+
self.reflections.append(reflection)
|
|
209
|
+
return f"Reflection: {reflection}"
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
error_msg = f"Error recording reflection: {e}"
|
|
213
|
+
logger.error(error_msg)
|
|
214
|
+
return error_msg
|
|
215
|
+
|
|
68
216
|
def get_tools(self) -> List[FunctionTool]:
|
|
69
217
|
r"""Get all tools in the toolkit.
|
|
70
218
|
|
|
71
219
|
Returns:
|
|
72
220
|
List[FunctionTool]: A list of tools.
|
|
73
221
|
"""
|
|
74
|
-
return [
|
|
222
|
+
return [
|
|
223
|
+
FunctionTool(self.plan),
|
|
224
|
+
FunctionTool(self.hypothesize),
|
|
225
|
+
FunctionTool(self.think),
|
|
226
|
+
FunctionTool(self.contemplate),
|
|
227
|
+
FunctionTool(self.critique),
|
|
228
|
+
FunctionTool(self.synthesize),
|
|
229
|
+
FunctionTool(self.reflect),
|
|
230
|
+
]
|
|
@@ -23,7 +23,7 @@ from requests_oauthlib import OAuth1
|
|
|
23
23
|
from camel.logger import get_logger
|
|
24
24
|
from camel.toolkits import FunctionTool
|
|
25
25
|
from camel.toolkits.base import BaseToolkit
|
|
26
|
-
from camel.utils import api_keys_required
|
|
26
|
+
from camel.utils import MCPServer, api_keys_required
|
|
27
27
|
|
|
28
28
|
TWEET_TEXT_LIMIT = 280
|
|
29
29
|
|
|
@@ -418,6 +418,7 @@ def _handle_http_error(response: requests.Response) -> str:
|
|
|
418
418
|
return "Unexpected Exception"
|
|
419
419
|
|
|
420
420
|
|
|
421
|
+
@MCPServer()
|
|
421
422
|
class TwitterToolkit(BaseToolkit):
|
|
422
423
|
r"""A class representing a toolkit for Twitter operations.
|
|
423
424
|
|
|
@@ -24,7 +24,7 @@ from camel.messages import BaseMessage
|
|
|
24
24
|
from camel.models import BaseModelBackend, OpenAIAudioModels
|
|
25
25
|
from camel.toolkits.base import BaseToolkit
|
|
26
26
|
from camel.toolkits.function_tool import FunctionTool
|
|
27
|
-
from camel.utils import dependencies_required
|
|
27
|
+
from camel.utils import MCPServer, dependencies_required
|
|
28
28
|
|
|
29
29
|
from .video_download_toolkit import (
|
|
30
30
|
VideoDownloaderToolkit,
|
|
@@ -77,6 +77,7 @@ similar-looking species or objects
|
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
79
|
|
|
80
|
+
@MCPServer()
|
|
80
81
|
class VideoAnalysisToolkit(BaseToolkit):
|
|
81
82
|
r"""A class for analysing videos with vision-language model.
|
|
82
83
|
|
|
@@ -23,7 +23,7 @@ from PIL import Image
|
|
|
23
23
|
from camel.logger import get_logger
|
|
24
24
|
from camel.toolkits.base import BaseToolkit
|
|
25
25
|
from camel.toolkits.function_tool import FunctionTool
|
|
26
|
-
from camel.utils import dependencies_required
|
|
26
|
+
from camel.utils import MCPServer, dependencies_required
|
|
27
27
|
|
|
28
28
|
logger = get_logger(__name__)
|
|
29
29
|
|
|
@@ -54,6 +54,7 @@ def _capture_screenshot(video_file: str, timestamp: float) -> Image.Image:
|
|
|
54
54
|
return Image.open(io.BytesIO(out))
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
@MCPServer()
|
|
57
58
|
class VideoDownloaderToolkit(BaseToolkit):
|
|
58
59
|
r"""A class for downloading videos and optionally splitting them into
|
|
59
60
|
chunks.
|
|
@@ -16,8 +16,10 @@ from typing import List, Literal
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits.base import BaseToolkit
|
|
18
18
|
from camel.toolkits.function_tool import FunctionTool
|
|
19
|
+
from camel.utils import MCPServer
|
|
19
20
|
|
|
20
21
|
|
|
22
|
+
@MCPServer()
|
|
21
23
|
class WeatherToolkit(BaseToolkit):
|
|
22
24
|
r"""A class representing a toolkit for interacting with weather data.
|
|
23
25
|
|
|
@@ -19,9 +19,10 @@ import requests
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits import FunctionTool
|
|
21
21
|
from camel.toolkits.base import BaseToolkit
|
|
22
|
-
from camel.utils import retry_on_error
|
|
22
|
+
from camel.utils import MCPServer, retry_on_error
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@MCPServer()
|
|
25
26
|
class WhatsAppToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for WhatsApp operations.
|
|
27
28
|
|
camel/toolkits/zapier_toolkit.py
CHANGED
|
@@ -19,9 +19,10 @@ import requests
|
|
|
19
19
|
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
21
|
from camel.toolkits.function_tool import FunctionTool
|
|
22
|
-
from camel.utils import api_keys_required, dependencies_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required, dependencies_required
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@MCPServer()
|
|
25
26
|
class ZapierToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for interacting with Zapier's NLA API.
|
|
27
28
|
|