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.
- camel/__init__.py +1 -11
- camel/agents/__init__.py +7 -5
- camel/agents/chat_agent.py +134 -86
- camel/agents/critic_agent.py +28 -17
- camel/agents/deductive_reasoner_agent.py +235 -0
- camel/agents/embodied_agent.py +92 -40
- camel/agents/knowledge_graph_agent.py +221 -0
- camel/agents/role_assignment_agent.py +27 -17
- camel/agents/task_agent.py +60 -34
- camel/agents/tool_agents/base.py +0 -1
- camel/agents/tool_agents/hugging_face_tool_agent.py +7 -4
- camel/configs/__init__.py +29 -0
- camel/configs/anthropic_config.py +73 -0
- camel/configs/base_config.py +22 -0
- camel/{configs.py → configs/openai_config.py} +37 -64
- camel/embeddings/__init__.py +2 -0
- camel/embeddings/base.py +3 -2
- camel/embeddings/openai_embedding.py +10 -5
- camel/embeddings/sentence_transformers_embeddings.py +65 -0
- camel/functions/__init__.py +18 -3
- camel/functions/google_maps_function.py +335 -0
- camel/functions/math_functions.py +7 -7
- camel/functions/open_api_function.py +380 -0
- camel/functions/open_api_specs/coursera/__init__.py +13 -0
- camel/functions/open_api_specs/coursera/openapi.yaml +82 -0
- camel/functions/open_api_specs/klarna/__init__.py +13 -0
- camel/functions/open_api_specs/klarna/openapi.yaml +87 -0
- camel/functions/open_api_specs/speak/__init__.py +13 -0
- camel/functions/open_api_specs/speak/openapi.yaml +151 -0
- camel/functions/openai_function.py +346 -42
- camel/functions/retrieval_functions.py +61 -0
- camel/functions/search_functions.py +100 -35
- camel/functions/slack_functions.py +275 -0
- camel/functions/twitter_function.py +484 -0
- camel/functions/weather_functions.py +36 -23
- camel/generators.py +65 -46
- camel/human.py +17 -11
- camel/interpreters/__init__.py +25 -0
- camel/interpreters/base.py +49 -0
- camel/{utils/python_interpreter.py → interpreters/internal_python_interpreter.py} +129 -48
- camel/interpreters/interpreter_error.py +19 -0
- camel/interpreters/subprocess_interpreter.py +190 -0
- camel/loaders/__init__.py +22 -0
- camel/{functions/base_io_functions.py → loaders/base_io.py} +38 -35
- camel/{functions/unstructured_io_fuctions.py → loaders/unstructured_io.py} +199 -110
- camel/memories/__init__.py +17 -7
- camel/memories/agent_memories.py +156 -0
- camel/memories/base.py +97 -32
- camel/memories/blocks/__init__.py +21 -0
- camel/memories/{chat_history_memory.py → blocks/chat_history_block.py} +34 -34
- camel/memories/blocks/vectordb_block.py +101 -0
- camel/memories/context_creators/__init__.py +3 -2
- camel/memories/context_creators/score_based.py +32 -20
- camel/memories/records.py +6 -5
- camel/messages/__init__.py +2 -2
- camel/messages/base.py +99 -16
- camel/messages/func_message.py +7 -4
- camel/models/__init__.py +6 -2
- camel/models/anthropic_model.py +146 -0
- camel/models/base_model.py +10 -3
- camel/models/model_factory.py +17 -11
- camel/models/open_source_model.py +25 -13
- camel/models/openai_audio_models.py +251 -0
- camel/models/openai_model.py +20 -13
- camel/models/stub_model.py +10 -5
- camel/prompts/__init__.py +7 -5
- camel/prompts/ai_society.py +21 -14
- camel/prompts/base.py +54 -47
- camel/prompts/code.py +22 -14
- camel/prompts/evaluation.py +8 -5
- camel/prompts/misalignment.py +26 -19
- camel/prompts/object_recognition.py +35 -0
- camel/prompts/prompt_templates.py +14 -8
- camel/prompts/role_description_prompt_template.py +16 -10
- camel/prompts/solution_extraction.py +9 -5
- camel/prompts/task_prompt_template.py +24 -21
- camel/prompts/translation.py +9 -5
- camel/responses/agent_responses.py +5 -2
- camel/retrievers/__init__.py +26 -0
- camel/retrievers/auto_retriever.py +330 -0
- camel/retrievers/base.py +69 -0
- camel/retrievers/bm25_retriever.py +140 -0
- camel/retrievers/cohere_rerank_retriever.py +108 -0
- camel/retrievers/vector_retriever.py +183 -0
- camel/societies/__init__.py +1 -1
- camel/societies/babyagi_playing.py +56 -32
- camel/societies/role_playing.py +188 -133
- camel/storages/__init__.py +18 -0
- camel/storages/graph_storages/__init__.py +23 -0
- camel/storages/graph_storages/base.py +82 -0
- camel/storages/graph_storages/graph_element.py +74 -0
- camel/storages/graph_storages/neo4j_graph.py +582 -0
- camel/storages/key_value_storages/base.py +1 -2
- camel/storages/key_value_storages/in_memory.py +1 -2
- camel/storages/key_value_storages/json.py +8 -13
- camel/storages/vectordb_storages/__init__.py +33 -0
- camel/storages/vectordb_storages/base.py +202 -0
- camel/storages/vectordb_storages/milvus.py +396 -0
- camel/storages/vectordb_storages/qdrant.py +373 -0
- camel/terminators/__init__.py +1 -1
- camel/terminators/base.py +2 -3
- camel/terminators/response_terminator.py +21 -12
- camel/terminators/token_limit_terminator.py +5 -3
- camel/toolkits/__init__.py +21 -0
- camel/toolkits/base.py +22 -0
- camel/toolkits/github_toolkit.py +245 -0
- camel/types/__init__.py +18 -6
- camel/types/enums.py +129 -15
- camel/types/openai_types.py +10 -5
- camel/utils/__init__.py +20 -13
- camel/utils/commons.py +170 -85
- camel/utils/token_counting.py +135 -15
- {camel_ai-0.1.1.dist-info → camel_ai-0.1.4.dist-info}/METADATA +123 -75
- camel_ai-0.1.4.dist-info/RECORD +119 -0
- {camel_ai-0.1.1.dist-info → camel_ai-0.1.4.dist-info}/WHEEL +1 -1
- camel/memories/context_creators/base.py +0 -72
- 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.
|
|
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
|
]
|
camel/agents/chat_agent.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 (
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 = (
|
|
120
|
-
|
|
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
|
|
124
|
-
for func in
|
|
125
|
-
self.func_dict[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:
|
|
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
|
|
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
|
|
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(
|
|
184
|
-
|
|
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 =
|
|
208
|
-
|
|
209
|
-
|
|
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(
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
247
|
+
tool_calls (List[FunctionCallingRecord]): The list of function
|
|
226
248
|
calling records, containing the information of called
|
|
227
|
-
|
|
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
|
-
"
|
|
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(
|
|
245
|
-
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
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(
|
|
291
|
-
|
|
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.
|
|
339
|
+
self.step_tool_call(response)
|
|
340
|
+
)
|
|
309
341
|
|
|
310
342
|
# Update the messages
|
|
311
|
-
self.update_memory(
|
|
312
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
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 = (
|
|
372
|
-
|
|
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(
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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(
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
499
|
+
def step_tool_call(
|
|
456
500
|
self,
|
|
457
501
|
response: ChatCompletion,
|
|
458
|
-
) -> Tuple[
|
|
459
|
-
|
|
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.
|
|
475
|
-
raise RuntimeError("
|
|
476
|
-
func_name = choice.message.
|
|
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.
|
|
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(
|
|
512
|
-
|
|
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(
|
|
527
|
-
|
|
528
|
-
|
|
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:
|
camel/agents/critic_agent.py
CHANGED
|
@@ -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
|
|
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[
|
|
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__(
|
|
60
|
-
|
|
61
|
-
|
|
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(
|
|
114
|
-
|
|
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(
|
|
129
|
-
|
|
130
|
-
|
|
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(
|
|
172
|
-
|
|
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)
|