camel-ai 0.1.5.9__py3-none-any.whl → 0.1.6.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.

Files changed (69) hide show
  1. camel/__init__.py +1 -1
  2. camel/agents/chat_agent.py +246 -33
  3. camel/agents/critic_agent.py +17 -1
  4. camel/agents/deductive_reasoner_agent.py +12 -0
  5. camel/agents/embodied_agent.py +19 -5
  6. camel/agents/knowledge_graph_agent.py +22 -3
  7. camel/agents/role_assignment_agent.py +12 -0
  8. camel/agents/search_agent.py +12 -0
  9. camel/agents/task_agent.py +15 -0
  10. camel/configs/__init__.py +2 -9
  11. camel/configs/anthropic_config.py +5 -6
  12. camel/configs/base_config.py +50 -4
  13. camel/configs/gemini_config.py +69 -18
  14. camel/configs/groq_config.py +6 -20
  15. camel/configs/litellm_config.py +2 -8
  16. camel/configs/mistral_config.py +17 -20
  17. camel/configs/ollama_config.py +6 -8
  18. camel/configs/openai_config.py +12 -23
  19. camel/configs/vllm_config.py +7 -8
  20. camel/configs/zhipuai_config.py +5 -11
  21. camel/human.py +1 -1
  22. camel/loaders/__init__.py +2 -0
  23. camel/loaders/firecrawl_reader.py +213 -0
  24. camel/memories/agent_memories.py +1 -4
  25. camel/memories/blocks/chat_history_block.py +6 -2
  26. camel/memories/blocks/vectordb_block.py +3 -1
  27. camel/memories/context_creators/score_based.py +6 -6
  28. camel/memories/records.py +9 -7
  29. camel/messages/base.py +1 -0
  30. camel/models/open_source_model.py +2 -2
  31. camel/prompts/__init__.py +7 -0
  32. camel/prompts/image_craft.py +34 -0
  33. camel/prompts/multi_condition_image_craft.py +34 -0
  34. camel/prompts/task_prompt_template.py +6 -0
  35. camel/responses/agent_responses.py +4 -3
  36. camel/retrievers/auto_retriever.py +0 -2
  37. camel/societies/babyagi_playing.py +6 -4
  38. camel/societies/role_playing.py +16 -8
  39. camel/storages/graph_storages/graph_element.py +10 -14
  40. camel/storages/vectordb_storages/base.py +24 -13
  41. camel/storages/vectordb_storages/milvus.py +1 -1
  42. camel/storages/vectordb_storages/qdrant.py +2 -3
  43. camel/tasks/__init__.py +22 -0
  44. camel/tasks/task.py +408 -0
  45. camel/tasks/task_prompt.py +65 -0
  46. camel/toolkits/__init__.py +3 -0
  47. camel/toolkits/base.py +3 -1
  48. camel/toolkits/dalle_toolkit.py +146 -0
  49. camel/toolkits/github_toolkit.py +16 -32
  50. camel/toolkits/google_maps_toolkit.py +2 -1
  51. camel/toolkits/open_api_toolkit.py +1 -2
  52. camel/toolkits/openai_function.py +2 -7
  53. camel/types/enums.py +6 -2
  54. camel/utils/__init__.py +12 -2
  55. camel/utils/commons.py +152 -2
  56. camel/utils/constants.py +3 -0
  57. camel/workforce/__init__.py +23 -0
  58. camel/workforce/base.py +50 -0
  59. camel/workforce/manager_node.py +299 -0
  60. camel/workforce/role_playing_node.py +168 -0
  61. camel/workforce/single_agent_node.py +77 -0
  62. camel/workforce/task_channel.py +173 -0
  63. camel/workforce/utils.py +97 -0
  64. camel/workforce/worker_node.py +115 -0
  65. camel/workforce/workforce.py +49 -0
  66. camel/workforce/workforce_prompt.py +125 -0
  67. {camel_ai-0.1.5.9.dist-info → camel_ai-0.1.6.1.dist-info}/METADATA +5 -2
  68. {camel_ai-0.1.5.9.dist-info → camel_ai-0.1.6.1.dist-info}/RECORD +69 -52
  69. {camel_ai-0.1.5.9.dist-info → camel_ai-0.1.6.1.dist-info}/WHEEL +0 -0
@@ -13,13 +13,13 @@
13
13
  # =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
14
14
 
15
15
  from abc import ABC, abstractmethod
16
- from dataclasses import dataclass, field
17
16
  from typing import Any, Dict, List, Optional
18
17
  from uuid import uuid4
19
18
 
19
+ from pydantic import BaseModel, Field
20
20
 
21
- @dataclass
22
- class VectorRecord:
21
+
22
+ class VectorRecord(BaseModel):
23
23
  r"""Encapsulates information about a vector's unique identifier and its
24
24
  payload, which is primarily used as a data transfer object when saving
25
25
  to vector storage.
@@ -33,12 +33,11 @@ class VectorRecord:
33
33
  """
34
34
 
35
35
  vector: List[float]
36
- id: str = field(default_factory=lambda: str(uuid4()))
36
+ id: str = Field(default_factory=lambda: str(uuid4()))
37
37
  payload: Optional[Dict[str, Any]] = None
38
38
 
39
39
 
40
- @dataclass
41
- class VectorDBQuery:
40
+ class VectorDBQuery(BaseModel):
42
41
  r"""Represents a query to a vector database.
43
42
 
44
43
  Attributes:
@@ -49,11 +48,24 @@ class VectorDBQuery:
49
48
  """
50
49
 
51
50
  query_vector: List[float]
51
+ """The numerical representation of the query vector."""
52
52
  top_k: int = 1
53
+ """The number of top similar vectors to retrieve from the database."""
54
+
55
+ def __init__(
56
+ self, query_vector: List[float], top_k: int, **kwargs: Any
57
+ ) -> None:
58
+ """Pass in query_vector and tok_k as positional arg.
59
+ Args:
60
+ query_vector (List[float]): The numerical representation of the
61
+ query vector.
62
+ top_k (int, optional): The number of top similar vectors to
63
+ retrieve from the database. (default: :obj:`1`)
64
+ """
65
+ super().__init__(query_vector=query_vector, top_k=top_k, **kwargs)
53
66
 
54
67
 
55
- @dataclass
56
- class VectorDBQueryResult:
68
+ class VectorDBQueryResult(BaseModel):
57
69
  r"""Encapsulates the result of a query against a vector database.
58
70
 
59
71
  Attributes:
@@ -66,7 +78,7 @@ class VectorDBQueryResult:
66
78
  similarity: float
67
79
 
68
80
  @classmethod
69
- def construct(
81
+ def create(
70
82
  cls,
71
83
  similarity: float,
72
84
  vector: List[float],
@@ -75,13 +87,12 @@ class VectorDBQueryResult:
75
87
  ) -> "VectorDBQueryResult":
76
88
  r"""A class method to construct a `VectorDBQueryResult` instance."""
77
89
  return cls(
78
- record=VectorRecord(vector, id, payload),
90
+ record=VectorRecord(vector=vector, id=id, payload=payload),
79
91
  similarity=similarity,
80
92
  )
81
93
 
82
94
 
83
- @dataclass
84
- class VectorDBStatus:
95
+ class VectorDBStatus(BaseModel):
85
96
  r"""Vector database status.
86
97
 
87
98
  Attributes:
@@ -195,7 +206,7 @@ class BaseVectorStorage(ABC):
195
206
  List[List[Dict[str, Any]]]: A list of vector payloads retrieved
196
207
  from the storage based on similarity to the query vector.
197
208
  """
198
- results = self.query(VectorDBQuery(vector, top_k))
209
+ results = self.query(VectorDBQuery(query_vector=vector, top_k=top_k))
199
210
  return [
200
211
  result.record.payload
201
212
  for result in results
@@ -361,7 +361,7 @@ class MilvusStorage(BaseVectorStorage):
361
361
  query_results = []
362
362
  for point in search_result:
363
363
  query_results.append(
364
- VectorDBQueryResult.construct(
364
+ VectorDBQueryResult.create(
365
365
  similarity=(point[0]['distance']),
366
366
  id=str(point[0]['id']),
367
367
  payload=(point[0]['entity'].get('payload')),
@@ -11,7 +11,6 @@
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 dataclasses import asdict
15
14
  from datetime import datetime
16
15
  from typing import Any, Dict, List, Optional, Tuple, Union, cast
17
16
 
@@ -261,7 +260,7 @@ class QdrantStorage(BaseVectorStorage):
261
260
  """
262
261
  from qdrant_client.http.models import PointStruct, UpdateStatus
263
262
 
264
- qdrant_points = [PointStruct(**asdict(p)) for p in records]
263
+ qdrant_points = [PointStruct(**p.model_dump()) for p in records]
265
264
  op_info = self._client.upsert(
266
265
  collection_name=self.collection_name,
267
266
  points=qdrant_points,
@@ -340,7 +339,7 @@ class QdrantStorage(BaseVectorStorage):
340
339
  query_results = []
341
340
  for point in search_result:
342
341
  query_results.append(
343
- VectorDBQueryResult.construct(
342
+ VectorDBQueryResult.create(
344
343
  similarity=point.score,
345
344
  id=str(point.id),
346
345
  payload=point.payload,
@@ -0,0 +1,22 @@
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 .task import Task, TaskManager
15
+ from .task_prompt import TASK_DECOMPOSE_PROMPT, TASK_EVOLVE_PROMPT
16
+
17
+ __all__ = [
18
+ "TASK_DECOMPOSE_PROMPT",
19
+ "TASK_EVOLVE_PROMPT",
20
+ "Task",
21
+ "TaskManager",
22
+ ]
camel/tasks/task.py ADDED
@@ -0,0 +1,408 @@
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
+
15
+ import re
16
+ from enum import Enum
17
+ from typing import Callable, Dict, List, Literal, Optional, Union
18
+
19
+ from pydantic import BaseModel
20
+
21
+ from camel.agents import ChatAgent
22
+ from camel.messages import BaseMessage
23
+ from camel.prompts import TextPrompt
24
+
25
+ from .task_prompt import (
26
+ TASK_COMPOSE_PROMPT,
27
+ TASK_DECOMPOSE_PROMPT,
28
+ TASK_EVOLVE_PROMPT,
29
+ )
30
+
31
+
32
+ def parse_response(
33
+ response: str, task_id: Optional[str] = None
34
+ ) -> List["Task"]:
35
+ r"""Parse Tasks from a response.
36
+
37
+ Args:
38
+ response (str): The model response.
39
+ task_id (str, optional): a parent task id,
40
+ the default value is "0"
41
+
42
+ Returns:
43
+ List[Task]: A list of tasks which is :obj:`Task` instance.
44
+ """
45
+ pattern = "<task>(.*?)</task>"
46
+ tasks_content = re.findall(pattern, response, re.DOTALL)
47
+
48
+ tasks = []
49
+ if task_id is None:
50
+ task_id = "0"
51
+ for i, content in enumerate(tasks_content):
52
+ tasks.append(Task(content=content.strip(), id=f"{task_id}.{i}"))
53
+ return tasks
54
+
55
+
56
+ class TaskState(str, Enum):
57
+ OPEN = "OPEN"
58
+ RUNNING = "RUNNING"
59
+ DONE = "DONE"
60
+ FAILED = "FAILED"
61
+ DELETED = "DELETED"
62
+
63
+ @classmethod
64
+ def states(cls):
65
+ return [s.value for s in cls]
66
+
67
+
68
+ class Task(BaseModel):
69
+ r"""Task is specific assignment that can be passed to a agent.
70
+
71
+ Attributes:
72
+ content: string content for task.
73
+ id: An unique string identifier for the task. This should
74
+ ideally be provided by the provider/model which created the task.
75
+ state: The state which should be OPEN, RUNNING, DONE or DELETED.
76
+ type: task type
77
+ parent: The parent task, None for root task.
78
+ subtasks: The childrent sub-tasks for the task.
79
+ result: The answer for the task.
80
+ """
81
+
82
+ content: str
83
+
84
+ id: str = ""
85
+
86
+ state: TaskState = TaskState.OPEN
87
+
88
+ type: Optional[str] = None
89
+
90
+ parent: Optional["Task"] = None
91
+
92
+ subtasks: List["Task"] = []
93
+
94
+ result: Optional[str] = ""
95
+
96
+ @classmethod
97
+ def from_message(cls, message: BaseMessage) -> "Task":
98
+ r"""Create a task from a message.
99
+
100
+ Args:
101
+ message (BaseMessage): The message to the task.
102
+
103
+ Returns:
104
+ Task
105
+ """
106
+ return cls(content=message.content, id="0")
107
+
108
+ @staticmethod
109
+ def to_message():
110
+ r"""Convert a Task to a Message."""
111
+ # TODO
112
+ pass
113
+
114
+ def reset(self):
115
+ r"""Reset Task to initial state."""
116
+ self.state = TaskState.OPEN
117
+ self.result = ""
118
+
119
+ def update_result(self, result: str):
120
+ r"""Set task result and mark the task as DONE.
121
+
122
+ Args:
123
+ result (str): The task result.
124
+ """
125
+ self.result = result
126
+ self.set_state(TaskState.DONE)
127
+
128
+ def set_id(self, id: str):
129
+ self.id = id
130
+
131
+ def set_state(self, state: TaskState):
132
+ r"""Recursively set the state of the task and its subtasks.
133
+
134
+ Args:
135
+ state (TaskState): The giving state.
136
+ """
137
+ self.state = state
138
+ if state == TaskState.DONE:
139
+ for subtask in self.subtasks:
140
+ if subtask.state != TaskState.DELETED:
141
+ subtask.set_state(state)
142
+ elif state == TaskState.RUNNING and self.parent:
143
+ self.parent.set_state(state)
144
+
145
+ def add_subtask(self, task: "Task"):
146
+ task.parent = self
147
+ self.subtasks.append(task)
148
+
149
+ def remove_subtask(self, id: str):
150
+ self.subtasks = [task for task in self.subtasks if task.id != id]
151
+
152
+ def get_running_task(self) -> Optional["Task"]:
153
+ r"""Get RUNNING task."""
154
+ for sub in self.subtasks:
155
+ if sub.state == TaskState.RUNNING:
156
+ return sub.get_running_task()
157
+ if self.state == TaskState.RUNNING:
158
+ return self
159
+ return None
160
+
161
+ def to_string(self, indent: str = "", state: bool = False) -> str:
162
+ r"""Convert task to a sting.
163
+
164
+ Args:
165
+ indent (str): The ident for hierarchical tasks.
166
+ state (bool): Include or not task state.
167
+
168
+ Returns:
169
+ str: The printable task string.
170
+ """
171
+ if state:
172
+ _str = f"{indent}[{self.state}] Task {self.id}: {self.content}\n"
173
+ else:
174
+ _str = f"{indent}Task {self.id}: {self.content}\n"
175
+ for subtask in self.subtasks:
176
+ _str += subtask.to_string(indent + " ", state)
177
+ return _str
178
+
179
+ def get_result(self, indent: str = "") -> str:
180
+ r"""Get task result to a sting.
181
+
182
+ Args:
183
+ indent (str): The ident for hierarchical tasks.
184
+
185
+ Returns:
186
+ str: The printable task string.
187
+ """
188
+ _str = f"{indent}Task {self.id} result: {self.result}\n"
189
+ for subtask in self.subtasks:
190
+ _str += subtask.get_result(indent + " ")
191
+ return _str
192
+
193
+ def decompose(
194
+ self,
195
+ agent: ChatAgent,
196
+ template: TextPrompt = TASK_DECOMPOSE_PROMPT,
197
+ task_parser: Callable[[str, str], List["Task"]] = parse_response,
198
+ ) -> List["Task"]:
199
+ r"""Decompose a task to a list of sub-tasks. It can be used for data
200
+ generation and planner of agent.
201
+
202
+ Args:
203
+ agent (ChatAgent): An agent that used to decompose the task.
204
+ template (TextPrompt): The prompt template to decompose
205
+ task. If not provided, the default template will be used.
206
+ task_parser (Callable[[str, str], List[Task]], optional): A
207
+ function to extract Task from response. If not provided,
208
+ the default parse_response will be used.
209
+
210
+ Returns:
211
+ List[Task]: A list of tasks which are :obj:`Task` instances.
212
+ """
213
+
214
+ role_name = agent.role_name
215
+ content = template.format(
216
+ role_name=role_name,
217
+ content=self.content,
218
+ )
219
+ msg = BaseMessage.make_user_message(
220
+ role_name=role_name, content=content
221
+ )
222
+ response = agent.step(msg)
223
+ tasks = task_parser(response.msg.content, self.id)
224
+ return tasks
225
+
226
+ def compose(
227
+ self,
228
+ agent: ChatAgent,
229
+ template: TextPrompt = TASK_COMPOSE_PROMPT,
230
+ result_parser: Optional[Callable[[str], str]] = None,
231
+ ):
232
+ r"""compose task result by the sub-tasks.
233
+
234
+ Args:
235
+ agent (ChatAgent): An agent that used to compose the task result.
236
+ template (TextPrompt, optional): The prompt template to compose
237
+ task. If not provided, the default template will be used.
238
+ result_parser (Callable[[str, str], List[Task]], optional): A
239
+ function to extract Task from response.
240
+ """
241
+
242
+ if not self.subtasks:
243
+ return
244
+
245
+ sub_tasks_result = self.get_result()
246
+
247
+ role_name = agent.role_name
248
+ content = template.format(
249
+ role_name=role_name,
250
+ content=self.content,
251
+ other_results=sub_tasks_result,
252
+ )
253
+ msg = BaseMessage.make_user_message(
254
+ role_name=role_name, content=content
255
+ )
256
+ response = agent.step(msg)
257
+ result = response.msg.content
258
+ if result_parser:
259
+ result = result_parser(result)
260
+ self.update_result(result)
261
+
262
+ def get_depth(self) -> int:
263
+ r"""Get current task depth."""
264
+ if self.parent is None:
265
+ return 1
266
+ return 1 + self.parent.get_depth()
267
+
268
+
269
+ class TaskManager:
270
+ r"""TaskManager is used to manage tasks.
271
+
272
+ Attributes:
273
+ root_task: The root task.
274
+ tasks: The ordered tasks.
275
+ task_map: A map for task.id to Task.
276
+ current_task_id: The current "RUNNING" task.id.
277
+
278
+ Args:
279
+ task (Task): The root Task.
280
+ """
281
+
282
+ def __init__(self, task: Task):
283
+ self.root_task: Task = task
284
+ self.current_task_id: str = task.id
285
+ self.tasks: List[Task] = [task]
286
+ self.task_map: Dict[str, Task] = {task.id: task}
287
+
288
+ def gen_task_id(self) -> str:
289
+ r"""Generate a new task id."""
290
+ return f"{len(self.tasks)}"
291
+
292
+ def exist(self, task_id: str) -> bool:
293
+ r"""Check if a task with the given id exists."""
294
+ return task_id in self.task_map
295
+
296
+ @property
297
+ def current_task(self) -> Optional[Task]:
298
+ r"""Get the current task."""
299
+ return self.task_map.get(self.current_task_id, None)
300
+
301
+ @staticmethod
302
+ def topological_sort(tasks: List[Task]) -> List[Task]:
303
+ r"""Sort a list of tasks by topological way.
304
+
305
+ Args:
306
+ tasks (List[Task]): The giving list of tasks.
307
+
308
+ Returns:
309
+ The sorted list of tasks.
310
+ """
311
+ stack = []
312
+ visited = set()
313
+
314
+ # recursive visit the vertices
315
+ def visit(task: Task):
316
+ if task.id in visited:
317
+ return
318
+ visited.add(task.id)
319
+
320
+ # go deep for dependencies
321
+ for sub_task in task.subtasks:
322
+ visit(sub_task)
323
+
324
+ # add current task to stack which have no dependencies.
325
+ stack.append(task)
326
+
327
+ for task in tasks:
328
+ visit(task)
329
+
330
+ return stack
331
+
332
+ @staticmethod
333
+ def set_tasks_dependence(
334
+ root: Task,
335
+ others: List[Task],
336
+ type: Literal["serial", "parallel"] = "parallel",
337
+ ):
338
+ r"""Set relationship between root task and other tasks.
339
+ Two relationships are currently supported: serial and parallel.
340
+ `serial` : root -> other1 -> other2
341
+ `parallel`: root -> other1
342
+ -> other2
343
+
344
+ Args:
345
+ root (Task): A root task.
346
+ others (List[Task]): A list of tasks.
347
+ """
348
+ # filter the root task in the others to avoid self-loop dependence.
349
+ others = [other for other in others if other != root]
350
+
351
+ if len(others) == 0:
352
+ return
353
+ if type == "parallel":
354
+ for other in others:
355
+ root.add_subtask(other)
356
+ else:
357
+ parent = root
358
+ for child in others:
359
+ parent.add_subtask(child)
360
+ parent = child
361
+
362
+ def add_tasks(self, tasks: Union[Task, List[Task]]) -> None:
363
+ r"""self.tasks and self.task_map will be updated by the input tasks."""
364
+ if not tasks:
365
+ return
366
+ if not isinstance(tasks, List):
367
+ tasks = [tasks]
368
+ for task in tasks:
369
+ assert not self.exist(task.id), f"`{task.id}` already existed."
370
+ self.tasks = self.topological_sort(self.tasks + tasks)
371
+ self.task_map = {task.id: task for task in self.tasks}
372
+
373
+ def evolve(
374
+ self,
375
+ task: Task,
376
+ agent: ChatAgent,
377
+ template: Optional[TextPrompt] = None,
378
+ task_parser: Optional[Callable[[str, str], List[Task]]] = None,
379
+ ) -> Optional[Task]:
380
+ r"""Evolve a task to a new task.
381
+ Evolve is only used for data generation.
382
+ Args:
383
+ task (Task): A given task.
384
+ agent (ChatAgent): An agent that used to evolve the task.
385
+ template (TextPrompt, optional): A prompt template to evolve task.
386
+ If not provided, the default template will be used.
387
+ task_parser (Callable, optional): A function to extract Task from
388
+ response. If not provided, the default parser will be used.
389
+
390
+ Returns:
391
+ Task: The created :obj:`Task` instance or None.
392
+ """
393
+
394
+ if template is None:
395
+ template = TASK_EVOLVE_PROMPT
396
+
397
+ role_name = agent.role_name
398
+ content = template.format(role_name=role_name, content=task.content)
399
+ msg = BaseMessage.make_user_message(
400
+ role_name=role_name, content=content
401
+ )
402
+ response = agent.step(msg)
403
+ if task_parser is None:
404
+ task_parser = parse_response
405
+ tasks = task_parser(response.msg.content, task.id)
406
+ if tasks:
407
+ return tasks[0]
408
+ return None
@@ -0,0 +1,65 @@
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.prompts import TextPrompt
15
+
16
+ # ruff: noqa: E501
17
+ TASK_DECOMPOSE_PROMPT = TextPrompt(
18
+ """As a Task Decomposer with the role of {role_name}, your objective is to divide the given task into subtasks.
19
+ You have been provided with the following objective:
20
+
21
+ {content}
22
+
23
+ Please format the subtasks as a numbered list within <tasks> tags, as demonstrated below:
24
+ <tasks>
25
+ <task>Subtask 1</task>
26
+ <task>Subtask 2</task>
27
+ </tasks>
28
+
29
+ Each subtask should be concise, concrete, and achievable for a {role_name}.
30
+ Ensure that the task plan is created without asking any questions.
31
+ Be specific and clear.
32
+ """
33
+ )
34
+
35
+
36
+ TASK_COMPOSE_PROMPT = TextPrompt(
37
+ """As a Task composer with the role of {role_name}, your objective is to gather result from all sub tasks to get the final answer.
38
+ The root task is:
39
+
40
+ {content}
41
+
42
+ The related tasks result and status:
43
+
44
+ {other_results}
45
+
46
+ so, the final answer of the root task is:
47
+ """
48
+ )
49
+
50
+
51
+ TASK_EVOLVE_PROMPT = TextPrompt(
52
+ """As a Task Creator for {role_name}, your objective is to draw inspiration from the provided task to develop an entirely new one.
53
+ The new task should fall within the same domain as the given task but be more complex and unique.
54
+ It must be reasonable, understandable, and actionable by {role_name}.
55
+ The created task must be enclosed within <task> </task> tags.
56
+ <task>
57
+ ... created task
58
+ </task>
59
+
60
+ ## given task
61
+ {content}
62
+
63
+ ## created task
64
+ """
65
+ )
@@ -27,6 +27,7 @@ from .search_toolkit import SEARCH_FUNCS, SearchToolkit
27
27
  from .twitter_toolkit import TWITTER_FUNCS, TwitterToolkit
28
28
  from .weather_toolkit import WEATHER_FUNCS, WeatherToolkit
29
29
  from .slack_toolkit import SLACK_FUNCS, SlackToolkit
30
+ from .dalle_toolkit import DALLE_FUNCS, DalleToolkit
30
31
 
31
32
  from .base import BaseToolkit
32
33
  from .code_execution import CodeExecutionToolkit
@@ -45,12 +46,14 @@ __all__ = [
45
46
  'TWITTER_FUNCS',
46
47
  'WEATHER_FUNCS',
47
48
  'SLACK_FUNCS',
49
+ 'DALLE_FUNCS',
48
50
  'BaseToolkit',
49
51
  'GithubToolkit',
50
52
  'MathToolkit',
51
53
  'GoogleMapsToolkit',
52
54
  'SearchToolkit',
53
55
  'SlackToolkit',
56
+ 'DalleToolkit',
54
57
  'TwitterToolkit',
55
58
  'WeatherToolkit',
56
59
  'RetrievalToolkit',
camel/toolkits/base.py CHANGED
@@ -14,9 +14,11 @@
14
14
 
15
15
  from typing import List
16
16
 
17
+ from camel.utils import AgentOpsMeta
18
+
17
19
  from .openai_function import OpenAIFunction
18
20
 
19
21
 
20
- class BaseToolkit:
22
+ class BaseToolkit(metaclass=AgentOpsMeta):
21
23
  def get_tools(self) -> List[OpenAIFunction]:
22
24
  raise NotImplementedError("Subclasses must implement this method.")