camel-ai 0.2.44__py3-none-any.whl → 0.2.46__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.

Files changed (60) hide show
  1. camel/__init__.py +1 -1
  2. camel/configs/__init__.py +6 -0
  3. camel/configs/bedrock_config.py +73 -0
  4. camel/configs/lmstudio_config.py +94 -0
  5. camel/configs/qwen_config.py +3 -3
  6. camel/models/__init__.py +4 -0
  7. camel/models/aiml_model.py +11 -104
  8. camel/models/anthropic_model.py +11 -76
  9. camel/models/aws_bedrock_model.py +112 -0
  10. camel/models/cohere_model.py +32 -4
  11. camel/models/deepseek_model.py +11 -44
  12. camel/models/gemini_model.py +10 -72
  13. camel/models/groq_model.py +11 -131
  14. camel/models/internlm_model.py +11 -61
  15. camel/models/litellm_model.py +11 -4
  16. camel/models/lmstudio_model.py +82 -0
  17. camel/models/mistral_model.py +14 -2
  18. camel/models/model_factory.py +7 -1
  19. camel/models/modelscope_model.py +11 -122
  20. camel/models/moonshot_model.py +10 -76
  21. camel/models/nemotron_model.py +4 -60
  22. camel/models/nvidia_model.py +11 -111
  23. camel/models/ollama_model.py +12 -205
  24. camel/models/openai_compatible_model.py +51 -12
  25. camel/models/openrouter_model.py +12 -131
  26. camel/models/ppio_model.py +10 -99
  27. camel/models/qwen_model.py +11 -122
  28. camel/models/reka_model.py +12 -4
  29. camel/models/sglang_model.py +5 -3
  30. camel/models/siliconflow_model.py +10 -58
  31. camel/models/togetherai_model.py +10 -177
  32. camel/models/vllm_model.py +11 -218
  33. camel/models/volcano_model.py +8 -17
  34. camel/models/yi_model.py +11 -98
  35. camel/models/zhipuai_model.py +11 -102
  36. camel/runtime/__init__.py +2 -0
  37. camel/runtime/ubuntu_docker_runtime.py +340 -0
  38. camel/toolkits/__init__.py +2 -0
  39. camel/toolkits/audio_analysis_toolkit.py +21 -17
  40. camel/toolkits/browser_toolkit.py +2 -1
  41. camel/toolkits/dalle_toolkit.py +15 -0
  42. camel/toolkits/excel_toolkit.py +14 -1
  43. camel/toolkits/image_analysis_toolkit.py +9 -1
  44. camel/toolkits/mcp_toolkit.py +2 -0
  45. camel/toolkits/networkx_toolkit.py +5 -0
  46. camel/toolkits/openai_agent_toolkit.py +5 -1
  47. camel/toolkits/pyautogui_toolkit.py +428 -0
  48. camel/toolkits/searxng_toolkit.py +7 -0
  49. camel/toolkits/slack_toolkit.py +15 -2
  50. camel/toolkits/video_analysis_toolkit.py +218 -78
  51. camel/toolkits/video_download_toolkit.py +10 -3
  52. camel/toolkits/weather_toolkit.py +14 -1
  53. camel/toolkits/zapier_toolkit.py +6 -2
  54. camel/types/enums.py +73 -0
  55. camel/types/unified_model_type.py +10 -0
  56. camel/verifiers/base.py +14 -0
  57. {camel_ai-0.2.44.dist-info → camel_ai-0.2.46.dist-info}/METADATA +6 -5
  58. {camel_ai-0.2.44.dist-info → camel_ai-0.2.46.dist-info}/RECORD +60 -54
  59. {camel_ai-0.2.44.dist-info → camel_ai-0.2.46.dist-info}/WHEEL +0 -0
  60. {camel_ai-0.2.44.dist-info → camel_ai-0.2.46.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,340 @@
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 logging
16
+ import sys
17
+ import time
18
+ from pathlib import Path
19
+ from typing import Callable, List, Optional, Union
20
+
21
+ from camel.runtime.docker_runtime import DockerRuntime
22
+ from camel.toolkits import FunctionTool
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class UbuntuDockerRuntime(DockerRuntime):
28
+ r"""A specialized Docker runtime for Ubuntu-based environments.
29
+
30
+ This runtime includes specific configurations and setup for Ubuntu
31
+ containers, including proper Python path handling and environment setup.
32
+ It provides methods for executing Python files, managing the container
33
+ lifecycle, and handling file operations within the Ubuntu container.
34
+
35
+ Attributes:
36
+ python_path (str): Path to the Python interpreter in the container
37
+ docker_config (dict): Configuration dict for Docker container setup
38
+ """
39
+
40
+ def __init__(
41
+ self,
42
+ image: str,
43
+ port: int = 0,
44
+ remove: bool = True,
45
+ python_path: str = "/usr/bin/python3",
46
+ **kwargs,
47
+ ):
48
+ r"""Initialize the Ubuntu Docker Runtime.
49
+
50
+ Args:
51
+ image (str): Docker image name to use
52
+ port (int, optional): Port to expose. Defaults to 0 (random port)
53
+ remove (bool, optional): Whether to remove container after use.
54
+ Defaults to True
55
+ python_path (str, optional): Path to Python interpreter.
56
+ Defaults to "/usr/bin/python3"
57
+ **kwargs: Additional arguments passed to DockerRuntime
58
+ """
59
+ super().__init__(image=image, port=port, remove=remove, **kwargs)
60
+
61
+ self.python_path = python_path
62
+ logger.info(
63
+ f"Initializing UbuntuDockerRuntime with python_path: {python_path}"
64
+ )
65
+
66
+ # Set default environment variables for Ubuntu
67
+ self.docker_config.setdefault("environment", {})
68
+ self.docker_config["environment"].update(
69
+ {
70
+ "PYTHON_PATH": python_path,
71
+ "PYTHON_EXECUTABLE": python_path,
72
+ "PATH": "/usr/local/bin:/usr/bin:/bin",
73
+ "PYTHONUNBUFFERED": "1",
74
+ }
75
+ )
76
+ logger.info(
77
+ f"Environment variables set: {self.docker_config['environment']}"
78
+ )
79
+
80
+ # Add default working directory
81
+ self.docker_config.setdefault("working_dir", "/app")
82
+
83
+ # Setup default volume mounts
84
+ self._setup_default_mounts()
85
+
86
+ def add(
87
+ self,
88
+ funcs: Union[FunctionTool, List[FunctionTool]],
89
+ entrypoint: str,
90
+ redirect_stdout: bool = False,
91
+ arguments: Optional[dict] = None,
92
+ ) -> "UbuntuDockerRuntime":
93
+ r"""Add functions to the runtime with Ubuntu-specific modifications.
94
+
95
+ Args:
96
+ funcs: Function(s) to add to the runtime
97
+ entrypoint: Entry point for function execution
98
+ redirect_stdout: Whether to redirect stdout
99
+ arguments: Optional arguments for function execution
100
+
101
+ Returns:
102
+ Self for method chaining
103
+ """
104
+ if not isinstance(funcs, list):
105
+ funcs = [funcs]
106
+
107
+ # Modify the code execution command to use python3
108
+ for func in funcs:
109
+ logger.info(f"Processing function: {func.get_function_name()}")
110
+ if hasattr(func, 'command'):
111
+ logger.info(f"Original command: {func.command}")
112
+ if isinstance(func.command, list):
113
+ if 'python' in func.command:
114
+ idx = func.command.index('python')
115
+ func.command[idx] = self.python_path
116
+ logger.info(f"Modified command: {func.command}")
117
+ else:
118
+ logger.info(
119
+ f"No command attribute found for function "
120
+ f"{func.get_function_name()}"
121
+ )
122
+
123
+ super().add(funcs, entrypoint, redirect_stdout, arguments)
124
+ return self
125
+
126
+ def _setup_default_mounts(self):
127
+ r"""Setup default volume mounts for the container.
128
+
129
+ This method can be extended to add Ubuntu-specific volume mounts.
130
+ """
131
+ pass
132
+
133
+ def build(self, time_out: int = 15) -> "UbuntuDockerRuntime":
134
+ r"""Build and initialize the Ubuntu container with proper setup.
135
+
136
+ Args:
137
+ time_out (int): Timeout in seconds for build operation
138
+
139
+ Returns:
140
+ Self for method chaining
141
+ """
142
+ logger.info("Starting container build...")
143
+
144
+ super().build(time_out=time_out)
145
+
146
+ if self.container:
147
+ logger.info("Container built successfully, verifying setup...")
148
+
149
+ # Verify Python installation
150
+ exit_code, output = self.container.exec_run(
151
+ [self.python_path, "--version"]
152
+ )
153
+ logger.info(f"Python version check result: {output.decode()}")
154
+ if exit_code != 0:
155
+ logger.error(
156
+ f"Python version check failed with exit code {exit_code}"
157
+ )
158
+ raise RuntimeError(
159
+ f"Python installation verification "
160
+ f"failed: {output.decode()}"
161
+ )
162
+
163
+ # Install required packages
164
+ logger.info("Installing required packages...")
165
+ exit_code, output = self.container.exec_run("apt-get update")
166
+ if exit_code != 0:
167
+ logger.error(
168
+ f"apt-get update failed with "
169
+ f"exit code {exit_code}: {output.decode()}"
170
+ )
171
+ raise RuntimeError(
172
+ f"Failed to update package lists: {output.decode()}"
173
+ )
174
+
175
+ exit_code, output = self.container.exec_run(
176
+ "apt-get install -y curl"
177
+ )
178
+ if exit_code != 0:
179
+ logger.error(
180
+ f"apt-get install curl failed with "
181
+ f"exit code {exit_code}: {output.decode()}"
182
+ )
183
+ raise RuntimeError(
184
+ f"Failed to install curl: {output.decode()}"
185
+ )
186
+
187
+ # Start API server with explicit Python path
188
+ logger.info("Starting API server...")
189
+ exec_result = self.container.exec_run(
190
+ [self.python_path, "/home/api.py"],
191
+ detach=True,
192
+ environment={
193
+ "PYTHONPATH": str(
194
+ Path(self.python_path).parent
195
+ / "lib/python3.10/site-packages"
196
+ ),
197
+ "PYTHON_EXECUTABLE": self.python_path,
198
+ },
199
+ )
200
+ logger.info("API server start result: %s", exec_result)
201
+
202
+ # Wait for API server to start
203
+ start_time = time.time()
204
+ while time.time() - start_time < 10:
205
+ try:
206
+ exit_code, curl_result = self.container.exec_run(
207
+ "curl -s -o /dev/null -w '%{http_code}' http://localhost:8000/docs"
208
+ )
209
+ status_code = curl_result.decode().strip()
210
+ if exit_code == 0 and status_code.startswith('2'):
211
+ logger.info(
212
+ f"API server is running "
213
+ f"(status code: {status_code})"
214
+ )
215
+ break
216
+ else:
217
+ logger.debug(
218
+ f"API server not ready yet (status: {status_code})"
219
+ )
220
+ except Exception as e:
221
+ logger.debug("Waiting for API server... %s", e)
222
+ time.sleep(0.5)
223
+ else:
224
+ logger.warning("API server may not be running properly")
225
+
226
+ return self
227
+
228
+ def exec_python_file(
229
+ self,
230
+ local_file_path: str,
231
+ container_path: Optional[str] = None,
232
+ args: Optional[List[str]] = None,
233
+ env: Optional[dict] = None,
234
+ callback: Optional[Callable[[str], None]] = None,
235
+ ) -> None:
236
+ r"""Execute a Python file inside the Docker container.
237
+
238
+ Args:
239
+ local_file_path: Path to the Python file on the local filesystem
240
+ container_path: Path where the file should be copied in the
241
+ container If None, the file will be copied to /tmp/
242
+ args: List of command-line arguments to pass to the Python script
243
+ env: Additional environment variables to set for the execution
244
+ callback: Optional function to process each line of output
245
+ If None, output is printed to stdout
246
+
247
+ Raises:
248
+ RuntimeError: If container is not running
249
+ FileNotFoundError: If Python file is not found
250
+ """
251
+ if not self.container:
252
+ raise RuntimeError("Container is not running. Call build() first.")
253
+
254
+ local_path = Path(local_file_path)
255
+ if not local_path.exists():
256
+ raise FileNotFoundError(f"Python file {local_file_path} not found")
257
+
258
+ # Determine where to put the file in the container
259
+ if container_path is None:
260
+ container_path = f"/tmp/{local_path.name}"
261
+
262
+ logger.info(
263
+ f"Copying {local_file_path} to container at {container_path}"
264
+ )
265
+
266
+ # Copy the file to the container
267
+ self.container.put_archive(
268
+ path=str(Path(container_path).parent),
269
+ data=self._create_archive_from_file(local_path),
270
+ )
271
+
272
+ # Prepare command
273
+ cmd = [self.python_path, container_path]
274
+ if args:
275
+ cmd.extend(args)
276
+
277
+ # Prepare environment
278
+ execution_env = {
279
+ "PYTHONPATH": "/usr/local/lib/python3.10/site-packages",
280
+ "PYTHON_EXECUTABLE": self.python_path,
281
+ }
282
+ execution_env["PYTHONPATH"] = str(
283
+ Path(self.python_path).parent / "lib/python3.10/site-packages"
284
+ )
285
+ if env:
286
+ execution_env.update(env)
287
+
288
+ logger.info(f"Executing Python file with command: {cmd}")
289
+
290
+ # Always use streaming output
291
+ exec_result = self.container.exec_run(
292
+ cmd,
293
+ environment=execution_env,
294
+ stream=True,
295
+ demux=True, # Separate stdout and stderr
296
+ )
297
+
298
+ # Handle output streams
299
+ try:
300
+ for stdout, stderr in exec_result[1]:
301
+ if stdout:
302
+ output = stdout.decode('utf-8')
303
+ if callback:
304
+ callback(output)
305
+ else:
306
+ print(output, end='')
307
+
308
+ if stderr:
309
+ error = stderr.decode('utf-8')
310
+ if callback:
311
+ callback(f"ERROR: {error}")
312
+ else:
313
+ print(f"ERROR: {error}", end='', file=sys.stderr)
314
+ except KeyboardInterrupt:
315
+ logger.info("Execution interrupted by user")
316
+ # Could add logic to stop container processes here
317
+ except Exception as e:
318
+ logger.error(f"Error during execution: {e}")
319
+ raise
320
+
321
+ def _create_archive_from_file(self, file_path: Union[str, Path]) -> bytes:
322
+ r"""Create a tar archive from a single file for docker.put_archive().
323
+
324
+ Args:
325
+ file_path: Path to the file to archive
326
+
327
+ Returns:
328
+ bytes: The tar archive as bytes
329
+ """
330
+ import io
331
+ import tarfile
332
+
333
+ file_path = Path(file_path)
334
+ tar_stream = io.BytesIO()
335
+
336
+ with tarfile.open(fileobj=tar_stream, mode='w') as tar:
337
+ tar.add(file_path, arcname=file_path.name)
338
+
339
+ tar_stream.seek(0)
340
+ return tar_stream.read()
@@ -64,6 +64,7 @@ from .terminal_toolkit import TerminalToolkit
64
64
  from .pubmed_toolkit import PubMedToolkit
65
65
  from .data_commons_toolkit import DataCommonsToolkit
66
66
  from .thinking_toolkit import ThinkingToolkit
67
+ from .pyautogui_toolkit import PyAutoGUIToolkit
67
68
  from .openai_agent_toolkit import OpenAIAgentToolkit
68
69
  from .searxng_toolkit import SearxNGToolkit
69
70
 
@@ -118,6 +119,7 @@ __all__ = [
118
119
  'PubMedToolkit',
119
120
  'DataCommonsToolkit',
120
121
  'ThinkingToolkit',
122
+ 'PyAutoGUIToolkit',
121
123
  'OpenAIAgentToolkit',
122
124
  'SearxNGToolkit',
123
125
  ]
@@ -83,29 +83,33 @@ def download_file(url: str, cache_dir: str) -> str:
83
83
 
84
84
  @MCPServer()
85
85
  class AudioAnalysisToolkit(BaseToolkit):
86
- r"""A toolkit for audio processing and analysis.
87
-
88
- This class provides methods for processing, transcribing, and extracting
89
- information from audio data, including direct question answering about
90
- audio content.
91
-
92
- Args:
93
- cache_dir (Optional[str]): Directory path for caching downloaded audio
94
- files. If not provided, 'tmp/' will be used. (default: :obj:`None`)
95
- transcribe_model (Optional[BaseAudioModel]): Model used for audio
96
- transcription. If not provided, OpenAIAudioModels will be used.
97
- (default: :obj:`None`)
98
- audio_reasoning_model (Optional[BaseModelBackend]): Model used for
99
- audio reasoning and question answering. If not provided, uses the
100
- default model from ChatAgent. (default: :obj:`None`)
101
- """
102
-
103
86
  def __init__(
104
87
  self,
105
88
  cache_dir: Optional[str] = None,
106
89
  transcribe_model: Optional[BaseAudioModel] = None,
107
90
  audio_reasoning_model: Optional[BaseModelBackend] = None,
91
+ timeout: Optional[float] = None,
108
92
  ):
93
+ r"""A toolkit for audio processing and analysis. This class provides
94
+ methods for processing, transcribing, and extracting information from
95
+ audio data, including direct question answering about audio content.
96
+
97
+ Args:
98
+ cache_dir (Optional[str]): Directory path for caching downloaded
99
+ audio files. If not provided, 'tmp/' will be used.
100
+ (default: :obj:`None`)
101
+ transcribe_model (Optional[BaseAudioModel]): Model used for audio
102
+ transcription. If not provided, OpenAIAudioModels will be used.
103
+ (default: :obj:`None`)
104
+ audio_reasoning_model (Optional[BaseModelBackend]): Model used for
105
+ audio reasoning and question answering.
106
+ If not provided, uses the default model from ChatAgent.
107
+ (default: :obj:`None`)
108
+ timeout (Optional[float]): The timeout value for API requests
109
+ in seconds. If None, no timeout is applied.
110
+ (default: :obj:`None`)
111
+ """
112
+ super().__init__(timeout=timeout)
109
113
  self.cache_dir = 'tmp/'
110
114
  if cache_dir:
111
115
  self.cache_dir = cache_dir
@@ -43,8 +43,9 @@ if TYPE_CHECKING:
43
43
  from camel.logger import get_logger
44
44
  from camel.messages import BaseMessage
45
45
  from camel.models import BaseModelBackend, ModelFactory
46
- from camel.toolkits import FunctionTool, VideoAnalysisToolkit
47
46
  from camel.toolkits.base import BaseToolkit
47
+ from camel.toolkits.function_tool import FunctionTool
48
+ from camel.toolkits.video_analysis_toolkit import VideoAnalysisToolkit
48
49
  from camel.types import ModelPlatformType, ModelType
49
50
  from camel.utils import dependencies_required, retry_on_error
50
51
 
@@ -22,13 +22,28 @@ from PIL import Image
22
22
 
23
23
  from camel.toolkits import FunctionTool
24
24
  from camel.toolkits.base import BaseToolkit
25
+ from camel.utils import MCPServer
25
26
 
26
27
 
28
+ @MCPServer()
27
29
  class DalleToolkit(BaseToolkit):
28
30
  r"""A class representing a toolkit for image generation using OpenAI's
29
31
  DALL-E model.
30
32
  """
31
33
 
34
+ def __init__(
35
+ self,
36
+ timeout: Optional[float] = None,
37
+ ):
38
+ r"""Initializes a new instance of the DalleToolkit class.
39
+
40
+ Args:
41
+ timeout (Optional[float]): The timeout value for API requests
42
+ in seconds. If None, no timeout is applied.
43
+ (default: :obj:`None`)
44
+ """
45
+ super().__init__(timeout=timeout)
46
+
32
47
  def base64_to_image(self, base64_string: str) -> Optional[Image.Image]:
33
48
  r"""Converts a base64 encoded string into a PIL Image object.
34
49
 
@@ -12,7 +12,7 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
- from typing import List
15
+ from typing import List, Optional
16
16
 
17
17
  import pandas as pd
18
18
 
@@ -33,6 +33,19 @@ class ExcelToolkit(BaseToolkit):
33
33
  process excel files.
34
34
  """
35
35
 
36
+ def __init__(
37
+ self,
38
+ timeout: Optional[float] = None,
39
+ ):
40
+ r"""Initializes a new instance of the ExcelToolkit class.
41
+
42
+ Args:
43
+ timeout (Optional[float]): The timeout value for API requests
44
+ in seconds. If None, no timeout is applied.
45
+ (default: :obj:`None`)
46
+ """
47
+ super().__init__(timeout=timeout)
48
+
36
49
  def _convert_to_markdown(self, df: pd.DataFrame) -> str:
37
50
  r"""Convert DataFrame to Markdown format table.
38
51
 
@@ -36,7 +36,11 @@ class ImageAnalysisToolkit(BaseToolkit):
36
36
  The toolkit uses vision-capable language models to perform these tasks.
37
37
  """
38
38
 
39
- def __init__(self, model: Optional[BaseModelBackend] = None):
39
+ def __init__(
40
+ self,
41
+ model: Optional[BaseModelBackend] = None,
42
+ timeout: Optional[float] = None,
43
+ ):
40
44
  r"""Initialize the ImageAnalysisToolkit.
41
45
 
42
46
  Args:
@@ -45,7 +49,11 @@ class ImageAnalysisToolkit(BaseToolkit):
45
49
  images for tasks like image description and visual question
46
50
  answering. If None, a default model will be created using
47
51
  ModelFactory. (default: :obj:`None`)
52
+ timeout (Optional[float]): The timeout value for API requests
53
+ in seconds. If None, no timeout is applied.
54
+ (default: :obj:`None`)
48
55
  """
56
+ super().__init__(timeout=timeout)
49
57
  if model:
50
58
  self.model = model
51
59
  else:
@@ -314,6 +314,7 @@ class MCPClient(BaseToolkit):
314
314
  "type": "object",
315
315
  "properties": properties,
316
316
  "required": required,
317
+ "additionalProperties": False,
317
318
  }
318
319
 
319
320
  return {
@@ -322,6 +323,7 @@ class MCPClient(BaseToolkit):
322
323
  "name": mcp_tool.name,
323
324
  "description": mcp_tool.description
324
325
  or "No description provided.",
326
+ "strict": True,
325
327
  "parameters": parameters,
326
328
  },
327
329
  }
@@ -38,6 +38,7 @@ class NetworkXToolkit(BaseToolkit):
38
38
 
39
39
  def __init__(
40
40
  self,
41
+ timeout: Optional[float] = None,
41
42
  graph_type: Literal[
42
43
  'graph', 'digraph', 'multigraph', 'multidigraph'
43
44
  ] = 'graph',
@@ -53,7 +54,11 @@ class NetworkXToolkit(BaseToolkit):
53
54
  - 'multigraph': Undirected graph with parallel edges
54
55
  - 'multidigraph': Directed graph with parallel edges
55
56
  (default: :obj:`'graph'`)
57
+ timeout (Optional[float]): The timeout value for API requests
58
+ in seconds. If None, no timeout is applied.
59
+ (default: :obj:`None`)
56
60
  """
61
+ super().__init__(timeout=timeout)
57
62
  nx = self._get_nx()
58
63
  graph_types = {
59
64
  'graph': nx.Graph,
@@ -45,6 +45,7 @@ class OpenAIAgentToolkit(BaseToolkit):
45
45
  self,
46
46
  model: Optional[BaseModelBackend] = None,
47
47
  api_key: Optional[str] = None,
48
+ timeout: Optional[float] = None,
48
49
  ) -> None:
49
50
  r"""Initialize the OpenAI agent toolkit.
50
51
 
@@ -53,8 +54,11 @@ class OpenAIAgentToolkit(BaseToolkit):
53
54
  If None, defaults to gpt-4o-mini. (default: :obj:`None`)
54
55
  api_key (str): OpenAI API key. If not provided, will attempt to
55
56
  use OPENAI_API_KEY environment variable. (default: :obj:`None`)
57
+ timeout (Optional[float]): The timeout value for API requests
58
+ in seconds. If None, no timeout is applied.
59
+ (default: :obj:`None`)
56
60
  """
57
- super().__init__()
61
+ super().__init__(timeout=timeout)
58
62
  self.api_key = api_key or os.getenv("OPENAI_API_KEY")
59
63
  self.client = OpenAI(api_key=self.api_key)
60
64
  self.model = model or ModelFactory.create(