camel-ai 0.2.35__py3-none-any.whl → 0.2.37__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 (59) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/__init__.py +2 -0
  3. camel/agents/repo_agent.py +579 -0
  4. camel/configs/__init__.py +3 -0
  5. camel/configs/aiml_config.py +20 -19
  6. camel/configs/anthropic_config.py +25 -27
  7. camel/configs/cohere_config.py +11 -10
  8. camel/configs/deepseek_config.py +16 -16
  9. camel/configs/gemini_config.py +8 -8
  10. camel/configs/groq_config.py +18 -19
  11. camel/configs/internlm_config.py +8 -8
  12. camel/configs/litellm_config.py +26 -24
  13. camel/configs/mistral_config.py +8 -8
  14. camel/configs/moonshot_config.py +11 -11
  15. camel/configs/nvidia_config.py +13 -13
  16. camel/configs/ollama_config.py +14 -15
  17. camel/configs/openai_config.py +3 -3
  18. camel/configs/openrouter_config.py +106 -0
  19. camel/configs/qwen_config.py +8 -8
  20. camel/configs/reka_config.py +12 -11
  21. camel/configs/samba_config.py +14 -14
  22. camel/configs/sglang_config.py +15 -16
  23. camel/configs/siliconflow_config.py +18 -17
  24. camel/configs/togetherai_config.py +18 -19
  25. camel/configs/vllm_config.py +18 -19
  26. camel/configs/yi_config.py +7 -8
  27. camel/configs/zhipuai_config.py +8 -9
  28. camel/datasets/few_shot_generator.py +2 -5
  29. camel/datasets/static_dataset.py +25 -23
  30. camel/environments/models.py +3 -0
  31. camel/environments/single_step.py +212 -132
  32. camel/extractors/__init__.py +16 -1
  33. camel/memories/agent_memories.py +2 -1
  34. camel/memories/blocks/chat_history_block.py +2 -1
  35. camel/models/__init__.py +2 -0
  36. camel/models/gemini_model.py +36 -0
  37. camel/models/groq_model.py +6 -3
  38. camel/models/model_factory.py +3 -0
  39. camel/models/openrouter_model.py +204 -0
  40. camel/storages/__init__.py +2 -0
  41. camel/storages/key_value_storages/__init__.py +2 -0
  42. camel/storages/key_value_storages/mem0_cloud.py +224 -0
  43. camel/storages/vectordb_storages/qdrant.py +3 -3
  44. camel/toolkits/__init__.py +2 -0
  45. camel/toolkits/browser_toolkit.py +43 -0
  46. camel/toolkits/code_execution.py +2 -1
  47. camel/toolkits/mcp_toolkit.py +30 -1
  48. camel/toolkits/thinking_toolkit.py +74 -0
  49. camel/types/enums.py +27 -0
  50. camel/types/unified_model_type.py +5 -0
  51. camel/utils/chunker/code_chunker.py +9 -15
  52. camel/verifiers/__init__.py +1 -2
  53. camel/verifiers/base.py +159 -99
  54. camel/verifiers/models.py +0 -12
  55. camel/verifiers/python_verifier.py +316 -60
  56. {camel_ai-0.2.35.dist-info → camel_ai-0.2.37.dist-info}/METADATA +54 -5
  57. {camel_ai-0.2.35.dist-info → camel_ai-0.2.37.dist-info}/RECORD +59 -54
  58. {camel_ai-0.2.35.dist-info → camel_ai-0.2.37.dist-info}/WHEEL +0 -0
  59. {camel_ai-0.2.35.dist-info → camel_ai-0.2.37.dist-info}/licenses/LICENSE +0 -0
@@ -12,18 +12,21 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
 
15
+ import ast
15
16
  import asyncio
16
17
  import os
17
18
  import shutil
18
19
  import subprocess
20
+ import sys
19
21
  import tempfile
20
22
  import venv
21
- from typing import List, Optional
23
+ from typing import List, Optional, Tuple
22
24
 
25
+ from camel.extractors.base import BaseExtractor
23
26
  from camel.logger import get_logger
24
27
  from camel.verifiers import BaseVerifier
25
28
 
26
- from .models import VerificationOutcome, VerificationResult, VerifierInput
29
+ from .models import VerificationOutcome, VerificationResult
27
30
 
28
31
  logger = get_logger(__name__)
29
32
 
@@ -45,12 +48,16 @@ class PythonVerifier(BaseVerifier):
45
48
 
46
49
  def __init__(
47
50
  self,
51
+ extractor: Optional[BaseExtractor] = None,
48
52
  timeout: Optional[float] = 30.0,
49
53
  required_packages: Optional[List[str]] = None,
54
+ **kwargs,
50
55
  ):
51
56
  r"""Initializes the PythonVerifier.
52
57
 
53
58
  Args:
59
+ extractor (Optional[BaseExtractor], optional): The extractor to use
60
+ for extracting code from the solution. (default: :obj:`None`)
54
61
  timeout (Optional[float], optional): The execution timeout in
55
62
  seconds. (default: :obj:`30.0`)
56
63
  required_packages (Optional[List[str]], optional): A list of
@@ -58,7 +65,7 @@ class PythonVerifier(BaseVerifier):
58
65
  (default: :obj:`None`)
59
66
  """
60
67
  # TODO: Use CAMEL's Interpreter to execute the code
61
- super().__init__(timeout=timeout)
68
+ super().__init__(extractor=extractor, timeout=timeout, **kwargs)
62
69
  self.venv_path: Optional[str] = None
63
70
  self.required_packages = required_packages or []
64
71
 
@@ -67,25 +74,39 @@ class PythonVerifier(BaseVerifier):
67
74
  else: # Unix-like systems
68
75
  self.bin_dir = 'bin'
69
76
 
70
- async def _setup(self) -> None:
71
- r"""Set up a virtual environment for execution
72
- and install required packages.
73
- """
77
+ async def _setup(self, **kwargs) -> None:
78
+ r"""Set up a virtual environment and install required packages."""
79
+ uv = kwargs.get('uv', False)
80
+ if uv or self._is_uv_environment():
81
+ logger.info("[UV] Detected uv environment. Using uv for setup.")
82
+ self._setup_with_uv()
83
+ return
84
+
74
85
  self.venv_path = tempfile.mkdtemp()
75
- venv.create(self.venv_path, with_pip=True)
76
- logger.info(f"Virtual environment created at {self.venv_path}")
86
+ try:
87
+ venv.create(self.venv_path, with_pip=True)
88
+ logger.info(f"Virtual environment created at {self.venv_path}")
89
+ except Exception as e:
90
+ logger.error(f"Failed to create virtual environment: {e}")
91
+ # Clean up resources before re-raising
92
+ if self.venv_path and os.path.exists(self.venv_path):
93
+ shutil.rmtree(self.venv_path)
94
+ self.venv_path = None
95
+ raise
77
96
 
78
97
  venv_pip = os.path.join(self.venv_path, self.bin_dir, "pip")
79
98
 
80
99
  if self.required_packages:
81
100
  try:
101
+ # Add timeout to subprocess call
82
102
  subprocess.run(
83
103
  [venv_pip, "install", *self.required_packages],
84
104
  check=True,
85
105
  capture_output=True,
106
+ timeout=self._timeout,
86
107
  )
87
108
  logger.info(
88
- "Installed required packages:"
109
+ "Installed required packages: "
89
110
  f"{', '.join(self.required_packages)}"
90
111
  )
91
112
  except subprocess.CalledProcessError as e:
@@ -93,6 +114,97 @@ class PythonVerifier(BaseVerifier):
93
114
  "Failed to install required packages: "
94
115
  f"{e.stderr.decode().strip()}"
95
116
  )
117
+ # Clean up resources before re-raising
118
+ if self.venv_path and os.path.exists(self.venv_path):
119
+ shutil.rmtree(self.venv_path)
120
+ self.venv_path = None
121
+ raise
122
+ except subprocess.TimeoutExpired:
123
+ logger.error(
124
+ f"Package installation timed out "
125
+ f"after {self._timeout} seconds"
126
+ )
127
+ if self.venv_path and os.path.exists(self.venv_path):
128
+ shutil.rmtree(self.venv_path)
129
+ self.venv_path = None
130
+ raise
131
+
132
+ def _is_uv_environment(self) -> bool:
133
+ r"""Detect whether the current Python runtime is managed by uv."""
134
+ return "UV_CACHE_DIR" in os.environ or "uv" in sys.executable
135
+
136
+ def _setup_with_uv(self) -> None:
137
+ r"""Create virtual environment and install packages using uv."""
138
+ self.venv_path = tempfile.mkdtemp()
139
+ try:
140
+ subprocess.run(
141
+ ["uv", "venv", self.venv_path],
142
+ check=True,
143
+ capture_output=True,
144
+ timeout=self._timeout,
145
+ )
146
+ logger.info(
147
+ f"[UV] Virtual environment created at {self.venv_path}"
148
+ )
149
+ except subprocess.CalledProcessError as e:
150
+ logger.error(
151
+ "[UV] Failed to create virtual environment:\n"
152
+ f"{e.stderr.decode().strip()}"
153
+ )
154
+ # Clean up resources before re-raising
155
+ if self.venv_path and os.path.exists(self.venv_path):
156
+ shutil.rmtree(self.venv_path)
157
+ self.venv_path = None
158
+ raise
159
+ except subprocess.TimeoutExpired:
160
+ logger.error(
161
+ f"[UV] Virtual environment creation timed "
162
+ f"out after {self._timeout} seconds"
163
+ )
164
+ if self.venv_path and os.path.exists(self.venv_path):
165
+ shutil.rmtree(self.venv_path)
166
+ self.venv_path = None
167
+ raise
168
+
169
+ if self.required_packages:
170
+ venv_python = os.path.join(self.venv_path, self.bin_dir, "python")
171
+ try:
172
+ subprocess.run(
173
+ [
174
+ "uv",
175
+ "pip",
176
+ "install",
177
+ "--python",
178
+ venv_python,
179
+ *self.required_packages,
180
+ ],
181
+ check=True,
182
+ capture_output=True,
183
+ timeout=self._timeout,
184
+ )
185
+ logger.info(
186
+ "[UV] Installed required packages via uv: "
187
+ f"{', '.join(self.required_packages)}"
188
+ )
189
+ except subprocess.CalledProcessError as e:
190
+ logger.error(
191
+ "[UV] Failed to install required packages via uv:\n"
192
+ f"{e.stderr.decode().strip()}"
193
+ )
194
+ # Clean up resources before re-raising
195
+ if self.venv_path and os.path.exists(self.venv_path):
196
+ shutil.rmtree(self.venv_path)
197
+ self.venv_path = None
198
+ raise
199
+ except subprocess.TimeoutExpired:
200
+ logger.error(
201
+ f"[UV] Package installation timed "
202
+ f"out after {self._timeout} seconds"
203
+ )
204
+ if self.venv_path and os.path.exists(self.venv_path):
205
+ shutil.rmtree(self.venv_path)
206
+ self.venv_path = None
207
+ raise
96
208
 
97
209
  async def _cleanup(self) -> None:
98
210
  r"""Clean up the virtual environment."""
@@ -102,25 +214,29 @@ class PythonVerifier(BaseVerifier):
102
214
  self.venv_path = None
103
215
 
104
216
  async def _verify_implementation(
105
- self, result: VerifierInput
217
+ self, solution: str, ground_truth: Optional[str]
106
218
  ) -> VerificationResult:
107
- r"""Executes the LLM-generated response in a Python virtual
108
- environment.
219
+ r"""Executes the provided Python solution in an isolated environment
220
+ and verifies its output against an expected ground truth expression.
221
+
222
+ This method runs the solution in a subprocess inside a virtual
223
+ environment. The ground truth is assumed to be a pure Python
224
+ expression and is evaluated directly in the verifier process.
225
+
226
+ If both executions are successful, the actual output is compared
227
+ against the evaluated ground truth using semantic equality. If
228
+ evaluation fails, string comparison is used as a fallback.
109
229
 
110
230
  Args:
111
- result (VerifierInput): Contains the LLM-generated Python code to
112
- execute and optional ground truth for comparison.
231
+ solution (str): The Python code or expression to execute and
232
+ verify.
233
+ ground_truth (Optional[str]): The expected value as a Python
234
+ expression. If None, only execution success is verified.
113
235
 
114
236
  Returns:
115
- VerificationResult: Contains verification status (SUCCESS/FAILURE/
116
- ERROR), execution output, error messages if any, and execution
117
- duration.
118
-
119
- Raises:
120
- asyncio.TimeoutError: If execution exceeds the configured timeout.
121
- Exception: Any unexpected errors during execution are caught and
122
- converted to an ERROR verification result.
237
+ VerificationResult: Result of the verification process.
123
238
  """
239
+ # Check for virtual environment setup
124
240
  if not self.venv_path:
125
241
  return VerificationResult(
126
242
  status=VerificationOutcome.ERROR,
@@ -128,9 +244,47 @@ class PythonVerifier(BaseVerifier):
128
244
  error_message="Virtual environment is not set up.",
129
245
  )
130
246
 
131
- script = result.llm_response.strip()
132
- venv_python = os.path.join(self.venv_path, self.bin_dir, "python")
247
+ # If the solution is an expression, evaluate it directly
248
+ if self._is_expression(solution):
249
+ try:
250
+ sol_val = ast.literal_eval(solution)
251
+ except Exception as e:
252
+ return VerificationResult(
253
+ status=VerificationOutcome.ERROR,
254
+ result="",
255
+ error_message=f"Expression evaluation error: {e}",
256
+ )
133
257
 
258
+ if ground_truth is not None:
259
+ try:
260
+ gt_val = ast.literal_eval(ground_truth)
261
+ except Exception as e:
262
+ return VerificationResult(
263
+ status=VerificationOutcome.ERROR,
264
+ result="",
265
+ error_message=f"Ground truth evaluation error: {e}",
266
+ )
267
+ if sol_val == gt_val:
268
+ return VerificationResult(
269
+ status=VerificationOutcome.SUCCESS,
270
+ result=str(sol_val),
271
+ )
272
+ else:
273
+ return VerificationResult(
274
+ status=VerificationOutcome.FAILURE,
275
+ result=str(sol_val),
276
+ error_message="Output mismatch: "
277
+ f"{sol_val} != {gt_val}",
278
+ )
279
+ else:
280
+ return VerificationResult(
281
+ status=VerificationOutcome.SUCCESS,
282
+ result=str(sol_val),
283
+ )
284
+
285
+ # Otherwise, run the code block,
286
+ # which should already include a print(...) in the end
287
+ venv_python = os.path.join(self.venv_path, self.bin_dir, "python")
134
288
  if not os.path.exists(venv_python):
135
289
  return VerificationResult(
136
290
  status=VerificationOutcome.ERROR,
@@ -139,64 +293,166 @@ class PythonVerifier(BaseVerifier):
139
293
  )
140
294
 
141
295
  try:
142
- process = await asyncio.create_subprocess_exec(
143
- venv_python,
144
- "-c",
145
- script,
146
- stdout=asyncio.subprocess.PIPE,
147
- stderr=asyncio.subprocess.PIPE,
148
- )
149
-
150
- stdout, stderr = await asyncio.wait_for(
151
- process.communicate(), timeout=self._timeout
296
+ sol_out, sol_err, sol_code = await self._run_code_block(
297
+ solution, venv_python
152
298
  )
299
+ if sol_code != 0:
300
+ return VerificationResult(
301
+ status=VerificationOutcome.ERROR,
302
+ result=sol_out,
303
+ error_message=f"Solution code error:\n{sol_err}",
304
+ )
153
305
 
154
- output_result = stdout.decode().strip()
155
- error_output = stderr.decode().strip()
156
-
157
- if process.returncode == 0:
158
- # If ground truth is provided, compare it with the result
159
- if result.ground_truth is not None:
160
- # Normalize both strings by removing extra whitespace
161
- normalized_output = ' '.join(output_result.strip().split())
162
- normalized_truth = ' '.join(
163
- str(result.ground_truth).strip().split()
306
+ if ground_truth is not None:
307
+ try:
308
+ # First, try to evaluate the output as-is.
309
+ sol_val = ast.literal_eval(sol_out)
310
+ except Exception as e:
311
+ logger.warning(
312
+ f"Direct eval failed: {e}. Trying repr on output."
164
313
  )
314
+ try:
315
+ # Try to convert sol_out to a literal
316
+ # by wrapping it with repr.
317
+ # FIXME: may be unnecessary
318
+ sol_val = ast.literal_eval(repr(sol_out))
319
+ except Exception as e2:
320
+ logger.warning(
321
+ f"repr eval also failed: {e2}."
322
+ "Falling back to string comparison."
323
+ )
324
+ sol_val = None
165
325
 
166
- if normalized_output == normalized_truth:
326
+ if sol_val is not None:
327
+ try:
328
+ gt_val = ast.literal_eval(ground_truth)
329
+ except Exception as e:
330
+ return VerificationResult(
331
+ status=VerificationOutcome.ERROR,
332
+ result="",
333
+ error_message="Ground truth evaluation error:"
334
+ f"{e}",
335
+ )
336
+ if sol_val == gt_val:
167
337
  return VerificationResult(
168
338
  status=VerificationOutcome.SUCCESS,
169
- result=output_result,
339
+ result=sol_out,
170
340
  )
171
341
  else:
172
342
  return VerificationResult(
173
343
  status=VerificationOutcome.FAILURE,
174
- error_message="Output doesn't match ground truth",
175
- result=output_result,
344
+ result=sol_out,
345
+ error_message="Output mismatch: "
346
+ f"{sol_val} != {gt_val}",
176
347
  )
177
348
  else:
178
- return VerificationResult(
179
- status=VerificationOutcome.SUCCESS,
180
- result=output_result,
181
- )
182
-
349
+ # Fallback: string comparison
350
+ if sol_out.strip() == ground_truth.strip():
351
+ return VerificationResult(
352
+ status=VerificationOutcome.SUCCESS,
353
+ result=sol_out,
354
+ )
355
+ else:
356
+ return VerificationResult(
357
+ status=VerificationOutcome.FAILURE,
358
+ result=sol_out,
359
+ error_message="Fallback string mismatch: "
360
+ f"'{sol_out}' != '{ground_truth}'",
361
+ )
183
362
  else:
184
363
  return VerificationResult(
185
- status=VerificationOutcome.ERROR,
186
- error_message=error_output,
187
- result=output_result,
364
+ status=VerificationOutcome.SUCCESS,
365
+ result=sol_out,
188
366
  )
189
-
190
367
  except asyncio.TimeoutError:
191
368
  return VerificationResult(
192
369
  status=VerificationOutcome.TIMEOUT,
193
370
  result="",
194
371
  error_message="Execution timed out.",
195
372
  )
196
-
197
373
  except Exception as e:
198
374
  return VerificationResult(
199
375
  status=VerificationOutcome.ERROR,
200
376
  result="",
201
- error_message=f"Execution error: {e}",
377
+ error_message=f"Unexpected error: {e}",
202
378
  )
379
+
380
+ async def _run_code_block(
381
+ self, code: str, venv_path: str
382
+ ) -> Tuple[str, str, int]:
383
+ r"""Executes a block of Python code in the virtual environment.
384
+
385
+ The code is written to a temporary file, executed using the Python
386
+ interpreter from the specified virtual environment, and
387
+ its output and error streams are captured.
388
+
389
+ Args:
390
+ code (str): The Python code to execute.
391
+ venv_path (str): The path to the virtual environment's Python
392
+ binary.
393
+
394
+ Returns:
395
+ Tuple[str, str, int]: A tuple containing the stdout output,
396
+ stderr output, and return code from the executed script.
397
+ """
398
+ # No longer checking for expressions since they're handled separately
399
+ with tempfile.NamedTemporaryFile(
400
+ "w+", suffix=".py", delete=False
401
+ ) as tmp:
402
+ tmp.write(code)
403
+ tmp_path = tmp.name
404
+
405
+ proc = await asyncio.create_subprocess_exec(
406
+ venv_path,
407
+ tmp_path,
408
+ stdout=asyncio.subprocess.PIPE,
409
+ stderr=asyncio.subprocess.PIPE,
410
+ )
411
+ stdout, stderr = await asyncio.wait_for(
412
+ proc.communicate(), timeout=self._timeout
413
+ )
414
+ os.remove(tmp_path)
415
+ return (
416
+ stdout.decode().strip(),
417
+ stderr.decode().strip(),
418
+ proc.returncode if proc.returncode is not None else -1,
419
+ )
420
+
421
+ def _is_expression(self, code: str) -> bool:
422
+ r"""Determines whether a given string of code is a single expression.
423
+
424
+ This utility uses Python's AST module to parse the code and checks if
425
+ it consists of a single expression node.
426
+
427
+ Args:
428
+ code (str): The Python code to analyze.
429
+
430
+ Returns:
431
+ bool: True if the code is a single expression, False otherwise.
432
+ """
433
+ # Skip empty or whitespace-only strings
434
+ if not code or code.isspace():
435
+ return False
436
+
437
+ try:
438
+ # First try parsing as an expression - this is more reliable than
439
+ # starting with literal_eval
440
+ tree = ast.parse(code.strip(), mode='eval')
441
+ # Check if it's a function call (like print()) - these should not
442
+ # be treated as expressions
443
+ if isinstance(tree.body, ast.Call):
444
+ return False
445
+ # If parsing succeeds in 'eval' mode and it's not a function call,
446
+ # it's a valid expression
447
+ return True
448
+ except SyntaxError:
449
+ # If parsing as expression fails, it's not a valid expression
450
+ return False
451
+ except Exception:
452
+ # For any other parsing errors, try literal_eval as fallback for
453
+ # simple literals
454
+ try:
455
+ ast.literal_eval(code)
456
+ return True
457
+ except Exception:
458
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: camel-ai
3
- Version: 0.2.35
3
+ Version: 0.2.37
4
4
  Summary: Communicative Agents for AI Society Study
5
5
  Project-URL: Homepage, https://www.camel-ai.org/
6
6
  Project-URL: Repository, https://github.com/camel-ai/camel
@@ -58,6 +58,7 @@ Requires-Dist: jupyter-client<9,>=8.6.2; extra == 'all'
58
58
  Requires-Dist: linkup-sdk<0.3,>=0.2.1; extra == 'all'
59
59
  Requires-Dist: litellm<2,>=1.38.1; extra == 'all'
60
60
  Requires-Dist: mcp>=1.3.0; extra == 'all'
61
+ Requires-Dist: mem0ai>=0.1.67; extra == 'all'
61
62
  Requires-Dist: mistralai<2,>=1.1.0; extra == 'all'
62
63
  Requires-Dist: mock<6,>=5; extra == 'all'
63
64
  Requires-Dist: mypy<2,>=1.5.1; extra == 'all'
@@ -78,7 +79,7 @@ Requires-Dist: prance<24,>=23.6.21.0; extra == 'all'
78
79
  Requires-Dist: praw<8,>=7.7.1; extra == 'all'
79
80
  Requires-Dist: pre-commit<4,>=3; extra == 'all'
80
81
  Requires-Dist: pydub<0.26,>=0.25.1; extra == 'all'
81
- Requires-Dist: pygithub<3,>=2.3.0; extra == 'all'
82
+ Requires-Dist: pygithub<3,>=2.6.0; extra == 'all'
82
83
  Requires-Dist: pymilvus<3,>=2.4.0; extra == 'all'
83
84
  Requires-Dist: pymupdf<2,>=1.22.5; extra == 'all'
84
85
  Requires-Dist: pyowm<4,>=3.3.0; extra == 'all'
@@ -124,7 +125,7 @@ Provides-Extra: communication-tools
124
125
  Requires-Dist: discord-py<3,>=2.3.2; extra == 'communication-tools'
125
126
  Requires-Dist: notion-client<3,>=2.2.1; extra == 'communication-tools'
126
127
  Requires-Dist: praw<8,>=7.7.1; extra == 'communication-tools'
127
- Requires-Dist: pygithub<3,>=2.3.0; extra == 'communication-tools'
128
+ Requires-Dist: pygithub<3,>=2.6.0; extra == 'communication-tools'
128
129
  Requires-Dist: pytelegrambotapi<5,>=4.18.0; extra == 'communication-tools'
129
130
  Requires-Dist: slack-bolt<2,>=1.20.1; extra == 'communication-tools'
130
131
  Requires-Dist: slack-sdk<4,>=3.27.2; extra == 'communication-tools'
@@ -225,6 +226,7 @@ Provides-Extra: storage
225
226
  Requires-Dist: azure-storage-blob<13,>=12.21.0; extra == 'storage'
226
227
  Requires-Dist: botocore<2,>=1.35.3; extra == 'storage'
227
228
  Requires-Dist: google-cloud-storage<3,>=2.18.0; extra == 'storage'
229
+ Requires-Dist: mem0ai>=0.1.73; extra == 'storage'
228
230
  Requires-Dist: nebula3-python==3.8.2; extra == 'storage'
229
231
  Requires-Dist: neo4j<6,>=5.18.0; extra == 'storage'
230
232
  Requires-Dist: pymilvus<3,>=2.4.0; extra == 'storage'
@@ -443,9 +445,56 @@ Installing CAMEL is a breeze thanks to its availability on PyPI. Simply open you
443
445
  pip install camel-ai
444
446
  ```
445
447
 
448
+ ### Starting with ChatAgent
449
+
450
+ This example demonstrates how to create a `ChatAgent` using the CAMEL framework and perform a search query using DuckDuckGo.
451
+
452
+ 1. **Install the tools package:**
453
+
454
+ ```bash
455
+ pip install 'camel-ai[web_tools]'
456
+ ```
457
+
458
+ 2. **Set up your OpenAI API key:**
459
+
460
+ ```bash
461
+ export OPENAI_API_KEY='your_openai_api_key'
462
+ ```
463
+
464
+ 3. **Run the following Python code:**
465
+
466
+ ```python
467
+ from camel.models import ModelFactory
468
+ from camel.types import ModelPlatformType, ModelType
469
+ from camel.agents import ChatAgent
470
+ from camel.toolkits import SearchToolkit
471
+
472
+ model = ModelFactory.create(
473
+ model_platform=ModelPlatformType.OPENAI,
474
+ model_type=ModelType.GPT_4O,
475
+ model_config_dict={"temperature": 0.0},
476
+ )
477
+
478
+ search_tool = SearchToolkit().search_duckduckgo
479
+
480
+ agent = ChatAgent(model=model, tools=[search_tool])
481
+
482
+ response_1 = agent.step("What is CAMEL-AI?")
483
+ print(response_1.msgs[0].content)
484
+ # CAMEL-AI is the first LLM (Large Language Model) multi-agent framework
485
+ # and an open-source community focused on finding the scaling laws of agents.
486
+ # ...
487
+
488
+ response_2 = agent.step("What is the Github link to CAMEL framework?")
489
+ print(response_2.msgs[0].content)
490
+ # The GitHub link to the CAMEL framework is
491
+ # [https://github.com/camel-ai/camel](https://github.com/camel-ai/camel).
492
+ ```
493
+
494
+
446
495
  For more detailed instructions and additional configuration options, check out the [installation section](https://github.com/camel-ai/camel/blob/master/docs/get_started/installation.md).
447
496
 
448
- After running, you can explore our CAMEL Tech Stack and Cookbooks at [www.docs.camel-ai.org](https://docs.camel-ai.org) to build powerful multi-agent systems.
497
+ After running, you can explore our CAMEL Tech Stack and Cookbooks at [docs.camel-ai.org](https://docs.camel-ai.org) to build powerful multi-agent systems.
449
498
 
450
499
  We provide a [![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1AzP33O8rnMW__7ocWJhVBXjKziJXPtim?usp=sharing) demo showcasing a conversation between two ChatGPT agents playing roles as a python programmer and a stock trader collaborating on developing a trading bot for stock market.
451
500
 
@@ -503,7 +552,7 @@ We believe that studying these agents on a large scale offers valuable insights
503
552
  </div>
504
553
 
505
554
  <div align="center">
506
- <a href="https://www.agent-trust.camel-ai.org/">
555
+ <a href="https://agent-trust.camel-ai.org/">
507
556
  <img src="docs/images/agent_trust.png" alt="Agent Trust">
508
557
  </a>
509
558
  </div>