camel-ai 0.2.9__py3-none-any.whl → 0.2.11__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 (242) hide show
  1. camel/__init__.py +10 -5
  2. camel/agents/__init__.py +4 -4
  3. camel/agents/base.py +4 -4
  4. camel/agents/chat_agent.py +106 -42
  5. camel/agents/critic_agent.py +4 -4
  6. camel/agents/deductive_reasoner_agent.py +8 -5
  7. camel/agents/embodied_agent.py +4 -4
  8. camel/agents/knowledge_graph_agent.py +4 -4
  9. camel/agents/role_assignment_agent.py +4 -4
  10. camel/agents/search_agent.py +4 -4
  11. camel/agents/task_agent.py +4 -4
  12. camel/agents/tool_agents/__init__.py +4 -4
  13. camel/agents/tool_agents/base.py +4 -4
  14. camel/agents/tool_agents/hugging_face_tool_agent.py +4 -4
  15. camel/bots/__init__.py +4 -4
  16. camel/bots/discord_app.py +4 -4
  17. camel/bots/slack/__init__.py +4 -4
  18. camel/bots/slack/models.py +4 -4
  19. camel/bots/slack/slack_app.py +4 -4
  20. camel/bots/telegram_bot.py +4 -4
  21. camel/configs/__init__.py +13 -4
  22. camel/configs/anthropic_config.py +4 -4
  23. camel/configs/base_config.py +4 -4
  24. camel/configs/cohere_config.py +76 -0
  25. camel/configs/deepseek_config.py +134 -0
  26. camel/configs/gemini_config.py +85 -127
  27. camel/configs/groq_config.py +4 -4
  28. camel/configs/litellm_config.py +4 -4
  29. camel/configs/mistral_config.py +4 -7
  30. camel/configs/nvidia_config.py +70 -0
  31. camel/configs/ollama_config.py +4 -4
  32. camel/configs/openai_config.py +32 -7
  33. camel/configs/qwen_config.py +4 -4
  34. camel/configs/reka_config.py +4 -4
  35. camel/configs/samba_config.py +4 -4
  36. camel/configs/togetherai_config.py +4 -4
  37. camel/configs/vllm_config.py +14 -5
  38. camel/configs/yi_config.py +4 -4
  39. camel/configs/zhipuai_config.py +4 -4
  40. camel/embeddings/__init__.py +6 -4
  41. camel/embeddings/base.py +4 -4
  42. camel/embeddings/mistral_embedding.py +4 -4
  43. camel/embeddings/openai_compatible_embedding.py +91 -0
  44. camel/embeddings/openai_embedding.py +4 -4
  45. camel/embeddings/sentence_transformers_embeddings.py +4 -4
  46. camel/embeddings/vlm_embedding.py +8 -5
  47. camel/generators.py +4 -4
  48. camel/human.py +4 -4
  49. camel/interpreters/__init__.py +4 -4
  50. camel/interpreters/base.py +4 -4
  51. camel/interpreters/docker_interpreter.py +11 -6
  52. camel/interpreters/internal_python_interpreter.py +4 -4
  53. camel/interpreters/interpreter_error.py +4 -4
  54. camel/interpreters/ipython_interpreter.py +4 -4
  55. camel/interpreters/subprocess_interpreter.py +11 -6
  56. camel/loaders/__init__.py +4 -4
  57. camel/loaders/apify_reader.py +4 -4
  58. camel/loaders/base_io.py +4 -4
  59. camel/loaders/chunkr_reader.py +4 -4
  60. camel/loaders/firecrawl_reader.py +4 -7
  61. camel/loaders/jina_url_reader.py +4 -4
  62. camel/loaders/unstructured_io.py +4 -4
  63. camel/logger.py +112 -0
  64. camel/memories/__init__.py +4 -4
  65. camel/memories/agent_memories.py +4 -4
  66. camel/memories/base.py +4 -4
  67. camel/memories/blocks/__init__.py +4 -4
  68. camel/memories/blocks/chat_history_block.py +4 -4
  69. camel/memories/blocks/vectordb_block.py +4 -4
  70. camel/memories/context_creators/__init__.py +4 -4
  71. camel/memories/context_creators/score_based.py +4 -4
  72. camel/memories/records.py +4 -4
  73. camel/messages/__init__.py +20 -4
  74. camel/messages/base.py +118 -11
  75. camel/messages/conversion/__init__.py +31 -0
  76. camel/messages/conversion/alpaca.py +122 -0
  77. camel/messages/conversion/conversation_models.py +178 -0
  78. camel/messages/conversion/sharegpt/__init__.py +20 -0
  79. camel/messages/conversion/sharegpt/function_call_formatter.py +49 -0
  80. camel/messages/conversion/sharegpt/hermes/__init__.py +19 -0
  81. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +128 -0
  82. camel/messages/func_message.py +50 -4
  83. camel/models/__init__.py +13 -4
  84. camel/models/anthropic_model.py +4 -4
  85. camel/models/azure_openai_model.py +4 -4
  86. camel/models/base_model.py +4 -4
  87. camel/models/cohere_model.py +282 -0
  88. camel/models/deepseek_model.py +139 -0
  89. camel/models/gemini_model.py +61 -146
  90. camel/models/groq_model.py +4 -4
  91. camel/models/litellm_model.py +4 -4
  92. camel/models/mistral_model.py +4 -4
  93. camel/models/model_factory.py +13 -4
  94. camel/models/model_manager.py +212 -0
  95. camel/models/nemotron_model.py +4 -4
  96. camel/models/nvidia_model.py +141 -0
  97. camel/models/ollama_model.py +4 -4
  98. camel/models/openai_audio_models.py +4 -4
  99. camel/models/openai_compatible_model.py +4 -4
  100. camel/models/openai_model.py +43 -4
  101. camel/models/qwen_model.py +4 -4
  102. camel/models/reka_model.py +4 -4
  103. camel/models/samba_model.py +6 -5
  104. camel/models/stub_model.py +4 -4
  105. camel/models/togetherai_model.py +4 -4
  106. camel/models/vllm_model.py +4 -4
  107. camel/models/yi_model.py +4 -4
  108. camel/models/zhipuai_model.py +4 -4
  109. camel/personas/__init__.py +17 -0
  110. camel/personas/persona.py +103 -0
  111. camel/personas/persona_hub.py +293 -0
  112. camel/prompts/__init__.py +6 -4
  113. camel/prompts/ai_society.py +4 -4
  114. camel/prompts/base.py +4 -4
  115. camel/prompts/code.py +4 -4
  116. camel/prompts/evaluation.py +4 -4
  117. camel/prompts/generate_text_embedding_data.py +4 -4
  118. camel/prompts/image_craft.py +4 -4
  119. camel/prompts/misalignment.py +4 -4
  120. camel/prompts/multi_condition_image_craft.py +4 -4
  121. camel/prompts/object_recognition.py +4 -4
  122. camel/prompts/persona_hub.py +61 -0
  123. camel/prompts/prompt_templates.py +4 -4
  124. camel/prompts/role_description_prompt_template.py +4 -4
  125. camel/prompts/solution_extraction.py +4 -4
  126. camel/prompts/task_prompt_template.py +4 -4
  127. camel/prompts/translation.py +4 -4
  128. camel/prompts/video_description_prompt.py +4 -4
  129. camel/responses/__init__.py +4 -4
  130. camel/responses/agent_responses.py +4 -4
  131. camel/retrievers/__init__.py +4 -4
  132. camel/retrievers/auto_retriever.py +4 -4
  133. camel/retrievers/base.py +4 -4
  134. camel/retrievers/bm25_retriever.py +4 -4
  135. camel/retrievers/cohere_rerank_retriever.py +7 -9
  136. camel/retrievers/vector_retriever.py +26 -9
  137. camel/runtime/__init__.py +29 -0
  138. camel/runtime/api.py +93 -0
  139. camel/runtime/base.py +45 -0
  140. camel/runtime/configs.py +56 -0
  141. camel/runtime/docker_runtime.py +404 -0
  142. camel/runtime/llm_guard_runtime.py +199 -0
  143. camel/runtime/remote_http_runtime.py +204 -0
  144. camel/runtime/utils/__init__.py +20 -0
  145. camel/runtime/utils/function_risk_toolkit.py +58 -0
  146. camel/runtime/utils/ignore_risk_toolkit.py +72 -0
  147. camel/schemas/__init__.py +17 -0
  148. camel/schemas/base.py +45 -0
  149. camel/schemas/openai_converter.py +116 -0
  150. camel/societies/__init__.py +4 -4
  151. camel/societies/babyagi_playing.py +8 -5
  152. camel/societies/role_playing.py +4 -4
  153. camel/societies/workforce/__init__.py +4 -4
  154. camel/societies/workforce/base.py +4 -4
  155. camel/societies/workforce/prompts.py +4 -4
  156. camel/societies/workforce/role_playing_worker.py +4 -4
  157. camel/societies/workforce/single_agent_worker.py +4 -4
  158. camel/societies/workforce/task_channel.py +4 -4
  159. camel/societies/workforce/utils.py +4 -4
  160. camel/societies/workforce/worker.py +4 -4
  161. camel/societies/workforce/workforce.py +7 -7
  162. camel/storages/__init__.py +4 -4
  163. camel/storages/graph_storages/__init__.py +4 -4
  164. camel/storages/graph_storages/base.py +4 -4
  165. camel/storages/graph_storages/graph_element.py +4 -4
  166. camel/storages/graph_storages/nebula_graph.py +4 -4
  167. camel/storages/graph_storages/neo4j_graph.py +4 -4
  168. camel/storages/key_value_storages/__init__.py +4 -4
  169. camel/storages/key_value_storages/base.py +4 -4
  170. camel/storages/key_value_storages/in_memory.py +4 -4
  171. camel/storages/key_value_storages/json.py +4 -4
  172. camel/storages/key_value_storages/redis.py +4 -4
  173. camel/storages/object_storages/__init__.py +4 -4
  174. camel/storages/object_storages/amazon_s3.py +4 -4
  175. camel/storages/object_storages/azure_blob.py +4 -4
  176. camel/storages/object_storages/base.py +4 -4
  177. camel/storages/object_storages/google_cloud.py +4 -4
  178. camel/storages/vectordb_storages/__init__.py +4 -4
  179. camel/storages/vectordb_storages/base.py +4 -4
  180. camel/storages/vectordb_storages/milvus.py +4 -4
  181. camel/storages/vectordb_storages/qdrant.py +4 -4
  182. camel/tasks/__init__.py +4 -4
  183. camel/tasks/task.py +4 -4
  184. camel/tasks/task_prompt.py +4 -4
  185. camel/terminators/__init__.py +4 -4
  186. camel/terminators/base.py +4 -4
  187. camel/terminators/response_terminator.py +4 -4
  188. camel/terminators/token_limit_terminator.py +4 -4
  189. camel/toolkits/__init__.py +16 -17
  190. camel/toolkits/arxiv_toolkit.py +4 -4
  191. camel/toolkits/ask_news_toolkit.py +7 -18
  192. camel/toolkits/base.py +4 -4
  193. camel/toolkits/code_execution.py +57 -10
  194. camel/toolkits/dalle_toolkit.py +4 -7
  195. camel/toolkits/data_commons_toolkit.py +4 -4
  196. camel/toolkits/function_tool.py +220 -69
  197. camel/toolkits/github_toolkit.py +4 -4
  198. camel/toolkits/google_maps_toolkit.py +4 -4
  199. camel/toolkits/google_scholar_toolkit.py +4 -4
  200. camel/toolkits/human_toolkit.py +53 -0
  201. camel/toolkits/linkedin_toolkit.py +4 -4
  202. camel/toolkits/math_toolkit.py +4 -7
  203. camel/toolkits/meshy_toolkit.py +185 -0
  204. camel/toolkits/notion_toolkit.py +4 -4
  205. camel/toolkits/open_api_specs/biztoc/__init__.py +4 -4
  206. camel/toolkits/open_api_specs/coursera/__init__.py +4 -4
  207. camel/toolkits/open_api_specs/create_qr_code/__init__.py +4 -4
  208. camel/toolkits/open_api_specs/klarna/__init__.py +4 -4
  209. camel/toolkits/open_api_specs/nasa_apod/__init__.py +4 -4
  210. camel/toolkits/open_api_specs/outschool/__init__.py +4 -4
  211. camel/toolkits/open_api_specs/outschool/paths/__init__.py +4 -4
  212. camel/toolkits/open_api_specs/outschool/paths/get_classes.py +4 -4
  213. camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +4 -4
  214. camel/toolkits/open_api_specs/security_config.py +4 -4
  215. camel/toolkits/open_api_specs/speak/__init__.py +4 -4
  216. camel/toolkits/open_api_specs/web_scraper/__init__.py +4 -4
  217. camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +4 -4
  218. camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +4 -4
  219. camel/toolkits/open_api_toolkit.py +4 -4
  220. camel/toolkits/reddit_toolkit.py +4 -4
  221. camel/toolkits/retrieval_toolkit.py +4 -4
  222. camel/toolkits/search_toolkit.py +49 -29
  223. camel/toolkits/slack_toolkit.py +4 -4
  224. camel/toolkits/twitter_toolkit.py +13 -13
  225. camel/toolkits/video_toolkit.py +211 -0
  226. camel/toolkits/weather_toolkit.py +4 -7
  227. camel/toolkits/whatsapp_toolkit.py +6 -6
  228. camel/types/__init__.py +6 -4
  229. camel/types/enums.py +118 -15
  230. camel/types/openai_types.py +6 -4
  231. camel/types/unified_model_type.py +9 -4
  232. camel/utils/__init__.py +35 -33
  233. camel/utils/async_func.py +4 -4
  234. camel/utils/commons.py +26 -9
  235. camel/utils/constants.py +4 -4
  236. camel/utils/response_format.py +63 -0
  237. camel/utils/token_counting.py +8 -5
  238. {camel_ai-0.2.9.dist-info → camel_ai-0.2.11.dist-info}/METADATA +108 -56
  239. camel_ai-0.2.11.dist-info/RECORD +252 -0
  240. camel_ai-0.2.9.dist-info/RECORD +0 -215
  241. {camel_ai-0.2.9.dist-info → camel_ai-0.2.11.dist-info}/LICENSE +0 -0
  242. {camel_ai-0.2.9.dist-info → camel_ai-0.2.11.dist-info}/WHEEL +0 -0
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import os
15
15
  import xml.etree.ElementTree as ET
16
16
  from typing import Any, Dict, List, Union
@@ -274,7 +274,7 @@ class SearchToolkit(BaseToolkit):
274
274
  """
275
275
  import wolframalpha
276
276
 
277
- WOLFRAMALPHA_APP_ID = os.environ.get('WOLFRAMALPHA_APP_ID')
277
+ WOLFRAMALPHA_APP_ID = os.environ.get("WOLFRAMALPHA_APP_ID")
278
278
  if not WOLFRAMALPHA_APP_ID:
279
279
  raise ValueError(
280
280
  "`WOLFRAMALPHA_APP_ID` not found in environment "
@@ -315,27 +315,42 @@ class SearchToolkit(BaseToolkit):
315
315
  """
316
316
 
317
317
  # Extract the original query
318
- query = result.get('@inputstring', '')
318
+ query = result.get("@inputstring", "")
319
319
 
320
320
  # Initialize a dictionary to hold structured output
321
321
  output = {"query": query, "pod_info": [], "final_answer": None}
322
322
 
323
323
  # Loop through each pod to extract the details
324
- for pod in result.get('pod', []):
324
+ for pod in result.get("pod", []):
325
+ # Handle the case where subpod might be a list
326
+ subpod_data = pod.get("subpod", {})
327
+ if isinstance(subpod_data, list):
328
+ # If it's a list, get the first item for 'plaintext' and 'img'
329
+ description, image_url = next(
330
+ (
331
+ (data["plaintext"], data["img"])
332
+ for data in subpod_data
333
+ if "plaintext" in data and "img" in data
334
+ ),
335
+ ("", ""),
336
+ )
337
+ else:
338
+ # Otherwise, handle it as a dictionary
339
+ description = subpod_data.get("plaintext", "")
340
+ image_url = subpod_data.get("img", {}).get("@src", "")
341
+
325
342
  pod_info = {
326
- "title": pod.get('@title', ''),
327
- "description": pod.get('subpod', {}).get('plaintext', ''),
328
- "image_url": pod.get('subpod', {})
329
- .get('img', {})
330
- .get('@src', ''),
343
+ "title": pod.get("@title", ""),
344
+ "description": description,
345
+ "image_url": image_url,
331
346
  }
332
347
 
333
348
  # Add to steps list
334
349
  output["pod_info"].append(pod_info)
335
350
 
336
351
  # Get final answer
337
- if pod.get('@primary', False):
338
- output["final_answer"] = pod_info["description"]
352
+ if pod.get("@primary", False):
353
+ output["final_answer"] = description
339
354
 
340
355
  return output
341
356
 
@@ -358,25 +373,33 @@ class SearchToolkit(BaseToolkit):
358
373
 
359
374
  # Set up the query parameters
360
375
  params = {
361
- 'appid': app_id,
362
- 'input': query,
363
- 'podstate': ['Result__Step-by-step solution', 'Show all steps'],
364
- 'format': 'plaintext',
376
+ "appid": app_id,
377
+ "input": query,
378
+ "podstate": ["Result__Step-by-step solution", "Show all steps"],
379
+ "format": "plaintext",
365
380
  }
366
381
 
367
382
  # Send the request
368
383
  response = requests.get(url, params=params)
369
384
  root = ET.fromstring(response.text)
370
385
 
371
- # Extracting step-by-step hints and removing 'Hint: |'
386
+ # Extracting step-by-step steps, including 'SBSStep' and 'SBSHintStep'
372
387
  steps = []
373
- for subpod in root.findall(
374
- ".//pod[@title='Results']//subpod[stepbystepcontenttype='SBSHintStep']//plaintext"
375
- ):
376
- if subpod.text:
377
- step_text = subpod.text.strip()
378
- cleaned_step = step_text.replace('Hint: |', '').strip()
379
- steps.append(cleaned_step)
388
+ # Find all subpods within the 'Results' pod
389
+ for subpod in root.findall(".//pod[@title='Results']//subpod"):
390
+ # Check if the subpod has the desired stepbystepcontenttype
391
+ content_type = subpod.find("stepbystepcontenttype")
392
+ if content_type is not None and content_type.text in [
393
+ "SBSStep",
394
+ "SBSHintStep",
395
+ ]:
396
+ plaintext = subpod.find("plaintext")
397
+ if plaintext is not None and plaintext.text:
398
+ step_text = plaintext.text.strip()
399
+ cleaned_step = step_text.replace(
400
+ "Hint: |", ""
401
+ ).strip() # Remove 'Hint: |' if present
402
+ steps.append(cleaned_step)
380
403
 
381
404
  # Structuring the steps into a dictionary
382
405
  structured_steps = {}
@@ -449,6 +472,3 @@ class SearchToolkit(BaseToolkit):
449
472
  FunctionTool(self.query_wolfram_alpha),
450
473
  FunctionTool(self.tavily_search),
451
474
  ]
452
-
453
-
454
- SEARCH_FUNCS: List[FunctionTool] = SearchToolkit().get_tools()
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
15
  from __future__ import annotations
16
16
 
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import datetime
15
15
  import os
16
16
  from http import HTTPStatus
@@ -20,12 +20,15 @@ from typing import Any, Dict, List, Optional, Union
20
20
  import requests
21
21
  from requests_oauthlib import OAuth1
22
22
 
23
+ from camel.logger import get_logger
23
24
  from camel.toolkits import FunctionTool
24
25
  from camel.toolkits.base import BaseToolkit
25
26
  from camel.utils import api_keys_required
26
27
 
27
28
  TWEET_TEXT_LIMIT = 280
28
29
 
30
+ logger = get_logger(__name__)
31
+
29
32
 
30
33
  @api_keys_required(
31
34
  "TWITTER_CONSUMER_KEY",
@@ -407,14 +410,6 @@ def _handle_http_error(response: requests.Response) -> str:
407
410
  return "Unexpected Exception"
408
411
 
409
412
 
410
- TWITTER_FUNCS = [
411
- FunctionTool(create_tweet),
412
- FunctionTool(delete_tweet),
413
- FunctionTool(get_my_user_profile),
414
- FunctionTool(get_user_by_username),
415
- ]
416
-
417
-
418
413
  class TwitterToolkit(BaseToolkit):
419
414
  r"""A class representing a toolkit for Twitter operations.
420
415
 
@@ -442,4 +437,9 @@ class TwitterToolkit(BaseToolkit):
442
437
  List[FunctionTool]: A list of FunctionTool objects
443
438
  representing the functions in the toolkit.
444
439
  """
445
- return TWITTER_FUNCS
440
+ return [
441
+ FunctionTool(create_tweet),
442
+ FunctionTool(delete_tweet),
443
+ FunctionTool(get_my_user_profile),
444
+ FunctionTool(get_user_by_username),
445
+ ]
@@ -0,0 +1,211 @@
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 io
16
+ import logging
17
+ import re
18
+ import tempfile
19
+ from pathlib import Path
20
+ from typing import List, Optional
21
+
22
+ from PIL import Image
23
+
24
+ from camel.toolkits.base import BaseToolkit
25
+ from camel.toolkits.function_tool import FunctionTool
26
+ from camel.utils import dependencies_required
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ def _standardize_url(url: str) -> str:
32
+ r"""Standardize the given URL."""
33
+ # Special case for YouTube embed URLs
34
+ if "youtube.com/embed/" in url:
35
+ match = re.search(r"embed/([a-zA-Z0-9_-]+)", url)
36
+ if match:
37
+ return f"https://www.youtube.com/watch?v={match.group(1)}"
38
+ else:
39
+ raise ValueError(f"Invalid YouTube URL: {url}")
40
+
41
+ return url
42
+
43
+
44
+ def _capture_screenshot(video_file: str, timestamp: float) -> Image.Image:
45
+ r"""Capture a screenshot from a video file at a specific timestamp.
46
+
47
+ Args:
48
+ video_file (str): The path to the video file.
49
+ timestamp (float): The time in seconds from which to capture the
50
+ screenshot.
51
+
52
+ Returns:
53
+ Image.Image: The captured screenshot in the form of Image.Image.
54
+ """
55
+ import ffmpeg
56
+
57
+ try:
58
+ out, _ = (
59
+ ffmpeg.input(video_file, ss=timestamp)
60
+ .filter('scale', 320, -1)
61
+ .output('pipe:', vframes=1, format='image2', vcodec='png')
62
+ .run(capture_stdout=True, capture_stderr=True)
63
+ )
64
+ except ffmpeg.Error as e:
65
+ raise RuntimeError(f"Failed to capture screenshot: {e.stderr}")
66
+
67
+ return Image.open(io.BytesIO(out))
68
+
69
+
70
+ class VideoDownloaderToolkit(BaseToolkit):
71
+ r"""A class for downloading videos and optionally splitting them into
72
+ chunks.
73
+
74
+ Args:
75
+ download_directory (Optional[str], optional): The directory where the
76
+ video will be downloaded to. If not provided, video will be stored
77
+ in a temporary directory and will be cleaned up after use.
78
+ (default: :obj:`None`)
79
+ cookies_path (Optional[str], optional): The path to the cookies file
80
+ for the video service in Netscape format. (default: :obj:`None`)
81
+ """
82
+
83
+ @dependencies_required("yt_dlp", "ffmpeg")
84
+ def __init__(
85
+ self,
86
+ download_directory: Optional[str] = None,
87
+ cookies_path: Optional[str] = None,
88
+ ) -> None:
89
+ self._cleanup = download_directory is None
90
+ self._cookies_path = cookies_path
91
+
92
+ self._download_directory = Path(
93
+ download_directory or tempfile.mkdtemp()
94
+ ).resolve()
95
+
96
+ try:
97
+ self._download_directory.mkdir(parents=True, exist_ok=True)
98
+ except FileExistsError:
99
+ raise ValueError(
100
+ f"{self._download_directory} is not a valid directory."
101
+ )
102
+ except OSError as e:
103
+ raise ValueError(
104
+ f"Error creating directory {self._download_directory}: {e}"
105
+ )
106
+
107
+ logger.info(f"Video will be downloaded to {self._download_directory}")
108
+
109
+ def __del__(self) -> None:
110
+ r"""Deconstructor for the VideoDownloaderToolkit class.
111
+
112
+ Cleans up the downloaded video if they are stored in a temporary
113
+ directory.
114
+ """
115
+ import shutil
116
+
117
+ if self._cleanup:
118
+ shutil.rmtree(self._download_directory, ignore_errors=True)
119
+
120
+ def _download_video(self, url: str) -> str:
121
+ r"""Download the video and optionally split it into chunks.
122
+
123
+ yt-dlp will detect if the video is downloaded automatically so there
124
+ is no need to check if the video exists.
125
+
126
+ Returns:
127
+ str: The path to the downloaded video file.
128
+ """
129
+ import yt_dlp
130
+
131
+ video_template = self._download_directory / "%(title)s.%(ext)s"
132
+ ydl_opts = {
133
+ 'format': 'bestvideo+bestaudio/best',
134
+ 'outtmpl': str(video_template),
135
+ 'force_generic_extractor': True,
136
+ 'cookiefile': self._cookies_path,
137
+ }
138
+
139
+ try:
140
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
141
+ # Download the video and get the filename
142
+ logger.info(f"Downloading video from {url}...")
143
+ info = ydl.extract_info(url, download=True)
144
+ return ydl.prepare_filename(info)
145
+ except yt_dlp.utils.DownloadError as e:
146
+ raise RuntimeError(f"Failed to download video from {url}: {e}")
147
+
148
+ def get_video_bytes(
149
+ self,
150
+ video_url: str,
151
+ ) -> bytes:
152
+ r"""Download video by the URL, and return the content in bytes.
153
+
154
+ Args:
155
+ video_url (str): The URL of the video to download.
156
+
157
+ Returns:
158
+ bytes: The video file content in bytes.
159
+ """
160
+ url = _standardize_url(video_url)
161
+ video_file = self._download_video(url)
162
+
163
+ with open(video_file, 'rb') as f:
164
+ video_bytes = f.read()
165
+
166
+ return video_bytes
167
+
168
+ def get_video_screenshots(
169
+ self, video_url: str, amount: int
170
+ ) -> List[Image.Image]:
171
+ r"""Capture screenshots from the video at specified timestamps or by
172
+ dividing the video into equal parts if an integer is provided.
173
+
174
+ Args:
175
+ video_url (str): The URL of the video to take screenshots.
176
+ amount (int): the amount of evenly split screenshots to capture.
177
+
178
+ Returns:
179
+ List[Image.Image]: A list of screenshots as Image.Image.
180
+ """
181
+ import ffmpeg
182
+
183
+ url = _standardize_url(video_url)
184
+ video_file = self._download_video(url)
185
+
186
+ # Get the video length
187
+ try:
188
+ probe = ffmpeg.probe(video_file)
189
+ video_length = float(probe['format']['duration'])
190
+ except ffmpeg.Error as e:
191
+ raise RuntimeError(f"Failed to determine video length: {e.stderr}")
192
+
193
+ interval = video_length / (amount + 1)
194
+ timestamps = [i * interval for i in range(1, amount + 1)]
195
+
196
+ images = [_capture_screenshot(video_file, ts) for ts in timestamps]
197
+
198
+ return images
199
+
200
+ def get_tools(self) -> List[FunctionTool]:
201
+ r"""Returns a list of FunctionTool objects representing the
202
+ functions in the toolkit.
203
+
204
+ Returns:
205
+ List[FunctionTool]: A list of FunctionTool objects representing
206
+ the functions in the toolkit.
207
+ """
208
+ return [
209
+ FunctionTool(self.get_video_bytes),
210
+ FunctionTool(self.get_video_screenshots),
211
+ ]
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import os
15
15
  from typing import List, Literal
16
16
 
@@ -168,6 +168,3 @@ class WeatherToolkit(BaseToolkit):
168
168
  return [
169
169
  FunctionTool(self.get_weather_data),
170
170
  ]
171
-
172
-
173
- WEATHER_FUNCS: List[FunctionTool] = WeatherToolkit().get_tools()
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
15
  import os
16
16
  from typing import Any, Dict, List, Union
@@ -163,11 +163,11 @@ class WhatsAppToolkit(BaseToolkit):
163
163
  return f"Failed to retrieve business profile: {e!s}"
164
164
 
165
165
  def get_tools(self) -> List[FunctionTool]:
166
- r"""Returns a list of OpenAIFunction objects representing the
166
+ r"""Returns a list of FunctionTool objects representing the
167
167
  functions in the toolkit.
168
168
 
169
169
  Returns:
170
- List[OpenAIFunction]: A list of OpenAIFunction objects for the
170
+ List[FunctionTool]: A list of FunctionTool objects for the
171
171
  toolkit methods.
172
172
  """
173
173
  return [
camel/types/__init__.py CHANGED
@@ -1,16 +1,16 @@
1
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
2
- # Licensed under the Apache License, Version 2.0 (the License);
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
3
  # you may not use this file except in compliance with the License.
4
4
  # You may obtain a copy of the License at
5
5
  #
6
6
  # http://www.apache.org/licenses/LICENSE-2.0
7
7
  #
8
8
  # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an AS IS BASIS,
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
10
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
- # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  from .enums import (
15
15
  AudioModelType,
16
16
  EmbeddingModelType,
@@ -40,6 +40,7 @@ from .openai_types import (
40
40
  Choice,
41
41
  CompletionUsage,
42
42
  NotGiven,
43
+ ParsedChatCompletion,
43
44
  )
44
45
  from .unified_model_type import UnifiedModelType
45
46
 
@@ -71,4 +72,5 @@ __all__ = [
71
72
  'UnifiedModelType',
72
73
  'NOT_GIVEN',
73
74
  'NotGiven',
75
+ 'ParsedChatCompletion',
74
76
  ]