camel-ai 0.2.3__py3-none-any.whl → 0.2.3a1__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 (87) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +69 -93
  3. camel/agents/knowledge_graph_agent.py +6 -4
  4. camel/bots/__init__.py +2 -16
  5. camel/bots/discord_bot.py +206 -0
  6. camel/configs/__init__.py +2 -1
  7. camel/configs/anthropic_config.py +5 -2
  8. camel/configs/base_config.py +6 -6
  9. camel/configs/groq_config.py +3 -2
  10. camel/configs/ollama_config.py +2 -1
  11. camel/configs/openai_config.py +23 -2
  12. camel/configs/samba_config.py +2 -2
  13. camel/configs/togetherai_config.py +1 -1
  14. camel/configs/vllm_config.py +1 -1
  15. camel/configs/zhipuai_config.py +3 -2
  16. camel/embeddings/openai_embedding.py +2 -2
  17. camel/loaders/__init__.py +0 -2
  18. camel/loaders/firecrawl_reader.py +3 -3
  19. camel/loaders/unstructured_io.py +33 -35
  20. camel/messages/__init__.py +0 -1
  21. camel/models/__init__.py +4 -2
  22. camel/models/anthropic_model.py +26 -32
  23. camel/models/azure_openai_model.py +36 -39
  24. camel/models/base_model.py +20 -31
  25. camel/models/gemini_model.py +29 -37
  26. camel/models/groq_model.py +23 -29
  27. camel/models/litellm_model.py +61 -44
  28. camel/models/mistral_model.py +29 -32
  29. camel/models/model_factory.py +76 -66
  30. camel/models/nemotron_model.py +23 -33
  31. camel/models/ollama_model.py +47 -42
  32. camel/models/open_source_model.py +170 -0
  33. camel/models/{openai_compatible_model.py → openai_compatibility_model.py} +49 -31
  34. camel/models/openai_model.py +29 -48
  35. camel/models/reka_model.py +28 -30
  36. camel/models/samba_model.py +177 -82
  37. camel/models/stub_model.py +2 -2
  38. camel/models/togetherai_model.py +43 -37
  39. camel/models/vllm_model.py +50 -43
  40. camel/models/zhipuai_model.py +27 -33
  41. camel/retrievers/auto_retriever.py +10 -28
  42. camel/retrievers/vector_retriever.py +47 -58
  43. camel/societies/babyagi_playing.py +3 -6
  44. camel/societies/role_playing.py +3 -5
  45. camel/storages/graph_storages/graph_element.py +5 -3
  46. camel/storages/key_value_storages/json.py +1 -6
  47. camel/toolkits/__init__.py +7 -20
  48. camel/toolkits/base.py +3 -2
  49. camel/toolkits/code_execution.py +7 -6
  50. camel/toolkits/dalle_toolkit.py +6 -6
  51. camel/toolkits/github_toolkit.py +10 -9
  52. camel/toolkits/google_maps_toolkit.py +7 -7
  53. camel/toolkits/linkedin_toolkit.py +7 -7
  54. camel/toolkits/math_toolkit.py +8 -8
  55. camel/toolkits/open_api_toolkit.py +5 -5
  56. camel/toolkits/{function_tool.py → openai_function.py} +11 -34
  57. camel/toolkits/reddit_toolkit.py +7 -7
  58. camel/toolkits/retrieval_toolkit.py +5 -5
  59. camel/toolkits/search_toolkit.py +9 -9
  60. camel/toolkits/slack_toolkit.py +11 -11
  61. camel/toolkits/twitter_toolkit.py +452 -378
  62. camel/toolkits/weather_toolkit.py +6 -6
  63. camel/types/__init__.py +1 -6
  64. camel/types/enums.py +85 -40
  65. camel/types/openai_types.py +0 -3
  66. camel/utils/__init__.py +2 -0
  67. camel/utils/async_func.py +7 -7
  68. camel/utils/commons.py +3 -32
  69. camel/utils/token_counting.py +212 -30
  70. camel/workforce/role_playing_worker.py +1 -1
  71. camel/workforce/single_agent_worker.py +1 -1
  72. camel/workforce/task_channel.py +3 -4
  73. camel/workforce/workforce.py +4 -4
  74. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/METADATA +56 -27
  75. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/RECORD +76 -85
  76. {camel_ai-0.2.3.dist-info → camel_ai-0.2.3a1.dist-info}/WHEEL +1 -1
  77. camel/bots/discord_app.py +0 -138
  78. camel/bots/slack/__init__.py +0 -30
  79. camel/bots/slack/models.py +0 -158
  80. camel/bots/slack/slack_app.py +0 -255
  81. camel/loaders/chunkr_reader.py +0 -163
  82. camel/toolkits/arxiv_toolkit.py +0 -155
  83. camel/toolkits/ask_news_toolkit.py +0 -653
  84. camel/toolkits/google_scholar_toolkit.py +0 -146
  85. camel/toolkits/whatsapp_toolkit.py +0 -177
  86. camel/types/unified_model_type.py +0 -104
  87. camel_ai-0.2.3.dist-info/LICENSE +0 -201
@@ -39,13 +39,13 @@ class BaseConfig(ABC, BaseModel):
39
39
  @classmethod
40
40
  def fields_type_checking(cls, tools):
41
41
  if tools is not None:
42
- from camel.toolkits import FunctionTool
42
+ from camel.toolkits import OpenAIFunction
43
43
 
44
44
  for tool in tools:
45
- if not isinstance(tool, FunctionTool):
45
+ if not isinstance(tool, OpenAIFunction):
46
46
  raise ValueError(
47
47
  f"The tool {tool} should "
48
- "be an instance of `FunctionTool`."
48
+ "be an instance of `OpenAIFunction`."
49
49
  )
50
50
  return tools
51
51
 
@@ -54,14 +54,14 @@ class BaseConfig(ABC, BaseModel):
54
54
 
55
55
  tools_schema = None
56
56
  if self.tools:
57
- from camel.toolkits import FunctionTool
57
+ from camel.toolkits import OpenAIFunction
58
58
 
59
59
  tools_schema = []
60
60
  for tool in self.tools:
61
- if not isinstance(tool, FunctionTool):
61
+ if not isinstance(tool, OpenAIFunction):
62
62
  raise ValueError(
63
63
  f"The tool {tool} should "
64
- "be an instance of `FunctionTool`."
64
+ "be an instance of `OpenAIFunction`."
65
65
  )
66
66
  tools_schema.append(tool.get_openai_tool_schema())
67
67
  config_dict["tools"] = tools_schema
@@ -15,8 +15,9 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Optional, Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
19
+
18
20
  from camel.configs.base_config import BaseConfig
19
- from camel.types import NOT_GIVEN, NotGiven
20
21
 
21
22
 
22
23
  class GroqConfig(BaseConfig):
@@ -72,7 +73,7 @@ class GroqConfig(BaseConfig):
72
73
  user (str, optional): A unique identifier representing your end-user,
73
74
  which can help OpenAI to monitor and detect abuse.
74
75
  (default: :obj:`""`)
75
- tools (list[FunctionTool], optional): A list of tools the model may
76
+ tools (list[OpenAIFunction], optional): A list of tools the model may
76
77
  call. Currently, only functions are supported as a tool. Use this
77
78
  to provide a list of functions the model may generate JSON inputs
78
79
  for. A max of 128 functions are supported.
@@ -15,8 +15,9 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
19
+
18
20
  from camel.configs.base_config import BaseConfig
19
- from camel.types import NOT_GIVEN, NotGiven
20
21
 
21
22
 
22
23
  class OllamaConfig(BaseConfig):
@@ -15,10 +15,10 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Optional, Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
18
19
  from pydantic import Field
19
20
 
20
21
  from camel.configs.base_config import BaseConfig
21
- from camel.types import NOT_GIVEN, NotGiven
22
22
 
23
23
 
24
24
  class ChatGPTConfig(BaseConfig):
@@ -81,7 +81,7 @@ class ChatGPTConfig(BaseConfig):
81
81
  user (str, optional): A unique identifier representing your end-user,
82
82
  which can help OpenAI to monitor and detect abuse.
83
83
  (default: :obj:`""`)
84
- tools (list[FunctionTool], optional): A list of tools the model may
84
+ tools (list[OpenAIFunction], optional): A list of tools the model may
85
85
  call. Currently, only functions are supported as a tool. Use this
86
86
  to provide a list of functions the model may generate JSON inputs
87
87
  for. A max of 128 functions are supported.
@@ -112,3 +112,24 @@ class ChatGPTConfig(BaseConfig):
112
112
 
113
113
 
114
114
  OPENAI_API_PARAMS = {param for param in ChatGPTConfig.model_fields.keys()}
115
+
116
+
117
+ class OpenSourceConfig(BaseConfig):
118
+ r"""Defines parameters for setting up open-source models and includes
119
+ parameters to be passed to chat completion function of OpenAI API.
120
+
121
+ Args:
122
+ model_path (str): The path to a local folder containing the model
123
+ files or the model card in HuggingFace hub.
124
+ server_url (str): The URL to the server running the model inference
125
+ which will be used as the API base of OpenAI API.
126
+ api_params (ChatGPTConfig): An instance of :obj:ChatGPTConfig to
127
+ contain the arguments to be passed to OpenAI API.
128
+ """
129
+
130
+ # Maybe the param needs to be renamed.
131
+ # Warning: Field "model_path" has conflict with protected namespace
132
+ # "model_".
133
+ model_path: str
134
+ server_url: str
135
+ api_params: ChatGPTConfig = Field(default_factory=ChatGPTConfig)
@@ -15,10 +15,10 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Any, Dict, Optional, Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
18
19
  from pydantic import Field
19
20
 
20
21
  from camel.configs.base_config import BaseConfig
21
- from camel.types import NOT_GIVEN, NotGiven
22
22
 
23
23
 
24
24
  class SambaFastAPIConfig(BaseConfig):
@@ -172,7 +172,7 @@ class SambaCloudAPIConfig(BaseConfig):
172
172
  user (str, optional): A unique identifier representing your end-user,
173
173
  which can help OpenAI to monitor and detect abuse.
174
174
  (default: :obj:`""`)
175
- tools (list[FunctionTool], optional): A list of tools the model may
175
+ tools (list[OpenAIFunction], optional): A list of tools the model may
176
176
  call. Currently, only functions are supported as a tool. Use this
177
177
  to provide a list of functions the model may generate JSON inputs
178
178
  for. A max of 128 functions are supported.
@@ -15,10 +15,10 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Any, Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
18
19
  from pydantic import Field
19
20
 
20
21
  from camel.configs.base_config import BaseConfig
21
- from camel.types import NOT_GIVEN, NotGiven
22
22
 
23
23
 
24
24
  class TogetherAIConfig(BaseConfig):
@@ -15,10 +15,10 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
18
19
  from pydantic import Field
19
20
 
20
21
  from camel.configs.base_config import BaseConfig
21
- from camel.types import NOT_GIVEN, NotGiven
22
22
 
23
23
 
24
24
  # flake8: noqa: E501
@@ -15,8 +15,9 @@ from __future__ import annotations
15
15
 
16
16
  from typing import Optional, Sequence, Union
17
17
 
18
+ from openai._types import NOT_GIVEN, NotGiven
19
+
18
20
  from camel.configs.base_config import BaseConfig
19
- from camel.types import NOT_GIVEN, NotGiven
20
21
 
21
22
 
22
23
  class ZhipuAIConfig(BaseConfig):
@@ -44,7 +45,7 @@ class ZhipuAIConfig(BaseConfig):
44
45
  in the chat completion. The total length of input tokens and
45
46
  generated tokens is limited by the model's context length.
46
47
  (default: :obj:`None`)
47
- tools (list[FunctionTool], optional): A list of tools the model may
48
+ tools (list[OpenAIFunction], optional): A list of tools the model may
48
49
  call. Currently, only functions are supported as a tool. Use this
49
50
  to provide a list of functions the model may generate JSON inputs
50
51
  for. A max of 128 functions are supported.
@@ -16,10 +16,10 @@ from __future__ import annotations
16
16
  import os
17
17
  from typing import Any
18
18
 
19
- from openai import OpenAI
19
+ from openai import NOT_GIVEN, NotGiven, OpenAI
20
20
 
21
21
  from camel.embeddings.base import BaseEmbedding
22
- from camel.types import NOT_GIVEN, EmbeddingModelType, NotGiven
22
+ from camel.types import EmbeddingModelType
23
23
  from camel.utils import api_keys_required
24
24
 
25
25
 
camel/loaders/__init__.py CHANGED
@@ -13,7 +13,6 @@
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
14
 
15
15
  from .base_io import File
16
- from .chunkr_reader import ChunkrReader
17
16
  from .firecrawl_reader import Firecrawl
18
17
  from .jina_url_reader import JinaURLReader
19
18
  from .unstructured_io import UnstructuredIO
@@ -23,5 +22,4 @@ __all__ = [
23
22
  'UnstructuredIO',
24
23
  'JinaURLReader',
25
24
  'Firecrawl',
26
- 'ChunkrReader',
27
25
  ]
@@ -155,12 +155,12 @@ class Firecrawl:
155
155
  except Exception as e:
156
156
  raise RuntimeError(f"Failed to scrape the URL: {e}")
157
157
 
158
- def structured_scrape(self, url: str, response_format: BaseModel) -> Dict:
158
+ def structured_scrape(self, url: str, output_schema: BaseModel) -> Dict:
159
159
  r"""Use LLM to extract structured data from given URL.
160
160
 
161
161
  Args:
162
162
  url (str): The URL to read.
163
- response_format (BaseModel): A pydantic model
163
+ output_schema (BaseModel): A pydantic model
164
164
  that includes value types and field descriptions used to
165
165
  generate a structured response by LLM. This schema helps
166
166
  in defining the expected output format.
@@ -176,7 +176,7 @@ class Firecrawl:
176
176
  url,
177
177
  {
178
178
  'formats': ['extract'],
179
- 'extract': {'schema': response_format.model_json_schema()},
179
+ 'extract': {'schema': output_schema.model_json_schema()},
180
180
  },
181
181
  )
182
182
  return data.get("extract", {})
@@ -13,9 +13,8 @@
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
14
  import uuid
15
15
  import warnings
16
+ from io import IOBase
16
17
  from typing import (
17
- IO,
18
- TYPE_CHECKING,
19
18
  Any,
20
19
  Dict,
21
20
  List,
@@ -25,8 +24,7 @@ from typing import (
25
24
  Union,
26
25
  )
27
26
 
28
- if TYPE_CHECKING:
29
- from unstructured.documents.elements import Element
27
+ from unstructured.documents.elements import Element
30
28
 
31
29
 
32
30
  class UnstructuredIO:
@@ -42,34 +40,33 @@ class UnstructuredIO:
42
40
  @staticmethod
43
41
  def create_element_from_text(
44
42
  text: str,
45
- element_id: Optional[str] = None,
43
+ element_id: Optional[Union[str, uuid.UUID]] = None,
46
44
  embeddings: Optional[List[float]] = None,
47
45
  filename: Optional[str] = None,
48
46
  file_directory: Optional[str] = None,
49
47
  last_modified: Optional[str] = None,
50
48
  filetype: Optional[str] = None,
51
- parent_id: Optional[str] = None,
52
- ) -> "Element":
49
+ parent_id: Optional[Union[str, uuid.UUID]] = None,
50
+ ) -> Element:
53
51
  r"""Creates a Text element from a given text input, with optional
54
52
  metadata and embeddings.
55
53
 
56
54
  Args:
57
55
  text (str): The text content for the element.
58
- element_id (Optional[str], optional): Unique identifier for the
59
- element. (default: :obj:`None`)
60
- embeddings (List[float], optional): A list of float
61
- numbers representing the text embeddings.
62
- (default: :obj:`None`)
56
+ element_id (Optional[Union[str, uuid.UUID]], optional): Unique
57
+ identifier for the element. Defaults to `None`.
58
+ embeddings (Optional[List[float]], optional): A list of float
59
+ numbers representing the text embeddings. Defaults to `None`.
63
60
  filename (Optional[str], optional): The name of the file the
64
- element is associated with. (default: :obj:`None`)
61
+ element is associated with. Defaults to `None`.
65
62
  file_directory (Optional[str], optional): The directory path where
66
- the file is located. (default: :obj:`None`)
63
+ the file is located. Defaults to `None`.
67
64
  last_modified (Optional[str], optional): The last modified date of
68
- the file. (default: :obj:`None`)
69
- filetype (Optional[str], optional): The type of the file.
70
- (default: :obj:`None`)
71
- parent_id (Optional[str], optional): The identifier of the parent
72
- element. (default: :obj:`None`)
65
+ the file. Defaults to `None`.
66
+ filetype (Optional[str], optional): The type of the file. Defaults
67
+ to `None`.
68
+ parent_id (Optional[Union[str, uuid.UUID]], optional): The
69
+ identifier of the parent element. Defaults to `None`.
73
70
 
74
71
  Returns:
75
72
  Element: An instance of Text with the provided content and
@@ -87,7 +84,7 @@ class UnstructuredIO:
87
84
 
88
85
  return Text(
89
86
  text=text,
90
- element_id=element_id or str(uuid.uuid4()),
87
+ element_id=element_id or uuid.uuid4(),
91
88
  metadata=metadata,
92
89
  embeddings=embeddings,
93
90
  )
@@ -96,7 +93,7 @@ class UnstructuredIO:
96
93
  def parse_file_or_url(
97
94
  input_path: str,
98
95
  **kwargs: Any,
99
- ) -> Union[List["Element"], None]:
96
+ ) -> Union[List[Element], None]:
100
97
  r"""Loads a file or a URL and parses its contents into elements.
101
98
 
102
99
  Args:
@@ -122,23 +119,25 @@ class UnstructuredIO:
122
119
  import os
123
120
  from urllib.parse import urlparse
124
121
 
125
- from unstructured.partition.auto import partition
126
-
127
122
  # Check if the input is a URL
128
123
  parsed_url = urlparse(input_path)
129
124
  is_url = all([parsed_url.scheme, parsed_url.netloc])
130
125
 
131
- # Handling URL
132
126
  if is_url:
127
+ # Handling URL
128
+ from unstructured.partition.html import partition_html
129
+
133
130
  try:
134
- elements = partition(url=input_path, **kwargs)
131
+ elements = partition_html(url=input_path, **kwargs)
135
132
  return elements
136
133
  except Exception:
137
134
  warnings.warn(f"Failed to parse the URL: {input_path}")
138
135
  return None
139
136
 
140
- # Handling file
141
137
  else:
138
+ # Handling file
139
+ from unstructured.partition.auto import partition
140
+
142
141
  # Check if the file exists
143
142
  if not os.path.exists(input_path):
144
143
  raise FileNotFoundError(
@@ -155,13 +154,11 @@ class UnstructuredIO:
155
154
  return None
156
155
 
157
156
  @staticmethod
158
- def parse_bytes(
159
- file: IO[bytes], **kwargs: Any
160
- ) -> Union[List["Element"], None]:
157
+ def parse_bytes(file: IOBase, **kwargs: Any) -> Union[List[Element], None]:
161
158
  r"""Parses a bytes stream and converts its contents into elements.
162
159
 
163
160
  Args:
164
- file (IO[bytes]): The file in bytes format to be parsed.
161
+ file (IOBase): The file in bytes format to be parsed.
165
162
  **kwargs: Extra kwargs passed to the partition function.
166
163
 
167
164
  Returns:
@@ -184,6 +181,8 @@ class UnstructuredIO:
184
181
  elements = partition(file=file, **kwargs)
185
182
  return elements
186
183
  except Exception as e:
184
+ import warnings
185
+
187
186
  warnings.warn(f"Failed to partition the file stream: {e}")
188
187
  return None
189
188
 
@@ -197,7 +196,7 @@ class UnstructuredIO:
197
196
 
198
197
  This function applies multiple text cleaning utilities by calling the
199
198
  `unstructured` library's cleaning bricks for operations like
200
- replacing Unicode quotes, removing extra whitespace, dashes, non-ascii
199
+ replacing unicode quotes, removing extra whitespace, dashes, non-ascii
201
200
  characters, and more.
202
201
 
203
202
  If no cleaning options are provided, a default set of cleaning
@@ -284,8 +283,7 @@ class UnstructuredIO:
284
283
  )
285
284
  else:
286
285
  raise ValueError(
287
- f"'{func_name}' is not a valid function in "
288
- "`Unstructured IO`."
286
+ f"'{func_name}' is not a valid function in `unstructured`."
289
287
  )
290
288
 
291
289
  return cleaned_text
@@ -442,8 +440,8 @@ class UnstructuredIO:
442
440
 
443
441
  @staticmethod
444
442
  def chunk_elements(
445
- elements: List["Element"], chunk_type: str, **kwargs
446
- ) -> List["Element"]:
443
+ elements: List[Any], chunk_type: str, **kwargs
444
+ ) -> List[Element]:
447
445
  r"""Chunks elements by titles.
448
446
 
449
447
  Args:
@@ -32,7 +32,6 @@ __all__ = [
32
32
  'OpenAISystemMessage',
33
33
  'OpenAIAssistantMessage',
34
34
  'OpenAIUserMessage',
35
- 'OpenAIFunctionMessage',
36
35
  'OpenAIMessage',
37
36
  'BaseMessage',
38
37
  'FunctionCallingMessage',
camel/models/__init__.py CHANGED
@@ -21,8 +21,9 @@ from .mistral_model import MistralModel
21
21
  from .model_factory import ModelFactory
22
22
  from .nemotron_model import NemotronModel
23
23
  from .ollama_model import OllamaModel
24
+ from .open_source_model import OpenSourceModel
24
25
  from .openai_audio_models import OpenAIAudioModels
25
- from .openai_compatible_model import OpenAICompatibleModel
26
+ from .openai_compatibility_model import OpenAICompatibilityModel
26
27
  from .openai_model import OpenAIModel
27
28
  from .reka_model import RekaModel
28
29
  from .samba_model import SambaModel
@@ -40,6 +41,7 @@ __all__ = [
40
41
  'GroqModel',
41
42
  'StubModel',
42
43
  'ZhipuAIModel',
44
+ 'OpenSourceModel',
43
45
  'ModelFactory',
44
46
  'LiteLLMModel',
45
47
  'OpenAIAudioModels',
@@ -47,7 +49,7 @@ __all__ = [
47
49
  'OllamaModel',
48
50
  'VLLMModel',
49
51
  'GeminiModel',
50
- 'OpenAICompatibleModel',
52
+ 'OpenAICompatibilityModel',
51
53
  'RekaModel',
52
54
  'SambaModel',
53
55
  'TogetherAIModel',
@@ -12,9 +12,11 @@
12
12
  # limitations under the License.
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
14
  import os
15
- from typing import Any, Dict, List, Optional, Union
15
+ from typing import Any, Dict, List, Optional
16
16
 
17
- from camel.configs import ANTHROPIC_API_PARAMS, AnthropicConfig
17
+ from anthropic import NOT_GIVEN, Anthropic
18
+
19
+ from camel.configs import ANTHROPIC_API_PARAMS
18
20
  from camel.messages import OpenAIMessage
19
21
  from camel.models.base_model import BaseModelBackend
20
22
  from camel.types import ChatCompletion, ModelType
@@ -22,47 +24,40 @@ from camel.utils import (
22
24
  AnthropicTokenCounter,
23
25
  BaseTokenCounter,
24
26
  api_keys_required,
25
- dependencies_required,
26
27
  )
27
28
 
28
29
 
29
30
  class AnthropicModel(BaseModelBackend):
30
- r"""Anthropic API in a unified BaseModelBackend interface.
31
-
32
- Args:
33
- model_type (Union[ModelType, str]): Model for which a backend is
34
- created, one of CLAUDE_* series.
35
- model_config_dict (Optional[Dict[str, Any]], optional): A dictionary
36
- that will be fed into Anthropic.messages.create(). If
37
- :obj:`None`, :obj:`AnthropicConfig().as_dict()` will be used.
38
- (default::obj:`None`)
39
- api_key (Optional[str], optional): The API key for authenticating with
40
- the Anthropic service. (default: :obj:`None`)
41
- url (Optional[str], optional): The url to the Anthropic service.
42
- (default: :obj:`None`)
43
- token_counter (Optional[BaseTokenCounter], optional): Token counter to
44
- use for the model. If not provided, :obj:`AnthropicTokenCounter`
45
- will be used. (default: :obj:`None`)
46
- """
47
-
48
- @dependencies_required('anthropic')
31
+ r"""Anthropic API in a unified BaseModelBackend interface."""
32
+
49
33
  def __init__(
50
34
  self,
51
- model_type: Union[ModelType, str],
52
- model_config_dict: Optional[Dict[str, Any]] = None,
35
+ model_type: ModelType,
36
+ model_config_dict: Dict[str, Any],
53
37
  api_key: Optional[str] = None,
54
38
  url: Optional[str] = None,
55
39
  token_counter: Optional[BaseTokenCounter] = None,
56
40
  ) -> None:
57
- from anthropic import Anthropic
41
+ r"""Constructor for Anthropic backend.
58
42
 
59
- if model_config_dict is None:
60
- model_config_dict = AnthropicConfig().as_dict()
61
- api_key = api_key or os.environ.get("ANTHROPIC_API_KEY")
62
- url = url or os.environ.get("ANTHROPIC_API_BASE_URL")
43
+ Args:
44
+ model_type (ModelType): Model for which a backend is created,
45
+ one of CLAUDE_* series.
46
+ model_config_dict (Dict[str, Any]): A dictionary that will
47
+ be fed into Anthropic.messages.create().
48
+ api_key (Optional[str]): The API key for authenticating with the
49
+ Anthropic service. (default: :obj:`None`)
50
+ url (Optional[str]): The url to the Anthropic service. (default:
51
+ :obj:`None`)
52
+ token_counter (Optional[BaseTokenCounter]): Token counter to use
53
+ for the model. If not provided, `AnthropicTokenCounter` will
54
+ be used.
55
+ """
63
56
  super().__init__(
64
57
  model_type, model_config_dict, api_key, url, token_counter
65
58
  )
59
+ self._api_key = api_key or os.environ.get("ANTHROPIC_API_KEY")
60
+ self._url = url or os.environ.get("ANTHROPIC_API_BASE_URL")
66
61
  self.client = Anthropic(api_key=self._api_key, base_url=self._url)
67
62
 
68
63
  def _convert_response_from_anthropic_to_openai(self, response):
@@ -94,7 +89,7 @@ class AnthropicModel(BaseModelBackend):
94
89
  tokenization style.
95
90
  """
96
91
  if not self._token_counter:
97
- self._token_counter = AnthropicTokenCounter()
92
+ self._token_counter = AnthropicTokenCounter(self.model_type)
98
93
  return self._token_counter
99
94
 
100
95
  def count_tokens_from_prompt(self, prompt: str) -> int:
@@ -122,14 +117,13 @@ class AnthropicModel(BaseModelBackend):
122
117
  Returns:
123
118
  ChatCompletion: Response in the OpenAI API format.
124
119
  """
125
- from anthropic import NOT_GIVEN
126
120
 
127
121
  if messages[0]["role"] == "system":
128
122
  sys_msg = str(messages.pop(0)["content"])
129
123
  else:
130
124
  sys_msg = NOT_GIVEN # type: ignore[assignment]
131
125
  response = self.client.messages.create(
132
- model=self.model_type,
126
+ model=self.model_type.value,
133
127
  system=sys_msg,
134
128
  messages=messages, # type: ignore[arg-type]
135
129
  **self.model_config_dict,
@@ -16,65 +16,60 @@ from typing import Any, Dict, List, Optional, Union
16
16
 
17
17
  from openai import AzureOpenAI, Stream
18
18
 
19
- from camel.configs import OPENAI_API_PARAMS, ChatGPTConfig
19
+ from camel.configs import OPENAI_API_PARAMS
20
20
  from camel.messages import OpenAIMessage
21
21
  from camel.models.base_model import BaseModelBackend
22
- from camel.types import (
23
- ChatCompletion,
24
- ChatCompletionChunk,
25
- ModelType,
26
- )
22
+ from camel.types import ChatCompletion, ChatCompletionChunk, ModelType
27
23
  from camel.utils import BaseTokenCounter, OpenAITokenCounter, api_keys_required
28
24
 
29
25
 
30
26
  class AzureOpenAIModel(BaseModelBackend):
31
27
  r"""Azure OpenAI API in a unified BaseModelBackend interface.
32
-
33
- Args:
34
- model_type (Union[ModelType, str]): Model for which a backend is
35
- created, one of GPT_* series.
36
- model_config_dict (Optional[Dict[str, Any]], optional): A dictionary
37
- that will be fed into:obj:`openai.ChatCompletion.create()`. If
38
- :obj:`None`, :obj:`ChatGPTConfig().as_dict()` will be used.
39
- (default: :obj:`None`)
40
- api_key (Optional[str], optional): The API key for authenticating with
41
- the OpenAI service. (default: :obj:`None`)
42
- url (Optional[str], optional): The url to the OpenAI service.
43
- (default: :obj:`None`)
44
- api_version (Optional[str], optional): The api version for the model.
45
- (default: :obj:`None`)
46
- azure_deployment_name (Optional[str], optional): The deployment name
47
- you chose when you deployed an azure model. (default: :obj:`None`)
48
- token_counter (Optional[BaseTokenCounter], optional): Token counter to
49
- use for the model. If not provided, :obj:`OpenAITokenCounter`
50
- will be used. (default: :obj:`None`)
51
-
52
- References:
53
- https://learn.microsoft.com/en-us/azure/ai-services/openai/
28
+ Doc: https://learn.microsoft.com/en-us/azure/ai-services/openai/
54
29
  """
55
30
 
56
31
  def __init__(
57
32
  self,
58
- model_type: Union[ModelType, str],
59
- model_config_dict: Optional[Dict[str, Any]] = None,
33
+ model_type: ModelType,
34
+ model_config_dict: Dict[str, Any],
60
35
  api_key: Optional[str] = None,
61
36
  url: Optional[str] = None,
62
- token_counter: Optional[BaseTokenCounter] = None,
63
37
  api_version: Optional[str] = None,
64
38
  azure_deployment_name: Optional[str] = None,
65
39
  ) -> None:
66
- if model_config_dict is None:
67
- model_config_dict = ChatGPTConfig().as_dict()
68
- api_key = api_key or os.environ.get("AZURE_OPENAI_API_KEY")
69
- url = url or os.environ.get("AZURE_OPENAI_BASE_URL")
70
- super().__init__(
71
- model_type, model_config_dict, api_key, url, token_counter
72
- )
40
+ r"""Constructor for OpenAI backend.
73
41
 
42
+ Args:
43
+ model_type (ModelType): Model for which a backend is created,
44
+ one of GPT_* series.
45
+ model_config_dict (Dict[str, Any]): A dictionary that will
46
+ be fed into openai.ChatCompletion.create().
47
+ api_key (Optional[str]): The API key for authenticating with the
48
+ OpenAI service. (default: :obj:`None`)
49
+ url (Optional[str]): The url to the OpenAI service. (default:
50
+ :obj:`None`)
51
+ api_version (Optional[str]): The api version for the model.
52
+ azure_deployment_name (Optional[str]): The deployment name you
53
+ chose when you deployed an azure model. (default: :obj:`None`)
54
+ """
55
+ super().__init__(model_type, model_config_dict, api_key, url)
56
+ self._url = url or os.environ.get("AZURE_OPENAI_ENDPOINT")
57
+ self._api_key = api_key or os.environ.get("AZURE_OPENAI_API_KEY")
74
58
  self.api_version = api_version or os.environ.get("AZURE_API_VERSION")
75
59
  self.azure_deployment_name = azure_deployment_name or os.environ.get(
76
60
  "AZURE_DEPLOYMENT_NAME"
77
61
  )
62
+
63
+ if self._url is None:
64
+ raise ValueError(
65
+ "Must provide either the `url` argument "
66
+ "or `AZURE_OPENAI_ENDPOINT` environment variable."
67
+ )
68
+ if self._api_key is None:
69
+ raise ValueError(
70
+ "Must provide either the `api_key` argument "
71
+ "or `AZURE_OPENAI_API_KEY` environment variable."
72
+ )
78
73
  if self.api_version is None:
79
74
  raise ValueError(
80
75
  "Must provide either the `api_version` argument "
@@ -85,6 +80,7 @@ class AzureOpenAIModel(BaseModelBackend):
85
80
  "Must provide either the `azure_deployment_name` argument "
86
81
  "or `AZURE_DEPLOYMENT_NAME` environment variable."
87
82
  )
83
+ self.model = str(self.azure_deployment_name)
88
84
 
89
85
  self._client = AzureOpenAI(
90
86
  azure_endpoint=str(self._url),
@@ -94,6 +90,7 @@ class AzureOpenAIModel(BaseModelBackend):
94
90
  timeout=60,
95
91
  max_retries=3,
96
92
  )
93
+ self._token_counter: Optional[BaseTokenCounter] = None
97
94
 
98
95
  @property
99
96
  def token_counter(self) -> BaseTokenCounter:
@@ -125,7 +122,7 @@ class AzureOpenAIModel(BaseModelBackend):
125
122
  """
126
123
  response = self._client.chat.completions.create(
127
124
  messages=messages,
128
- model=self.azure_deployment_name, # type:ignore[arg-type]
125
+ model=self.model,
129
126
  **self.model_config_dict,
130
127
  )
131
128
  return response