camel-ai 0.1.1__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 +30 -0
- camel/agents/__init__.py +40 -0
- camel/agents/base.py +29 -0
- camel/agents/chat_agent.py +539 -0
- camel/agents/critic_agent.py +179 -0
- camel/agents/embodied_agent.py +138 -0
- camel/agents/role_assignment_agent.py +117 -0
- camel/agents/task_agent.py +382 -0
- camel/agents/tool_agents/__init__.py +20 -0
- camel/agents/tool_agents/base.py +40 -0
- camel/agents/tool_agents/hugging_face_tool_agent.py +203 -0
- camel/configs.py +159 -0
- camel/embeddings/__init__.py +20 -0
- camel/embeddings/base.py +65 -0
- camel/embeddings/openai_embedding.py +74 -0
- camel/functions/__init__.py +27 -0
- camel/functions/base_io_functions.py +261 -0
- camel/functions/math_functions.py +61 -0
- camel/functions/openai_function.py +88 -0
- camel/functions/search_functions.py +309 -0
- camel/functions/unstructured_io_fuctions.py +616 -0
- camel/functions/weather_functions.py +136 -0
- camel/generators.py +263 -0
- camel/human.py +130 -0
- camel/memories/__init__.py +28 -0
- camel/memories/base.py +75 -0
- camel/memories/chat_history_memory.py +111 -0
- camel/memories/context_creators/__init__.py +18 -0
- camel/memories/context_creators/base.py +72 -0
- camel/memories/context_creators/score_based.py +130 -0
- camel/memories/records.py +92 -0
- camel/messages/__init__.py +38 -0
- camel/messages/base.py +223 -0
- camel/messages/func_message.py +106 -0
- camel/models/__init__.py +26 -0
- camel/models/base_model.py +110 -0
- camel/models/model_factory.py +59 -0
- camel/models/open_source_model.py +144 -0
- camel/models/openai_model.py +103 -0
- camel/models/stub_model.py +106 -0
- camel/prompts/__init__.py +38 -0
- camel/prompts/ai_society.py +121 -0
- camel/prompts/base.py +227 -0
- camel/prompts/code.py +111 -0
- camel/prompts/evaluation.py +40 -0
- camel/prompts/misalignment.py +84 -0
- camel/prompts/prompt_templates.py +117 -0
- camel/prompts/role_description_prompt_template.py +53 -0
- camel/prompts/solution_extraction.py +44 -0
- camel/prompts/task_prompt_template.py +56 -0
- camel/prompts/translation.py +42 -0
- camel/responses/__init__.py +18 -0
- camel/responses/agent_responses.py +42 -0
- camel/societies/__init__.py +20 -0
- camel/societies/babyagi_playing.py +254 -0
- camel/societies/role_playing.py +456 -0
- camel/storages/__init__.py +23 -0
- camel/storages/key_value_storages/__init__.py +23 -0
- camel/storages/key_value_storages/base.py +57 -0
- camel/storages/key_value_storages/in_memory.py +51 -0
- camel/storages/key_value_storages/json.py +97 -0
- camel/terminators/__init__.py +23 -0
- camel/terminators/base.py +44 -0
- camel/terminators/response_terminator.py +118 -0
- camel/terminators/token_limit_terminator.py +55 -0
- camel/types/__init__.py +54 -0
- camel/types/enums.py +176 -0
- camel/types/openai_types.py +39 -0
- camel/utils/__init__.py +47 -0
- camel/utils/commons.py +243 -0
- camel/utils/python_interpreter.py +435 -0
- camel/utils/token_counting.py +220 -0
- camel_ai-0.1.1.dist-info/METADATA +311 -0
- camel_ai-0.1.1.dist-info/RECORD +75 -0
- camel_ai-0.1.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
+
from typing import Any, Dict, List, Optional, Union
|
|
15
|
+
|
|
16
|
+
from camel.agents import ChatAgent
|
|
17
|
+
from camel.configs import ChatGPTConfig
|
|
18
|
+
from camel.messages import BaseMessage
|
|
19
|
+
from camel.prompts import PromptTemplateGenerator, TextPrompt
|
|
20
|
+
from camel.types import ModelType, RoleType, TaskType
|
|
21
|
+
from camel.utils import get_task_list
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TaskSpecifyAgent(ChatAgent):
|
|
25
|
+
r"""An agent that specifies a given task prompt by prompting the user to
|
|
26
|
+
provide more details.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
DEFAULT_WORD_LIMIT (int): The default word limit for the task prompt.
|
|
30
|
+
task_specify_prompt (TextPrompt): The prompt for specifying the task.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
model_type (ModelType, optional): The type of model to use for the
|
|
34
|
+
agent. (default: :obj:`ModelType.GPT_3_5_TURBO`)
|
|
35
|
+
task_type (TaskType, optional): The type of task for which to generate
|
|
36
|
+
a prompt. (default: :obj:`TaskType.AI_SOCIETY`)
|
|
37
|
+
model_config (Any, optional): The configuration for the model.
|
|
38
|
+
(default: :obj:`None`)
|
|
39
|
+
task_specify_prompt (Union[str, TextPrompt], optional): The prompt for
|
|
40
|
+
specifying the task. (default: :obj:`None`)
|
|
41
|
+
word_limit (int, optional): The word limit for the task prompt.
|
|
42
|
+
(default: :obj:`50`)
|
|
43
|
+
output_language (str, optional): The language to be output by the
|
|
44
|
+
agent. (default: :obj:`None`)
|
|
45
|
+
"""
|
|
46
|
+
DEFAULT_WORD_LIMIT = 50
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
model_type: Optional[ModelType] = None,
|
|
51
|
+
task_type: TaskType = TaskType.AI_SOCIETY,
|
|
52
|
+
model_config: Optional[Any] = None,
|
|
53
|
+
task_specify_prompt: Optional[Union[str, TextPrompt]] = None,
|
|
54
|
+
word_limit: int = DEFAULT_WORD_LIMIT,
|
|
55
|
+
output_language: Optional[str] = None,
|
|
56
|
+
) -> None:
|
|
57
|
+
|
|
58
|
+
self.task_specify_prompt: Union[str, TextPrompt]
|
|
59
|
+
if task_specify_prompt is None:
|
|
60
|
+
task_specify_prompt_template = PromptTemplateGenerator(
|
|
61
|
+
).get_task_specify_prompt(task_type)
|
|
62
|
+
|
|
63
|
+
self.task_specify_prompt = task_specify_prompt_template.format(
|
|
64
|
+
word_limit=word_limit)
|
|
65
|
+
else:
|
|
66
|
+
self.task_specify_prompt = TextPrompt(task_specify_prompt)
|
|
67
|
+
|
|
68
|
+
model_config = model_config or ChatGPTConfig(temperature=1.0)
|
|
69
|
+
|
|
70
|
+
system_message = BaseMessage(
|
|
71
|
+
role_name="Task Specifier",
|
|
72
|
+
role_type=RoleType.ASSISTANT,
|
|
73
|
+
meta_dict=None,
|
|
74
|
+
content="You can make a task more specific.",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
super().__init__(system_message, model_type=model_type,
|
|
78
|
+
model_config=model_config,
|
|
79
|
+
output_language=output_language)
|
|
80
|
+
|
|
81
|
+
def run(
|
|
82
|
+
self,
|
|
83
|
+
task_prompt: Union[str, TextPrompt],
|
|
84
|
+
meta_dict: Optional[Dict[str, Any]] = None,
|
|
85
|
+
) -> TextPrompt:
|
|
86
|
+
r"""Specify the given task prompt by providing more details.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
task_prompt (Union[str, TextPrompt]): The original task
|
|
90
|
+
prompt.
|
|
91
|
+
meta_dict (Dict[str, Any], optional): A dictionary containing
|
|
92
|
+
additional information to include in the prompt.
|
|
93
|
+
(default: :obj:`None`)
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
TextPrompt: The specified task prompt.
|
|
97
|
+
"""
|
|
98
|
+
self.reset()
|
|
99
|
+
task_specify_prompt = self.task_specify_prompt.format(task=task_prompt)
|
|
100
|
+
|
|
101
|
+
if meta_dict is not None:
|
|
102
|
+
task_specify_prompt = task_specify_prompt.format(**meta_dict)
|
|
103
|
+
|
|
104
|
+
task_msg = BaseMessage.make_user_message(role_name="Task Specifier",
|
|
105
|
+
content=task_specify_prompt)
|
|
106
|
+
specifier_response = self.step(task_msg)
|
|
107
|
+
|
|
108
|
+
if specifier_response.terminated:
|
|
109
|
+
raise RuntimeError("Task specification failed.")
|
|
110
|
+
if len(specifier_response.msgs) == 0:
|
|
111
|
+
raise RuntimeError("Got no specification message.")
|
|
112
|
+
|
|
113
|
+
specified_task_msg = specifier_response.msgs[0]
|
|
114
|
+
|
|
115
|
+
return TextPrompt(specified_task_msg.content)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class TaskPlannerAgent(ChatAgent):
|
|
119
|
+
r"""An agent that helps divide a task into subtasks based on the input
|
|
120
|
+
task prompt.
|
|
121
|
+
|
|
122
|
+
Attributes:
|
|
123
|
+
task_planner_prompt (TextPrompt): A prompt for the agent to divide
|
|
124
|
+
the task into subtasks.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
model_type (ModelType, optional): The type of model to use for the
|
|
128
|
+
agent. (default: :obj:`ModelType.GPT_3_5_TURBO`)
|
|
129
|
+
model_config (Any, optional): The configuration for the model.
|
|
130
|
+
(default: :obj:`None`)
|
|
131
|
+
output_language (str, optional): The language to be output by the
|
|
132
|
+
agent. (default: :obj:`None`)
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def __init__(
|
|
136
|
+
self,
|
|
137
|
+
model_type: Optional[ModelType] = None,
|
|
138
|
+
model_config: Optional[Any] = None,
|
|
139
|
+
output_language: Optional[str] = None,
|
|
140
|
+
) -> None:
|
|
141
|
+
|
|
142
|
+
self.task_planner_prompt = TextPrompt(
|
|
143
|
+
"Divide this task into subtasks: {task}. Be concise.")
|
|
144
|
+
system_message = BaseMessage(
|
|
145
|
+
role_name="Task Planner",
|
|
146
|
+
role_type=RoleType.ASSISTANT,
|
|
147
|
+
meta_dict=None,
|
|
148
|
+
content="You are a helpful task planner.",
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
super().__init__(system_message, model_type, model_config,
|
|
152
|
+
output_language=output_language)
|
|
153
|
+
|
|
154
|
+
def run(
|
|
155
|
+
self,
|
|
156
|
+
task_prompt: Union[str, TextPrompt],
|
|
157
|
+
) -> TextPrompt:
|
|
158
|
+
r"""Generate subtasks based on the input task prompt.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
task_prompt (Union[str, TextPrompt]): The prompt for the task to
|
|
162
|
+
be divided into subtasks.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
TextPrompt: A prompt for the subtasks generated by the agent.
|
|
166
|
+
"""
|
|
167
|
+
# TODO: Maybe include roles information.
|
|
168
|
+
self.reset()
|
|
169
|
+
task_planner_prompt = self.task_planner_prompt.format(task=task_prompt)
|
|
170
|
+
|
|
171
|
+
task_msg = BaseMessage.make_user_message(role_name="Task Planner",
|
|
172
|
+
content=task_planner_prompt)
|
|
173
|
+
|
|
174
|
+
task_response = self.step(task_msg)
|
|
175
|
+
|
|
176
|
+
if task_response.terminated:
|
|
177
|
+
raise RuntimeError("Task planning failed.")
|
|
178
|
+
if len(task_response.msgs) == 0:
|
|
179
|
+
raise RuntimeError("Got no task planning message.")
|
|
180
|
+
|
|
181
|
+
sub_tasks_msg = task_response.msgs[0]
|
|
182
|
+
return TextPrompt(sub_tasks_msg.content)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class TaskCreationAgent(ChatAgent):
|
|
186
|
+
r"""An agent that helps create new tasks based on the objective
|
|
187
|
+
and last completed task. Compared to :obj:`TaskPlannerAgent`,
|
|
188
|
+
it's still a task planner, but it has more context information
|
|
189
|
+
like last task and incomplete task list. Modified from
|
|
190
|
+
`BabyAGI <https://github.com/yoheinakajima/babyagi>`_.
|
|
191
|
+
|
|
192
|
+
Attributes:
|
|
193
|
+
task_creation_prompt (TextPrompt): A prompt for the agent to
|
|
194
|
+
create new tasks.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
role_name (str): The role name of the Agent to create the task.
|
|
198
|
+
objective (Union[str, TextPrompt]): The objective of the Agent to
|
|
199
|
+
perform the task.
|
|
200
|
+
model_type (ModelType, optional): The type of model to use for the
|
|
201
|
+
agent. (default: :obj:`ModelType.GPT_3_5_TURBO`)
|
|
202
|
+
model_config (Any, optional): The configuration for the model.
|
|
203
|
+
(default: :obj:`None`)
|
|
204
|
+
output_language (str, optional): The language to be output by the
|
|
205
|
+
agent. (default: :obj:`None`)
|
|
206
|
+
message_window_size (int, optional): The maximum number of previous
|
|
207
|
+
messages to include in the context window. If `None`, no windowing
|
|
208
|
+
is performed. (default: :obj:`None`)
|
|
209
|
+
max_task_num (int, optional): The maximum number of planned
|
|
210
|
+
tasks in one round. (default: :obj:3)
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
def __init__(
|
|
214
|
+
self,
|
|
215
|
+
role_name: str,
|
|
216
|
+
objective: Union[str, TextPrompt],
|
|
217
|
+
model_type: Optional[ModelType] = None,
|
|
218
|
+
model_config: Optional[Any] = None,
|
|
219
|
+
output_language: Optional[str] = None,
|
|
220
|
+
message_window_size: Optional[int] = None,
|
|
221
|
+
max_task_num: Optional[int] = 3,
|
|
222
|
+
) -> None:
|
|
223
|
+
|
|
224
|
+
task_creation_prompt = TextPrompt(
|
|
225
|
+
"""Create new a task with the following objective: {objective}.
|
|
226
|
+
Never forget you are a Task Creator of {role_name}.
|
|
227
|
+
You must instruct me based on my expertise and your needs to solve the task.
|
|
228
|
+
You should consider past solved tasks and in-progress tasks: {task_list}.
|
|
229
|
+
The new created tasks must not overlap with these past tasks.
|
|
230
|
+
The result must be a numbered list in the format:
|
|
231
|
+
|
|
232
|
+
#. First Task
|
|
233
|
+
#. Second Task
|
|
234
|
+
#. Third Task
|
|
235
|
+
|
|
236
|
+
You can only give me up to {max_task_num} tasks at a time. \
|
|
237
|
+
Each task shoud be concise, concrete and doable for a {role_name}.
|
|
238
|
+
You should make task plan and not ask me questions.
|
|
239
|
+
If you think no new tasks are needed right now, write "No tasks to add."
|
|
240
|
+
Now start to give me new tasks one by one. No more than three tasks.
|
|
241
|
+
Be concrete.
|
|
242
|
+
""")
|
|
243
|
+
|
|
244
|
+
self.task_creation_prompt = task_creation_prompt.format(
|
|
245
|
+
objective=objective, role_name=role_name,
|
|
246
|
+
max_task_num=max_task_num)
|
|
247
|
+
self.objective = objective
|
|
248
|
+
|
|
249
|
+
system_message = BaseMessage(
|
|
250
|
+
role_name="Task Creator",
|
|
251
|
+
role_type=RoleType.ASSISTANT,
|
|
252
|
+
meta_dict=None,
|
|
253
|
+
content="You are a helpful task creator.",
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
super().__init__(system_message, model_type, model_config,
|
|
257
|
+
output_language=output_language,
|
|
258
|
+
message_window_size=message_window_size)
|
|
259
|
+
|
|
260
|
+
def run(
|
|
261
|
+
self,
|
|
262
|
+
task_list: List[str],
|
|
263
|
+
) -> List[str]:
|
|
264
|
+
r"""Generate subtasks based on the previous task results and
|
|
265
|
+
incomplete task list.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
task_list (List[str]): The completed or in-progress
|
|
269
|
+
tasks which should not overlap with new created tasks.
|
|
270
|
+
Returns:
|
|
271
|
+
List[str]: The new task list generated by the Agent.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
if len(task_list) > 0:
|
|
275
|
+
task_creation_prompt = self.task_creation_prompt.format(
|
|
276
|
+
task_list=task_list)
|
|
277
|
+
else:
|
|
278
|
+
task_creation_prompt = self.task_creation_prompt.format(
|
|
279
|
+
task_list="")
|
|
280
|
+
|
|
281
|
+
task_msg = BaseMessage.make_user_message(role_name="Task Creator",
|
|
282
|
+
content=task_creation_prompt)
|
|
283
|
+
task_response = self.step(task_msg)
|
|
284
|
+
|
|
285
|
+
if task_response.terminated:
|
|
286
|
+
raise RuntimeError("Task creation failed.")
|
|
287
|
+
if len(task_response.msgs) == 0:
|
|
288
|
+
raise RuntimeError("Got no task creation message.")
|
|
289
|
+
|
|
290
|
+
sub_tasks_msg = task_response.msgs[0]
|
|
291
|
+
return get_task_list(sub_tasks_msg.content)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class TaskPrioritizationAgent(ChatAgent):
|
|
295
|
+
r"""An agent that helps re-prioritize the task list and
|
|
296
|
+
returns numbered prioritized list. Modified from
|
|
297
|
+
`BabyAGI <https://github.com/yoheinakajima/babyagi>`_.
|
|
298
|
+
|
|
299
|
+
Attributes:
|
|
300
|
+
task_prioritization_prompt (TextPrompt): A prompt for the agent to
|
|
301
|
+
prioritize tasks.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
objective (Union[str, TextPrompt]): The objective of the Agent to
|
|
305
|
+
perform the task.
|
|
306
|
+
model_type (ModelType, optional): The type of model to use for the
|
|
307
|
+
agent. (default: :obj:`ModelType.GPT_3_5_TURBO`)
|
|
308
|
+
model_config (Any, optional): The configuration for the model.
|
|
309
|
+
(default: :obj:`None`)
|
|
310
|
+
output_language (str, optional): The language to be output by the
|
|
311
|
+
agent. (default: :obj:`None`)
|
|
312
|
+
message_window_size (int, optional): The maximum number of previous
|
|
313
|
+
messages to include in the context window. If `None`, no windowing
|
|
314
|
+
is performed. (default: :obj:`None`)
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
def __init__(
|
|
318
|
+
self,
|
|
319
|
+
objective: Union[str, TextPrompt],
|
|
320
|
+
model_type: Optional[ModelType] = None,
|
|
321
|
+
model_config: Optional[Any] = None,
|
|
322
|
+
output_language: Optional[str] = None,
|
|
323
|
+
message_window_size: Optional[int] = None,
|
|
324
|
+
) -> None:
|
|
325
|
+
task_prioritization_prompt = TextPrompt(
|
|
326
|
+
"""Prioritize the following tasks : {task_list}.
|
|
327
|
+
Consider the ultimate objective of you: {objective}.
|
|
328
|
+
Tasks should be sorted from highest to lowest priority, where higher-priority \
|
|
329
|
+
tasks are those that act as pre-requisites or are more essential for meeting \
|
|
330
|
+
the objective. Return one task per line in your response.
|
|
331
|
+
Do not remove or modify any tasks.
|
|
332
|
+
The result must be a numbered list in the format:
|
|
333
|
+
|
|
334
|
+
#. First task
|
|
335
|
+
#. Second task
|
|
336
|
+
|
|
337
|
+
The entries must be consecutively numbered, starting with 1.
|
|
338
|
+
The number of each entry must be followed by a period.
|
|
339
|
+
Do not include any headers before your ranked list or follow your list \
|
|
340
|
+
with any other output.""")
|
|
341
|
+
|
|
342
|
+
self.task_prioritization_prompt = task_prioritization_prompt.format(
|
|
343
|
+
objective=objective)
|
|
344
|
+
self.objective = objective
|
|
345
|
+
|
|
346
|
+
system_message = BaseMessage(
|
|
347
|
+
role_name="Task Prioritizer",
|
|
348
|
+
role_type=RoleType.ASSISTANT,
|
|
349
|
+
meta_dict=None,
|
|
350
|
+
content="You are a helpful task prioritizer.",
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
super().__init__(system_message, model_type, model_config,
|
|
354
|
+
output_language=output_language,
|
|
355
|
+
message_window_size=message_window_size)
|
|
356
|
+
|
|
357
|
+
def run(
|
|
358
|
+
self,
|
|
359
|
+
task_list: List[str],
|
|
360
|
+
) -> List[str]:
|
|
361
|
+
r"""Prioritize the task list given the agent objective.
|
|
362
|
+
|
|
363
|
+
Args:
|
|
364
|
+
task_list (List[str]): The unprioritized tasks of agent.
|
|
365
|
+
Returns:
|
|
366
|
+
List[str]: The new prioritized task list generated by the Agent.
|
|
367
|
+
"""
|
|
368
|
+
task_prioritization_prompt = self.task_prioritization_prompt.format(
|
|
369
|
+
task_list=task_list)
|
|
370
|
+
|
|
371
|
+
task_msg = BaseMessage.make_user_message(
|
|
372
|
+
role_name="Task Prioritizer", content=task_prioritization_prompt)
|
|
373
|
+
|
|
374
|
+
task_response = self.step(task_msg)
|
|
375
|
+
|
|
376
|
+
if task_response.terminated:
|
|
377
|
+
raise RuntimeError("Task prioritization failed.")
|
|
378
|
+
if len(task_response.msgs) == 0:
|
|
379
|
+
raise RuntimeError("Got no task prioritization message.")
|
|
380
|
+
|
|
381
|
+
sub_tasks_msg = task_response.msgs[0]
|
|
382
|
+
return get_task_list(sub_tasks_msg.content)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
+
from .base import BaseToolAgent
|
|
15
|
+
from .hugging_face_tool_agent import HuggingFaceToolAgent
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
'BaseToolAgent',
|
|
19
|
+
'HuggingFaceToolAgent',
|
|
20
|
+
]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
+
from camel.agents import BaseAgent
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseToolAgent(BaseAgent):
|
|
18
|
+
r"""Creates a :obj:`BaseToolAgent` object with the specified name and
|
|
19
|
+
description.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name (str): The name of the tool agent.
|
|
23
|
+
description (str): The description of the tool agent.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, name: str, description: str) -> None:
|
|
27
|
+
|
|
28
|
+
self.name = name
|
|
29
|
+
self.description = description
|
|
30
|
+
|
|
31
|
+
def reset(self) -> None:
|
|
32
|
+
r"""Resets the agent to its initial state."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def step(self) -> None:
|
|
36
|
+
r"""Performs a single step of the agent."""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
def __str__(self) -> str:
|
|
40
|
+
return f"{self.name}: {self.description}"
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# =========== Copyright 2023 @ 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 @ CAMEL-AI.org. All Rights Reserved. ===========
|
|
14
|
+
from typing import Any, Optional
|
|
15
|
+
|
|
16
|
+
from camel.agents.tool_agents import BaseToolAgent
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# flake8: noqa :E501
|
|
20
|
+
class HuggingFaceToolAgent(BaseToolAgent):
|
|
21
|
+
r"""Tool agent for calling HuggingFace models. This agent is a wrapper
|
|
22
|
+
around agents from the `transformers` library. For more information
|
|
23
|
+
about the available models, please see the `transformers` documentation
|
|
24
|
+
at https://huggingface.co/docs/transformers/transformers_agents.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
name (str): The name of the agent.
|
|
28
|
+
*args (Any): Additional positional arguments to pass to the underlying
|
|
29
|
+
Agent class.
|
|
30
|
+
remote (bool, optional): Flag indicating whether to run the agent
|
|
31
|
+
remotely. (default: :obj:`True`)
|
|
32
|
+
**kwargs (Any): Additional keyword arguments to pass to the underlying
|
|
33
|
+
Agent class.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
name: str,
|
|
39
|
+
*args: Any,
|
|
40
|
+
remote: bool = True,
|
|
41
|
+
**kwargs: Any,
|
|
42
|
+
) -> None:
|
|
43
|
+
try:
|
|
44
|
+
# TODO: Support other tool agents
|
|
45
|
+
import transformers
|
|
46
|
+
from packaging import version
|
|
47
|
+
if version.parse(
|
|
48
|
+
transformers.__version__) < version.parse("4.31.0"):
|
|
49
|
+
raise ValueError(
|
|
50
|
+
"The version of \"transformers\" package should >= 4.31.0")
|
|
51
|
+
|
|
52
|
+
from transformers.tools import OpenAiAgent
|
|
53
|
+
from transformers.tools.agent_types import AgentImage
|
|
54
|
+
except (ImportError, ValueError):
|
|
55
|
+
raise ValueError(
|
|
56
|
+
"Could not import transformers tool agents. "
|
|
57
|
+
"Please setup the environment with "
|
|
58
|
+
"pip install huggingface_hub==0.14.1 transformers==4.31.0 diffusers accelerate==0.20.3 datasets torch soundfile sentencepiece opencv-python"
|
|
59
|
+
)
|
|
60
|
+
self.agent_image_type = AgentImage
|
|
61
|
+
self.agent = OpenAiAgent(*args, **kwargs)
|
|
62
|
+
description = f"""The `{name}` is a tool agent that can perform a variety of tasks including:
|
|
63
|
+
- Document question answering: given a document (such as a PDF) in image format, answer a question on this document
|
|
64
|
+
- Text question answering: given a long text and a question, answer the question in the text
|
|
65
|
+
- Unconditional image captioning: Caption the image!
|
|
66
|
+
- Image question answering: given an image, answer a question on this image
|
|
67
|
+
- Image segmentation: given an image and a prompt, output the segmentation mask of that prompt
|
|
68
|
+
- Speech to text: given an audio recording of a person talking, transcribe the speech into text
|
|
69
|
+
- Text to speech: convert text to speech
|
|
70
|
+
- Zero-shot text classification: given a text and a list of labels, identify to which label the text corresponds the most
|
|
71
|
+
- Text summarization: summarize a long text in one or a few sentences
|
|
72
|
+
- Translation: translate the text into a given language
|
|
73
|
+
- Text downloading: to download a text from a web URL
|
|
74
|
+
- Text to image: generate an image according to a prompt, leveraging stable diffusion
|
|
75
|
+
- Image transformation: modify an image given an initial image and a prompt, leveraging instruct pix2pix stable diffusion
|
|
76
|
+
- Text to video: generate a small video according to a prompt
|
|
77
|
+
|
|
78
|
+
Here are some python code examples of what you can do with this agent:
|
|
79
|
+
|
|
80
|
+
Single execution (step) mode, the single execution method is when using the step() method of the agent:
|
|
81
|
+
```
|
|
82
|
+
# Text to image
|
|
83
|
+
rivers_and_lakes_image = {name}.step("Draw me a picture of rivers and lakes.")
|
|
84
|
+
rivers_and_lakes_image.save("./rivers_and_lakes_image.png")
|
|
85
|
+
|
|
86
|
+
# Text to image -> Image transformation
|
|
87
|
+
sea_add_island_image = {name}.step("Draw me a picture of the sea then transform the picture to add an island")
|
|
88
|
+
sea_add_island_image.save("./sea_add_island_image.png")
|
|
89
|
+
|
|
90
|
+
# If you'd like to keep a state across executions or to pass non-text objects to the agent,
|
|
91
|
+
# you can do so by specifying variables that you would like the agent to use. For example,
|
|
92
|
+
# you could generate the first image of rivers and lakes, and ask the model to update that picture to add an island by doing the following:
|
|
93
|
+
picture = {name}.step("Generate a picture of rivers and lakes.")
|
|
94
|
+
picture.save("./picture.png")
|
|
95
|
+
updated_picture = {name}.step("Transform the image in `picture` to add an island to it.", picture=picture)
|
|
96
|
+
updated_picture.save("./updated_picture.png")
|
|
97
|
+
|
|
98
|
+
capybara_sea_image = {name}.step("Draw me a picture of the `prompt`", prompt="a capybara swimming in the sea")
|
|
99
|
+
capybara_sea_image.save("./capybara_sea_image.png")
|
|
100
|
+
|
|
101
|
+
# Document question answering
|
|
102
|
+
answer = {name}.step(
|
|
103
|
+
"In the following `document`, where will the TRRF Scientific Advisory Council Meeting take place?",
|
|
104
|
+
document=document,
|
|
105
|
+
)
|
|
106
|
+
print(answer)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# Text to image
|
|
110
|
+
boat_image = {name}.step("Generate an image of a boat in the water")
|
|
111
|
+
boat_image.save("./boat_image.png")
|
|
112
|
+
|
|
113
|
+
# Unconditional image captioning
|
|
114
|
+
boat_image_caption = {name}.step("Can you caption the `boat_image`?", boat_image=boat_image)
|
|
115
|
+
print(boat_image_caption)
|
|
116
|
+
|
|
117
|
+
# Text to image -> Unconditional image captioning -> Text to speech
|
|
118
|
+
boat_audio = {name}.step("Can you generate an image of a boat? Please read out loud the contents of the image afterwards")
|
|
119
|
+
|
|
120
|
+
# Text downloading
|
|
121
|
+
document = {name}.step("Download the text from http://hf.co")
|
|
122
|
+
print(document)
|
|
123
|
+
|
|
124
|
+
# Text summarization
|
|
125
|
+
summary = {name}.step("Summarize the following text: `document`", document=document)
|
|
126
|
+
print(summary)
|
|
127
|
+
|
|
128
|
+
# Text downloading -> Text summarization -> Text to speech
|
|
129
|
+
audio = {name}.step("Read out loud the summary of http://hf.co")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Chat-based execution (chat), the agent also has a chat-based approach, using the chat() method:
|
|
133
|
+
```
|
|
134
|
+
# Clean the chat history
|
|
135
|
+
{name}.reset()
|
|
136
|
+
|
|
137
|
+
# Text to image
|
|
138
|
+
capybara_image = {name}.chat("Show me an an image of a capybara")
|
|
139
|
+
capybara_image.save("./capybara_image.png")
|
|
140
|
+
|
|
141
|
+
# Image transformation
|
|
142
|
+
transformed_capybara_image = {name}.chat("Transform the image so that it snows")
|
|
143
|
+
transformed_capybara_image.save("./transformed_capybara_image.png")
|
|
144
|
+
|
|
145
|
+
# Image segmentation
|
|
146
|
+
segmented_transformed_capybara_image = {name}.chat("Show me a mask of the snowy capybaras")
|
|
147
|
+
segmented_transformed_capybara_image.save("./segmented_transformed_capybara_image.png")
|
|
148
|
+
```
|
|
149
|
+
"""
|
|
150
|
+
super(HuggingFaceToolAgent, self).__init__(name, description)
|
|
151
|
+
self.remote = remote
|
|
152
|
+
|
|
153
|
+
def reset(self) -> None:
|
|
154
|
+
r"""Resets the chat history of the agent."""
|
|
155
|
+
self.agent.prepare_for_new_chat()
|
|
156
|
+
|
|
157
|
+
def step(
|
|
158
|
+
self,
|
|
159
|
+
*args: Any,
|
|
160
|
+
remote: Optional[bool] = None,
|
|
161
|
+
**kwargs: Any,
|
|
162
|
+
) -> Any:
|
|
163
|
+
r"""Runs the agent in single execution mode.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
*args (Any): Positional arguments to pass to the agent.
|
|
167
|
+
remote (bool, optional): Flag indicating whether to run the agent
|
|
168
|
+
remotely. Overrides the default setting. (default: :obj:`None`)
|
|
169
|
+
**kwargs (Any): Keyword arguments to pass to the agent.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
str: The response from the agent.
|
|
173
|
+
"""
|
|
174
|
+
if remote is None:
|
|
175
|
+
remote = self.remote
|
|
176
|
+
agent_output = self.agent.run(*args, remote=remote, **kwargs)
|
|
177
|
+
if isinstance(agent_output, self.agent_image_type):
|
|
178
|
+
agent_output = agent_output.to_raw()
|
|
179
|
+
return agent_output
|
|
180
|
+
|
|
181
|
+
def chat(
|
|
182
|
+
self,
|
|
183
|
+
*args: Any,
|
|
184
|
+
remote: Optional[bool] = None,
|
|
185
|
+
**kwargs: Any,
|
|
186
|
+
) -> Any:
|
|
187
|
+
r"""Runs the agent in a chat conversation mode.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
*args (Any): Positional arguments to pass to the agent.
|
|
191
|
+
remote (bool, optional): Flag indicating whether to run the agent
|
|
192
|
+
remotely. Overrides the default setting. (default: :obj:`None`)
|
|
193
|
+
**kwargs (Any): Keyword arguments to pass to the agent.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
str: The response from the agent.
|
|
197
|
+
"""
|
|
198
|
+
if remote is None:
|
|
199
|
+
remote = self.remote
|
|
200
|
+
agent_output = self.agent.chat(*args, remote=remote, **kwargs)
|
|
201
|
+
if isinstance(agent_output, self.agent_image_type):
|
|
202
|
+
agent_output = agent_output.to_raw()
|
|
203
|
+
return agent_output
|