camel-ai 0.1.1__py3-none-any.whl → 0.1.4__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 (117) hide show
  1. camel/__init__.py +1 -11
  2. camel/agents/__init__.py +7 -5
  3. camel/agents/chat_agent.py +134 -86
  4. camel/agents/critic_agent.py +28 -17
  5. camel/agents/deductive_reasoner_agent.py +235 -0
  6. camel/agents/embodied_agent.py +92 -40
  7. camel/agents/knowledge_graph_agent.py +221 -0
  8. camel/agents/role_assignment_agent.py +27 -17
  9. camel/agents/task_agent.py +60 -34
  10. camel/agents/tool_agents/base.py +0 -1
  11. camel/agents/tool_agents/hugging_face_tool_agent.py +7 -4
  12. camel/configs/__init__.py +29 -0
  13. camel/configs/anthropic_config.py +73 -0
  14. camel/configs/base_config.py +22 -0
  15. camel/{configs.py → configs/openai_config.py} +37 -64
  16. camel/embeddings/__init__.py +2 -0
  17. camel/embeddings/base.py +3 -2
  18. camel/embeddings/openai_embedding.py +10 -5
  19. camel/embeddings/sentence_transformers_embeddings.py +65 -0
  20. camel/functions/__init__.py +18 -3
  21. camel/functions/google_maps_function.py +335 -0
  22. camel/functions/math_functions.py +7 -7
  23. camel/functions/open_api_function.py +380 -0
  24. camel/functions/open_api_specs/coursera/__init__.py +13 -0
  25. camel/functions/open_api_specs/coursera/openapi.yaml +82 -0
  26. camel/functions/open_api_specs/klarna/__init__.py +13 -0
  27. camel/functions/open_api_specs/klarna/openapi.yaml +87 -0
  28. camel/functions/open_api_specs/speak/__init__.py +13 -0
  29. camel/functions/open_api_specs/speak/openapi.yaml +151 -0
  30. camel/functions/openai_function.py +346 -42
  31. camel/functions/retrieval_functions.py +61 -0
  32. camel/functions/search_functions.py +100 -35
  33. camel/functions/slack_functions.py +275 -0
  34. camel/functions/twitter_function.py +484 -0
  35. camel/functions/weather_functions.py +36 -23
  36. camel/generators.py +65 -46
  37. camel/human.py +17 -11
  38. camel/interpreters/__init__.py +25 -0
  39. camel/interpreters/base.py +49 -0
  40. camel/{utils/python_interpreter.py → interpreters/internal_python_interpreter.py} +129 -48
  41. camel/interpreters/interpreter_error.py +19 -0
  42. camel/interpreters/subprocess_interpreter.py +190 -0
  43. camel/loaders/__init__.py +22 -0
  44. camel/{functions/base_io_functions.py → loaders/base_io.py} +38 -35
  45. camel/{functions/unstructured_io_fuctions.py → loaders/unstructured_io.py} +199 -110
  46. camel/memories/__init__.py +17 -7
  47. camel/memories/agent_memories.py +156 -0
  48. camel/memories/base.py +97 -32
  49. camel/memories/blocks/__init__.py +21 -0
  50. camel/memories/{chat_history_memory.py → blocks/chat_history_block.py} +34 -34
  51. camel/memories/blocks/vectordb_block.py +101 -0
  52. camel/memories/context_creators/__init__.py +3 -2
  53. camel/memories/context_creators/score_based.py +32 -20
  54. camel/memories/records.py +6 -5
  55. camel/messages/__init__.py +2 -2
  56. camel/messages/base.py +99 -16
  57. camel/messages/func_message.py +7 -4
  58. camel/models/__init__.py +6 -2
  59. camel/models/anthropic_model.py +146 -0
  60. camel/models/base_model.py +10 -3
  61. camel/models/model_factory.py +17 -11
  62. camel/models/open_source_model.py +25 -13
  63. camel/models/openai_audio_models.py +251 -0
  64. camel/models/openai_model.py +20 -13
  65. camel/models/stub_model.py +10 -5
  66. camel/prompts/__init__.py +7 -5
  67. camel/prompts/ai_society.py +21 -14
  68. camel/prompts/base.py +54 -47
  69. camel/prompts/code.py +22 -14
  70. camel/prompts/evaluation.py +8 -5
  71. camel/prompts/misalignment.py +26 -19
  72. camel/prompts/object_recognition.py +35 -0
  73. camel/prompts/prompt_templates.py +14 -8
  74. camel/prompts/role_description_prompt_template.py +16 -10
  75. camel/prompts/solution_extraction.py +9 -5
  76. camel/prompts/task_prompt_template.py +24 -21
  77. camel/prompts/translation.py +9 -5
  78. camel/responses/agent_responses.py +5 -2
  79. camel/retrievers/__init__.py +26 -0
  80. camel/retrievers/auto_retriever.py +330 -0
  81. camel/retrievers/base.py +69 -0
  82. camel/retrievers/bm25_retriever.py +140 -0
  83. camel/retrievers/cohere_rerank_retriever.py +108 -0
  84. camel/retrievers/vector_retriever.py +183 -0
  85. camel/societies/__init__.py +1 -1
  86. camel/societies/babyagi_playing.py +56 -32
  87. camel/societies/role_playing.py +188 -133
  88. camel/storages/__init__.py +18 -0
  89. camel/storages/graph_storages/__init__.py +23 -0
  90. camel/storages/graph_storages/base.py +82 -0
  91. camel/storages/graph_storages/graph_element.py +74 -0
  92. camel/storages/graph_storages/neo4j_graph.py +582 -0
  93. camel/storages/key_value_storages/base.py +1 -2
  94. camel/storages/key_value_storages/in_memory.py +1 -2
  95. camel/storages/key_value_storages/json.py +8 -13
  96. camel/storages/vectordb_storages/__init__.py +33 -0
  97. camel/storages/vectordb_storages/base.py +202 -0
  98. camel/storages/vectordb_storages/milvus.py +396 -0
  99. camel/storages/vectordb_storages/qdrant.py +373 -0
  100. camel/terminators/__init__.py +1 -1
  101. camel/terminators/base.py +2 -3
  102. camel/terminators/response_terminator.py +21 -12
  103. camel/terminators/token_limit_terminator.py +5 -3
  104. camel/toolkits/__init__.py +21 -0
  105. camel/toolkits/base.py +22 -0
  106. camel/toolkits/github_toolkit.py +245 -0
  107. camel/types/__init__.py +18 -6
  108. camel/types/enums.py +129 -15
  109. camel/types/openai_types.py +10 -5
  110. camel/utils/__init__.py +20 -13
  111. camel/utils/commons.py +170 -85
  112. camel/utils/token_counting.py +135 -15
  113. {camel_ai-0.1.1.dist-info → camel_ai-0.1.4.dist-info}/METADATA +123 -75
  114. camel_ai-0.1.4.dist-info/RECORD +119 -0
  115. {camel_ai-0.1.1.dist-info → camel_ai-0.1.4.dist-info}/WHEEL +1 -1
  116. camel/memories/context_creators/base.py +0 -72
  117. camel_ai-0.1.1.dist-info/RECORD +0 -75
camel/__init__.py CHANGED
@@ -11,18 +11,8 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
- import camel.agents
15
- import camel.configs
16
- import camel.generators
17
- import camel.messages
18
- import camel.prompts
19
- import camel.types
20
- import camel.utils
21
- import camel.functions
22
- import camel.memories
23
- import camel.storages
24
14
 
25
- __version__ = '0.1.1'
15
+ __version__ = '0.1.4'
26
16
 
27
17
  __all__ = [
28
18
  '__version__',
camel/agents/__init__.py CHANGED
@@ -13,17 +13,18 @@
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
14
  from .base import BaseAgent
15
15
  from .chat_agent import ChatAgent
16
+ from .critic_agent import CriticAgent
17
+ from .embodied_agent import EmbodiedAgent
18
+ from .knowledge_graph_agent import KnowledgeGraphAgent
19
+ from .role_assignment_agent import RoleAssignmentAgent
16
20
  from .task_agent import (
17
- TaskSpecifyAgent,
18
- TaskPlannerAgent,
19
21
  TaskCreationAgent,
22
+ TaskPlannerAgent,
20
23
  TaskPrioritizationAgent,
24
+ TaskSpecifyAgent,
21
25
  )
22
- from .critic_agent import CriticAgent
23
26
  from .tool_agents.base import BaseToolAgent
24
27
  from .tool_agents.hugging_face_tool_agent import HuggingFaceToolAgent
25
- from .embodied_agent import EmbodiedAgent
26
- from .role_assignment_agent import RoleAssignmentAgent
27
28
 
28
29
  __all__ = [
29
30
  'BaseAgent',
@@ -37,4 +38,5 @@ __all__ = [
37
38
  'HuggingFaceToolAgent',
38
39
  'EmbodiedAgent',
39
40
  'RoleAssignmentAgent',
41
+ 'KnowledgeGraphAgent',
40
42
  ]
@@ -11,18 +11,17 @@
11
11
  # See the License for the specific language governing permissions and
12
12
  # limitations under the License.
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
+ from __future__ import annotations
15
+
14
16
  import json
15
17
  from collections import defaultdict
16
18
  from dataclasses import dataclass
17
- from typing import Any, Callable, Dict, List, Optional, Tuple
18
-
19
- from openai import Stream
19
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
20
20
 
21
- from camel.agents import BaseAgent
22
- from camel.configs import BaseConfig, ChatGPTConfig
23
- from camel.functions import OpenAIFunction
21
+ from camel.agents.base import BaseAgent
22
+ from camel.configs import ChatGPTConfig
24
23
  from camel.memories import (
25
- BaseMemory,
24
+ AgentMemory,
26
25
  ChatHistoryMemory,
27
26
  MemoryRecord,
28
27
  ScoreBasedContextCreator,
@@ -30,7 +29,6 @@ from camel.memories import (
30
29
  from camel.messages import BaseMessage, FunctionCallingMessage, OpenAIMessage
31
30
  from camel.models import BaseModelBackend, ModelFactory
32
31
  from camel.responses import ChatAgentResponse
33
- from camel.terminators import ResponseTerminator
34
32
  from camel.types import (
35
33
  ChatCompletion,
36
34
  ChatCompletionChunk,
@@ -40,6 +38,13 @@ from camel.types import (
40
38
  )
41
39
  from camel.utils import get_model_encoding
42
40
 
41
+ if TYPE_CHECKING:
42
+ from openai import Stream
43
+
44
+ from camel.configs import BaseConfig
45
+ from camel.functions import OpenAIFunction
46
+ from camel.terminators import ResponseTerminator
47
+
43
48
 
44
49
  @dataclass(frozen=True)
45
50
  class FunctionCallingRecord:
@@ -51,6 +56,7 @@ class FunctionCallingRecord:
51
56
  the function.
52
57
  result (Any): The execution result of calling this function.
53
58
  """
59
+
54
60
  func_name: str
55
61
  args: Dict[str, Any]
56
62
  result: Any
@@ -62,9 +68,11 @@ class FunctionCallingRecord:
62
68
  str: Modified string to represent the function calling.
63
69
  """
64
70
 
65
- return (f"Function Execution: {self.func_name}\n"
66
- f"\tArgs: {self.args}\n"
67
- f"\tResult: {self.result}")
71
+ return (
72
+ f"Function Execution: {self.func_name}\n"
73
+ f"\tArgs: {self.args}\n"
74
+ f"\tResult: {self.result}"
75
+ )
68
76
 
69
77
 
70
78
  class ChatAgent(BaseAgent):
@@ -76,19 +84,22 @@ class ChatAgent(BaseAgent):
76
84
  responses. (default :obj:`ModelType.GPT_3_5_TURBO`)
77
85
  model_config (BaseConfig, optional): Configuration options for the
78
86
  LLM model. (default: :obj:`None`)
79
- memory (BaseMemory, optional): The agent memory for managing chat
87
+ api_key (str, optional): The API key for authenticating with the
88
+ LLM service. Only OpenAI and Anthropic model supported (default:
89
+ :obj:`None`)
90
+ memory (AgentMemory, optional): The agent memory for managing chat
80
91
  messages. If `None`, a :obj:`ChatHistoryMemory` will be used.
81
92
  (default: :obj:`None`)
82
93
  message_window_size (int, optional): The maximum number of previous
83
94
  messages to include in the context window. If `None`, no windowing
84
95
  is performed. (default: :obj:`None`)
85
- token_limit (int, optional): The maxinum number of tokens in a context.
96
+ token_limit (int, optional): The maximum number of tokens in a context.
86
97
  The context will be automatically pruned to fulfill the limitation.
87
98
  If `None`, it will be set according to the backend model.
88
99
  (default: :obj:`None`)
89
100
  output_language (str, optional): The language to be output by the
90
101
  agent. (default: :obj:`None`)
91
- function_list (List[OpenAIFunction], optional): List of available
102
+ tools (List[OpenAIFunction], optional): List of available
92
103
  :obj:`OpenAIFunction`. (default: :obj:`None`)
93
104
  response_terminators (List[ResponseTerminator], optional): List of
94
105
  :obj:`ResponseTerminator` bind to one chat agent.
@@ -100,14 +111,14 @@ class ChatAgent(BaseAgent):
100
111
  system_message: BaseMessage,
101
112
  model_type: Optional[ModelType] = None,
102
113
  model_config: Optional[BaseConfig] = None,
103
- memory: Optional[BaseMemory] = None,
114
+ api_key: Optional[str] = None,
115
+ memory: Optional[AgentMemory] = None,
104
116
  message_window_size: Optional[int] = None,
105
117
  token_limit: Optional[int] = None,
106
118
  output_language: Optional[str] = None,
107
- function_list: Optional[List[OpenAIFunction]] = None,
119
+ tools: Optional[List[OpenAIFunction]] = None,
108
120
  response_terminators: Optional[List[ResponseTerminator]] = None,
109
121
  ) -> None:
110
-
111
122
  self.orig_sys_message: BaseMessage = system_message
112
123
  self.system_message = system_message
113
124
  self.role_name: str = system_message.role_name
@@ -116,24 +127,28 @@ class ChatAgent(BaseAgent):
116
127
  if self.output_language is not None:
117
128
  self.set_output_language(self.output_language)
118
129
 
119
- self.model_type: ModelType = (model_type if model_type is not None else
120
- ModelType.GPT_3_5_TURBO)
130
+ self.model_type: ModelType = (
131
+ model_type if model_type is not None else ModelType.GPT_3_5_TURBO
132
+ )
121
133
 
122
134
  self.func_dict: Dict[str, Callable] = {}
123
- if function_list is not None:
124
- for func in function_list:
125
- self.func_dict[func.name] = func.func
126
- self.model_config = model_config or ChatGPTConfig()
135
+ if tools is not None:
136
+ for func in tools:
137
+ self.func_dict[func.get_function_name()] = func.func
127
138
 
139
+ self.model_config = model_config or ChatGPTConfig()
140
+ self._api_key = api_key
128
141
  self.model_backend: BaseModelBackend = ModelFactory.create(
129
- self.model_type, self.model_config.__dict__)
142
+ self.model_type, self.model_config.__dict__, self._api_key
143
+ )
130
144
  self.model_token_limit = token_limit or self.model_backend.token_limit
131
145
  context_creator = ScoreBasedContextCreator(
132
146
  self.model_backend.token_counter,
133
147
  self.model_token_limit,
134
148
  )
135
- self.memory: BaseMemory = memory or ChatHistoryMemory(
136
- context_creator, window_size=message_window_size)
149
+ self.memory: AgentMemory = memory or ChatHistoryMemory(
150
+ context_creator, window_size=message_window_size
151
+ )
137
152
 
138
153
  self.terminated: bool = False
139
154
  self.response_terminators = response_terminators or []
@@ -170,18 +185,19 @@ class ChatAgent(BaseAgent):
170
185
  """
171
186
  self._system_message = message
172
187
 
173
- def is_function_calling_enabled(self) -> bool:
188
+ def is_tools_added(self) -> bool:
174
189
  r"""Whether OpenAI function calling is enabled for this agent.
175
190
 
176
191
  Returns:
177
192
  bool: Whether OpenAI function calling is enabled for this
178
- agent, determined by whether the dictionary of functions
193
+ agent, determined by whether the dictionary of tools
179
194
  is empty.
180
195
  """
181
196
  return len(self.func_dict) > 0
182
197
 
183
- def update_memory(self, message: BaseMessage,
184
- role: OpenAIBackendRole) -> None:
198
+ def update_memory(
199
+ self, message: BaseMessage, role: OpenAIBackendRole
200
+ ) -> None:
185
201
  r"""Updates the agent memory with a new message.
186
202
 
187
203
  Args:
@@ -204,15 +220,21 @@ class ChatAgent(BaseAgent):
204
220
  BaseMessage: The updated system message object.
205
221
  """
206
222
  self.output_language = output_language
207
- content = (self.orig_sys_message.content +
208
- ("\nRegardless of the input language, "
209
- f"you must output text in {output_language}."))
223
+ content = self.orig_sys_message.content + (
224
+ "\nRegardless of the input language, "
225
+ f"you must output text in {output_language}."
226
+ )
210
227
  self.system_message = self.system_message.create_new_instance(content)
211
228
  return self.system_message
212
229
 
213
- def get_info(self, id: Optional[str], usage: Optional[Dict[str, int]],
214
- termination_reasons: List[str], num_tokens: int,
215
- called_funcs: List[FunctionCallingRecord]) -> Dict[str, Any]:
230
+ def get_info(
231
+ self,
232
+ id: Optional[str],
233
+ usage: Optional[Dict[str, int]],
234
+ termination_reasons: List[str],
235
+ num_tokens: int,
236
+ tool_calls: List[FunctionCallingRecord],
237
+ ) -> Dict[str, Any]:
216
238
  r"""Returns a dictionary containing information about the chat session.
217
239
 
218
240
  Args:
@@ -222,9 +244,9 @@ class ChatAgent(BaseAgent):
222
244
  termination_reasons (List[str]): The reasons for the termination
223
245
  of the chat session.
224
246
  num_tokens (int): The number of tokens used in the chat session.
225
- called_funcs (List[FunctionCallingRecord]): The list of function
247
+ tool_calls (List[FunctionCallingRecord]): The list of function
226
248
  calling records, containing the information of called
227
- functions.
249
+ tools.
228
250
 
229
251
  Returns:
230
252
  Dict[str, Any]: The chat session information.
@@ -234,15 +256,16 @@ class ChatAgent(BaseAgent):
234
256
  "usage": usage,
235
257
  "termination_reasons": termination_reasons,
236
258
  "num_tokens": num_tokens,
237
- "called_functions": called_funcs,
259
+ "tool_calls": tool_calls,
238
260
  }
239
261
 
240
262
  def init_messages(self) -> None:
241
263
  r"""Initializes the stored messages list with the initial system
242
264
  message.
243
265
  """
244
- system_record = MemoryRecord(self.system_message,
245
- OpenAIBackendRole.SYSTEM)
266
+ system_record = MemoryRecord(
267
+ self.system_message, OpenAIBackendRole.SYSTEM
268
+ )
246
269
  self.memory.clear()
247
270
  self.memory.write_record(system_record)
248
271
 
@@ -266,9 +289,10 @@ class ChatAgent(BaseAgent):
266
289
 
267
290
  Args:
268
291
  input_message (BaseMessage): The input message to the agent.
269
- Its `role` field that specifies the role at backend may be either
270
- `user` or `assistant` but it will be set to `user` anyway since
271
- for the self agent any incoming message is external.
292
+ Its `role` field that specifies the role at backend may be
293
+ either `user` or `assistant` but it will be set to `user`
294
+ anyway since for the self agent any incoming message is
295
+ external.
272
296
 
273
297
  Returns:
274
298
  ChatAgentResponse: A struct containing the output messages,
@@ -279,7 +303,7 @@ class ChatAgent(BaseAgent):
279
303
 
280
304
  output_messages: List[BaseMessage]
281
305
  info: Dict[str, Any]
282
- called_funcs: List[FunctionCallingRecord] = []
306
+ tool_calls: List[FunctionCallingRecord] = []
283
307
  while True:
284
308
  # Format messages and get the token number
285
309
  openai_messages: Optional[List[OpenAIMessage]]
@@ -287,33 +311,43 @@ class ChatAgent(BaseAgent):
287
311
  try:
288
312
  openai_messages, num_tokens = self.memory.get_context()
289
313
  except RuntimeError as e:
290
- return self.step_token_exceed(e.args[1], called_funcs,
291
- "max_tokens_exceeded")
314
+ return self.step_token_exceed(
315
+ e.args[1], tool_calls, "max_tokens_exceeded"
316
+ )
292
317
 
293
318
  # Obtain the model's response
294
319
  response = self.model_backend.run(openai_messages)
295
320
 
296
321
  if isinstance(response, ChatCompletion):
297
322
  output_messages, finish_reasons, usage_dict, response_id = (
298
- self.handle_batch_response(response))
323
+ self.handle_batch_response(response)
324
+ )
299
325
  else:
300
326
  output_messages, finish_reasons, usage_dict, response_id = (
301
- self.handle_stream_response(response, num_tokens))
327
+ self.handle_stream_response(response, num_tokens)
328
+ )
329
+
330
+ if (
331
+ self.is_tools_added()
332
+ and isinstance(response, ChatCompletion)
333
+ and response.choices[0].message.tool_calls is not None
334
+ ):
335
+ # Tools added for function calling and not in stream mode
302
336
 
303
- if (self.is_function_calling_enabled()
304
- and finish_reasons[0] == 'function_call'
305
- and isinstance(response, ChatCompletion)):
306
337
  # Do function calling
307
338
  func_assistant_msg, func_result_msg, func_record = (
308
- self.step_function_call(response))
339
+ self.step_tool_call(response)
340
+ )
309
341
 
310
342
  # Update the messages
311
- self.update_memory(func_assistant_msg,
312
- OpenAIBackendRole.ASSISTANT)
343
+ self.update_memory(
344
+ func_assistant_msg, OpenAIBackendRole.ASSISTANT
345
+ )
313
346
  self.update_memory(func_result_msg, OpenAIBackendRole.FUNCTION)
314
347
 
315
348
  # Record the function calling
316
- called_funcs.append(func_record)
349
+ tool_calls.append(func_record)
350
+
317
351
  else:
318
352
  # Function calling disabled or not a function calling
319
353
 
@@ -326,9 +360,13 @@ class ChatAgent(BaseAgent):
326
360
  ]
327
361
  # Terminate the agent if any of the terminator terminates
328
362
  self.terminated, termination_reason = next(
329
- ((terminated, termination_reason)
330
- for terminated, termination_reason in termination
331
- if terminated), (False, None))
363
+ (
364
+ (terminated, termination_reason)
365
+ for terminated, termination_reason in termination
366
+ if terminated
367
+ ),
368
+ (False, None),
369
+ )
332
370
  # For now only retain the first termination reason
333
371
  if self.terminated and termination_reason is not None:
334
372
  finish_reasons = [termination_reason] * len(finish_reasons)
@@ -338,7 +376,7 @@ class ChatAgent(BaseAgent):
338
376
  usage_dict,
339
377
  finish_reasons,
340
378
  num_tokens,
341
- called_funcs,
379
+ tool_calls,
342
380
  )
343
381
  break
344
382
 
@@ -368,8 +406,9 @@ class ChatAgent(BaseAgent):
368
406
  finish_reasons = [
369
407
  str(choice.finish_reason) for choice in response.choices
370
408
  ]
371
- usage = (response.usage.model_dump()
372
- if response.usage is not None else {})
409
+ usage = (
410
+ response.usage.model_dump() if response.usage is not None else {}
411
+ )
373
412
  return (
374
413
  output_messages,
375
414
  finish_reasons,
@@ -408,10 +447,12 @@ class ChatAgent(BaseAgent):
408
447
  content_dict[index] += delta.content
409
448
  else:
410
449
  finish_reasons_dict[index] = choice.finish_reason
411
- chat_message = BaseMessage(role_name=self.role_name,
412
- role_type=self.role_type,
413
- meta_dict=dict(),
414
- content=content_dict[index])
450
+ chat_message = BaseMessage(
451
+ role_name=self.role_name,
452
+ role_type=self.role_type,
453
+ meta_dict=dict(),
454
+ content=content_dict[index],
455
+ )
415
456
  output_messages.append(chat_message)
416
457
  finish_reasons = [
417
458
  finish_reasons_dict[i] for i in range(len(finish_reasons_dict))
@@ -419,15 +460,18 @@ class ChatAgent(BaseAgent):
419
460
  usage_dict = self.get_usage_dict(output_messages, prompt_tokens)
420
461
  return output_messages, finish_reasons, usage_dict, response_id
421
462
 
422
- def step_token_exceed(self, num_tokens: int,
423
- called_funcs: List[FunctionCallingRecord],
424
- termination_reason: str) -> ChatAgentResponse:
463
+ def step_token_exceed(
464
+ self,
465
+ num_tokens: int,
466
+ tool_calls: List[FunctionCallingRecord],
467
+ termination_reason: str,
468
+ ) -> ChatAgentResponse:
425
469
  r"""Return trivial response containing number of tokens and information
426
470
  of called functions when the number of tokens exceeds.
427
471
 
428
472
  Args:
429
473
  num_tokens (int): Number of tokens in the messages.
430
- called_funcs (List[FunctionCallingRecord]): List of information
474
+ tool_calls (List[FunctionCallingRecord]): List of information
431
475
  objects of functions called in the current step.
432
476
  termination_reason (str): String of termination reason.
433
477
 
@@ -443,7 +487,7 @@ class ChatAgent(BaseAgent):
443
487
  None,
444
488
  [termination_reason],
445
489
  num_tokens,
446
- called_funcs,
490
+ tool_calls,
447
491
  )
448
492
 
449
493
  return ChatAgentResponse(
@@ -452,11 +496,12 @@ class ChatAgent(BaseAgent):
452
496
  info,
453
497
  )
454
498
 
455
- def step_function_call(
499
+ def step_tool_call(
456
500
  self,
457
501
  response: ChatCompletion,
458
- ) -> Tuple[FunctionCallingMessage, FunctionCallingMessage,
459
- FunctionCallingRecord]:
502
+ ) -> Tuple[
503
+ FunctionCallingMessage, FunctionCallingMessage, FunctionCallingRecord
504
+ ]:
460
505
  r"""Execute the function with arguments following the model's response.
461
506
 
462
507
  Args:
@@ -469,15 +514,14 @@ class ChatAgent(BaseAgent):
469
514
  result, and a struct for logging information about this
470
515
  function call.
471
516
  """
472
- # Note that when function calling is enabled, `n` is set to 1.
473
517
  choice = response.choices[0]
474
- if choice.message.function_call is None:
475
- raise RuntimeError("Function call is None")
476
- func_name = choice.message.function_call.name
518
+ if choice.message.tool_calls is None:
519
+ raise RuntimeError("Tool calls is None")
520
+ func_name = choice.message.tool_calls[0].function.name
477
521
  func = self.func_dict[func_name]
478
522
 
479
- args_str: str = choice.message.function_call.arguments
480
- args = json.loads(args_str.replace("\'", "\""))
523
+ args_str: str = choice.message.tool_calls[0].function.arguments
524
+ args = json.loads(args_str.replace("'", "\""))
481
525
 
482
526
  # Pass the extracted arguments to the indicated function
483
527
  try:
@@ -485,7 +529,8 @@ class ChatAgent(BaseAgent):
485
529
  except Exception:
486
530
  raise ValueError(
487
531
  f"Execution of function {func.__name__} failed with "
488
- f"arguments being {args}.")
532
+ f"arguments being {args}."
533
+ )
489
534
 
490
535
  assist_msg = FunctionCallingMessage(
491
536
  role_name=self.role_name,
@@ -508,8 +553,9 @@ class ChatAgent(BaseAgent):
508
553
  func_record = FunctionCallingRecord(func_name, args, result)
509
554
  return assist_msg, func_msg, func_record
510
555
 
511
- def get_usage_dict(self, output_messages: List[BaseMessage],
512
- prompt_tokens: int) -> Dict[str, int]:
556
+ def get_usage_dict(
557
+ self, output_messages: List[BaseMessage], prompt_tokens: int
558
+ ) -> Dict[str, int]:
513
559
  r"""Get usage dictionary when using the stream mode.
514
560
 
515
561
  Args:
@@ -523,9 +569,11 @@ class ChatAgent(BaseAgent):
523
569
  completion_tokens = 0
524
570
  for message in output_messages:
525
571
  completion_tokens += len(encoding.encode(message.content))
526
- usage_dict = dict(completion_tokens=completion_tokens,
527
- prompt_tokens=prompt_tokens,
528
- total_tokens=completion_tokens + prompt_tokens)
572
+ usage_dict = dict(
573
+ completion_tokens=completion_tokens,
574
+ prompt_tokens=prompt_tokens,
575
+ total_tokens=completion_tokens + prompt_tokens,
576
+ )
529
577
  return usage_dict
530
578
 
531
579
  def __repr__(self) -> str:
@@ -17,8 +17,8 @@ from typing import Any, Dict, Optional, Sequence
17
17
 
18
18
  from colorama import Fore
19
19
 
20
- from camel.agents import ChatAgent
21
- from camel.memories import BaseMemory
20
+ from camel.agents.chat_agent import ChatAgent
21
+ from camel.memories import AgentMemory
22
22
  from camel.messages import BaseMessage
23
23
  from camel.responses import ChatAgentResponse
24
24
  from camel.types import ModelType
@@ -50,15 +50,19 @@ class CriticAgent(ChatAgent):
50
50
  system_message: BaseMessage,
51
51
  model_type: ModelType = ModelType.GPT_3_5_TURBO,
52
52
  model_config: Optional[Any] = None,
53
- memory: Optional[BaseMemory] = None,
53
+ memory: Optional[AgentMemory] = None,
54
54
  message_window_size: int = 6,
55
55
  retry_attempts: int = 2,
56
56
  verbose: bool = False,
57
57
  logger_color: Any = Fore.MAGENTA,
58
58
  ) -> None:
59
- super().__init__(system_message, model_type=model_type,
60
- model_config=model_config, memory=memory,
61
- message_window_size=message_window_size)
59
+ super().__init__(
60
+ system_message,
61
+ model_type=model_type,
62
+ model_config=model_config,
63
+ memory=memory,
64
+ message_window_size=message_window_size,
65
+ )
62
66
  self.options_dict: Dict[str, str] = dict()
63
67
  self.retry_attempts = retry_attempts
64
68
  self.verbose = verbose
@@ -77,13 +81,15 @@ class CriticAgent(ChatAgent):
77
81
  flatten_options = (
78
82
  f"> Proposals from "
79
83
  f"{messages[0].role_name} ({messages[0].role_type}). "
80
- "Please choose an option:\n")
84
+ "Please choose an option:\n"
85
+ )
81
86
  for index, option in enumerate(options):
82
87
  flatten_options += f"Option {index + 1}:\n{option}\n\n"
83
88
  self.options_dict[str(index + 1)] = option
84
89
  format = (
85
90
  f"Please first enter your choice ([1-{len(self.options_dict)}]) "
86
- "and then your explanation and comparison: ")
91
+ "and then your explanation and comparison: "
92
+ )
87
93
  return flatten_options + format
88
94
 
89
95
  def get_option(self, input_message: BaseMessage) -> str:
@@ -110,8 +116,10 @@ class CriticAgent(ChatAgent):
110
116
  critic_msg = critic_response.msg
111
117
  self.record_message(critic_msg)
112
118
  if self.verbose:
113
- print_text_animated(self.logger_color + "\n> Critic response: "
114
- f"\x1b[3m{critic_msg.content}\x1b[0m\n")
119
+ print_text_animated(
120
+ self.logger_color + "\n> Critic response: "
121
+ f"\x1b[3m{critic_msg.content}\x1b[0m\n"
122
+ )
115
123
  choice = self.parse_critic(critic_msg)
116
124
 
117
125
  if choice in self.options_dict:
@@ -121,13 +129,15 @@ class CriticAgent(ChatAgent):
121
129
  role_name=input_message.role_name,
122
130
  role_type=input_message.role_type,
123
131
  meta_dict=input_message.meta_dict,
124
- content="> Invalid choice. Please choose again.\n" +
125
- msg_content,
132
+ content="> Invalid choice. Please choose again.\n"
133
+ + msg_content,
126
134
  )
127
135
  i += 1
128
- warnings.warn("Critic failed to get a valid option. "
129
- f"After {self.retry_attempts} attempts. "
130
- "Returning a random option.")
136
+ warnings.warn(
137
+ "Critic failed to get a valid option. "
138
+ f"After {self.retry_attempts} attempts. "
139
+ "Returning a random option."
140
+ )
131
141
  return random.choice(list(self.options_dict.values()))
132
142
 
133
143
  def parse_critic(self, critic_msg: BaseMessage) -> Optional[str]:
@@ -168,8 +178,9 @@ class CriticAgent(ChatAgent):
168
178
 
169
179
  flatten_options = self.flatten_options(input_messages)
170
180
  if self.verbose:
171
- print_text_animated(self.logger_color +
172
- f"\x1b[3m{flatten_options}\x1b[0m\n")
181
+ print_text_animated(
182
+ self.logger_color + f"\x1b[3m{flatten_options}\x1b[0m\n"
183
+ )
173
184
  input_msg = meta_chat_message.create_new_instance(flatten_options)
174
185
 
175
186
  option = self.get_option(input_msg)