camel-ai 0.2.13__py3-none-any.whl → 0.2.15__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 (72) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +362 -237
  3. camel/benchmarks/__init__.py +11 -1
  4. camel/benchmarks/apibank.py +560 -0
  5. camel/benchmarks/apibench.py +496 -0
  6. camel/benchmarks/gaia.py +2 -2
  7. camel/benchmarks/nexus.py +518 -0
  8. camel/datagen/__init__.py +21 -0
  9. camel/datagen/cotdatagen.py +448 -0
  10. camel/datagen/self_instruct/__init__.py +36 -0
  11. camel/datagen/self_instruct/filter/__init__.py +34 -0
  12. camel/datagen/self_instruct/filter/filter_function.py +208 -0
  13. camel/datagen/self_instruct/filter/filter_registry.py +56 -0
  14. camel/datagen/self_instruct/filter/instruction_filter.py +76 -0
  15. camel/datagen/self_instruct/self_instruct.py +393 -0
  16. camel/datagen/self_instruct/templates.py +384 -0
  17. camel/datahubs/huggingface.py +12 -2
  18. camel/datahubs/models.py +4 -2
  19. camel/embeddings/mistral_embedding.py +5 -1
  20. camel/embeddings/openai_compatible_embedding.py +6 -1
  21. camel/embeddings/openai_embedding.py +5 -1
  22. camel/interpreters/e2b_interpreter.py +5 -1
  23. camel/loaders/apify_reader.py +5 -1
  24. camel/loaders/chunkr_reader.py +5 -1
  25. camel/loaders/firecrawl_reader.py +0 -30
  26. camel/logger.py +11 -5
  27. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +4 -1
  28. camel/models/anthropic_model.py +5 -1
  29. camel/models/azure_openai_model.py +1 -2
  30. camel/models/cohere_model.py +5 -1
  31. camel/models/deepseek_model.py +5 -1
  32. camel/models/gemini_model.py +5 -1
  33. camel/models/groq_model.py +5 -1
  34. camel/models/mistral_model.py +5 -1
  35. camel/models/nemotron_model.py +5 -1
  36. camel/models/nvidia_model.py +5 -1
  37. camel/models/openai_model.py +28 -12
  38. camel/models/qwen_model.py +5 -1
  39. camel/models/reka_model.py +5 -1
  40. camel/models/reward/nemotron_model.py +5 -1
  41. camel/models/samba_model.py +5 -1
  42. camel/models/togetherai_model.py +5 -1
  43. camel/models/yi_model.py +5 -1
  44. camel/models/zhipuai_model.py +5 -1
  45. camel/retrievers/auto_retriever.py +8 -0
  46. camel/retrievers/vector_retriever.py +6 -3
  47. camel/schemas/__init__.py +2 -1
  48. camel/schemas/base.py +2 -4
  49. camel/schemas/openai_converter.py +5 -1
  50. camel/schemas/outlines_converter.py +249 -0
  51. camel/societies/role_playing.py +4 -4
  52. camel/societies/workforce/workforce.py +2 -2
  53. camel/storages/graph_storages/nebula_graph.py +119 -27
  54. camel/storages/graph_storages/neo4j_graph.py +138 -0
  55. camel/toolkits/__init__.py +2 -0
  56. camel/toolkits/arxiv_toolkit.py +20 -3
  57. camel/toolkits/function_tool.py +61 -61
  58. camel/toolkits/meshy_toolkit.py +5 -1
  59. camel/toolkits/notion_toolkit.py +1 -1
  60. camel/toolkits/openbb_toolkit.py +869 -0
  61. camel/toolkits/search_toolkit.py +91 -5
  62. camel/toolkits/stripe_toolkit.py +5 -1
  63. camel/toolkits/twitter_toolkit.py +24 -16
  64. camel/types/enums.py +10 -1
  65. camel/types/unified_model_type.py +5 -0
  66. camel/utils/__init__.py +4 -0
  67. camel/utils/commons.py +146 -42
  68. camel/utils/token_counting.py +1 -0
  69. {camel_ai-0.2.13.dist-info → camel_ai-0.2.15.dist-info}/METADATA +18 -7
  70. {camel_ai-0.2.13.dist-info → camel_ai-0.2.15.dist-info}/RECORD +72 -58
  71. {camel_ai-0.2.13.dist-info → camel_ai-0.2.15.dist-info}/LICENSE +0 -0
  72. {camel_ai-0.2.13.dist-info → camel_ai-0.2.15.dist-info}/WHEEL +0 -0
@@ -13,9 +13,10 @@
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import os
15
15
  import xml.etree.ElementTree as ET
16
- from typing import Any, Dict, List, Optional, TypeAlias, Union
16
+ from typing import Any, Dict, List, Literal, Optional, Type, TypeAlias, Union
17
17
 
18
18
  import requests
19
+ from pydantic import BaseModel
19
20
 
20
21
  from camel.toolkits.base import BaseToolkit
21
22
  from camel.toolkits.function_tool import FunctionTool
@@ -63,6 +64,82 @@ class SearchToolkit(BaseToolkit):
63
64
 
64
65
  return result
65
66
 
67
+ @dependencies_required("linkup")
68
+ @api_keys_required(
69
+ [
70
+ (None, "LINKUP_API_KEY"),
71
+ ]
72
+ )
73
+ def search_linkup(
74
+ self,
75
+ query: str,
76
+ depth: Literal["standard", "deep"] = "standard",
77
+ output_type: Literal[
78
+ "searchResults", "sourcedAnswer", "structured"
79
+ ] = "searchResults",
80
+ structured_output_schema: Union[Type[BaseModel], str, None] = None,
81
+ ) -> Dict[str, Any]:
82
+ r"""Search for a query in the Linkup API and return results in various
83
+ formats.
84
+
85
+ Args:
86
+ query (str): The search query.
87
+ depth (Literal["standard", "deep"]): The depth of the search.
88
+ "standard" for a straightforward search, "deep" for a more
89
+ comprehensive search.
90
+ output_type (Literal["searchResults", "sourcedAnswer",
91
+ "structured"]): The type of output:
92
+ - "searchResults" for raw search results,
93
+ - "sourcedAnswer" for an answer with supporting sources,
94
+ - "structured" for output based on a provided schema.
95
+ structured_output_schema (Union[Type[BaseModel], str, None]): If
96
+ `output_type` is "structured",specify the schema of the
97
+ output. Can be a Pydantic BaseModel or a JSON schema string.
98
+
99
+ Returns:
100
+ Dict[str, Any]: A dictionary representing the search result. The
101
+ structure depends on the `output_type`. If an error occurs,
102
+ returns an error message.
103
+ """
104
+ try:
105
+ from linkup import LinkupClient
106
+
107
+ # Initialize the Linkup client with the API key
108
+ LINKUP_API_KEY = os.getenv("LINKUP_API_KEY")
109
+ client = LinkupClient(api_key=LINKUP_API_KEY)
110
+
111
+ # Perform the search using the specified output_type
112
+ response = client.search(
113
+ query=query,
114
+ depth=depth,
115
+ output_type=output_type,
116
+ structured_output_schema=structured_output_schema,
117
+ )
118
+
119
+ if output_type == "searchResults":
120
+ results = [
121
+ item.__dict__
122
+ for item in response.__dict__.get('results', [])
123
+ ]
124
+ return {"results": results}
125
+
126
+ elif output_type == "sourcedAnswer":
127
+ answer = response.__dict__.get('answer', '')
128
+ sources = [
129
+ item.__dict__
130
+ for item in response.__dict__.get('sources', [])
131
+ ]
132
+ return {"answer": answer, "sources": sources}
133
+
134
+ elif output_type == "structured" and structured_output_schema:
135
+ return response.__dict__
136
+
137
+ else:
138
+ return {"error": f"Invalid output_type: {output_type}"}
139
+
140
+ except Exception as e:
141
+ return {"error": f"An unexpected error occurred: {e!s}"}
142
+
66
143
  @dependencies_required("duckduckgo_search")
67
144
  def search_duckduckgo(
68
145
  self, query: str, source: str = "text", max_results: int = 5
@@ -151,7 +228,11 @@ class SearchToolkit(BaseToolkit):
151
228
  # If no answer found, return an empty list
152
229
  return responses
153
230
 
154
- @api_keys_required("BRAVE_API_KEY")
231
+ @api_keys_required(
232
+ [
233
+ (None, 'BRAVE_API_KEY'),
234
+ ]
235
+ )
155
236
  def search_brave(
156
237
  self,
157
238
  q: str,
@@ -297,7 +378,12 @@ class SearchToolkit(BaseToolkit):
297
378
  data = response.json()["web"]
298
379
  return data
299
380
 
300
- @api_keys_required("GOOGLE_API_KEY", "SEARCH_ENGINE_ID")
381
+ @api_keys_required(
382
+ [
383
+ (None, 'GOOGLE_API_KEY'),
384
+ (None, 'SEARCH_ENGINE_ID'),
385
+ ]
386
+ )
301
387
  def search_google(
302
388
  self, query: str, num_result_pages: int = 5
303
389
  ) -> List[Dict[str, Any]]:
@@ -429,8 +515,7 @@ class SearchToolkit(BaseToolkit):
429
515
  if not WOLFRAMALPHA_APP_ID:
430
516
  raise ValueError(
431
517
  "`WOLFRAMALPHA_APP_ID` not found in environment "
432
- "variables. Get `WOLFRAMALPHA_APP_ID` here: "
433
- "`https://products.wolframalpha.com/api/`."
518
+ "variables. Get `WOLFRAMALPHA_APP_ID` here: `https://products.wolframalpha.com/api/`."
434
519
  )
435
520
 
436
521
  try:
@@ -618,6 +703,7 @@ class SearchToolkit(BaseToolkit):
618
703
  """
619
704
  return [
620
705
  FunctionTool(self.search_wiki),
706
+ FunctionTool(self.search_linkup),
621
707
  FunctionTool(self.search_google),
622
708
  FunctionTool(self.search_duckduckgo),
623
709
  FunctionTool(self.query_wolfram_alpha),
@@ -36,7 +36,11 @@ class StripeToolkit(BaseToolkit):
36
36
  logger (Logger): a logger to write logs.
37
37
  """
38
38
 
39
- @api_keys_required("STRIPE_API_KEY")
39
+ @api_keys_required(
40
+ [
41
+ (None, "STRIPE_API_KEY"),
42
+ ]
43
+ )
40
44
  def __init__(self, retries: int = 3):
41
45
  r"""Initializes the StripeToolkit with the specified number of
42
46
  retries.
@@ -31,10 +31,12 @@ logger = get_logger(__name__)
31
31
 
32
32
 
33
33
  @api_keys_required(
34
- "TWITTER_CONSUMER_KEY",
35
- "TWITTER_CONSUMER_SECRET",
36
- "TWITTER_ACCESS_TOKEN",
37
- "TWITTER_ACCESS_TOKEN_SECRET",
34
+ [
35
+ (None, "TWITTER_CONSUMER_KEY"),
36
+ (None, "TWITTER_CONSUMER_SECRET"),
37
+ (None, "TWITTER_ACCESS_TOKEN"),
38
+ (None, "TWITTER_ACCESS_TOKEN_SECRET"),
39
+ ]
38
40
  )
39
41
  def create_tweet(
40
42
  text: str,
@@ -132,10 +134,12 @@ def create_tweet(
132
134
 
133
135
 
134
136
  @api_keys_required(
135
- "TWITTER_CONSUMER_KEY",
136
- "TWITTER_CONSUMER_SECRET",
137
- "TWITTER_ACCESS_TOKEN",
138
- "TWITTER_ACCESS_TOKEN_SECRET",
137
+ [
138
+ (None, "TWITTER_CONSUMER_KEY"),
139
+ (None, "TWITTER_CONSUMER_SECRET"),
140
+ (None, "TWITTER_ACCESS_TOKEN"),
141
+ (None, "TWITTER_ACCESS_TOKEN_SECRET"),
142
+ ]
139
143
  )
140
144
  def delete_tweet(tweet_id: str) -> str:
141
145
  r"""Deletes a tweet with the specified ID for an authorized user.
@@ -187,10 +191,12 @@ def delete_tweet(tweet_id: str) -> str:
187
191
 
188
192
 
189
193
  @api_keys_required(
190
- "TWITTER_CONSUMER_KEY",
191
- "TWITTER_CONSUMER_SECRET",
192
- "TWITTER_ACCESS_TOKEN",
193
- "TWITTER_ACCESS_TOKEN_SECRET",
194
+ [
195
+ (None, "TWITTER_CONSUMER_KEY"),
196
+ (None, "TWITTER_CONSUMER_SECRET"),
197
+ (None, "TWITTER_ACCESS_TOKEN"),
198
+ (None, "TWITTER_ACCESS_TOKEN_SECRET"),
199
+ ]
194
200
  )
195
201
  def get_my_user_profile() -> str:
196
202
  r"""Retrieves the authenticated user's Twitter profile info.
@@ -214,10 +220,12 @@ def get_my_user_profile() -> str:
214
220
 
215
221
 
216
222
  @api_keys_required(
217
- "TWITTER_CONSUMER_KEY",
218
- "TWITTER_CONSUMER_SECRET",
219
- "TWITTER_ACCESS_TOKEN",
220
- "TWITTER_ACCESS_TOKEN_SECRET",
223
+ [
224
+ (None, "TWITTER_CONSUMER_KEY"),
225
+ (None, "TWITTER_CONSUMER_SECRET"),
226
+ (None, "TWITTER_ACCESS_TOKEN"),
227
+ (None, "TWITTER_ACCESS_TOKEN_SECRET"),
228
+ ]
221
229
  )
222
230
  def get_user_by_username(username: str) -> str:
223
231
  r"""Retrieves one user's Twitter profile info by username (handle).
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
+ O1 = "o1"
37
38
  O1_PREVIEW = "o1-preview"
38
39
  O1_MINI = "o1-mini"
39
40
 
@@ -153,9 +154,15 @@ class ModelType(UnifiedModelType, Enum):
153
154
  return self.value
154
155
  return "gpt-4o-mini"
155
156
 
157
+ @property
158
+ def support_native_structured_output(self) -> bool:
159
+ return self.is_openai
160
+
156
161
  @property
157
162
  def support_native_tool_calling(self) -> bool:
158
- return any([self.is_openai, self.is_gemini, self.is_mistral])
163
+ return any(
164
+ [self.is_openai, self.is_gemini, self.is_mistral, self.is_qwen]
165
+ )
159
166
 
160
167
  @property
161
168
  def is_openai(self) -> bool:
@@ -166,6 +173,7 @@ class ModelType(UnifiedModelType, Enum):
166
173
  ModelType.GPT_4_TURBO,
167
174
  ModelType.GPT_4O,
168
175
  ModelType.GPT_4O_MINI,
176
+ ModelType.O1,
169
177
  ModelType.O1_PREVIEW,
170
178
  ModelType.O1_MINI,
171
179
  }
@@ -452,6 +460,7 @@ class ModelType(UnifiedModelType, Enum):
452
460
  }:
453
461
  return 131_072
454
462
  elif self in {
463
+ ModelType.O1,
455
464
  ModelType.CLAUDE_2_1,
456
465
  ModelType.CLAUDE_3_OPUS,
457
466
  ModelType.CLAUDE_3_SONNET,
@@ -113,6 +113,11 @@ class UnifiedModelType(str):
113
113
  r"""Returns whether the model is a Qwen model."""
114
114
  return True
115
115
 
116
+ @property
117
+ def support_native_structured_output(self) -> bool:
118
+ r"""Returns whether the model supports native structured output."""
119
+ return False
120
+
116
121
  @property
117
122
  def support_native_tool_calling(self) -> bool:
118
123
  r"""Returns whether the model supports native tool calling."""
camel/utils/__init__.py CHANGED
@@ -19,8 +19,10 @@ from .commons import (
19
19
  check_server_running,
20
20
  create_chunks,
21
21
  dependencies_required,
22
+ download_github_subdirectory,
22
23
  download_tasks,
23
24
  func_string_to_callable,
25
+ generate_prompt_for_structured_output,
24
26
  get_first_int,
25
27
  get_prompt_template_key_words,
26
28
  get_pydantic_major_version,
@@ -78,4 +80,6 @@ __all__ = [
78
80
  "track_agent",
79
81
  "handle_http_error",
80
82
  "get_pydantic_model",
83
+ "download_github_subdirectory",
84
+ "generate_prompt_for_structured_output",
81
85
  ]
camel/utils/commons.py CHANGED
@@ -12,7 +12,6 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import importlib
15
- import logging
16
15
  import os
17
16
  import platform
18
17
  import re
@@ -22,6 +21,7 @@ import time
22
21
  import zipfile
23
22
  from functools import wraps
24
23
  from http import HTTPStatus
24
+ from pathlib import Path
25
25
  from typing import (
26
26
  Any,
27
27
  Callable,
@@ -30,6 +30,7 @@ from typing import (
30
30
  Mapping,
31
31
  Optional,
32
32
  Set,
33
+ Tuple,
33
34
  Type,
34
35
  TypeVar,
35
36
  cast,
@@ -40,19 +41,14 @@ import pydantic
40
41
  import requests
41
42
  from pydantic import BaseModel
42
43
 
43
- from camel.logger import get_logger
44
44
  from camel.types import TaskType
45
45
 
46
46
  from .constants import Constants
47
47
 
48
48
  F = TypeVar('F', bound=Callable[..., Any])
49
49
 
50
- logger = get_logger(__name__)
51
50
 
52
-
53
- def print_text_animated(
54
- text, delay: float = 0.02, end: str = "", log_level: int = logging.INFO
55
- ):
51
+ def print_text_animated(text, delay: float = 0.02, end: str = ""):
56
52
  r"""Prints the given text with an animated effect.
57
53
 
58
54
  Args:
@@ -61,22 +57,10 @@ def print_text_animated(
61
57
  (default: :obj:`0.02`)
62
58
  end (str, optional): The end character to print after each
63
59
  character of text. (default: :obj:`""`)
64
- log_level (int, optional): The log level to use.
65
- See https://docs.python.org/3/library/logging.html#levels
66
- (default: :obj:`logging.INFO`)
67
60
  """
68
- if logger.isEnabledFor(log_level):
69
- # timestamp and other prefixes
70
- logger.log(log_level, '')
71
-
72
- for char in text:
73
- print(char, end=end, flush=True)
74
- time.sleep(delay)
75
- # Close the log entry
76
- logger.log(log_level, '')
77
- else:
78
- # This may be relevant for logging frameworks
79
- logger.log(log_level, text)
61
+ for char in text:
62
+ print(char, end=end, flush=True)
63
+ time.sleep(delay)
80
64
 
81
65
 
82
66
  def get_prompt_template_key_words(template: str) -> Set[str]:
@@ -249,41 +233,79 @@ def is_module_available(module_name: str) -> bool:
249
233
  return False
250
234
 
251
235
 
252
- def api_keys_required(*required_keys: str) -> Callable[[F], F]:
253
- r"""A decorator to check if the required API keys are
254
- presented in the environment variables or as an instance attribute.
236
+ def api_keys_required(
237
+ param_env_list: List[Tuple[Optional[str], str]],
238
+ ) -> Callable[[F], F]:
239
+ r"""A decorator to check if the required API keys are provided in the
240
+ environment variables or as function arguments.
255
241
 
256
242
  Args:
257
- required_keys (str): The required API keys to be checked.
243
+ param_env_list (List[Tuple[Optional[str], str]]): A list of tuples
244
+ where each tuple contains a function argument name (as the first
245
+ element, or None) and the corresponding environment variable name
246
+ (as the second element) that holds the API key.
258
247
 
259
248
  Returns:
260
- Callable[[F], F]: The original function with the added check
261
- for required API keys.
249
+ Callable[[F], F]: The original function wrapped with the added check
250
+ for the required API keys.
262
251
 
263
252
  Raises:
264
- ValueError: If any of the required API keys are missing in the
265
- environment variables and the instance attribute.
253
+ ValueError: If any of the required API keys are missing, either
254
+ from the function arguments or environment variables.
266
255
 
267
256
  Example:
268
257
  ::
269
258
 
270
- @api_keys_required('API_KEY_1', 'API_KEY_2')
271
- def some_api_function():
272
- # Function implementation...
259
+ @api_keys_required([
260
+ ('api_key_arg', 'API_KEY_1'),
261
+ ('another_key_arg', 'API_KEY_2'),
262
+ (None, 'API_KEY_3'),
263
+ ])
264
+ def some_api_function(api_key_arg=None, another_key_arg=None):
265
+ # Function implementation that requires API keys
273
266
  """
267
+ import inspect
274
268
 
275
269
  def decorator(func: F) -> F:
276
270
  @wraps(func)
277
271
  def wrapper(*args: Any, **kwargs: Any) -> Any:
278
- missing_environment_keys = [
279
- k for k in required_keys if k not in os.environ
280
- ]
281
- if (
282
- not (args and getattr(args[0], '_api_key', None))
283
- and missing_environment_keys
284
- ):
272
+ signature = inspect.signature(func)
273
+ bound_arguments = signature.bind(*args, **kwargs)
274
+ bound_arguments.apply_defaults()
275
+ arguments = bound_arguments.arguments
276
+
277
+ missing_keys = []
278
+ for param_name, env_var_name in param_env_list:
279
+ if not isinstance(env_var_name, str):
280
+ raise TypeError(
281
+ f"Environment variable name must be a string, got"
282
+ f" {type(env_var_name)}"
283
+ )
284
+
285
+ value = None
286
+ if (
287
+ param_name
288
+ ): # If param_name is provided, check function argument first
289
+ if not isinstance(param_name, str):
290
+ raise TypeError(
291
+ f"Parameter name must be a string, "
292
+ f"got {type(param_name)}"
293
+ )
294
+ value = arguments.get(param_name)
295
+ # If we found a valid value in arguments, continue to next
296
+ # item
297
+ if value:
298
+ continue
299
+
300
+ # Check environment variable if no valid value found yet
301
+ value = os.environ.get(env_var_name)
302
+ if not value or value.strip() == "":
303
+ missing_keys.append(env_var_name)
304
+
305
+ if missing_keys:
285
306
  raise ValueError(
286
- f"Missing API keys: {', '.join(missing_environment_keys)}"
307
+ "Missing or empty required API keys in "
308
+ f"environment variables: {', '.join(missing_keys)}"
287
309
  )
288
310
  return func(*args, **kwargs)
289
311
 
@@ -406,7 +428,8 @@ def json_to_function_code(json_obj: Dict) -> str:
406
428
  }
407
429
 
408
430
  for prop in required:
409
- description = properties[prop]['description']
431
+ # if no description, return empty string
432
+ description = properties[prop].get('description', "")
410
433
  prop_type = properties[prop]['type']
411
434
  python_type = prop_to_python.get(prop_type, prop_type)
412
435
  args.append(f"{prop}: {python_type}")
@@ -624,3 +647,84 @@ def retry_request(
624
647
  time.sleep(delay)
625
648
  else:
626
649
  raise
650
+
651
+
652
+ def download_github_subdirectory(
653
+ repo: str, subdir: str, data_dir: Path, branch="main"
654
+ ):
655
+ r"""Download subdirectory of the Github repo of
656
+ the benchmark.
657
+
658
+ This function downloads all files and subdirectories from a
659
+ specified subdirectory of a GitHub repository and
660
+ saves them to a local directory.
661
+
662
+ Args:
663
+ repo (str): The name of the GitHub repository
664
+ in the format "owner/repo".
665
+ subdir (str): The path to the subdirectory
666
+ within the repository to download.
667
+ data_dir (Path): The local directory where
668
+ the files will be saved.
669
+ branch (str, optional): The branch of the repository to use.
670
+ Defaults to "main".
671
+ """
672
+ from tqdm import tqdm
673
+
674
+ api_url = (
675
+ f"https://api.github.com/repos/{repo}/contents/{subdir}?ref={branch}"
676
+ )
677
+ headers = {"Accept": "application/vnd.github.v3+json"}
678
+ response = requests.get(api_url, headers=headers)
679
+ response.raise_for_status()
680
+ files = response.json()
681
+ os.makedirs(data_dir, exist_ok=True)
682
+
683
+ for file in tqdm(files, desc="Downloading"):
684
+ file_path = data_dir / file["name"]
685
+
686
+ if file["type"] == "file":
687
+ file_url = file["download_url"]
688
+ file_response = requests.get(file_url)
689
+ with open(file_path, "wb") as f:
690
+ f.write(file_response.content)
691
+ elif file["type"] == "dir":
692
+ download_github_subdirectory(
693
+ repo, f'{subdir}/{file["name"]}', file_path, branch
694
+ )
695
+
696
+
697
+ def generate_prompt_for_structured_output(
698
+ response_format: Optional[Type[BaseModel]],
699
+ user_message: str,
700
+ ) -> str:
701
+ """
702
+ This function generates a prompt based on the provided Pydantic model and
703
+ user message.
704
+
705
+ Args:
706
+ response_format (Type[BaseModel]): The Pydantic model class.
707
+ user_message (str): The user message to be used in the prompt.
708
+
709
+ Returns:
710
+ str: A prompt string for the LLM.
711
+ """
712
+ if response_format is None:
713
+ return user_message
714
+
715
+ json_schema = response_format.model_json_schema()
716
+ sys_prompt = (
717
+ "Given the user message, please generate a JSON response adhering "
718
+ "to the following JSON schema:\n"
719
+ f"{json_schema}\n"
720
+ "Make sure the JSON response is valid and matches the EXACT structure "
721
+ "defined in the schema. Your result should only be a valid json "
722
+ "object, without any other text or comments.\n"
723
+ )
724
+ user_prompt = f"User message: {user_message}\n"
725
+
726
+ final_prompt = f"""
727
+ {sys_prompt}
728
+ {user_prompt}
729
+ """
730
+ return final_prompt
@@ -63,6 +63,7 @@ def get_model_encoding(value_for_tiktoken: str):
63
63
  encoding = tiktoken.encoding_for_model(value_for_tiktoken)
64
64
  except KeyError:
65
65
  if value_for_tiktoken in [
66
+ ModelType.O1.value,
66
67
  ModelType.O1_MINI.value,
67
68
  ModelType.O1_PREVIEW.value,
68
69
  ]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: camel-ai
3
- Version: 0.2.13
3
+ Version: 0.2.15
4
4
  Summary: Communicative Agents for AI Society Study
5
5
  Home-page: https://www.camel-ai.org/
6
6
  License: Apache-2.0
@@ -42,13 +42,13 @@ Requires-Dist: colorama (>=0,<1)
42
42
  Requires-Dist: curl_cffi (==0.6.2)
43
43
  Requires-Dist: datacommons (>=1.4.3,<2.0.0) ; extra == "tools" or extra == "all"
44
44
  Requires-Dist: datacommons_pandas (>=0.0.3,<0.0.4) ; extra == "tools" or extra == "all"
45
- Requires-Dist: datasets (>=2,<3) ; extra == "huggingface-agent" or extra == "all"
45
+ Requires-Dist: datasets (>=3,<4) ; extra == "huggingface-agent" or extra == "all"
46
46
  Requires-Dist: diffusers (>=0,<1) ; extra == "huggingface-agent" or extra == "all"
47
47
  Requires-Dist: discord.py (>=2.3.2,<3.0.0) ; extra == "tools" or extra == "all"
48
48
  Requires-Dist: docker (>=7.1.0,<8.0.0) ; extra == "tools" or extra == "runtime" or extra == "all"
49
49
  Requires-Dist: docstring-parser (>=0.15,<0.16)
50
50
  Requires-Dist: docx2txt (>=0.8,<0.9) ; extra == "tools" or extra == "all"
51
- Requires-Dist: duckduckgo-search (>=6.2.12,<7.0.0) ; extra == "search-tools" or extra == "tools" or extra == "all"
51
+ Requires-Dist: duckduckgo-search (>=6.3.5,<7.0.0) ; extra == "search-tools" or extra == "tools" or extra == "all"
52
52
  Requires-Dist: e2b-code-interpreter (>=1.0.3,<2.0.0) ; extra == "tools" or extra == "all"
53
53
  Requires-Dist: eval-type-backport (==0.2.0)
54
54
  Requires-Dist: ffmpeg-python (>=0.2.0,<0.3.0) ; extra == "tools" or extra == "all"
@@ -62,18 +62,21 @@ Requires-Dist: imageio[pyav] (>=2.34.2,<3.0.0) ; extra == "tools" or extra == "a
62
62
  Requires-Dist: ipykernel (>=6.0.0,<7.0.0) ; extra == "tools" or extra == "all"
63
63
  Requires-Dist: jsonschema (>=4,<5)
64
64
  Requires-Dist: jupyter_client (>=8.6.2,<9.0.0) ; extra == "tools" or extra == "all"
65
+ Requires-Dist: linkup-sdk (>=0.2.1,<0.3.0) ; extra == "search-tools" or extra == "tools" or extra == "all"
65
66
  Requires-Dist: litellm (>=1.38.1,<2.0.0) ; extra == "model-platforms" or extra == "all"
66
67
  Requires-Dist: mistralai (>=1.1.0,<2.0.0) ; extra == "model-platforms" or extra == "all"
67
68
  Requires-Dist: mock (>=5,<6) ; extra == "test"
68
69
  Requires-Dist: nebula3-python (==3.8.2) ; extra == "rag" or extra == "graph-storages" or extra == "all"
69
70
  Requires-Dist: neo4j (>=5.18.0,<6.0.0) ; extra == "rag" or extra == "graph-storages" or extra == "all"
70
71
  Requires-Dist: newspaper3k (>=0.2.8,<0.3.0) ; extra == "tools" or extra == "all"
71
- Requires-Dist: nltk (==3.9.1) ; extra == "tools" or extra == "all"
72
72
  Requires-Dist: notion-client (>=2.2.1,<3.0.0) ; extra == "tools" or extra == "all"
73
73
  Requires-Dist: numpy (>=1,<2)
74
- Requires-Dist: openai (>=1.45.0,<2.0.0)
74
+ Requires-Dist: openai (>=1.58.1,<2.0.0)
75
75
  Requires-Dist: openapi-spec-validator (>=0.7.1,<0.8.0) ; extra == "tools" or extra == "all"
76
+ Requires-Dist: openbb (>=4.3.5,<5.0.0) ; extra == "tools" or extra == "all"
76
77
  Requires-Dist: opencv-python (>=4,<5) ; extra == "huggingface-agent" or extra == "all"
78
+ Requires-Dist: outlines (>=0.1.7,<0.2.0) ; extra == "tools" or extra == "all"
79
+ Requires-Dist: pandas (>=2.2.3,<3.0.0) ; extra == "tools" or extra == "all"
77
80
  Requires-Dist: pandoc
78
81
  Requires-Dist: pathlib (>=1.0.1,<2.0.0)
79
82
  Requires-Dist: pdfplumber (>=0.11.0,<0.12.0) ; extra == "tools" or extra == "all"
@@ -95,6 +98,7 @@ Requires-Dist: rank-bm25 (>=0.2.2,<0.3.0) ; extra == "rag" or extra == "retrieve
95
98
  Requires-Dist: redis (>=5.0.6,<6.0.0) ; extra == "kv-stroages" or extra == "all"
96
99
  Requires-Dist: reka-api (>=3.0.8,<4.0.0) ; extra == "model-platforms" or extra == "all"
97
100
  Requires-Dist: requests_oauthlib (>=1.3.1,<2.0.0) ; extra == "tools" or extra == "all"
101
+ Requires-Dist: rouge (>=1.0.1,<2.0.0) ; extra == "tools" or extra == "all"
98
102
  Requires-Dist: scholarly[tor] (==1.7.11) ; extra == "tools" or extra == "all"
99
103
  Requires-Dist: sentence-transformers (>=3.0.1,<4.0.0) ; extra == "rag" or extra == "encoders" or extra == "all"
100
104
  Requires-Dist: sentencepiece (>=0,<1) ; extra == "huggingface-agent" or extra == "all"
@@ -109,7 +113,9 @@ Requires-Dist: tiktoken (>=0.7.0,<0.8.0)
109
113
  Requires-Dist: torch (==2.2.1) ; (platform_system == "Darwin" and platform_machine != "arm64") and (extra == "huggingface-agent" or extra == "all")
110
114
  Requires-Dist: torch (>=2,<3) ; (platform_system != "Darwin" or platform_machine == "arm64") and (extra == "huggingface-agent" or extra == "all")
111
115
  Requires-Dist: transformers (>=4,<5) ; extra == "huggingface-agent" or extra == "all"
112
- Requires-Dist: unstructured[all-docs] (==0.16.11) ; extra == "rag" or extra == "all"
116
+ Requires-Dist: tree-sitter (>=0.23.2,<0.24.0) ; extra == "tools" or extra == "all"
117
+ Requires-Dist: tree-sitter-python (>=0.23.6,<0.24.0) ; extra == "tools" or extra == "all"
118
+ Requires-Dist: unstructured[all-docs] (==0.16.11) ; extra == "rag" or extra == "tools" or extra == "all"
113
119
  Requires-Dist: wikipedia (>=1,<2) ; extra == "search-tools" or extra == "tools" or extra == "all"
114
120
  Requires-Dist: wolframalpha (>=5.0.0,<6.0.0) ; extra == "search-tools" or extra == "tools" or extra == "all"
115
121
  Requires-Dist: yt-dlp (>=2024.11.4,<2025.0.0) ; extra == "tools" or extra == "all"
@@ -263,7 +269,7 @@ conda create --name camel python=3.10
263
269
  conda activate camel
264
270
 
265
271
  # Clone github repo
266
- git clone -b v0.2.13 https://github.com/camel-ai/camel.git
272
+ git clone -b v0.2.15 https://github.com/camel-ai/camel.git
267
273
 
268
274
  # Change directory into project directory
269
275
  cd camel
@@ -444,6 +450,9 @@ Practical guides and tutorials for implementing specific functionalities in CAME
444
450
  | **[Customer Service Discord Bot with Agentic RAG](https://docs.camel-ai.org/cookbooks/customer_service_Discord_bot_with_agentic_RAG.html)** | Learn how to build a robust customer service bot for Discord using Agentic RAG. |
445
451
  | **[Create AI Agents that work with your PDFs using Chunkr & Mistral AI](https://docs.camel-ai.org/cookbooks/agent_with_chunkr_for_pdf_parsing.html)** | Learn how to create AI agents that work with your PDFs using Chunkr and Mistral AI. |
446
452
  | **[Data Gen with Real Function Calls and Hermes Format](https://docs.camel-ai.org/cookbooks/data_gen_with_real_function_calls_and_hermes_format.html)** | Explore how to generate data with real function calls and the Hermes format. |
453
+ | **[CoT Data Generation and Upload Data to Huggingface](https://docs.camel-ai.org/cookbooks/cot_data_gen_upload_to_huggingface.html)** | Uncover how to generate CoT data with CAMEL and seamlessly upload it to Huggingface. |
454
+ | **[CoT Data Generation and SFT Qwen with Unsolth, Uploading Data and Model to Hugging Face](https://docs.camel-ai.org/cookbooks/cot_data_gen_sft_qwen_unsolth_upload_huggingface.html)** | Discover how to generate CoT data using CAMEL and SFT Qwen with Unsolth, and seamlessly upload your data and model to Huggingface. |
455
+ | **[Customer Service Discord Bot with Agentic RAG supports local model deployment](https://docs.camel-ai.org/cookbooks/customer_service_Discord_bot_using_local_model_with_agentic_RAG.html)** | Learn how to build a robust customer service bot for Discord using Agentic RAG which supports local deployment. |
447
456
 
448
457
  ## Utilize Various LLMs as Backends
449
458
 
@@ -473,6 +482,8 @@ We implemented amazing research ideas from other works for you to build, compare
473
482
 
474
483
  - `PersonaHub` from *Tao Ge et al.*: [Scaling Synthetic Data Creation with 1,000,000,000 Personas](https://arxiv.org/pdf/2406.20094). [[Example](https://github.com/camel-ai/camel/blob/master/examples/personas/personas_generation.py)]
475
484
 
485
+ - `Self-Instruct` from *Yizhong Wang et al.*: [SELF-INSTRUCT: Aligning Language Models with Self-Generated Instructions](https://arxiv.org/pdf/2212.10560). [[Example](https://github.com/camel-ai/camel/blob/master/examples/datagen/self_instruct/self_instruct.py)]
486
+
476
487
  ## Other Research Works Based on Camel
477
488
  - [Agent Trust](http://agent-trust.camel-ai.org/): Can Large Language Model Agents Simulate Human Trust Behavior?
478
489