camel-ai 0.2.73a4__py3-none-any.whl → 0.2.80a2__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.
Files changed (173) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/_utils.py +38 -0
  3. camel/agents/chat_agent.py +2217 -519
  4. camel/agents/mcp_agent.py +30 -27
  5. camel/configs/__init__.py +15 -0
  6. camel/configs/aihubmix_config.py +88 -0
  7. camel/configs/amd_config.py +70 -0
  8. camel/configs/cometapi_config.py +104 -0
  9. camel/configs/minimax_config.py +93 -0
  10. camel/configs/nebius_config.py +103 -0
  11. camel/data_collectors/alpaca_collector.py +15 -6
  12. camel/datasets/base_generator.py +39 -10
  13. camel/environments/single_step.py +28 -3
  14. camel/environments/tic_tac_toe.py +1 -1
  15. camel/interpreters/__init__.py +2 -0
  16. camel/interpreters/docker/Dockerfile +3 -12
  17. camel/interpreters/e2b_interpreter.py +34 -1
  18. camel/interpreters/microsandbox_interpreter.py +395 -0
  19. camel/loaders/__init__.py +11 -2
  20. camel/loaders/chunkr_reader.py +9 -0
  21. camel/memories/agent_memories.py +48 -4
  22. camel/memories/base.py +26 -0
  23. camel/memories/blocks/chat_history_block.py +122 -4
  24. camel/memories/context_creators/score_based.py +25 -384
  25. camel/memories/records.py +88 -8
  26. camel/messages/base.py +153 -34
  27. camel/models/__init__.py +10 -0
  28. camel/models/aihubmix_model.py +83 -0
  29. camel/models/aiml_model.py +1 -16
  30. camel/models/amd_model.py +101 -0
  31. camel/models/anthropic_model.py +6 -19
  32. camel/models/aws_bedrock_model.py +2 -33
  33. camel/models/azure_openai_model.py +114 -89
  34. camel/models/base_audio_model.py +3 -1
  35. camel/models/base_model.py +32 -14
  36. camel/models/cohere_model.py +1 -16
  37. camel/models/cometapi_model.py +83 -0
  38. camel/models/crynux_model.py +1 -16
  39. camel/models/deepseek_model.py +1 -16
  40. camel/models/fish_audio_model.py +6 -0
  41. camel/models/gemini_model.py +36 -18
  42. camel/models/groq_model.py +1 -17
  43. camel/models/internlm_model.py +1 -16
  44. camel/models/litellm_model.py +1 -16
  45. camel/models/lmstudio_model.py +1 -17
  46. camel/models/minimax_model.py +83 -0
  47. camel/models/mistral_model.py +1 -16
  48. camel/models/model_factory.py +27 -1
  49. camel/models/modelscope_model.py +1 -16
  50. camel/models/moonshot_model.py +105 -24
  51. camel/models/nebius_model.py +83 -0
  52. camel/models/nemotron_model.py +0 -5
  53. camel/models/netmind_model.py +1 -16
  54. camel/models/novita_model.py +1 -16
  55. camel/models/nvidia_model.py +1 -16
  56. camel/models/ollama_model.py +4 -19
  57. camel/models/openai_compatible_model.py +62 -41
  58. camel/models/openai_model.py +62 -57
  59. camel/models/openrouter_model.py +1 -17
  60. camel/models/ppio_model.py +1 -16
  61. camel/models/qianfan_model.py +1 -16
  62. camel/models/qwen_model.py +1 -16
  63. camel/models/reka_model.py +1 -16
  64. camel/models/samba_model.py +34 -47
  65. camel/models/sglang_model.py +64 -31
  66. camel/models/siliconflow_model.py +1 -16
  67. camel/models/stub_model.py +0 -4
  68. camel/models/togetherai_model.py +1 -16
  69. camel/models/vllm_model.py +1 -16
  70. camel/models/volcano_model.py +0 -17
  71. camel/models/watsonx_model.py +1 -16
  72. camel/models/yi_model.py +1 -16
  73. camel/models/zhipuai_model.py +60 -16
  74. camel/parsers/__init__.py +18 -0
  75. camel/parsers/mcp_tool_call_parser.py +176 -0
  76. camel/retrievers/auto_retriever.py +1 -0
  77. camel/runtimes/daytona_runtime.py +11 -12
  78. camel/societies/__init__.py +2 -0
  79. camel/societies/workforce/__init__.py +2 -0
  80. camel/societies/workforce/events.py +122 -0
  81. camel/societies/workforce/prompts.py +146 -66
  82. camel/societies/workforce/role_playing_worker.py +15 -11
  83. camel/societies/workforce/single_agent_worker.py +302 -65
  84. camel/societies/workforce/structured_output_handler.py +30 -18
  85. camel/societies/workforce/task_channel.py +163 -27
  86. camel/societies/workforce/utils.py +107 -13
  87. camel/societies/workforce/workflow_memory_manager.py +772 -0
  88. camel/societies/workforce/workforce.py +1949 -579
  89. camel/societies/workforce/workforce_callback.py +74 -0
  90. camel/societies/workforce/workforce_logger.py +168 -145
  91. camel/societies/workforce/workforce_metrics.py +33 -0
  92. camel/storages/key_value_storages/json.py +15 -2
  93. camel/storages/key_value_storages/mem0_cloud.py +48 -47
  94. camel/storages/object_storages/google_cloud.py +1 -1
  95. camel/storages/vectordb_storages/oceanbase.py +13 -13
  96. camel/storages/vectordb_storages/qdrant.py +3 -3
  97. camel/storages/vectordb_storages/tidb.py +8 -6
  98. camel/tasks/task.py +4 -3
  99. camel/toolkits/__init__.py +20 -7
  100. camel/toolkits/aci_toolkit.py +45 -0
  101. camel/toolkits/base.py +6 -4
  102. camel/toolkits/code_execution.py +28 -1
  103. camel/toolkits/context_summarizer_toolkit.py +684 -0
  104. camel/toolkits/dappier_toolkit.py +5 -1
  105. camel/toolkits/dingtalk.py +1135 -0
  106. camel/toolkits/edgeone_pages_mcp_toolkit.py +11 -31
  107. camel/toolkits/excel_toolkit.py +1 -1
  108. camel/toolkits/{file_write_toolkit.py → file_toolkit.py} +430 -36
  109. camel/toolkits/function_tool.py +13 -3
  110. camel/toolkits/github_toolkit.py +104 -17
  111. camel/toolkits/gmail_toolkit.py +1839 -0
  112. camel/toolkits/google_calendar_toolkit.py +38 -4
  113. camel/toolkits/google_drive_mcp_toolkit.py +12 -31
  114. camel/toolkits/hybrid_browser_toolkit/config_loader.py +15 -0
  115. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +77 -8
  116. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +884 -88
  117. camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
  118. camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +5 -612
  119. camel/toolkits/hybrid_browser_toolkit/ts/package.json +0 -1
  120. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +959 -89
  121. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +9 -2
  122. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +281 -213
  123. camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
  124. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
  125. camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
  126. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +23 -3
  127. camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +72 -7
  128. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +582 -132
  129. camel/toolkits/hybrid_browser_toolkit_py/actions.py +158 -0
  130. camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +55 -8
  131. camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +43 -0
  132. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +321 -8
  133. camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +10 -4
  134. camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +45 -4
  135. camel/toolkits/{openai_image_toolkit.py → image_generation_toolkit.py} +151 -53
  136. camel/toolkits/klavis_toolkit.py +5 -1
  137. camel/toolkits/markitdown_toolkit.py +27 -1
  138. camel/toolkits/math_toolkit.py +64 -10
  139. camel/toolkits/mcp_toolkit.py +366 -71
  140. camel/toolkits/memory_toolkit.py +5 -1
  141. camel/toolkits/message_integration.py +18 -13
  142. camel/toolkits/minimax_mcp_toolkit.py +195 -0
  143. camel/toolkits/note_taking_toolkit.py +19 -10
  144. camel/toolkits/notion_mcp_toolkit.py +16 -26
  145. camel/toolkits/openbb_toolkit.py +5 -1
  146. camel/toolkits/origene_mcp_toolkit.py +8 -49
  147. camel/toolkits/playwright_mcp_toolkit.py +12 -31
  148. camel/toolkits/resend_toolkit.py +168 -0
  149. camel/toolkits/search_toolkit.py +264 -91
  150. camel/toolkits/slack_toolkit.py +64 -10
  151. camel/toolkits/terminal_toolkit/__init__.py +18 -0
  152. camel/toolkits/terminal_toolkit/terminal_toolkit.py +957 -0
  153. camel/toolkits/terminal_toolkit/utils.py +532 -0
  154. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  155. camel/toolkits/video_analysis_toolkit.py +17 -11
  156. camel/toolkits/wechat_official_toolkit.py +483 -0
  157. camel/toolkits/zapier_toolkit.py +5 -1
  158. camel/types/__init__.py +2 -2
  159. camel/types/enums.py +274 -7
  160. camel/types/openai_types.py +2 -2
  161. camel/types/unified_model_type.py +15 -0
  162. camel/utils/commons.py +36 -5
  163. camel/utils/constants.py +3 -0
  164. camel/utils/context_utils.py +1003 -0
  165. camel/utils/mcp.py +138 -4
  166. camel/utils/token_counting.py +43 -20
  167. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/METADATA +223 -83
  168. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/RECORD +170 -141
  169. camel/loaders/pandas_reader.py +0 -368
  170. camel/toolkits/openai_agent_toolkit.py +0 -135
  171. camel/toolkits/terminal_toolkit.py +0 -1550
  172. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/WHEEL +0 -0
  173. {camel_ai-0.2.73a4.dist-info → camel_ai-0.2.80a2.dist-info}/licenses/LICENSE +0 -0
@@ -13,6 +13,7 @@
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import copy
15
15
  import os
16
+ import warnings
16
17
  from typing import Any, Callable, Dict, List, Optional, Type, Union
17
18
 
18
19
  from openai import AsyncAzureOpenAI, AsyncStream, AzureOpenAI, Stream
@@ -22,7 +23,7 @@ from openai.lib.streaming.chat import (
22
23
  )
23
24
  from pydantic import BaseModel
24
25
 
25
- from camel.configs import OPENAI_API_PARAMS, ChatGPTConfig
26
+ from camel.configs import ChatGPTConfig
26
27
  from camel.messages import OpenAIMessage
27
28
  from camel.models.base_model import BaseModelBackend
28
29
  from camel.types import (
@@ -60,7 +61,8 @@ class AzureOpenAIModel(BaseModelBackend):
60
61
 
61
62
  Args:
62
63
  model_type (Union[ModelType, str]): Model for which a backend is
63
- created, one of GPT_* series.
64
+ created, Should be the deployment name you chose when you deployed
65
+ an azure model.
64
66
  model_config_dict (Optional[Dict[str, Any]], optional): A dictionary
65
67
  that will be fed into:obj:`openai.ChatCompletion.create()`. If
66
68
  :obj:`None`, :obj:`ChatGPTConfig().as_dict()` will be used.
@@ -71,8 +73,6 @@ class AzureOpenAIModel(BaseModelBackend):
71
73
  (default: :obj:`None`)
72
74
  api_version (Optional[str], optional): The api version for the model.
73
75
  (default: :obj:`None`)
74
- azure_deployment_name (Optional[str], optional): The deployment name
75
- you chose when you deployed an azure model. (default: :obj:`None`)
76
76
  azure_ad_token (Optional[str], optional): Your Azure Active Directory
77
77
  token, https://www.microsoft.com/en-us/security/business/
78
78
  identity-access/microsoft-entra-id. (default: :obj:`None`)
@@ -88,8 +88,23 @@ class AzureOpenAIModel(BaseModelBackend):
88
88
  (default: :obj:`None`)
89
89
  max_retries (int, optional): Maximum number of retries for API calls.
90
90
  (default: :obj:`3`)
91
+ client (Optional[Any], optional): A custom synchronous AzureOpenAI
92
+ client instance. If provided, this client will be used instead of
93
+ creating a new one. Useful for RL frameworks like AReaL or rLLM
94
+ that provide Azure OpenAI-compatible clients. The client should
95
+ implement the AzureOpenAI client interface with
96
+ `.chat.completions.create()` and `.beta.chat.completions.parse()`
97
+ methods. (default: :obj:`None`)
98
+ async_client (Optional[Any], optional): A custom asynchronous
99
+ AzureOpenAI client instance. If provided, this client will be
100
+ used instead of creating a new one. The client should implement
101
+ the AsyncAzureOpenAI client interface. (default: :obj:`None`)
102
+ azure_deployment_name (Optional[str], optional): **Deprecated**.
103
+ Use `model_type` parameter instead. This parameter is kept for
104
+ backward compatibility and will be removed in a future version.
105
+ (default: :obj:`None`)
91
106
  **kwargs (Any): Additional arguments to pass to the client
92
- initialization.
107
+ initialization. Ignored if custom clients are provided.
93
108
 
94
109
  References:
95
110
  https://learn.microsoft.com/en-us/azure/ai-services/openai/
@@ -104,12 +119,35 @@ class AzureOpenAIModel(BaseModelBackend):
104
119
  timeout: Optional[float] = None,
105
120
  token_counter: Optional[BaseTokenCounter] = None,
106
121
  api_version: Optional[str] = None,
107
- azure_deployment_name: Optional[str] = None,
108
122
  azure_ad_token_provider: Optional["AzureADTokenProvider"] = None,
109
123
  azure_ad_token: Optional[str] = None,
110
124
  max_retries: int = 3,
125
+ client: Optional[Any] = None,
126
+ async_client: Optional[Any] = None,
127
+ azure_deployment_name: Optional[str] = None,
111
128
  **kwargs: Any,
112
129
  ) -> None:
130
+ # Handle deprecated azure_deployment_name parameter
131
+ if azure_deployment_name is not None:
132
+ warnings.warn(
133
+ "The 'azure_deployment_name' parameter is deprecated. "
134
+ "Please use 'model_type' parameter instead. "
135
+ "The 'azure_deployment_name' parameter is being ignored.",
136
+ DeprecationWarning,
137
+ stacklevel=2,
138
+ )
139
+
140
+ # Handle deprecated AZURE_DEPLOYMENT_NAME environment variable
141
+ if os.environ.get("AZURE_DEPLOYMENT_NAME") is not None:
142
+ warnings.warn(
143
+ "The 'AZURE_DEPLOYMENT_NAME' environment variable is "
144
+ "deprecated. Please use the 'model_type' parameter "
145
+ "instead. The 'AZURE_DEPLOYMENT_NAME' environment "
146
+ "variable is being ignored.",
147
+ DeprecationWarning,
148
+ stacklevel=2,
149
+ )
150
+
113
151
  if model_config_dict is None:
114
152
  model_config_dict = ChatGPTConfig().as_dict()
115
153
  api_key = api_key or os.environ.get("AZURE_OPENAI_API_KEY")
@@ -120,9 +158,6 @@ class AzureOpenAIModel(BaseModelBackend):
120
158
  )
121
159
 
122
160
  self.api_version = api_version or os.environ.get("AZURE_API_VERSION")
123
- self._azure_deployment_name = azure_deployment_name or os.environ.get(
124
- "AZURE_DEPLOYMENT_NAME"
125
- )
126
161
  self._azure_ad_token = azure_ad_token or os.environ.get(
127
162
  "AZURE_AD_TOKEN"
128
163
  )
@@ -132,62 +167,73 @@ class AzureOpenAIModel(BaseModelBackend):
132
167
  "Must provide either the `api_version` argument "
133
168
  "or `AZURE_API_VERSION` environment variable."
134
169
  )
135
- if self._azure_deployment_name is None:
136
- raise ValueError(
137
- "Must provide either the `azure_deployment_name` argument "
138
- "or `AZURE_DEPLOYMENT_NAME` environment variable."
139
- )
140
170
 
141
- if is_langfuse_available():
142
- from langfuse.openai import AsyncAzureOpenAI as LangfuseAsyncOpenAI
143
- from langfuse.openai import AzureOpenAI as LangfuseOpenAI
144
-
145
- self._client = LangfuseOpenAI(
146
- azure_endpoint=str(self._url),
147
- azure_deployment=self._azure_deployment_name,
148
- api_version=self.api_version,
149
- api_key=self._api_key,
150
- azure_ad_token=self._azure_ad_token,
151
- azure_ad_token_provider=self.azure_ad_token_provider,
152
- timeout=self._timeout,
153
- max_retries=max_retries,
154
- **kwargs,
155
- )
156
- self._async_client = LangfuseAsyncOpenAI(
157
- azure_endpoint=str(self._url),
158
- azure_deployment=self._azure_deployment_name,
159
- api_version=self.api_version,
160
- api_key=self._api_key,
161
- azure_ad_token=self._azure_ad_token,
162
- azure_ad_token_provider=self.azure_ad_token_provider,
163
- timeout=self._timeout,
164
- max_retries=max_retries,
165
- **kwargs,
166
- )
171
+ # Use custom clients if provided, otherwise create new ones
172
+ if client is not None:
173
+ # Use the provided custom sync client
174
+ self._client = client
167
175
  else:
168
- self._client = AzureOpenAI(
169
- azure_endpoint=str(self._url),
170
- azure_deployment=self._azure_deployment_name,
171
- api_version=self.api_version,
172
- api_key=self._api_key,
173
- azure_ad_token=self._azure_ad_token,
174
- azure_ad_token_provider=self.azure_ad_token_provider,
175
- timeout=self._timeout,
176
- max_retries=max_retries,
177
- **kwargs,
178
- )
176
+ # Create default sync client
177
+ if is_langfuse_available():
178
+ from langfuse.openai import AzureOpenAI as LangfuseOpenAI
179
+
180
+ self._client = LangfuseOpenAI(
181
+ azure_endpoint=str(self._url),
182
+ azure_deployment=str(self.model_type),
183
+ api_version=self.api_version,
184
+ api_key=self._api_key,
185
+ azure_ad_token=self._azure_ad_token,
186
+ azure_ad_token_provider=self.azure_ad_token_provider,
187
+ timeout=self._timeout,
188
+ max_retries=max_retries,
189
+ **kwargs,
190
+ )
191
+ else:
192
+ self._client = AzureOpenAI(
193
+ azure_endpoint=str(self._url),
194
+ azure_deployment=str(self.model_type),
195
+ api_version=self.api_version,
196
+ api_key=self._api_key,
197
+ azure_ad_token=self._azure_ad_token,
198
+ azure_ad_token_provider=self.azure_ad_token_provider,
199
+ timeout=self._timeout,
200
+ max_retries=max_retries,
201
+ **kwargs,
202
+ )
179
203
 
180
- self._async_client = AsyncAzureOpenAI(
181
- azure_endpoint=str(self._url),
182
- azure_deployment=self._azure_deployment_name,
183
- api_version=self.api_version,
184
- api_key=self._api_key,
185
- azure_ad_token=self._azure_ad_token,
186
- azure_ad_token_provider=self.azure_ad_token_provider,
187
- timeout=self._timeout,
188
- max_retries=max_retries,
189
- **kwargs,
190
- )
204
+ if async_client is not None:
205
+ # Use the provided custom async client
206
+ self._async_client = async_client
207
+ else:
208
+ # Create default async client
209
+ if is_langfuse_available():
210
+ from langfuse.openai import (
211
+ AsyncAzureOpenAI as LangfuseAsyncOpenAI,
212
+ )
213
+
214
+ self._async_client = LangfuseAsyncOpenAI(
215
+ azure_endpoint=str(self._url),
216
+ azure_deployment=str(self.model_type),
217
+ api_version=self.api_version,
218
+ api_key=self._api_key,
219
+ azure_ad_token=self._azure_ad_token,
220
+ azure_ad_token_provider=self.azure_ad_token_provider,
221
+ timeout=self._timeout,
222
+ max_retries=max_retries,
223
+ **kwargs,
224
+ )
225
+ else:
226
+ self._async_client = AsyncAzureOpenAI(
227
+ azure_endpoint=str(self._url),
228
+ azure_deployment=str(self.model_type),
229
+ api_version=self.api_version,
230
+ api_key=self._api_key,
231
+ azure_ad_token=self._azure_ad_token,
232
+ azure_ad_token_provider=self.azure_ad_token_provider,
233
+ timeout=self._timeout,
234
+ max_retries=max_retries,
235
+ **kwargs,
236
+ )
191
237
 
192
238
  @property
193
239
  def token_counter(self) -> BaseTokenCounter:
@@ -247,9 +293,6 @@ class AzureOpenAIModel(BaseModelBackend):
247
293
  )
248
294
  is_streaming = self.model_config_dict.get("stream", False)
249
295
  if response_format:
250
- result: Union[ChatCompletion, Stream[ChatCompletionChunk]] = (
251
- self._request_parse(messages, response_format, tools)
252
- )
253
296
  if is_streaming:
254
297
  return self._request_stream_parse(
255
298
  messages, response_format, tools
@@ -308,9 +351,6 @@ class AzureOpenAIModel(BaseModelBackend):
308
351
  )
309
352
  is_streaming = self.model_config_dict.get("stream", False)
310
353
  if response_format:
311
- result: Union[
312
- ChatCompletion, AsyncStream[ChatCompletionChunk]
313
- ] = await self._arequest_parse(messages, response_format, tools)
314
354
  if is_streaming:
315
355
  return await self._arequest_stream_parse(
316
356
  messages, response_format, tools
@@ -336,7 +376,7 @@ class AzureOpenAIModel(BaseModelBackend):
336
376
 
337
377
  return self._client.chat.completions.create(
338
378
  messages=messages,
339
- model=self._azure_deployment_name, # type:ignore[arg-type]
379
+ model=str(self.model_type),
340
380
  **request_config,
341
381
  )
342
382
 
@@ -352,7 +392,7 @@ class AzureOpenAIModel(BaseModelBackend):
352
392
 
353
393
  return await self._async_client.chat.completions.create(
354
394
  messages=messages,
355
- model=self._azure_deployment_name, # type:ignore[arg-type]
395
+ model=str(self.model_type),
356
396
  **request_config,
357
397
  )
358
398
 
@@ -373,7 +413,7 @@ class AzureOpenAIModel(BaseModelBackend):
373
413
 
374
414
  return self._client.beta.chat.completions.parse(
375
415
  messages=messages,
376
- model=self._azure_deployment_name, # type:ignore[arg-type]
416
+ model=str(self.model_type),
377
417
  **request_config,
378
418
  )
379
419
 
@@ -394,7 +434,7 @@ class AzureOpenAIModel(BaseModelBackend):
394
434
 
395
435
  return await self._async_client.beta.chat.completions.parse(
396
436
  messages=messages,
397
- model=self._azure_deployment_name, # type:ignore[arg-type]
437
+ model=str(self.model_type),
398
438
  **request_config,
399
439
  )
400
440
 
@@ -420,7 +460,7 @@ class AzureOpenAIModel(BaseModelBackend):
420
460
  # Use the beta streaming API for structured outputs
421
461
  return self._client.beta.chat.completions.stream(
422
462
  messages=messages,
423
- model=self.model_type,
463
+ model=str(self.model_type),
424
464
  response_format=response_format,
425
465
  **request_config,
426
466
  )
@@ -447,26 +487,11 @@ class AzureOpenAIModel(BaseModelBackend):
447
487
  # Use the beta streaming API for structured outputs
448
488
  return self._async_client.beta.chat.completions.stream(
449
489
  messages=messages,
450
- model=self.model_type,
490
+ model=str(self.model_type),
451
491
  response_format=response_format,
452
492
  **request_config,
453
493
  )
454
494
 
455
- def check_model_config(self):
456
- r"""Check whether the model configuration contains any
457
- unexpected arguments to Azure OpenAI API.
458
-
459
- Raises:
460
- ValueError: If the model configuration dictionary contains any
461
- unexpected arguments to Azure OpenAI API.
462
- """
463
- for param in self.model_config_dict:
464
- if param not in OPENAI_API_PARAMS:
465
- raise ValueError(
466
- f"Unexpected argument `{param}` is "
467
- "input into Azure OpenAI model backend."
468
- )
469
-
470
495
  @property
471
496
  def stream(self) -> bool:
472
497
  r"""Returns whether the model is in stream mode,
@@ -16,6 +16,8 @@ import os
16
16
  from abc import ABC, abstractmethod
17
17
  from typing import Any, Optional
18
18
 
19
+ from camel.utils import Constants
20
+
19
21
 
20
22
  class BaseAudioModel(ABC):
21
23
  r"""Base class for audio models providing Text-to-Speech (TTS) and
@@ -26,7 +28,7 @@ class BaseAudioModel(ABC):
26
28
  self,
27
29
  api_key: Optional[str] = None,
28
30
  url: Optional[str] = None,
29
- timeout: Optional[float] = None,
31
+ timeout: Optional[float] = Constants.TIMEOUT_THRESHOLD,
30
32
  ) -> None:
31
33
  r"""Initialize an instance of BaseAudioModel.
32
34
 
@@ -24,6 +24,7 @@ from openai.lib.streaming.chat import (
24
24
  )
25
25
  from pydantic import BaseModel
26
26
 
27
+ from camel.logger import get_logger as camel_get_logger
27
28
  from camel.messages import OpenAIMessage
28
29
  from camel.types import (
29
30
  ChatCompletion,
@@ -32,7 +33,22 @@ from camel.types import (
32
33
  ParsedChatCompletion,
33
34
  UnifiedModelType,
34
35
  )
35
- from camel.utils import BaseTokenCounter
36
+ from camel.utils import BaseTokenCounter, Constants
37
+
38
+ if os.environ.get("TRACEROOT_ENABLED", "False").lower() == "true":
39
+ try:
40
+ from traceroot import get_logger # type: ignore[import]
41
+ from traceroot import trace as observe # type: ignore[import]
42
+
43
+ logger = get_logger('base_model')
44
+ except ImportError:
45
+ from camel.utils import observe
46
+
47
+ logger = camel_get_logger('base_model')
48
+ else:
49
+ from camel.utils import observe
50
+
51
+ logger = camel_get_logger('base_model')
36
52
 
37
53
 
38
54
  class ModelBackendMeta(abc.ABCMeta):
@@ -87,7 +103,7 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
87
103
  api_key: Optional[str] = None,
88
104
  url: Optional[str] = None,
89
105
  token_counter: Optional[BaseTokenCounter] = None,
90
- timeout: Optional[float] = None,
106
+ timeout: Optional[float] = Constants.TIMEOUT_THRESHOLD,
91
107
  max_retries: int = 3,
92
108
  ) -> None:
93
109
  self.model_type: UnifiedModelType = UnifiedModelType(model_type)
@@ -105,7 +121,6 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
105
121
  == "true"
106
122
  )
107
123
  self._log_dir = os.environ.get("CAMEL_LOG_DIR", "camel_logs")
108
- self.check_model_config()
109
124
 
110
125
  @property
111
126
  @abstractmethod
@@ -365,6 +380,7 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
365
380
  """
366
381
  pass
367
382
 
383
+ @observe()
368
384
  def run(
369
385
  self,
370
386
  messages: List[OpenAIMessage],
@@ -404,7 +420,13 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
404
420
  elif not tools:
405
421
  tools = None
406
422
 
423
+ logger.info("Running model: %s", self.model_type)
424
+ logger.info("Messages: %s", messages)
425
+ logger.info("Response format: %s", response_format)
426
+ logger.info("Tools: %s", tools)
427
+
407
428
  result = self._run(messages, response_format, tools)
429
+ logger.info("Result: %s", result)
408
430
 
409
431
  # Log the response if logging is enabled
410
432
  if log_path:
@@ -412,6 +434,7 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
412
434
 
413
435
  return result
414
436
 
437
+ @observe()
415
438
  async def arun(
416
439
  self,
417
440
  messages: List[OpenAIMessage],
@@ -449,7 +472,13 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
449
472
  elif not tools:
450
473
  tools = None
451
474
 
475
+ logger.info("Running model: %s", self.model_type)
476
+ logger.info("Messages: %s", messages)
477
+ logger.info("Response format: %s", response_format)
478
+ logger.info("Tools: %s", tools)
479
+
452
480
  result = await self._arun(messages, response_format, tools)
481
+ logger.info("Result: %s", result)
453
482
 
454
483
  # Log the response if logging is enabled
455
484
  if log_path:
@@ -457,17 +486,6 @@ class BaseModelBackend(ABC, metaclass=ModelBackendMeta):
457
486
 
458
487
  return result
459
488
 
460
- @abstractmethod
461
- def check_model_config(self):
462
- r"""Check whether the input model configuration contains unexpected
463
- arguments
464
-
465
- Raises:
466
- ValueError: If the model configuration dictionary contains any
467
- unexpected argument for this model class.
468
- """
469
- pass
470
-
471
489
  def count_tokens_from_messages(self, messages: List[OpenAIMessage]) -> int:
472
490
  r"""Count the number of tokens in the messages using the specific
473
491
  tokenizer.
@@ -26,7 +26,7 @@ if TYPE_CHECKING:
26
26
  ChatResponse,
27
27
  )
28
28
 
29
- from camel.configs import COHERE_API_PARAMS, CohereConfig
29
+ from camel.configs import CohereConfig
30
30
  from camel.messages import OpenAIMessage
31
31
  from camel.models import BaseModelBackend
32
32
  from camel.models._utils import try_modify_message_with_format
@@ -454,21 +454,6 @@ class CohereModel(BaseModelBackend):
454
454
 
455
455
  return openai_response
456
456
 
457
- def check_model_config(self):
458
- r"""Check whether the model configuration contains any unexpected
459
- arguments to Cohere API.
460
-
461
- Raises:
462
- ValueError: If the model configuration dictionary contains any
463
- unexpected arguments to Cohere API.
464
- """
465
- for param in self.model_config_dict:
466
- if param not in COHERE_API_PARAMS:
467
- raise ValueError(
468
- f"Unexpected argument `{param}` is "
469
- "input into Cohere model backend."
470
- )
471
-
472
457
  @property
473
458
  def stream(self) -> bool:
474
459
  r"""Returns whether the model is in stream mode, which sends partial
@@ -0,0 +1,83 @@
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
+ import os
15
+ from typing import Any, Dict, Optional, Union
16
+
17
+ from camel.configs import CometAPIConfig
18
+ from camel.models.openai_compatible_model import OpenAICompatibleModel
19
+ from camel.types import ModelType
20
+ from camel.utils import (
21
+ BaseTokenCounter,
22
+ api_keys_required,
23
+ )
24
+
25
+
26
+ class CometAPIModel(OpenAICompatibleModel):
27
+ r"""LLM API served by CometAPI in a unified OpenAICompatibleModel
28
+ interface.
29
+
30
+ Args:
31
+ model_type (Union[ModelType, str]): Model for which a backend is
32
+ created.
33
+ model_config_dict (Optional[Dict[str, Any]], optional): A dictionary
34
+ that will be fed into:obj:`openai.ChatCompletion.create()`.
35
+ If:obj:`None`, :obj:`CometAPIConfig().as_dict()` will be used.
36
+ (default: :obj:`None`)
37
+ api_key (Optional[str], optional): The API key for authenticating
38
+ with the CometAPI service. (default: :obj:`None`).
39
+ url (Optional[str], optional): The url to the CometAPI service.
40
+ (default: :obj:`None`)
41
+ token_counter (Optional[BaseTokenCounter], optional): Token counter to
42
+ use for the model. If not provided, :obj:`OpenAITokenCounter(
43
+ ModelType.GPT_4O_MINI)` will be used.
44
+ (default: :obj:`None`)
45
+ timeout (Optional[float], optional): The timeout value in seconds for
46
+ API calls. If not provided, will fall back to the MODEL_TIMEOUT
47
+ environment variable or default to 180 seconds.
48
+ (default: :obj:`None`)
49
+ max_retries (int, optional): Maximum number of retries for API calls.
50
+ (default: :obj:`3`)
51
+ **kwargs (Any): Additional arguments to pass to the client
52
+ initialization.
53
+ """
54
+
55
+ @api_keys_required([("api_key", "COMETAPI_KEY")])
56
+ def __init__(
57
+ self,
58
+ model_type: Union[ModelType, str],
59
+ model_config_dict: Optional[Dict[str, Any]] = None,
60
+ api_key: Optional[str] = None,
61
+ url: Optional[str] = None,
62
+ token_counter: Optional[BaseTokenCounter] = None,
63
+ timeout: Optional[float] = None,
64
+ max_retries: int = 3,
65
+ **kwargs: Any,
66
+ ) -> None:
67
+ if model_config_dict is None:
68
+ model_config_dict = CometAPIConfig().as_dict()
69
+ api_key = api_key or os.environ.get("COMETAPI_KEY")
70
+ url = url or os.environ.get(
71
+ "COMETAPI_API_BASE_URL", "https://api.cometapi.com/v1"
72
+ )
73
+ timeout = timeout or float(os.environ.get("MODEL_TIMEOUT", 180))
74
+ super().__init__(
75
+ model_type=model_type,
76
+ model_config_dict=model_config_dict,
77
+ api_key=api_key,
78
+ url=url,
79
+ token_counter=token_counter,
80
+ timeout=timeout,
81
+ max_retries=max_retries,
82
+ **kwargs,
83
+ )
@@ -15,7 +15,7 @@
15
15
  import os
16
16
  from typing import Any, Dict, Optional, Union
17
17
 
18
- from camel.configs import CRYNUX_API_PARAMS, CrynuxConfig
18
+ from camel.configs import CrynuxConfig
19
19
  from camel.models.openai_compatible_model import OpenAICompatibleModel
20
20
  from camel.types import ModelType
21
21
  from camel.utils import (
@@ -85,18 +85,3 @@ class CrynuxModel(OpenAICompatibleModel):
85
85
  max_retries=max_retries,
86
86
  **kwargs,
87
87
  )
88
-
89
- def check_model_config(self):
90
- r"""Check whether the model configuration contains any
91
- unexpected arguments to Crynux API.
92
-
93
- Raises:
94
- ValueError: If the model configuration dictionary contains any
95
- unexpected arguments to Crynux API.
96
- """
97
- for param in self.model_config_dict:
98
- if param not in CRYNUX_API_PARAMS:
99
- raise ValueError(
100
- f"Unexpected argument `{param}` is "
101
- "input into Crynux model backend."
102
- )
@@ -18,7 +18,7 @@ from typing import Any, Dict, List, Optional, Type, Union
18
18
  from openai import AsyncStream, Stream
19
19
  from pydantic import BaseModel
20
20
 
21
- from camel.configs import DEEPSEEK_API_PARAMS, DeepSeekConfig
21
+ from camel.configs import DeepSeekConfig
22
22
  from camel.logger import get_logger
23
23
  from camel.messages import OpenAIMessage
24
24
  from camel.models._utils import try_modify_message_with_format
@@ -287,18 +287,3 @@ class DeepSeekModel(OpenAICompatibleModel):
287
287
  )
288
288
 
289
289
  return self._post_handle_response(response)
290
-
291
- def check_model_config(self):
292
- r"""Check whether the model configuration contains any
293
- unexpected arguments to DeepSeek API.
294
-
295
- Raises:
296
- ValueError: If the model configuration dictionary contains any
297
- unexpected arguments to DeepSeek API.
298
- """
299
- for param in self.model_config_dict:
300
- if param not in DEEPSEEK_API_PARAMS:
301
- raise ValueError(
302
- f"Unexpected argument `{param}` is "
303
- "input into DeepSeek model backend."
304
- )
@@ -44,6 +44,12 @@ class FishAudioModel(BaseAudioModel):
44
44
  self._url = url or os.environ.get(
45
45
  "FISHAUDIO_API_BASE_URL", "https://api.fish.audio"
46
46
  )
47
+ if self._api_key is None:
48
+ raise ValueError(
49
+ "API key is required for FishAudio. Please provide it via "
50
+ "the 'api_key' parameter or set the 'FISHAUDIO_API_KEY' "
51
+ "environment variable."
52
+ )
47
53
  self.session = Session(apikey=self._api_key, base_url=self._url)
48
54
 
49
55
  def text_to_speech(