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
camel/toolkits/mcp_toolkit.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import inspect
|
|
15
15
|
import json
|
|
16
16
|
import os
|
|
17
|
+
import shlex
|
|
17
18
|
from contextlib import AsyncExitStack, asynccontextmanager
|
|
18
19
|
from typing import (
|
|
19
20
|
TYPE_CHECKING,
|
|
@@ -25,11 +26,12 @@ from typing import (
|
|
|
25
26
|
Optional,
|
|
26
27
|
Set,
|
|
27
28
|
Union,
|
|
29
|
+
cast,
|
|
28
30
|
)
|
|
29
31
|
from urllib.parse import urlparse
|
|
30
32
|
|
|
31
33
|
if TYPE_CHECKING:
|
|
32
|
-
from mcp import ListToolsResult, Tool
|
|
34
|
+
from mcp import ClientSession, ListToolsResult, Tool
|
|
33
35
|
|
|
34
36
|
from camel.logger import get_logger
|
|
35
37
|
from camel.toolkits import BaseToolkit, FunctionTool
|
|
@@ -37,7 +39,7 @@ from camel.toolkits import BaseToolkit, FunctionTool
|
|
|
37
39
|
logger = get_logger(__name__)
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
class
|
|
42
|
+
class MCPClient(BaseToolkit):
|
|
41
43
|
r"""Internal class that provides an abstraction layer to interact with
|
|
42
44
|
external tools using the Model Context Protocol (MCP). It supports two
|
|
43
45
|
modes of connection:
|
|
@@ -69,7 +71,6 @@ class _MCPServer(BaseToolkit):
|
|
|
69
71
|
headers: Optional[Dict[str, str]] = None,
|
|
70
72
|
):
|
|
71
73
|
from mcp import Tool
|
|
72
|
-
from mcp.client.session import ClientSession
|
|
73
74
|
|
|
74
75
|
super().__init__(timeout=timeout)
|
|
75
76
|
|
|
@@ -87,7 +88,7 @@ class _MCPServer(BaseToolkit):
|
|
|
87
88
|
r"""Explicitly connect to the MCP server.
|
|
88
89
|
|
|
89
90
|
Returns:
|
|
90
|
-
|
|
91
|
+
MCPClient: The client used to connect to the server.
|
|
91
92
|
"""
|
|
92
93
|
from mcp.client.session import ClientSession
|
|
93
94
|
from mcp.client.sse import sse_client
|
|
@@ -110,11 +111,20 @@ class _MCPServer(BaseToolkit):
|
|
|
110
111
|
)
|
|
111
112
|
else:
|
|
112
113
|
command = self.command_or_url
|
|
114
|
+
arguments = self.args
|
|
115
|
+
if not self.args:
|
|
116
|
+
argv = shlex.split(command)
|
|
117
|
+
if not argv:
|
|
118
|
+
raise ValueError("Command is empty")
|
|
119
|
+
|
|
120
|
+
command = argv[0]
|
|
121
|
+
arguments = argv[1:]
|
|
122
|
+
|
|
113
123
|
if os.name == "nt" and command.lower() == "npx":
|
|
114
124
|
command = "npx.cmd"
|
|
115
125
|
|
|
116
126
|
server_parameters = StdioServerParameters(
|
|
117
|
-
command=command, args=
|
|
127
|
+
command=command, args=arguments, env=self.env
|
|
118
128
|
)
|
|
119
129
|
(
|
|
120
130
|
read_stream,
|
|
@@ -135,6 +145,7 @@ class _MCPServer(BaseToolkit):
|
|
|
135
145
|
# Ensure resources are cleaned up on connection failure
|
|
136
146
|
await self.disconnect()
|
|
137
147
|
logger.error(f"Failed to connect to MCP server: {e}")
|
|
148
|
+
raise e
|
|
138
149
|
|
|
139
150
|
async def disconnect(self):
|
|
140
151
|
r"""Explicitly disconnect from the MCP server."""
|
|
@@ -149,7 +160,7 @@ class _MCPServer(BaseToolkit):
|
|
|
149
160
|
on the provided `command_or_url`.
|
|
150
161
|
|
|
151
162
|
Yields:
|
|
152
|
-
|
|
163
|
+
MCPClient: Instance with active connection ready for tool
|
|
153
164
|
interaction.
|
|
154
165
|
"""
|
|
155
166
|
try:
|
|
@@ -170,7 +181,8 @@ class _MCPServer(BaseToolkit):
|
|
|
170
181
|
try:
|
|
171
182
|
return await self._session.list_tools()
|
|
172
183
|
except Exception as e:
|
|
173
|
-
|
|
184
|
+
logger.exception("Failed to list MCP tools")
|
|
185
|
+
raise e
|
|
174
186
|
|
|
175
187
|
def generate_function_from_mcp_tool(self, mcp_tool: "Tool") -> Callable:
|
|
176
188
|
r"""Dynamically generates a Python callable function corresponding to
|
|
@@ -235,7 +247,7 @@ class _MCPServer(BaseToolkit):
|
|
|
235
247
|
logger.error(
|
|
236
248
|
"MCP Client is not connected. Call `connection()` first."
|
|
237
249
|
)
|
|
238
|
-
|
|
250
|
+
raise RuntimeError(
|
|
239
251
|
"MCP Client is not connected. Call `connection()` first."
|
|
240
252
|
)
|
|
241
253
|
|
|
@@ -245,7 +257,7 @@ class _MCPServer(BaseToolkit):
|
|
|
245
257
|
)
|
|
246
258
|
except Exception as e:
|
|
247
259
|
logger.error(f"Failed to call MCP tool '{func_name}': {e!s}")
|
|
248
|
-
|
|
260
|
+
raise e
|
|
249
261
|
|
|
250
262
|
if not result.content or len(result.content) == 0:
|
|
251
263
|
return "No data available for this request."
|
|
@@ -272,7 +284,7 @@ class _MCPServer(BaseToolkit):
|
|
|
272
284
|
logger.error(
|
|
273
285
|
f"Error processing content from MCP tool response: {e!s}"
|
|
274
286
|
)
|
|
275
|
-
|
|
287
|
+
raise e
|
|
276
288
|
|
|
277
289
|
dynamic_function.__name__ = func_name
|
|
278
290
|
dynamic_function.__doc__ = func_desc
|
|
@@ -331,6 +343,10 @@ class _MCPServer(BaseToolkit):
|
|
|
331
343
|
for mcp_tool in self._mcp_tools
|
|
332
344
|
]
|
|
333
345
|
|
|
346
|
+
@property
|
|
347
|
+
def session(self) -> Optional["ClientSession"]:
|
|
348
|
+
return self._session
|
|
349
|
+
|
|
334
350
|
|
|
335
351
|
class MCPToolkit(BaseToolkit):
|
|
336
352
|
r"""MCPToolkit provides a unified interface for managing multiple
|
|
@@ -341,7 +357,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
341
357
|
MCP services.
|
|
342
358
|
|
|
343
359
|
Args:
|
|
344
|
-
servers (Optional[List[
|
|
360
|
+
servers (Optional[List[MCPClient]]): List of MCPClient
|
|
345
361
|
instances to manage.
|
|
346
362
|
config_path (Optional[str]): Path to a JSON configuration file
|
|
347
363
|
defining MCP servers.
|
|
@@ -359,7 +375,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
359
375
|
.. code-block:: json
|
|
360
376
|
|
|
361
377
|
{
|
|
362
|
-
"
|
|
378
|
+
"mcpServers": {
|
|
363
379
|
"protected-server": {
|
|
364
380
|
"url": "https://example.com/mcp",
|
|
365
381
|
"timeout": 30,
|
|
@@ -372,12 +388,12 @@ class MCPToolkit(BaseToolkit):
|
|
|
372
388
|
}
|
|
373
389
|
|
|
374
390
|
Attributes:
|
|
375
|
-
servers (List[
|
|
391
|
+
servers (List[MCPClient]): List of MCPClient instances being managed.
|
|
376
392
|
"""
|
|
377
393
|
|
|
378
394
|
def __init__(
|
|
379
395
|
self,
|
|
380
|
-
servers: Optional[List[
|
|
396
|
+
servers: Optional[List[MCPClient]] = None,
|
|
381
397
|
config_path: Optional[str] = None,
|
|
382
398
|
):
|
|
383
399
|
super().__init__()
|
|
@@ -388,7 +404,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
388
404
|
"Servers from both sources will be combined."
|
|
389
405
|
)
|
|
390
406
|
|
|
391
|
-
self.servers = servers or []
|
|
407
|
+
self.servers: List[MCPClient] = servers or []
|
|
392
408
|
|
|
393
409
|
if config_path:
|
|
394
410
|
self.servers.extend(self._load_servers_from_config(config_path))
|
|
@@ -396,14 +412,14 @@ class MCPToolkit(BaseToolkit):
|
|
|
396
412
|
self._exit_stack = AsyncExitStack()
|
|
397
413
|
self._connected = False
|
|
398
414
|
|
|
399
|
-
def _load_servers_from_config(self, config_path: str) -> List[
|
|
415
|
+
def _load_servers_from_config(self, config_path: str) -> List[MCPClient]:
|
|
400
416
|
r"""Loads MCP server configurations from a JSON file.
|
|
401
417
|
|
|
402
418
|
Args:
|
|
403
419
|
config_path (str): Path to the JSON configuration file.
|
|
404
420
|
|
|
405
421
|
Returns:
|
|
406
|
-
List[
|
|
422
|
+
List[MCPClient]: List of configured MCPClient instances.
|
|
407
423
|
"""
|
|
408
424
|
try:
|
|
409
425
|
with open(config_path, "r", encoding="utf-8") as f:
|
|
@@ -413,14 +429,13 @@ class MCPToolkit(BaseToolkit):
|
|
|
413
429
|
logger.warning(
|
|
414
430
|
f"Invalid JSON in config file '{config_path}': {e!s}"
|
|
415
431
|
)
|
|
416
|
-
|
|
417
|
-
except FileNotFoundError:
|
|
432
|
+
raise e
|
|
433
|
+
except FileNotFoundError as e:
|
|
418
434
|
logger.warning(f"Config file not found: '{config_path}'")
|
|
419
|
-
|
|
435
|
+
raise e
|
|
420
436
|
|
|
421
437
|
all_servers = []
|
|
422
438
|
|
|
423
|
-
# Process local MCP servers
|
|
424
439
|
mcp_servers = data.get("mcpServers", {})
|
|
425
440
|
if not isinstance(mcp_servers, dict):
|
|
426
441
|
logger.warning("'mcpServers' is not a dictionary, skipping...")
|
|
@@ -433,47 +448,21 @@ class MCPToolkit(BaseToolkit):
|
|
|
433
448
|
)
|
|
434
449
|
continue
|
|
435
450
|
|
|
436
|
-
if "command" not in cfg:
|
|
451
|
+
if "command" not in cfg and "url" not in cfg:
|
|
437
452
|
logger.warning(
|
|
438
|
-
f"Missing required 'command' field for server
|
|
453
|
+
f"Missing required 'command' or 'url' field for server "
|
|
454
|
+
f"'{name}'"
|
|
439
455
|
)
|
|
440
456
|
continue
|
|
441
457
|
|
|
442
|
-
server =
|
|
443
|
-
command_or_url=cfg
|
|
458
|
+
server = MCPClient(
|
|
459
|
+
command_or_url=cast(str, cfg.get("command") or cfg.get("url")),
|
|
444
460
|
args=cfg.get("args", []),
|
|
445
461
|
env={**os.environ, **cfg.get("env", {})},
|
|
446
462
|
timeout=cfg.get("timeout", None),
|
|
447
463
|
)
|
|
448
464
|
all_servers.append(server)
|
|
449
465
|
|
|
450
|
-
# Process remote MCP web servers
|
|
451
|
-
mcp_web_servers = data.get("mcpWebServers", {})
|
|
452
|
-
if not isinstance(mcp_web_servers, dict):
|
|
453
|
-
logger.warning("'mcpWebServers' is not a dictionary, skipping...")
|
|
454
|
-
mcp_web_servers = {}
|
|
455
|
-
|
|
456
|
-
for name, cfg in mcp_web_servers.items():
|
|
457
|
-
if not isinstance(cfg, dict):
|
|
458
|
-
logger.warning(
|
|
459
|
-
f"Configuration for web server '{name}' must"
|
|
460
|
-
"be a dictionary"
|
|
461
|
-
)
|
|
462
|
-
continue
|
|
463
|
-
|
|
464
|
-
if "url" not in cfg:
|
|
465
|
-
logger.warning(
|
|
466
|
-
f"Missing required 'url' field for web server '{name}'"
|
|
467
|
-
)
|
|
468
|
-
continue
|
|
469
|
-
|
|
470
|
-
server = _MCPServer(
|
|
471
|
-
command_or_url=cfg["url"],
|
|
472
|
-
timeout=cfg.get("timeout", None),
|
|
473
|
-
headers=cfg.get("headers", {}),
|
|
474
|
-
)
|
|
475
|
-
all_servers.append(server)
|
|
476
|
-
|
|
477
466
|
return all_servers
|
|
478
467
|
|
|
479
468
|
async def connect(self):
|
|
@@ -497,6 +486,7 @@ class MCPToolkit(BaseToolkit):
|
|
|
497
486
|
# Ensure resources are cleaned up on connection failure
|
|
498
487
|
await self.disconnect()
|
|
499
488
|
logger.error(f"Failed to connect to one or more MCP servers: {e}")
|
|
489
|
+
raise e
|
|
500
490
|
|
|
501
491
|
async def disconnect(self):
|
|
502
492
|
r"""Explicitly disconnect from all MCP servers."""
|
camel/toolkits/meshy_toolkit.py
CHANGED
|
@@ -13,14 +13,16 @@
|
|
|
13
13
|
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
|
|
15
15
|
import os
|
|
16
|
-
from typing import Any, Dict, Optional
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
17
|
|
|
18
18
|
import requests
|
|
19
19
|
|
|
20
|
+
from camel.toolkits import FunctionTool
|
|
20
21
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
-
from camel.utils import api_keys_required
|
|
22
|
+
from camel.utils import MCPServer, api_keys_required
|
|
22
23
|
|
|
23
24
|
|
|
25
|
+
@MCPServer()
|
|
24
26
|
class MeshyToolkit(BaseToolkit):
|
|
25
27
|
r"""A class representing a toolkit for 3D model generation using Meshy.
|
|
26
28
|
|
|
@@ -188,3 +190,19 @@ class MeshyToolkit(BaseToolkit):
|
|
|
188
190
|
|
|
189
191
|
# Wait for refinement completion and return final result
|
|
190
192
|
return self.wait_for_task_completion(refine_task_id)
|
|
193
|
+
|
|
194
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
195
|
+
r"""Returns a list of FunctionTool objects representing the
|
|
196
|
+
functions in the toolkit.
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
List[FunctionTool]: A list of FunctionTool objects
|
|
200
|
+
representing the functions in the toolkit.
|
|
201
|
+
"""
|
|
202
|
+
return [
|
|
203
|
+
FunctionTool(self.generate_3d_preview),
|
|
204
|
+
FunctionTool(self.refine_3d_model),
|
|
205
|
+
FunctionTool(self.get_task_status),
|
|
206
|
+
FunctionTool(self.wait_for_task_completion),
|
|
207
|
+
FunctionTool(self.generate_3d_model_complete),
|
|
208
|
+
]
|
|
@@ -18,10 +18,12 @@ from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union
|
|
|
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 NetworkXToolkit(BaseToolkit):
|
|
26
28
|
_nx = None # Class variable to store the networkx module
|
|
27
29
|
|
camel/toolkits/notion_toolkit.py
CHANGED
|
@@ -16,6 +16,7 @@ from typing import List, Optional, cast
|
|
|
16
16
|
|
|
17
17
|
from camel.toolkits import FunctionTool
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
|
+
from camel.utils import MCPServer, api_keys_required
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def get_plain_text_from_rich_text(rich_text: List[dict]) -> str:
|
|
@@ -66,6 +67,7 @@ def get_media_source_text(block: dict) -> str:
|
|
|
66
67
|
return source
|
|
67
68
|
|
|
68
69
|
|
|
70
|
+
@MCPServer()
|
|
69
71
|
class NotionToolkit(BaseToolkit):
|
|
70
72
|
r"""A toolkit for retrieving information from the user's notion pages.
|
|
71
73
|
|
|
@@ -76,6 +78,11 @@ class NotionToolkit(BaseToolkit):
|
|
|
76
78
|
the notion APIs.
|
|
77
79
|
"""
|
|
78
80
|
|
|
81
|
+
@api_keys_required(
|
|
82
|
+
[
|
|
83
|
+
("notion_token", 'NOTION_TOKEN'),
|
|
84
|
+
]
|
|
85
|
+
)
|
|
79
86
|
def __init__(
|
|
80
87
|
self,
|
|
81
88
|
notion_token: Optional[str] = None,
|
|
@@ -0,0 +1,131 @@
|
|
|
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
|
+
import os
|
|
16
|
+
from typing import List, Optional
|
|
17
|
+
|
|
18
|
+
from openai import OpenAI
|
|
19
|
+
|
|
20
|
+
from camel.logger import get_logger
|
|
21
|
+
from camel.models import BaseModelBackend, ModelFactory
|
|
22
|
+
from camel.toolkits.base import BaseToolkit
|
|
23
|
+
from camel.toolkits.function_tool import FunctionTool
|
|
24
|
+
from camel.types import ModelPlatformType, ModelType
|
|
25
|
+
from camel.utils import api_keys_required
|
|
26
|
+
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class OpenAIAgentToolkit(BaseToolkit):
|
|
31
|
+
r"""Toolkit for accessing OpenAI's agent tools including web search and
|
|
32
|
+
file search.
|
|
33
|
+
|
|
34
|
+
Provides access to OpenAI's web search and file search capabilities
|
|
35
|
+
through the Responses API, allowing agents to retrieve information from
|
|
36
|
+
the web and search through uploaded files.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
@api_keys_required(
|
|
40
|
+
[
|
|
41
|
+
(None, "OPENAI_API_KEY"),
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
model: Optional[BaseModelBackend] = None,
|
|
47
|
+
api_key: Optional[str] = None,
|
|
48
|
+
) -> None:
|
|
49
|
+
r"""Initialize the OpenAI agent toolkit.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
model (BaseModelBackend): The OpenAI model to use for responses.
|
|
53
|
+
If None, defaults to gpt-4o-mini. (default: :obj:`None`)
|
|
54
|
+
api_key (str): OpenAI API key. If not provided, will attempt to
|
|
55
|
+
use OPENAI_API_KEY environment variable. (default: :obj:`None`)
|
|
56
|
+
"""
|
|
57
|
+
super().__init__()
|
|
58
|
+
self.api_key = api_key or os.getenv("OPENAI_API_KEY")
|
|
59
|
+
self.client = OpenAI(api_key=self.api_key)
|
|
60
|
+
self.model = model or ModelFactory.create(
|
|
61
|
+
model_platform=ModelPlatformType.OPENAI,
|
|
62
|
+
model_type=ModelType.GPT_4O_MINI,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def web_search(self, query: str) -> str:
|
|
66
|
+
r"""Perform a web search using OpenAI's web search tool.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
query (str): The search query.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
str: The search result or error message.
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
response = self.client.responses.create(
|
|
76
|
+
model=str(self.model.model_type),
|
|
77
|
+
tools=[{"type": "web_search_preview"}],
|
|
78
|
+
input=query,
|
|
79
|
+
)
|
|
80
|
+
return response.output_text
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
logger.error(f"Web search failed: {e!s}")
|
|
84
|
+
return f"Web search failed: {e!s}"
|
|
85
|
+
|
|
86
|
+
def file_search(
|
|
87
|
+
self,
|
|
88
|
+
query: str,
|
|
89
|
+
vector_store_id: str,
|
|
90
|
+
) -> str:
|
|
91
|
+
r"""Search through files using OpenAI's file search tool.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
query (str): The search query.
|
|
95
|
+
vector_store_id (str): The vector store ID to search in.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
str: The search result or error message.
|
|
99
|
+
"""
|
|
100
|
+
if not vector_store_id.strip():
|
|
101
|
+
logger.error("Empty vector store ID provided.")
|
|
102
|
+
return "Empty vector store ID provided, it cannot be empty."
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
response = self.client.responses.create(
|
|
106
|
+
model=str(self.model.model_type),
|
|
107
|
+
tools=[
|
|
108
|
+
{
|
|
109
|
+
"type": "file_search",
|
|
110
|
+
"vector_store_ids": [vector_store_id],
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
input=query,
|
|
114
|
+
)
|
|
115
|
+
return response.output_text
|
|
116
|
+
|
|
117
|
+
except Exception as e:
|
|
118
|
+
logger.error(f"File search failed: {e!s}")
|
|
119
|
+
return f"File search failed: {e!s}"
|
|
120
|
+
|
|
121
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
122
|
+
r"""Retrieve available toolkit functions as FunctionTool objects.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
List[FunctionTool]: Collection of FunctionTool objects representing
|
|
126
|
+
the available search functions in this toolkit.
|
|
127
|
+
"""
|
|
128
|
+
return [
|
|
129
|
+
FunctionTool(self.web_search),
|
|
130
|
+
FunctionTool(self.file_search),
|
|
131
|
+
]
|
camel/toolkits/openbb_toolkit.py
CHANGED
|
@@ -17,9 +17,10 @@ from typing import List, Literal, Optional
|
|
|
17
17
|
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
19
|
from camel.toolkits.function_tool import FunctionTool
|
|
20
|
-
from camel.utils import api_keys_required, dependencies_required
|
|
20
|
+
from camel.utils import MCPServer, api_keys_required, dependencies_required
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
@MCPServer()
|
|
23
24
|
class OpenBBToolkit(BaseToolkit):
|
|
24
25
|
r"""A toolkit for accessing financial data and analysis through OpenBB
|
|
25
26
|
Platform.
|
camel/toolkits/pubmed_toolkit.py
CHANGED
|
@@ -18,10 +18,12 @@ import requests
|
|
|
18
18
|
|
|
19
19
|
from camel.logger import get_logger
|
|
20
20
|
from camel.toolkits import BaseToolkit, FunctionTool
|
|
21
|
+
from camel.utils import MCPServer
|
|
21
22
|
|
|
22
23
|
logger = get_logger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
26
|
+
@MCPServer()
|
|
25
27
|
class PubMedToolkit(BaseToolkit):
|
|
26
28
|
r"""A toolkit for interacting with PubMed's E-utilities API to access
|
|
27
29
|
MEDLINE data.
|
camel/toolkits/reddit_toolkit.py
CHANGED
|
@@ -18,9 +18,10 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
18
18
|
|
|
19
19
|
from camel.toolkits import FunctionTool
|
|
20
20
|
from camel.toolkits.base import BaseToolkit
|
|
21
|
-
from camel.utils import retry_on_error
|
|
21
|
+
from camel.utils import MCPServer, retry_on_error
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
@MCPServer()
|
|
24
25
|
class RedditToolkit(BaseToolkit):
|
|
25
26
|
r"""A class representing a toolkit for Reddit operations.
|
|
26
27
|
|
|
@@ -17,9 +17,10 @@ from camel.retrievers import AutoRetriever
|
|
|
17
17
|
from camel.toolkits import FunctionTool
|
|
18
18
|
from camel.toolkits.base import BaseToolkit
|
|
19
19
|
from camel.types import StorageType
|
|
20
|
-
from camel.utils import Constants
|
|
20
|
+
from camel.utils import Constants, MCPServer
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
@MCPServer()
|
|
23
24
|
class RetrievalToolkit(BaseToolkit):
|
|
24
25
|
r"""A class representing a toolkit for information retrieval.
|
|
25
26
|
|
camel/toolkits/search_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 SearchToolkit(BaseToolkit):
|
|
26
27
|
r"""A class representing a toolkit for web search.
|
|
27
28
|
|