camel-ai 0.2.3__py3-none-any.whl → 0.2.3a0__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 (87) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +69 -93
  3. camel/agents/knowledge_graph_agent.py +6 -4
  4. camel/bots/__init__.py +2 -16
  5. camel/bots/discord_bot.py +206 -0
  6. camel/configs/__init__.py +2 -1
  7. camel/configs/anthropic_config.py +5 -2
  8. camel/configs/base_config.py +6 -6
  9. camel/configs/groq_config.py +3 -2
  10. camel/configs/ollama_config.py +2 -1
  11. camel/configs/openai_config.py +23 -2
  12. camel/configs/samba_config.py +2 -2
  13. camel/configs/togetherai_config.py +1 -1
  14. camel/configs/vllm_config.py +1 -1
  15. camel/configs/zhipuai_config.py +3 -2
  16. camel/embeddings/openai_embedding.py +2 -2
  17. camel/loaders/__init__.py +0 -2
  18. camel/loaders/firecrawl_reader.py +3 -3
  19. camel/loaders/unstructured_io.py +33 -35
  20. camel/messages/__init__.py +0 -1
  21. camel/models/__init__.py +4 -2
  22. camel/models/anthropic_model.py +26 -32
  23. camel/models/azure_openai_model.py +36 -39
  24. camel/models/base_model.py +20 -31
  25. camel/models/gemini_model.py +29 -37
  26. camel/models/groq_model.py +23 -29
  27. camel/models/litellm_model.py +61 -44
  28. camel/models/mistral_model.py +29 -32
  29. camel/models/model_factory.py +76 -66
  30. camel/models/nemotron_model.py +23 -33
  31. camel/models/ollama_model.py +47 -42
  32. camel/models/open_source_model.py +170 -0
  33. camel/models/{openai_compatible_model.py → openai_compatibility_model.py} +49 -31
  34. camel/models/openai_model.py +29 -48
  35. camel/models/reka_model.py +28 -30
  36. camel/models/samba_model.py +177 -82
  37. camel/models/stub_model.py +2 -2
  38. camel/models/togetherai_model.py +43 -37
  39. camel/models/vllm_model.py +50 -43
  40. camel/models/zhipuai_model.py +27 -33
  41. camel/retrievers/auto_retriever.py +10 -28
  42. camel/retrievers/vector_retriever.py +47 -58
  43. camel/societies/babyagi_playing.py +3 -6
  44. camel/societies/role_playing.py +3 -5
  45. camel/storages/graph_storages/graph_element.py +5 -3
  46. camel/storages/key_value_storages/json.py +1 -6
  47. camel/toolkits/__init__.py +7 -20
  48. camel/toolkits/base.py +3 -2
  49. camel/toolkits/code_execution.py +7 -6
  50. camel/toolkits/dalle_toolkit.py +6 -6
  51. camel/toolkits/github_toolkit.py +10 -9
  52. camel/toolkits/google_maps_toolkit.py +7 -7
  53. camel/toolkits/linkedin_toolkit.py +7 -7
  54. camel/toolkits/math_toolkit.py +8 -8
  55. camel/toolkits/open_api_toolkit.py +5 -5
  56. camel/toolkits/{function_tool.py → openai_function.py} +11 -34
  57. camel/toolkits/reddit_toolkit.py +7 -7
  58. camel/toolkits/retrieval_toolkit.py +5 -5
  59. camel/toolkits/search_toolkit.py +9 -9
  60. camel/toolkits/slack_toolkit.py +11 -11
  61. camel/toolkits/twitter_toolkit.py +452 -378
  62. camel/toolkits/weather_toolkit.py +6 -6
  63. camel/types/__init__.py +1 -6
  64. camel/types/enums.py +85 -40
  65. camel/types/openai_types.py +0 -3
  66. camel/utils/__init__.py +2 -0
  67. camel/utils/async_func.py +7 -7
  68. camel/utils/commons.py +3 -32
  69. camel/utils/token_counting.py +212 -30
  70. camel/workforce/role_playing_worker.py +1 -1
  71. camel/workforce/single_agent_worker.py +1 -1
  72. camel/workforce/task_channel.py +3 -4
  73. camel/workforce/workforce.py +4 -4
  74. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a0.dist-info}/METADATA +56 -27
  75. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a0.dist-info}/RECORD +76 -85
  76. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a0.dist-info}/WHEEL +1 -1
  77. camel/bots/discord_app.py +0 -138
  78. camel/bots/slack/__init__.py +0 -30
  79. camel/bots/slack/models.py +0 -158
  80. camel/bots/slack/slack_app.py +0 -255
  81. camel/loaders/chunkr_reader.py +0 -163
  82. camel/toolkits/arxiv_toolkit.py +0 -155
  83. camel/toolkits/ask_news_toolkit.py +0 -653
  84. camel/toolkits/google_scholar_toolkit.py +0 -146
  85. camel/toolkits/whatsapp_toolkit.py +0 -177
  86. camel/types/unified_model_type.py +0 -104
  87. camel_ai-0.2.3.dist-info/LICENSE +0 -201
@@ -15,7 +15,7 @@ import os
15
15
  from typing import List, Literal
16
16
 
17
17
  from camel.toolkits.base import BaseToolkit
18
- from camel.toolkits.function_tool import FunctionTool
18
+ from camel.toolkits.openai_function import OpenAIFunction
19
19
 
20
20
 
21
21
  class WeatherToolkit(BaseToolkit):
@@ -157,17 +157,17 @@ class WeatherToolkit(BaseToolkit):
157
157
  )
158
158
  return error_message
159
159
 
160
- def get_tools(self) -> List[FunctionTool]:
161
- r"""Returns a list of FunctionTool objects representing the
160
+ def get_tools(self) -> List[OpenAIFunction]:
161
+ r"""Returns a list of OpenAIFunction objects representing the
162
162
  functions in the toolkit.
163
163
 
164
164
  Returns:
165
- List[FunctionTool]: A list of FunctionTool objects
165
+ List[OpenAIFunction]: A list of OpenAIFunction objects
166
166
  representing the functions in the toolkit.
167
167
  """
168
168
  return [
169
- FunctionTool(self.get_weather_data),
169
+ OpenAIFunction(self.get_weather_data),
170
170
  ]
171
171
 
172
172
 
173
- WEATHER_FUNCS: List[FunctionTool] = WeatherToolkit().get_tools()
173
+ WEATHER_FUNCS: List[OpenAIFunction] = WeatherToolkit().get_tools()
camel/types/__init__.py CHANGED
@@ -28,7 +28,6 @@ from .enums import (
28
28
  VoiceType,
29
29
  )
30
30
  from .openai_types import (
31
- NOT_GIVEN,
32
31
  ChatCompletion,
33
32
  ChatCompletionAssistantMessageParam,
34
33
  ChatCompletionChunk,
@@ -39,9 +38,7 @@ from .openai_types import (
39
38
  ChatCompletionUserMessageParam,
40
39
  Choice,
41
40
  CompletionUsage,
42
- NotGiven,
43
41
  )
44
- from .unified_model_type import UnifiedModelType
45
42
 
46
43
  __all__ = [
47
44
  'RoleType',
@@ -62,13 +59,11 @@ __all__ = [
62
59
  'ChatCompletionAssistantMessageParam',
63
60
  'ChatCompletionFunctionMessageParam',
64
61
  'CompletionUsage',
62
+ 'OpenAIVideoType',
65
63
  'OpenAIImageType',
66
64
  'OpenAIVisionDetailType',
67
65
  'OpenAPIName',
68
66
  'ModelPlatformType',
69
67
  'AudioModelType',
70
68
  'VoiceType',
71
- 'UnifiedModelType',
72
- 'NOT_GIVEN',
73
- 'NotGiven',
74
69
  ]
camel/types/enums.py CHANGED
@@ -11,10 +11,8 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
+ import re
14
15
  from enum import Enum, EnumMeta
15
- from typing import cast
16
-
17
- from camel.types.unified_model_type import UnifiedModelType
18
16
 
19
17
 
20
18
  class RoleType(Enum):
@@ -25,9 +23,7 @@ class RoleType(Enum):
25
23
  DEFAULT = "default"
26
24
 
27
25
 
28
- class ModelType(UnifiedModelType, Enum):
29
- DEFAULT = "gpt-4o-mini"
30
-
26
+ class ModelType(Enum):
31
27
  GPT_3_5_TURBO = "gpt-3.5-turbo"
32
28
  GPT_4 = "gpt-4"
33
29
  GPT_4_TURBO = "gpt-4-turbo"
@@ -37,6 +33,7 @@ class ModelType(UnifiedModelType, Enum):
37
33
  O1_MINI = "o1-mini"
38
34
 
39
35
  GLM_4 = "glm-4"
36
+ GLM_4_OPEN_SOURCE = "glm-4-open-source"
40
37
  GLM_4V = 'glm-4v'
41
38
  GLM_3_TURBO = "glm-3-turbo"
42
39
 
@@ -51,6 +48,13 @@ class ModelType(UnifiedModelType, Enum):
51
48
 
52
49
  STUB = "stub"
53
50
 
51
+ LLAMA_2 = "llama-2"
52
+ LLAMA_3 = "llama-3"
53
+ VICUNA = "vicuna"
54
+ VICUNA_16K = "vicuna-16k"
55
+
56
+ QWEN_2 = "qwen-2"
57
+
54
58
  # Legacy anthropic models
55
59
  # NOTE: anthropic legacy models only Claude 2.1 has system prompt support
56
60
  CLAUDE_2_1 = "claude-2.1"
@@ -71,15 +75,13 @@ class ModelType(UnifiedModelType, Enum):
71
75
  GEMINI_1_5_PRO = "gemini-1.5-pro"
72
76
 
73
77
  # Mistral AI models
74
- MISTRAL_3B = "ministral-3b-latest"
75
- MISTRAL_7B = "open-mistral-7b"
76
- MISTRAL_8B = "ministral-8b-latest"
77
- MISTRAL_CODESTRAL = "codestral-latest"
78
- MISTRAL_CODESTRAL_MAMBA = "open-codestral-mamba"
79
78
  MISTRAL_LARGE = "mistral-large-latest"
79
+ MISTRAL_NEMO = "open-mistral-nemo"
80
+ MISTRAL_CODESTRAL = "codestral-latest"
81
+ MISTRAL_7B = "open-mistral-7b"
80
82
  MISTRAL_MIXTRAL_8x7B = "open-mixtral-8x7b"
81
83
  MISTRAL_MIXTRAL_8x22B = "open-mixtral-8x22b"
82
- MISTRAL_NEMO = "open-mistral-nemo"
84
+ MISTRAL_CODESTRAL_MAMBA = "open-codestral-mamba"
83
85
  MISTRAL_PIXTRAL_12B = "pixtral-12b-2409"
84
86
 
85
87
  # Reka models
@@ -87,12 +89,6 @@ class ModelType(UnifiedModelType, Enum):
87
89
  REKA_FLASH = "reka-flash"
88
90
  REKA_EDGE = "reka-edge"
89
91
 
90
- def __str__(self):
91
- return self.value
92
-
93
- def __new__(cls, value) -> "ModelType":
94
- return cast("ModelType", UnifiedModelType.__new__(cls, value))
95
-
96
92
  @property
97
93
  def value_for_tiktoken(self) -> str:
98
94
  if self.is_openai:
@@ -100,7 +96,7 @@ class ModelType(UnifiedModelType, Enum):
100
96
  return "gpt-4o-mini"
101
97
 
102
98
  @property
103
- def support_native_tool_calling(self) -> bool:
99
+ def supports_tool_calling(self) -> bool:
104
100
  return any([self.is_openai, self.is_gemini, self.is_mistral])
105
101
 
106
102
  @property
@@ -137,6 +133,18 @@ class ModelType(UnifiedModelType, Enum):
137
133
  ModelType.GLM_4V,
138
134
  }
139
135
 
136
+ @property
137
+ def is_open_source(self) -> bool:
138
+ r"""Returns whether this type of models is open-source."""
139
+ return self in {
140
+ ModelType.LLAMA_2,
141
+ ModelType.LLAMA_3,
142
+ ModelType.QWEN_2,
143
+ ModelType.GLM_4_OPEN_SOURCE,
144
+ ModelType.VICUNA,
145
+ ModelType.VICUNA_16K,
146
+ }
147
+
140
148
  @property
141
149
  def is_anthropic(self) -> bool:
142
150
  r"""Returns whether this type of models is Anthropic-released model.
@@ -180,8 +188,6 @@ class ModelType(UnifiedModelType, Enum):
180
188
  ModelType.MISTRAL_MIXTRAL_8x22B,
181
189
  ModelType.MISTRAL_CODESTRAL_MAMBA,
182
190
  ModelType.MISTRAL_PIXTRAL_12B,
183
- ModelType.MISTRAL_8B,
184
- ModelType.MISTRAL_3B,
185
191
  }
186
192
 
187
193
  @property
@@ -202,10 +208,7 @@ class ModelType(UnifiedModelType, Enum):
202
208
  Returns:
203
209
  bool: Whether this type of models is gemini.
204
210
  """
205
- return self in {
206
- ModelType.GEMINI_1_5_FLASH,
207
- ModelType.GEMINI_1_5_PRO,
208
- }
211
+ return self in {ModelType.GEMINI_1_5_FLASH, ModelType.GEMINI_1_5_PRO}
209
212
 
210
213
  @property
211
214
  def is_reka(self) -> bool:
@@ -229,7 +232,11 @@ class ModelType(UnifiedModelType, Enum):
229
232
  """
230
233
  if self is ModelType.GLM_4V:
231
234
  return 1024
235
+ elif self is ModelType.VICUNA:
236
+ # reference: https://lmsys.org/blog/2023-03-30-vicuna/
237
+ return 2048
232
238
  elif self in {
239
+ ModelType.LLAMA_2,
233
240
  ModelType.NEMOTRON_4_REWARD,
234
241
  ModelType.STUB,
235
242
  ModelType.REKA_CORE,
@@ -243,12 +250,15 @@ class ModelType(UnifiedModelType, Enum):
243
250
  ModelType.GROQ_LLAMA_3_70B,
244
251
  ModelType.GROQ_GEMMA_7B_IT,
245
252
  ModelType.GROQ_GEMMA_2_9B_IT,
253
+ ModelType.LLAMA_3,
246
254
  ModelType.GLM_3_TURBO,
247
255
  ModelType.GLM_4,
256
+ ModelType.GLM_4_OPEN_SOURCE,
248
257
  }:
249
258
  return 8_192
250
259
  elif self in {
251
260
  ModelType.GPT_3_5_TURBO,
261
+ ModelType.VICUNA_16K,
252
262
  }:
253
263
  return 16_384
254
264
  elif self in {
@@ -260,10 +270,7 @@ class ModelType(UnifiedModelType, Enum):
260
270
  return 32_768
261
271
  elif self in {ModelType.MISTRAL_MIXTRAL_8x22B}:
262
272
  return 64_000
263
- elif self in {
264
- ModelType.CLAUDE_2_0,
265
- ModelType.CLAUDE_INSTANT_1_2,
266
- }:
273
+ elif self in {ModelType.CLAUDE_2_0, ModelType.CLAUDE_INSTANT_1_2}:
267
274
  return 100_000
268
275
  elif self in {
269
276
  ModelType.GPT_4O,
@@ -274,8 +281,7 @@ class ModelType(UnifiedModelType, Enum):
274
281
  ModelType.MISTRAL_LARGE,
275
282
  ModelType.MISTRAL_NEMO,
276
283
  ModelType.MISTRAL_PIXTRAL_12B,
277
- ModelType.MISTRAL_8B,
278
- ModelType.MISTRAL_3B,
284
+ ModelType.QWEN_2,
279
285
  }:
280
286
  return 128_000
281
287
  elif self in {
@@ -296,14 +302,48 @@ class ModelType(UnifiedModelType, Enum):
296
302
  ModelType.MISTRAL_CODESTRAL_MAMBA,
297
303
  }:
298
304
  return 256_000
299
- elif self in {
300
- ModelType.GEMINI_1_5_FLASH,
301
- ModelType.GEMINI_1_5_PRO,
302
- }:
305
+ elif self in {ModelType.GEMINI_1_5_FLASH, ModelType.GEMINI_1_5_PRO}:
303
306
  return 1_048_576
304
307
  else:
305
308
  raise ValueError("Unknown model type")
306
309
 
310
+ def validate_model_name(self, model_name: str) -> bool:
311
+ r"""Checks whether the model type and the model name matches.
312
+
313
+ Args:
314
+ model_name (str): The name of the model, e.g. "vicuna-7b-v1.5".
315
+
316
+ Returns:
317
+ bool: Whether the model type matches the model name.
318
+ """
319
+ if self is ModelType.VICUNA:
320
+ pattern = r'^vicuna-\d+b-v\d+\.\d+$'
321
+ return bool(re.match(pattern, model_name))
322
+ elif self is ModelType.VICUNA_16K:
323
+ pattern = r'^vicuna-\d+b-v\d+\.\d+-16k$'
324
+ return bool(re.match(pattern, model_name))
325
+ elif self is ModelType.LLAMA_2:
326
+ return (
327
+ self.value in model_name.lower()
328
+ or "llama2" in model_name.lower()
329
+ )
330
+ elif self is ModelType.LLAMA_3:
331
+ return (
332
+ self.value in model_name.lower()
333
+ or "llama3" in model_name.lower()
334
+ )
335
+ elif self is ModelType.QWEN_2:
336
+ return (
337
+ self.value in model_name.lower()
338
+ or "qwen2" in model_name.lower()
339
+ )
340
+ elif self is ModelType.GLM_4_OPEN_SOURCE:
341
+ return (
342
+ 'glm-4' in model_name.lower() or "glm4" in model_name.lower()
343
+ )
344
+ else:
345
+ return self.value in model_name.lower()
346
+
307
347
 
308
348
  class EmbeddingModelType(Enum):
309
349
  TEXT_EMBEDDING_ADA_2 = "text-embedding-ada-002"
@@ -429,21 +469,21 @@ class OpenAPIName(Enum):
429
469
 
430
470
 
431
471
  class ModelPlatformType(Enum):
432
- DEFAULT = "openai"
433
-
434
472
  OPENAI = "openai"
435
473
  AZURE = "azure"
436
474
  ANTHROPIC = "anthropic"
437
475
  GROQ = "groq"
476
+ OPEN_SOURCE = "open-source"
438
477
  OLLAMA = "ollama"
439
478
  LITELLM = "litellm"
440
479
  ZHIPU = "zhipuai"
480
+ DEFAULT = "default"
441
481
  GEMINI = "gemini"
442
482
  VLLM = "vllm"
443
483
  MISTRAL = "mistral"
444
484
  REKA = "reka"
445
485
  TOGETHER = "together"
446
- OPENAI_COMPATIBLE_MODEL = "openai-compatible-model"
486
+ OPENAI_COMPATIBILITY_MODEL = "openai-compatibility-model"
447
487
  SAMBA = "samba-nova"
448
488
 
449
489
  @property
@@ -497,10 +537,15 @@ class ModelPlatformType(Enum):
497
537
  return self is ModelPlatformType.MISTRAL
498
538
 
499
539
  @property
500
- def is_openai_compatible_model(self) -> bool:
540
+ def is_open_source(self) -> bool:
541
+ r"""Returns whether this platform is opensource."""
542
+ return self is ModelPlatformType.OPEN_SOURCE
543
+
544
+ @property
545
+ def is_openai_compatibility_model(self) -> bool:
501
546
  r"""Returns whether this is a platform supporting openai
502
547
  compatibility"""
503
- return self is ModelPlatformType.OPENAI_COMPATIBLE_MODEL
548
+ return self is ModelPlatformType.OPENAI_COMPATIBILITY_MODEL
504
549
 
505
550
  @property
506
551
  def is_gemini(self) -> bool:
@@ -31,7 +31,6 @@ from openai.types.chat.chat_completion_user_message_param import (
31
31
  ChatCompletionUserMessageParam,
32
32
  )
33
33
  from openai.types.completion_usage import CompletionUsage
34
- from openai._types import NOT_GIVEN, NotGiven
35
34
 
36
35
  Choice = Choice
37
36
  ChatCompletion = ChatCompletion
@@ -43,5 +42,3 @@ ChatCompletionUserMessageParam = ChatCompletionUserMessageParam
43
42
  ChatCompletionAssistantMessageParam = ChatCompletionAssistantMessageParam
44
43
  ChatCompletionFunctionMessageParam = ChatCompletionFunctionMessageParam
45
44
  CompletionUsage = CompletionUsage
46
- NOT_GIVEN = NOT_GIVEN
47
- NotGiven = NotGiven
camel/utils/__init__.py CHANGED
@@ -43,6 +43,7 @@ from .token_counting import (
43
43
  LiteLLMTokenCounter,
44
44
  MistralTokenCounter,
45
45
  OpenAITokenCounter,
46
+ OpenSourceTokenCounter,
46
47
  get_model_encoding,
47
48
  )
48
49
 
@@ -59,6 +60,7 @@ __all__ = [
59
60
  'get_model_encoding',
60
61
  'BaseTokenCounter',
61
62
  'OpenAITokenCounter',
63
+ 'OpenSourceTokenCounter',
62
64
  'LiteLLMTokenCounter',
63
65
  'Constants',
64
66
  'text_extract_from_web',
camel/utils/async_func.py CHANGED
@@ -14,20 +14,20 @@
14
14
  import asyncio
15
15
  from copy import deepcopy
16
16
 
17
- from camel.toolkits import FunctionTool
17
+ from camel.toolkits import OpenAIFunction
18
18
 
19
19
 
20
- def sync_funcs_to_async(funcs: list[FunctionTool]) -> list[FunctionTool]:
20
+ def sync_funcs_to_async(funcs: list[OpenAIFunction]) -> list[OpenAIFunction]:
21
21
  r"""Convert a list of Python synchronous functions to Python
22
22
  asynchronous functions.
23
23
 
24
24
  Args:
25
- funcs (list[FunctionTool]): List of Python synchronous
26
- functions in the :obj:`FunctionTool` format.
25
+ funcs (list[OpenAIFunction]): List of Python synchronous
26
+ functions in the :obj:`OpenAIFunction` format.
27
27
 
28
28
  Returns:
29
- list[FunctionTool]: List of Python asynchronous functions
30
- in the :obj:`FunctionTool` format.
29
+ list[OpenAIFunction]: List of Python asynchronous functions
30
+ in the :obj:`OpenAIFunction` format.
31
31
  """
32
32
  async_funcs = []
33
33
  for func in funcs:
@@ -37,6 +37,6 @@ def sync_funcs_to_async(funcs: list[FunctionTool]) -> list[FunctionTool]:
37
37
  return asyncio.to_thread(sync_func, *args, **kwargs) # noqa: B023
38
38
 
39
39
  async_funcs.append(
40
- FunctionTool(async_callable, deepcopy(func.openai_tool_schema))
40
+ OpenAIFunction(async_callable, deepcopy(func.openai_tool_schema))
41
41
  )
42
42
  return async_funcs
camel/utils/commons.py CHANGED
@@ -257,18 +257,18 @@ def api_keys_required(*required_keys: str) -> Callable[[F], F]:
257
257
 
258
258
  def decorator(func: F) -> F:
259
259
  @wraps(func)
260
- def wrapper(*args: Any, **kwargs: Any) -> Any:
260
+ def wrapper(self, *args: Any, **kwargs: Any) -> Any:
261
261
  missing_environment_keys = [
262
262
  k for k in required_keys if k not in os.environ
263
263
  ]
264
264
  if (
265
- not (args and getattr(args[0], '_api_key', None))
265
+ not getattr(self, '_api_key', None)
266
266
  and missing_environment_keys
267
267
  ):
268
268
  raise ValueError(
269
269
  f"Missing API keys: {', '.join(missing_environment_keys)}"
270
270
  )
271
- return func(*args, **kwargs)
271
+ return func(self, *args, **kwargs)
272
272
 
273
273
  return cast(F, wrapper)
274
274
 
@@ -577,32 +577,3 @@ def handle_http_error(response: requests.Response) -> str:
577
577
  return "Too Many Requests. You have hit the rate limit."
578
578
  else:
579
579
  return "HTTP Error"
580
-
581
-
582
- def retry_request(
583
- func: Callable, retries: int = 3, delay: int = 1, *args: Any, **kwargs: Any
584
- ) -> Any:
585
- r"""Retries a function in case of any errors.
586
-
587
- Args:
588
- func (Callable): The function to be retried.
589
- retries (int): Number of retry attempts. (default: :obj:`3`)
590
- delay (int): Delay between retries in seconds. (default: :obj:`1`)
591
- *args: Arguments to pass to the function.
592
- **kwargs: Keyword arguments to pass to the function.
593
-
594
- Returns:
595
- Any: The result of the function call if successful.
596
-
597
- Raises:
598
- Exception: If all retry attempts fail.
599
- """
600
- for attempt in range(retries):
601
- try:
602
- return func(*args, **kwargs)
603
- except Exception as e:
604
- print(f"Attempt {attempt + 1}/{retries} failed: {e}")
605
- if attempt < retries - 1:
606
- time.sleep(delay)
607
- else:
608
- raise