camel-ai 0.2.21__py3-none-any.whl → 0.2.23__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 (116) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/_types.py +41 -0
  3. camel/agents/_utils.py +188 -0
  4. camel/agents/chat_agent.py +570 -965
  5. camel/agents/knowledge_graph_agent.py +7 -1
  6. camel/agents/multi_hop_generator_agent.py +1 -1
  7. camel/configs/base_config.py +10 -13
  8. camel/configs/deepseek_config.py +4 -30
  9. camel/configs/gemini_config.py +5 -31
  10. camel/configs/openai_config.py +14 -32
  11. camel/configs/qwen_config.py +36 -36
  12. camel/datagen/self_improving_cot.py +81 -3
  13. camel/datagen/self_instruct/filter/instruction_filter.py +19 -3
  14. camel/datagen/self_instruct/self_instruct.py +53 -4
  15. camel/datasets/__init__.py +28 -0
  16. camel/datasets/base.py +969 -0
  17. camel/embeddings/openai_embedding.py +10 -1
  18. camel/environments/__init__.py +16 -0
  19. camel/environments/base.py +503 -0
  20. camel/extractors/__init__.py +16 -0
  21. camel/extractors/base.py +263 -0
  22. camel/interpreters/docker/Dockerfile +12 -0
  23. camel/interpreters/docker_interpreter.py +19 -1
  24. camel/interpreters/subprocess_interpreter.py +42 -17
  25. camel/loaders/__init__.py +2 -0
  26. camel/loaders/mineru_extractor.py +250 -0
  27. camel/memories/agent_memories.py +16 -1
  28. camel/memories/blocks/chat_history_block.py +10 -2
  29. camel/memories/blocks/vectordb_block.py +1 -0
  30. camel/memories/context_creators/score_based.py +20 -3
  31. camel/memories/records.py +10 -0
  32. camel/messages/base.py +8 -8
  33. camel/models/__init__.py +2 -0
  34. camel/models/_utils.py +57 -0
  35. camel/models/aiml_model.py +48 -17
  36. camel/models/anthropic_model.py +41 -3
  37. camel/models/azure_openai_model.py +39 -3
  38. camel/models/base_audio_model.py +92 -0
  39. camel/models/base_model.py +132 -4
  40. camel/models/cohere_model.py +88 -11
  41. camel/models/deepseek_model.py +107 -63
  42. camel/models/fish_audio_model.py +18 -8
  43. camel/models/gemini_model.py +133 -15
  44. camel/models/groq_model.py +72 -10
  45. camel/models/internlm_model.py +14 -3
  46. camel/models/litellm_model.py +9 -2
  47. camel/models/mistral_model.py +42 -5
  48. camel/models/model_manager.py +57 -3
  49. camel/models/moonshot_model.py +33 -4
  50. camel/models/nemotron_model.py +32 -3
  51. camel/models/nvidia_model.py +43 -3
  52. camel/models/ollama_model.py +139 -17
  53. camel/models/openai_audio_models.py +87 -2
  54. camel/models/openai_compatible_model.py +37 -3
  55. camel/models/openai_model.py +158 -46
  56. camel/models/qwen_model.py +61 -4
  57. camel/models/reka_model.py +53 -3
  58. camel/models/samba_model.py +209 -4
  59. camel/models/sglang_model.py +153 -14
  60. camel/models/siliconflow_model.py +16 -3
  61. camel/models/stub_model.py +46 -4
  62. camel/models/togetherai_model.py +38 -3
  63. camel/models/vllm_model.py +37 -3
  64. camel/models/yi_model.py +36 -3
  65. camel/models/zhipuai_model.py +38 -3
  66. camel/retrievers/__init__.py +3 -0
  67. camel/retrievers/hybrid_retrival.py +237 -0
  68. camel/toolkits/__init__.py +20 -3
  69. camel/toolkits/arxiv_toolkit.py +2 -1
  70. camel/toolkits/ask_news_toolkit.py +4 -2
  71. camel/toolkits/audio_analysis_toolkit.py +238 -0
  72. camel/toolkits/base.py +22 -3
  73. camel/toolkits/code_execution.py +2 -0
  74. camel/toolkits/dappier_toolkit.py +2 -1
  75. camel/toolkits/data_commons_toolkit.py +38 -12
  76. camel/toolkits/excel_toolkit.py +172 -0
  77. camel/toolkits/function_tool.py +13 -0
  78. camel/toolkits/github_toolkit.py +5 -1
  79. camel/toolkits/google_maps_toolkit.py +2 -1
  80. camel/toolkits/google_scholar_toolkit.py +2 -0
  81. camel/toolkits/human_toolkit.py +0 -3
  82. camel/toolkits/image_analysis_toolkit.py +202 -0
  83. camel/toolkits/linkedin_toolkit.py +3 -2
  84. camel/toolkits/meshy_toolkit.py +3 -2
  85. camel/toolkits/mineru_toolkit.py +178 -0
  86. camel/toolkits/networkx_toolkit.py +240 -0
  87. camel/toolkits/notion_toolkit.py +2 -0
  88. camel/toolkits/openbb_toolkit.py +3 -2
  89. camel/toolkits/page_script.js +376 -0
  90. camel/toolkits/reddit_toolkit.py +11 -3
  91. camel/toolkits/retrieval_toolkit.py +6 -1
  92. camel/toolkits/semantic_scholar_toolkit.py +2 -1
  93. camel/toolkits/stripe_toolkit.py +8 -2
  94. camel/toolkits/sympy_toolkit.py +44 -1
  95. camel/toolkits/video_analysis_toolkit.py +407 -0
  96. camel/toolkits/{video_toolkit.py → video_download_toolkit.py} +21 -25
  97. camel/toolkits/web_toolkit.py +1307 -0
  98. camel/toolkits/whatsapp_toolkit.py +3 -2
  99. camel/toolkits/zapier_toolkit.py +191 -0
  100. camel/types/__init__.py +2 -2
  101. camel/types/agents/__init__.py +16 -0
  102. camel/types/agents/tool_calling_record.py +52 -0
  103. camel/types/enums.py +3 -0
  104. camel/types/openai_types.py +16 -14
  105. camel/utils/__init__.py +2 -1
  106. camel/utils/async_func.py +2 -2
  107. camel/utils/commons.py +114 -1
  108. camel/verifiers/__init__.py +23 -0
  109. camel/verifiers/base.py +340 -0
  110. camel/verifiers/models.py +82 -0
  111. camel/verifiers/python_verifier.py +202 -0
  112. camel_ai-0.2.23.dist-info/METADATA +671 -0
  113. {camel_ai-0.2.21.dist-info → camel_ai-0.2.23.dist-info}/RECORD +127 -99
  114. {camel_ai-0.2.21.dist-info → camel_ai-0.2.23.dist-info}/WHEEL +1 -1
  115. camel_ai-0.2.21.dist-info/METADATA +0 -528
  116. {camel_ai-0.2.21.dist-info → camel_ai-0.2.23.dist-info/licenses}/LICENSE +0 -0
@@ -13,7 +13,7 @@
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
15
  import os
16
- from typing import Any, Dict, List, Union
16
+ from typing import Any, Dict, List, Optional, Union
17
17
 
18
18
  import requests
19
19
 
@@ -36,8 +36,9 @@ class WhatsAppToolkit(BaseToolkit):
36
36
  version (str): API version.
37
37
  """
38
38
 
39
- def __init__(self):
39
+ def __init__(self, timeout: Optional[float] = None):
40
40
  r"""Initializes the WhatsAppToolkit."""
41
+ super().__init__(timeout=timeout)
41
42
  self.base_url = "https://graph.facebook.com"
42
43
  self.version = "v17.0"
43
44
 
@@ -0,0 +1,191 @@
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 Any, Dict, List
17
+
18
+ import requests
19
+
20
+ from camel.toolkits.base import BaseToolkit
21
+ from camel.toolkits.function_tool import FunctionTool
22
+ from camel.utils import api_keys_required, dependencies_required
23
+
24
+
25
+ class ZapierToolkit(BaseToolkit):
26
+ r"""A class representing a toolkit for interacting with Zapier's NLA API.
27
+
28
+ This class provides methods for executing Zapier actions through natural
29
+ language commands, allowing integration with various web services and
30
+ automation of workflows through the Zapier platform.
31
+
32
+ Attributes:
33
+ api_key (str): The API key for authenticating with Zapier's API.
34
+ base_url (str): The base URL for Zapier's API endpoints.
35
+ """
36
+
37
+ @dependencies_required("requests")
38
+ @api_keys_required(
39
+ [
40
+ (None, "ZAPIER_NLA_API_KEY"),
41
+ ]
42
+ )
43
+ def __init__(self) -> None:
44
+ r"""Initialize the ZapierToolkit with API client. The API key is
45
+ retrieved from environment variables.
46
+ """
47
+ self.api_key = os.environ.get("ZAPIER_NLA_API_KEY")
48
+ self.base_url = "https://actions.zapier.com/api/v1/"
49
+
50
+ def list_actions(self) -> Dict[str, Any]:
51
+ r"""List all available Zapier actions.
52
+
53
+ Returns:
54
+ Dict[str, Any]: A dictionary containing the list of available
55
+ actions.
56
+ """
57
+ headers = {
58
+ 'accept': 'application/json',
59
+ 'x-api-key': self.api_key,
60
+ }
61
+ response = requests.get(
62
+ f"{self.base_url}exposed/",
63
+ params={'api_key': self.api_key},
64
+ headers=headers,
65
+ )
66
+ response.raise_for_status()
67
+ return response.json()
68
+
69
+ def execute_action(
70
+ self,
71
+ action_id: str,
72
+ instructions: str,
73
+ ) -> Dict[str, Any]:
74
+ r"""Execute a specific Zapier action using natural language
75
+ instructions.
76
+
77
+ Args:
78
+ action_id (str): The ID of the Zapier action to execute.
79
+ instructions (str): Natural language instructions for executing
80
+ the action. For example: "Send an email to john@example.com
81
+ with subject 'Hello' and body 'How are you?'"
82
+
83
+ Returns:
84
+ Dict[str, Any]: The result of the action execution, including
85
+ status and any output data.
86
+ """
87
+ try:
88
+ headers = {
89
+ 'accept': 'application/json',
90
+ 'x-api-key': self.api_key,
91
+ 'Content-Type': 'application/json',
92
+ }
93
+ data = {
94
+ "instructions": instructions,
95
+ "preview_only": False,
96
+ }
97
+ response = requests.post(
98
+ f"{self.base_url}exposed/{action_id}/execute/",
99
+ params={'api_key': self.api_key},
100
+ headers=headers,
101
+ json=data,
102
+ )
103
+ response.raise_for_status()
104
+ return response.json()
105
+ except requests.exceptions.RequestException as e:
106
+ return {"error": f"Request failed: {e!s}"}
107
+ except ValueError:
108
+ return {"error": "Response is not valid JSON"}
109
+
110
+ def preview_action(
111
+ self,
112
+ action_id: str,
113
+ instructions: str,
114
+ ) -> Dict[str, Any]:
115
+ r"""Preview a specific Zapier action using natural language
116
+ instructions.
117
+
118
+ Args:
119
+ action_id (str): The ID of the Zapier action to preview.
120
+ instructions (str): Natural language instructions for previewing
121
+ the action. For example: "Send an email to john@example.com
122
+ with subject 'Hello' and body 'How are you?'"
123
+
124
+ Returns:
125
+ Dict[str, Any]: The preview result showing what parameters would
126
+ be used if the action were executed.
127
+ """
128
+ try:
129
+ headers = {
130
+ 'accept': 'application/json',
131
+ 'x-api-key': self.api_key,
132
+ 'Content-Type': 'application/json',
133
+ }
134
+ data = {
135
+ "instructions": instructions,
136
+ "preview_only": True,
137
+ }
138
+ response = requests.post(
139
+ f"{self.base_url}exposed/{action_id}/execute/",
140
+ params={'api_key': self.api_key},
141
+ headers=headers,
142
+ json=data,
143
+ )
144
+ response.raise_for_status()
145
+ return response.json()
146
+ except requests.exceptions.RequestException as e:
147
+ return {"error": f"Request failed: {e!s}"}
148
+ except ValueError:
149
+ return {"error": "Response is not valid JSON"}
150
+
151
+ def get_execution_result(self, execution_id: str) -> Dict[str, Any]:
152
+ r"""Get the execution result of a Zapier action.
153
+
154
+ Args:
155
+ execution_id (str): The execution ID returned from execute_action.
156
+
157
+ Returns:
158
+ Dict[str, Any]: The execution result containing status, logs,
159
+ and any output data from the action execution.
160
+ """
161
+ try:
162
+ headers = {
163
+ 'accept': 'application/json',
164
+ 'x-api-key': self.api_key,
165
+ }
166
+ response = requests.get(
167
+ f"{self.base_url}execution-log/{execution_id}/",
168
+ params={'api_key': self.api_key},
169
+ headers=headers,
170
+ )
171
+ response.raise_for_status()
172
+ return response.json()
173
+ except requests.exceptions.RequestException as e:
174
+ return {"error": f"Request failed: {e!s}"}
175
+ except ValueError:
176
+ return {"error": "Response is not valid JSON"}
177
+
178
+ def get_tools(self) -> List[FunctionTool]:
179
+ r"""Returns a list of FunctionTool objects representing the functions
180
+ in the toolkit.
181
+
182
+ Returns:
183
+ List[FunctionTool]: A list of FunctionTool objects representing
184
+ the functions in the toolkit.
185
+ """
186
+ return [
187
+ FunctionTool(self.list_actions),
188
+ FunctionTool(self.execute_action),
189
+ FunctionTool(self.preview_action),
190
+ FunctionTool(self.get_execution_result),
191
+ ]
camel/types/__init__.py CHANGED
@@ -73,8 +73,8 @@ __all__ = [
73
73
  'AudioModelType',
74
74
  'VoiceType',
75
75
  'UnifiedModelType',
76
- 'NOT_GIVEN',
77
- 'NotGiven',
78
76
  'ParsedChatCompletion',
79
77
  'HuggingFaceRepoType',
78
+ 'NOT_GIVEN',
79
+ 'NotGiven',
80
80
  ]
@@ -0,0 +1,16 @@
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
+ from .tool_calling_record import ToolCallingRecord
15
+
16
+ __all__ = ["ToolCallingRecord"]
@@ -0,0 +1,52 @@
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
+ from typing import Any, Dict
15
+
16
+ from pydantic import BaseModel
17
+
18
+
19
+ class ToolCallingRecord(BaseModel):
20
+ r"""Historical records of tools called in the conversation.
21
+
22
+ Attributes:
23
+ func_name (str): The name of the tool being called.
24
+ args (Dict[str, Any]): The dictionary of arguments passed to the tool.
25
+ result (Any): The execution result of calling this tool.
26
+ tool_call_id (str): The ID of the tool call, if available.
27
+ """
28
+
29
+ tool_name: str
30
+ args: Dict[str, Any]
31
+ result: Any
32
+ tool_call_id: str
33
+
34
+ def __str__(self) -> str:
35
+ r"""Overridden version of the string function.
36
+
37
+ Returns:
38
+ str: Modified string to represent the tool calling.
39
+ """
40
+ return (
41
+ f"Tool Execution: {self.tool_name}\n"
42
+ f"\tArgs: {self.args}\n"
43
+ f"\tResult: {self.result}\n"
44
+ )
45
+
46
+ def as_dict(self) -> dict[str, Any]:
47
+ r"""Returns the tool calling record as a dictionary.
48
+
49
+ Returns:
50
+ dict[str, Any]: The tool calling record as a dictionary.
51
+ """
52
+ return self.model_dump()
camel/types/enums.py CHANGED
@@ -34,6 +34,7 @@ class ModelType(UnifiedModelType, Enum):
34
34
  GPT_4_TURBO = "gpt-4-turbo"
35
35
  GPT_4O = "gpt-4o"
36
36
  GPT_4O_MINI = "gpt-4o-mini"
37
+ GPT_4_5_PREVIEW = "gpt-4.5-preview"
37
38
  O1 = "o1"
38
39
  O1_PREVIEW = "o1-preview"
39
40
  O1_MINI = "o1-mini"
@@ -263,6 +264,7 @@ class ModelType(UnifiedModelType, Enum):
263
264
  ModelType.O1_PREVIEW,
264
265
  ModelType.O1_MINI,
265
266
  ModelType.O3_MINI,
267
+ ModelType.GPT_4_5_PREVIEW,
266
268
  }
267
269
 
268
270
  @property
@@ -623,6 +625,7 @@ class ModelType(UnifiedModelType, Enum):
623
625
  ModelType.GPT_4_TURBO,
624
626
  ModelType.O1_PREVIEW,
625
627
  ModelType.O1_MINI,
628
+ ModelType.GPT_4_5_PREVIEW,
626
629
  ModelType.MISTRAL_LARGE,
627
630
  ModelType.MISTRAL_NEMO,
628
631
  ModelType.MISTRAL_PIXTRAL_12B,
@@ -35,17 +35,19 @@ from openai.types.chat import ParsedChatCompletion
35
35
  from openai._types import NOT_GIVEN, NotGiven
36
36
  from openai.types.chat import ChatCompletionMessageToolCall
37
37
 
38
- Choice = Choice
39
- ChatCompletion = ChatCompletion
40
- ChatCompletionChunk = ChatCompletionChunk
41
- ChatCompletionMessage = ChatCompletionMessage
42
- ChatCompletionMessageParam = ChatCompletionMessageParam
43
- ChatCompletionSystemMessageParam = ChatCompletionSystemMessageParam
44
- ChatCompletionUserMessageParam = ChatCompletionUserMessageParam
45
- ChatCompletionAssistantMessageParam = ChatCompletionAssistantMessageParam
46
- ChatCompletionToolMessageParam = ChatCompletionToolMessageParam
47
- ChatCompletionMessageToolCall = ChatCompletionMessageToolCall
48
- CompletionUsage = CompletionUsage
49
- NOT_GIVEN = NOT_GIVEN
50
- NotGiven = NotGiven
51
- ParsedChatCompletion = ParsedChatCompletion
38
+ __all__ = [
39
+ "Choice",
40
+ "ChatCompletion",
41
+ "ChatCompletionChunk",
42
+ "ChatCompletionMessage",
43
+ "ChatCompletionMessageParam",
44
+ "ChatCompletionSystemMessageParam",
45
+ "ChatCompletionUserMessageParam",
46
+ "ChatCompletionAssistantMessageParam",
47
+ "ChatCompletionToolMessageParam",
48
+ "ChatCompletionMessageToolCall",
49
+ "CompletionUsage",
50
+ "ParsedChatCompletion",
51
+ "NOT_GIVEN",
52
+ "NotGiven",
53
+ ]
camel/utils/__init__.py CHANGED
@@ -23,7 +23,6 @@ from .commons import (
23
23
  download_github_subdirectory,
24
24
  download_tasks,
25
25
  func_string_to_callable,
26
- generate_prompt_for_structured_output,
27
26
  get_first_int,
28
27
  get_prompt_template_key_words,
29
28
  get_pydantic_major_version,
@@ -38,6 +37,7 @@ from .commons import (
38
37
  text_extract_from_web,
39
38
  to_pascal,
40
39
  track_agent,
40
+ with_timeout,
41
41
  )
42
42
  from .constants import Constants
43
43
  from .deduplication import DeduplicationResult, deduplicate_internally
@@ -87,4 +87,5 @@ __all__ = [
87
87
  "DeduplicationResult",
88
88
  "retry_on_error",
89
89
  "BatchProcessor",
90
+ "with_timeout",
90
91
  ]
camel/utils/async_func.py CHANGED
@@ -33,8 +33,8 @@ def sync_funcs_to_async(funcs: list[FunctionTool]) -> list[FunctionTool]:
33
33
  for func in funcs:
34
34
  sync_func = func.func
35
35
 
36
- def async_callable(*args, **kwargs):
37
- return asyncio.to_thread(sync_func, *args, **kwargs) # noqa: B023
36
+ async def async_callable(*args, **kwargs):
37
+ return await asyncio.to_thread(sync_func, *args, **kwargs) # noqa: B023
38
38
 
39
39
  async_funcs.append(
40
40
  FunctionTool(async_callable, deepcopy(func.openai_tool_schema))
camel/utils/commons.py CHANGED
@@ -19,6 +19,7 @@ import platform
19
19
  import re
20
20
  import socket
21
21
  import subprocess
22
+ import threading
22
23
  import time
23
24
  import zipfile
24
25
  from functools import wraps
@@ -306,10 +307,55 @@ def api_keys_required(
306
307
  if not value or value.strip() == "":
307
308
  missing_keys.append(env_var_name)
308
309
 
310
+ key_way = "the official website"
311
+ if env_var_name == 'ANTHROPIC_API_KEY':
312
+ key_way = (
313
+ "https://docs.anthropic.com/zh-CN/api/getting-started"
314
+ )
315
+ elif env_var_name == 'AIML_API_KEY':
316
+ key_way = "https://aimlapi.com/"
317
+ elif env_var_name == 'COHERE_API_KEY':
318
+ key_way = "https://cohere.com/"
319
+ elif env_var_name == 'DEEPSEEK_API_KEY':
320
+ key_way = "https://www.deepseek.com/"
321
+ elif env_var_name == 'AZURE_OPENAI_API_KEY':
322
+ key_way = "https://portal.azure.com/"
323
+ elif env_var_name == 'OPENAI_API_KEY':
324
+ key_way = "https://platform.openai.com/docs/overview"
325
+ elif env_var_name == 'FISHAUDIO_API_KEY':
326
+ key_way = "https://fish.audio/"
327
+ elif env_var_name == 'GEMINI_API_KEY':
328
+ key_way = "https://gemini.google.com/"
329
+ elif env_var_name == 'INTERNLM_API_KEY':
330
+ key_way = "https://internlm-chat.intern-ai.org.cn/puyu/api/v1"
331
+ elif env_var_name == 'GROQ_API_KEY':
332
+ key_way = "https://api.groq.com/openai/v1"
333
+ elif env_var_name == 'MISTRAL_API_KEY':
334
+ key_way = "https://mistral.ai/"
335
+ elif env_var_name == 'MOONSHOT_API_KEY':
336
+ key_way = "https://api.moonshot.cn/v1"
337
+ elif env_var_name == 'NVIDIA_API_KEY':
338
+ key_way = "https://integrate.api.nvidia.com/"
339
+ elif env_var_name == 'OPENAI_COMPATIBILIY_API_KEY':
340
+ key_way = "https://platform.openai.com/docs/overview"
341
+ elif env_var_name == 'QWEN_API_KEY':
342
+ key_way = "https://tongyi.aliyun.com/"
343
+ elif env_var_name == 'REKA_API_KEY':
344
+ key_way = "https://docs.reka.ai/quick-start"
345
+ elif env_var_name == 'SAMBA_API_KEY':
346
+ key_way = "https://community.sambanova.ai/t/looking-for-api-key-and-url-for-sambanova/576"
347
+ elif env_var_name == 'TOGETHER_API_KEY':
348
+ key_way = "https://docs.together.ai/docs/quickstart"
349
+ elif env_var_name == 'YI_API_KEY':
350
+ key_way = "https://platform.lingyiwanwu.com/docs"
351
+ elif env_var_name == 'ZHIPUAI_API_KEY':
352
+ key_way = "https://www.zhipuai.cn/"
353
+
309
354
  if missing_keys:
310
355
  raise ValueError(
311
356
  "Missing or empty required API keys in "
312
- f"environment variables: {', '.join(missing_keys)}"
357
+ f"environment variables: {', '.join(missing_keys)}.\n"
358
+ f"You can obtain the API key from {key_way}"
313
359
  )
314
360
  return func(*args, **kwargs)
315
361
 
@@ -905,3 +951,70 @@ def generate_prompt_for_structured_output(
905
951
  {user_prompt}
906
952
  """
907
953
  return final_prompt
954
+
955
+
956
+ def with_timeout(timeout=None):
957
+ r"""Decorator that adds timeout functionality to functions.
958
+
959
+ Executes functions with a specified timeout value. Returns a timeout
960
+ message if execution time is exceeded.
961
+
962
+ Args:
963
+ timeout (float, optional): The timeout duration in seconds. If None,
964
+ will try to get timeout from the instance's timeout attribute.
965
+ (default: :obj:`None`)
966
+
967
+ Example:
968
+ >>> @with_timeout(5)
969
+ ... def my_function():
970
+ ... return "Success"
971
+ >>> my_function()
972
+
973
+ >>> class MyClass:
974
+ ... timeout = 5
975
+ ... @with_timeout()
976
+ ... def my_method(self):
977
+ ... return "Success"
978
+ """
979
+
980
+ def decorator(func):
981
+ @functools.wraps(func)
982
+ def wrapper(*args, **kwargs):
983
+ # Determine the effective timeout value
984
+ effective_timeout = timeout
985
+ if effective_timeout is None and args:
986
+ effective_timeout = getattr(args[0], 'timeout', None)
987
+
988
+ # If no timeout value is provided, execute function normally
989
+ if effective_timeout is None:
990
+ return func(*args, **kwargs)
991
+
992
+ # Container to hold the result of the function call
993
+ result_container = []
994
+
995
+ def target():
996
+ result_container.append(func(*args, **kwargs))
997
+
998
+ # Start the function in a new thread
999
+ thread = threading.Thread(target=target)
1000
+ thread.start()
1001
+ thread.join(effective_timeout)
1002
+
1003
+ # Check if the thread is still alive after the timeout
1004
+ if thread.is_alive():
1005
+ return (
1006
+ f"Function `{func.__name__}` execution timed out, "
1007
+ f"exceeded {effective_timeout} seconds."
1008
+ )
1009
+ else:
1010
+ return result_container[0]
1011
+
1012
+ return wrapper
1013
+
1014
+ # Handle both @with_timeout and @with_timeout() usage
1015
+ if callable(timeout):
1016
+ # If timeout is passed as a function, apply it to the decorator
1017
+ func, timeout = timeout, None
1018
+ return decorator(func)
1019
+
1020
+ return decorator
@@ -0,0 +1,23 @@
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
+ from .base import BaseVerifier
15
+ from .models import VerificationOutcome, VerifierInput
16
+ from .python_verifier import PythonVerifier
17
+
18
+ __all__ = [
19
+ "BaseVerifier",
20
+ "VerificationOutcome",
21
+ "VerifierInput",
22
+ "PythonVerifier",
23
+ ]