camel-ai 0.2.38__py3-none-any.whl → 0.2.39__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 (85) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +4 -0
  3. camel/agents/repo_agent.py +2 -2
  4. camel/benchmarks/apibank.py +1 -1
  5. camel/benchmarks/apibench.py +1 -1
  6. camel/configs/__init__.py +3 -0
  7. camel/configs/modelscope_config.py +59 -0
  8. camel/datagen/self_improving_cot.py +1 -1
  9. camel/datasets/__init__.py +2 -0
  10. camel/datasets/base_generator.py +22 -9
  11. camel/datasets/few_shot_generator.py +2 -3
  12. camel/datasets/self_instruct_generator.py +415 -0
  13. camel/embeddings/openai_compatible_embedding.py +13 -5
  14. camel/environments/models.py +1 -1
  15. camel/environments/single_step.py +155 -89
  16. camel/interpreters/docker_interpreter.py +1 -1
  17. camel/interpreters/internal_python_interpreter.py +1 -1
  18. camel/loaders/unstructured_io.py +2 -1
  19. camel/memories/blocks/chat_history_block.py +1 -1
  20. camel/memories/context_creators/score_based.py +2 -2
  21. camel/models/__init__.py +2 -0
  22. camel/models/model_factory.py +119 -0
  23. camel/models/modelscope_model.py +208 -0
  24. camel/models/openai_audio_models.py +2 -2
  25. camel/models/openai_model.py +49 -2
  26. camel/models/togetherai_model.py +2 -2
  27. camel/models/vllm_model.py +1 -1
  28. camel/models/zhipuai_model.py +2 -2
  29. camel/retrievers/vector_retriever.py +1 -1
  30. camel/storages/graph_storages/neo4j_graph.py +1 -1
  31. camel/storages/vectordb_storages/base.py +2 -2
  32. camel/storages/vectordb_storages/milvus.py +2 -2
  33. camel/storages/vectordb_storages/qdrant.py +2 -2
  34. camel/tasks/task.py +2 -2
  35. camel/toolkits/__init__.py +4 -1
  36. camel/toolkits/arxiv_toolkit.py +2 -1
  37. camel/toolkits/ask_news_toolkit.py +11 -3
  38. camel/toolkits/audio_analysis_toolkit.py +2 -0
  39. camel/toolkits/base.py +3 -0
  40. camel/toolkits/code_execution.py +3 -1
  41. camel/toolkits/dappier_toolkit.py +2 -1
  42. camel/toolkits/data_commons_toolkit.py +2 -0
  43. camel/toolkits/excel_toolkit.py +2 -0
  44. camel/toolkits/file_write_toolkit.py +2 -0
  45. camel/toolkits/github_toolkit.py +6 -4
  46. camel/toolkits/google_scholar_toolkit.py +2 -0
  47. camel/toolkits/human_toolkit.py +17 -1
  48. camel/toolkits/image_analysis_toolkit.py +2 -0
  49. camel/toolkits/linkedin_toolkit.py +2 -1
  50. camel/toolkits/math_toolkit.py +2 -0
  51. camel/toolkits/mcp_toolkit.py +42 -52
  52. camel/toolkits/meshy_toolkit.py +20 -2
  53. camel/toolkits/networkx_toolkit.py +2 -0
  54. camel/toolkits/notion_toolkit.py +7 -0
  55. camel/toolkits/openbb_toolkit.py +2 -1
  56. camel/toolkits/pubmed_toolkit.py +2 -0
  57. camel/toolkits/reddit_toolkit.py +2 -1
  58. camel/toolkits/retrieval_toolkit.py +2 -1
  59. camel/toolkits/search_toolkit.py +2 -1
  60. camel/toolkits/semantic_scholar_toolkit.py +2 -0
  61. camel/toolkits/slack_toolkit.py +2 -0
  62. camel/toolkits/stripe_toolkit.py +2 -1
  63. camel/toolkits/sympy_toolkit.py +2 -0
  64. camel/toolkits/terminal_toolkit.py +2 -0
  65. camel/toolkits/twitter_toolkit.py +2 -1
  66. camel/toolkits/video_analysis_toolkit.py +2 -1
  67. camel/toolkits/video_download_toolkit.py +2 -1
  68. camel/toolkits/weather_toolkit.py +2 -0
  69. camel/toolkits/whatsapp_toolkit.py +2 -1
  70. camel/toolkits/zapier_toolkit.py +2 -1
  71. camel/types/enums.py +65 -0
  72. camel/types/unified_model_type.py +5 -0
  73. camel/utils/__init__.py +2 -0
  74. camel/utils/chunker/code_chunker.py +9 -9
  75. camel/utils/commons.py +50 -30
  76. camel/utils/constants.py +2 -2
  77. camel/utils/mcp.py +79 -0
  78. camel/verifiers/__init__.py +2 -0
  79. camel/verifiers/base.py +15 -15
  80. camel/verifiers/math_verifier.py +182 -0
  81. camel/verifiers/python_verifier.py +18 -26
  82. {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/METADATA +3 -1
  83. {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/RECORD +85 -80
  84. {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/WHEEL +0 -0
  85. {camel_ai-0.2.38.dist-info → camel_ai-0.2.39.dist-info}/licenses/LICENSE +0 -0
@@ -19,9 +19,10 @@ import requests
19
19
 
20
20
  from camel.toolkits import FunctionTool
21
21
  from camel.toolkits.base import BaseToolkit
22
- from camel.utils import retry_on_error
22
+ from camel.utils import MCPServer, retry_on_error
23
23
 
24
24
 
25
+ @MCPServer()
25
26
  class WhatsAppToolkit(BaseToolkit):
26
27
  r"""A class representing a toolkit for WhatsApp operations.
27
28
 
@@ -19,9 +19,10 @@ import requests
19
19
 
20
20
  from camel.toolkits.base import BaseToolkit
21
21
  from camel.toolkits.function_tool import FunctionTool
22
- from camel.utils import api_keys_required, dependencies_required
22
+ from camel.utils import MCPServer, api_keys_required, dependencies_required
23
23
 
24
24
 
25
+ @MCPServer()
25
26
  class ZapierToolkit(BaseToolkit):
26
27
  r"""A class representing a toolkit for interacting with Zapier's NLA API.
27
28
 
camel/types/enums.py CHANGED
@@ -217,6 +217,29 @@ class ModelType(UnifiedModelType, Enum):
217
217
  AIML_MIXTRAL_8X7B = "mistralai/Mixtral-8x7B-Instruct-v0.1"
218
218
  AIML_MISTRAL_7B_INSTRUCT = "mistralai/Mistral-7B-Instruct-v0.1"
219
219
 
220
+ # ModelScope models support tool calling
221
+ MODELSCOPE_QWEN_2_5_7B_INSTRUCT = "Qwen/Qwen2.5-7B-Instruct"
222
+ MODELSCOPE_QWEN_2_5_14B_INSTRUCT = "Qwen/Qwen2.5-14B-Instruct"
223
+ MODELSCOPE_QWEN_2_5_32B_INSTRUCT = "Qwen/Qwen2.5-32B-Instruct"
224
+ MODELSCOPE_QWEN_2_5_72B_INSTRUCT = "Qwen/Qwen2.5-72B-Instruct"
225
+ MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT = "Qwen/Qwen2.5-Coder-7B-Instruct"
226
+ MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT = "Qwen/Qwen2.5-Coder-14B-Instruct"
227
+ MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT = "Qwen/Qwen2.5-Coder-32B-Instruct"
228
+ MODELSCOPE_QWQ_32B = "Qwen/QwQ-32B"
229
+ MODELSCOPE_QWQ_32B_PREVIEW = "Qwen/QwQ-32B-Preview"
230
+ MODELSCOPE_LLAMA_3_1_8B_INSTRUCT = (
231
+ "LLM-Research/Meta-Llama-3.1-8B-Instruct"
232
+ )
233
+ MODELSCOPE_LLAMA_3_1_70B_INSTRUCT = (
234
+ "LLM-Research/Meta-Llama-3.1-70B-Instruct"
235
+ )
236
+ MODELSCOPE_LLAMA_3_1_405B_INSTRUCT = (
237
+ "LLM-Research/Meta-Llama-3.1-405B-Instruct"
238
+ )
239
+ MODELSCOPE_LLAMA_3_3_70B_INSTRUCT = "LLM-Research/Llama-3.3-70B-Instruct"
240
+ MODELSCOPE_MINISTRAL_8B_INSTRUCT = "mistralai/Ministral-8B-Instruct-2410"
241
+ MODELSCOPE_DEEPSEEK_V3_0324 = "deepseek-ai/DeepSeek-V3-0324"
242
+
220
243
  def __str__(self):
221
244
  return self.value
222
245
 
@@ -263,6 +286,7 @@ class ModelType(UnifiedModelType, Enum):
263
286
  self.is_sglang,
264
287
  self.is_moonshot,
265
288
  self.is_siliconflow,
289
+ self.is_modelscope,
266
290
  self.is_zhipuai,
267
291
  self.is_aiml,
268
292
  self.is_azure_openai,
@@ -515,6 +539,26 @@ class ModelType(UnifiedModelType, Enum):
515
539
  ModelType.INTERNLM2_PRO_CHAT,
516
540
  }
517
541
 
542
+ @property
543
+ def is_modelscope(self) -> bool:
544
+ return self in {
545
+ ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,
546
+ ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,
547
+ ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,
548
+ ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,
549
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,
550
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,
551
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,
552
+ ModelType.MODELSCOPE_QWQ_32B,
553
+ ModelType.MODELSCOPE_QWQ_32B_PREVIEW,
554
+ ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,
555
+ ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,
556
+ ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,
557
+ ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,
558
+ ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,
559
+ ModelType.MODELSCOPE_DEEPSEEK_V3_0324,
560
+ }
561
+
518
562
  @property
519
563
  def is_moonshot(self) -> bool:
520
564
  return self in {
@@ -638,6 +682,21 @@ class ModelType(UnifiedModelType, Enum):
638
682
  ModelType.MOONSHOT_V1_32K,
639
683
  ModelType.AIML_MIXTRAL_8X7B,
640
684
  ModelType.AIML_MISTRAL_7B_INSTRUCT,
685
+ ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,
686
+ ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,
687
+ ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,
688
+ ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,
689
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,
690
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,
691
+ ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,
692
+ ModelType.MODELSCOPE_QWQ_32B,
693
+ ModelType.MODELSCOPE_QWQ_32B_PREVIEW,
694
+ ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,
695
+ ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,
696
+ ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,
697
+ ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,
698
+ ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,
699
+ ModelType.MODELSCOPE_DEEPSEEK_V3_0324,
641
700
  }:
642
701
  return 32_768
643
702
  elif self in {
@@ -922,6 +981,7 @@ class ModelPlatformType(Enum):
922
981
  SGLANG = "sglang"
923
982
  INTERNLM = "internlm"
924
983
  MOONSHOT = "moonshot"
984
+ MODELSCOPE = "modelscope"
925
985
  SILICONFLOW = "siliconflow"
926
986
  AIML = "aiml"
927
987
  VOLCANO = "volcano"
@@ -1050,6 +1110,11 @@ class ModelPlatformType(Enum):
1050
1110
  r"""Returns whether this platform is Moonshot model."""
1051
1111
  return self is ModelPlatformType.MOONSHOT
1052
1112
 
1113
+ @property
1114
+ def is_modelscope(self) -> bool:
1115
+ r"""Returns whether this platform is ModelScope model."""
1116
+ return self is ModelPlatformType.MODELSCOPE
1117
+
1053
1118
  @property
1054
1119
  def is_siliconflow(self) -> bool:
1055
1120
  r"""Returns whether this platform is SiliconFlow."""
@@ -123,6 +123,11 @@ class UnifiedModelType(str):
123
123
  r"""Returns whether the model is a InternLM model."""
124
124
  return True
125
125
 
126
+ @property
127
+ def is_modelscope(self) -> bool:
128
+ r"""Returns whether the model is a ModelScope serverd model."""
129
+ return True
130
+
126
131
  @property
127
132
  def is_moonshot(self) -> bool:
128
133
  r"""Returns whether this platform is Moonshot model."""
camel/utils/__init__.py CHANGED
@@ -41,6 +41,7 @@ from .commons import (
41
41
  )
42
42
  from .constants import Constants
43
43
  from .deduplication import DeduplicationResult, deduplicate_internally
44
+ from .mcp import MCPServer
44
45
  from .response_format import get_pydantic_model
45
46
  from .token_counting import (
46
47
  AnthropicTokenCounter,
@@ -88,4 +89,5 @@ __all__ = [
88
89
  "retry_on_error",
89
90
  "BatchProcessor",
90
91
  "with_timeout",
92
+ "MCPServer",
91
93
  ]
@@ -12,9 +12,10 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  import re
15
- from typing import List, Optional
15
+ from typing import TYPE_CHECKING, List, Optional
16
16
 
17
- from unstructured.documents.elements import Element, ElementMetadata
17
+ if TYPE_CHECKING:
18
+ from unstructured.documents.elements import Element
18
19
 
19
20
  from camel.utils import get_model_encoding
20
21
 
@@ -23,18 +24,15 @@ from .base import BaseChunker
23
24
 
24
25
  class CodeChunker(BaseChunker):
25
26
  r"""A class for chunking code or text while respecting structure
26
- and token limits.
27
+ and token limits.
27
28
 
28
- This class ensures that structured elements such as functions,
29
- classes, and regions are not arbitrarily split across chunks.
30
- It also handles oversized lines and Base64-encoded images.
29
+ This class ensures that structured elements such as functions,
30
+ classes, and regions are not arbitrarily split across chunks.
31
+ It also handles oversized lines and Base64-encoded images.
31
32
 
32
33
  Attributes:
33
34
  chunk_size (int, optional): The maximum token size per chunk.
34
35
  (default: :obj:`8192`)
35
- token_counter (BaseTokenCounter, optional): The tokenizer used for
36
- token counting, if `None`, OpenAITokenCounter will be used.
37
- (default: :obj:`None`)
38
36
  remove_image: (bool, optional): If the chunker should skip the images.
39
37
  model_name (str, optional): The tokenizer model name used
40
38
  for token counting. (default: :obj:`"cl100k_base"`)
@@ -108,6 +106,8 @@ class CodeChunker(BaseChunker):
108
106
  Returns:
109
107
  List[str]: A list of chunked text segments.
110
108
  """
109
+ from unstructured.documents.elements import Element, ElementMetadata
110
+
111
111
  content_str = "\n".join(map(str, content))
112
112
  chunks = []
113
113
  current_chunk: list[str] = []
camel/utils/commons.py CHANGED
@@ -11,8 +11,10 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
+ import asyncio
14
15
  import functools
15
16
  import importlib
17
+ import inspect
16
18
  import logging
17
19
  import os
18
20
  import platform
@@ -161,7 +163,7 @@ def get_task_list(task_response: str) -> List[str]:
161
163
 
162
164
 
163
165
  def check_server_running(server_url: str) -> bool:
164
- r"""Check whether the port refered by the URL to the server
166
+ r"""Check whether the port referred by the URL to the server
165
167
  is open.
166
168
 
167
169
  Args:
@@ -978,36 +980,54 @@ def with_timeout(timeout=None):
978
980
  """
979
981
 
980
982
  def decorator(func):
981
- @functools.wraps(func)
982
- def wrapper(*args, **kwargs):
983
- # Determine the effective timeout value
984
- effective_timeout = timeout
985
- if effective_timeout is None and args:
986
- effective_timeout = getattr(args[0], 'timeout', None)
987
-
988
- # If no timeout value is provided, execute function normally
989
- if effective_timeout is None:
990
- return func(*args, **kwargs)
991
-
992
- # Container to hold the result of the function call
993
- result_container = []
994
-
995
- def target():
996
- result_container.append(func(*args, **kwargs))
997
-
998
- # Start the function in a new thread
999
- thread = threading.Thread(target=target)
1000
- thread.start()
1001
- thread.join(effective_timeout)
1002
-
1003
- # Check if the thread is still alive after the timeout
1004
- if thread.is_alive():
1005
- return (
1006
- f"Function `{func.__name__}` execution timed out, "
1007
- f"exceeded {effective_timeout} seconds."
983
+ if inspect.iscoroutinefunction(func):
984
+
985
+ @functools.wraps(func)
986
+ async def async_wrapper(*args, **kwargs):
987
+ eff_timeout = timeout
988
+ if eff_timeout is None and args:
989
+ eff_timeout = getattr(args[0], 'timeout', None)
990
+
991
+ if eff_timeout is None:
992
+ return await func(*args, **kwargs)
993
+
994
+ return await asyncio.wait_for(
995
+ func(*args, **kwargs), timeout=eff_timeout
1008
996
  )
1009
- else:
1010
- return result_container[0]
997
+
998
+ return async_wrapper
999
+ else:
1000
+
1001
+ @functools.wraps(func)
1002
+ def wrapper(*args, **kwargs):
1003
+ # Determine the effective timeout value
1004
+ effective_timeout = timeout
1005
+ if effective_timeout is None and args:
1006
+ effective_timeout = getattr(args[0], 'timeout', None)
1007
+
1008
+ # If no timeout value is provided, execute function normally
1009
+ if effective_timeout is None:
1010
+ return func(*args, **kwargs)
1011
+
1012
+ # Container to hold the result of the function call
1013
+ result_container = []
1014
+
1015
+ def target():
1016
+ result_container.append(func(*args, **kwargs))
1017
+
1018
+ # Start the function in a new thread
1019
+ thread = threading.Thread(target=target)
1020
+ thread.start()
1021
+ thread.join(effective_timeout)
1022
+
1023
+ # Check if the thread is still alive after the timeout
1024
+ if thread.is_alive():
1025
+ return (
1026
+ f"Function `{func.__name__}` execution timed out, "
1027
+ f"exceeded {effective_timeout} seconds."
1028
+ )
1029
+ else:
1030
+ return result_container[0]
1011
1031
 
1012
1032
  return wrapper
1013
1033
 
camel/utils/constants.py CHANGED
@@ -30,8 +30,8 @@ class Constants:
30
30
  # Return response with json format
31
31
  FUNC_NAME_FOR_STRUCTURED_OUTPUT = "return_json_response"
32
32
 
33
- # Default top k vaule for RAG
33
+ # Default top k value for RAG
34
34
  DEFAULT_TOP_K_RESULTS = 1
35
35
 
36
- # Default similarity threshold vaule for RAG
36
+ # Default similarity threshold value for RAG
37
37
  DEFAULT_SIMILARITY_THRESHOLD = 0.7
camel/utils/mcp.py ADDED
@@ -0,0 +1,79 @@
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 functools
15
+ import inspect
16
+ from typing import Any, Callable, Optional
17
+
18
+
19
+ class MCPServer:
20
+ def __init__(
21
+ self,
22
+ function_names: Optional[list[str]] = None,
23
+ server_name: Optional[str] = None,
24
+ ):
25
+ self.function_names = function_names
26
+ self.server_name = server_name
27
+
28
+ def make_wrapper(self, func: Callable[..., Any]) -> Callable[..., Any]:
29
+ if inspect.iscoroutinefunction(func):
30
+
31
+ @functools.wraps(func)
32
+ async def wrapper(*args, **kwargs):
33
+ return await func(*args, **kwargs)
34
+ else:
35
+
36
+ @functools.wraps(func)
37
+ def wrapper(*args, **kwargs):
38
+ return func(*args, **kwargs)
39
+
40
+ wrapper.__signature__ = inspect.signature(func) # type: ignore[attr-defined]
41
+ return wrapper
42
+
43
+ def __call__(self, cls):
44
+ from mcp.server.fastmcp import FastMCP
45
+
46
+ from camel.toolkits.base import BaseToolkit
47
+
48
+ original_init = cls.__init__
49
+
50
+ def new_init(instance, *args, **kwargs):
51
+ original_init(instance, *args, **kwargs)
52
+ self.server_name = self.server_name or cls.__name__
53
+ instance.mcp = FastMCP(self.server_name)
54
+
55
+ if not self.function_names and not isinstance(
56
+ instance, BaseToolkit
57
+ ):
58
+ raise ValueError(
59
+ "Please specify function names or use BaseToolkit."
60
+ )
61
+
62
+ function_names = self.function_names
63
+ if not function_names and isinstance(instance, BaseToolkit):
64
+ function_names = [
65
+ tool.get_function_name() for tool in instance.get_tools()
66
+ ]
67
+
68
+ for name in function_names:
69
+ func = getattr(instance, name, None)
70
+ if func is None or not callable(func):
71
+ raise ValueError(
72
+ f"Method {name} not found in class {cls.__name} or "
73
+ "cannot be called."
74
+ )
75
+ wrapper = self.make_wrapper(func)
76
+ instance.mcp.tool(name=name)(wrapper)
77
+
78
+ cls.__init__ = new_init
79
+ return cls
@@ -12,6 +12,7 @@
12
12
  # limitations under the License.
13
13
  # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
14
  from .base import BaseVerifier
15
+ from .math_verifier import MathVerifier
15
16
  from .models import VerificationOutcome
16
17
  from .python_verifier import PythonVerifier
17
18
 
@@ -19,4 +20,5 @@ __all__ = [
19
20
  "BaseVerifier",
20
21
  "VerificationOutcome",
21
22
  "PythonVerifier",
23
+ "MathVerifier",
22
24
  ]
camel/verifiers/base.py CHANGED
@@ -163,7 +163,7 @@ class BaseVerifier(ABC):
163
163
  pass
164
164
 
165
165
  async def verify(
166
- self, solution: str, ground_truth: Optional[str]
166
+ self, solution: str, reference_answer: Optional[str]
167
167
  ) -> VerificationResult:
168
168
  r"""Perform verification with full error handling.
169
169
 
@@ -174,7 +174,7 @@ class BaseVerifier(ABC):
174
174
 
175
175
  Args:
176
176
  solution (str): The generated response that needs verification.
177
- ground_truth (Optional[str]): The expected correct answer to
177
+ reference_answer (Optional[str]): The expected correct answer to
178
178
  compare against.
179
179
 
180
180
  Returns:
@@ -215,13 +215,13 @@ class BaseVerifier(ABC):
215
215
  verification_result = (
216
216
  await asyncio.wait_for(
217
217
  self._verify_implementation(
218
- verifiable_solution, ground_truth
218
+ verifiable_solution, reference_answer
219
219
  ),
220
220
  timeout=self._timeout,
221
221
  )
222
222
  if self._timeout
223
223
  else await self._verify_implementation(
224
- verifiable_solution, ground_truth
224
+ verifiable_solution, reference_answer
225
225
  )
226
226
  )
227
227
 
@@ -267,7 +267,7 @@ class BaseVerifier(ABC):
267
267
 
268
268
  @abstractmethod
269
269
  async def _verify_implementation(
270
- self, solution: str, ground_truth: Optional[str]
270
+ self, solution: str, reference_answer: Optional[str]
271
271
  ) -> VerificationResult:
272
272
  r"""Abstract method for verification logic.
273
273
 
@@ -276,7 +276,7 @@ class BaseVerifier(ABC):
276
276
 
277
277
  Args:
278
278
  solution (str): The generated response requiring verification.
279
- ground_truth (Optional[str]): The expected reference output.
279
+ reference_answer (Optional[str]): The expected reference output.
280
280
 
281
281
  Returns:
282
282
  VerificationResult: Contains verification status and details.
@@ -293,7 +293,7 @@ class BaseVerifier(ABC):
293
293
  async def verify_batch(
294
294
  self,
295
295
  solutions: List[str],
296
- ground_truths: List[Optional[str]],
296
+ reference_answers: List[Optional[str]],
297
297
  raise_on_error: bool = False,
298
298
  ) -> List[VerificationResult]:
299
299
  r"""Verify multiple solutions in parallel with controlled concurrency.
@@ -305,8 +305,8 @@ class BaseVerifier(ABC):
305
305
  Args:
306
306
  solutions (List[str]): A list of generated solutions to be
307
307
  verified.
308
- ground_truths (List[Optional[str]]): A list of expected outputs for
309
- comparison. Each element corresponds to a solution.
308
+ reference_answers (List[Optional[str]]): A list of expected outputs
309
+ for comparison. Each element corresponds to a solution.
310
310
  raise_on_error (bool, optional): If True, raises an exception if
311
311
  any verification fails. (default: :obj:`False`)
312
312
 
@@ -337,13 +337,13 @@ class BaseVerifier(ABC):
337
337
  semaphore = asyncio.Semaphore(max(1, max_workers))
338
338
 
339
339
  async def _verify_with_semaphore(
340
- solution: str, ground_truth: Optional[str]
340
+ solution: str, reference_answer: Optional[str]
341
341
  ) -> VerificationResult:
342
342
  start_time = time.time()
343
343
  try:
344
344
  async with semaphore:
345
345
  verification_result = await self.verify(
346
- solution, ground_truth
346
+ solution, reference_answer
347
347
  )
348
348
  processing_time = time.time() - start_time
349
349
  success = (
@@ -368,12 +368,12 @@ class BaseVerifier(ABC):
368
368
  all_results: List[VerificationResult] = []
369
369
  for i in range(0, len(solutions), batch_size):
370
370
  batch_solutions = solutions[i : i + batch_size]
371
- batch_ground_truths = ground_truths[i : i + batch_size]
371
+ batch_reference_answers = reference_answers[i : i + batch_size]
372
372
 
373
373
  verification_tasks = [
374
- _verify_with_semaphore(solution, ground_truth)
375
- for solution, ground_truth in zip(
376
- batch_solutions, batch_ground_truths
374
+ _verify_with_semaphore(solution, reference_answer)
375
+ for solution, reference_answer in zip(
376
+ batch_solutions, batch_reference_answers
377
377
  )
378
378
  ]
379
379
  try: