Skip to content

Commit 46b1b43

Browse files
YuujeeYuujeeactions-userzjrwtxWendong-Fan
authored
feat: Task planning toolkit (#2535)
Co-authored-by: Yuujee <xiongyj@stu.pku.edu.cn> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Yifeng Wang(正经人王同学) <86822589+zjrwtx@users.noreply.github.com> Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
1 parent 9f7f252 commit 46b1b43

File tree

5 files changed

+391
-0
lines changed

5 files changed

+391
-0
lines changed

camel/tasks/task.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ class Task(BaseModel):
106106

107107
additional_info: Optional[Dict[str, Any]] = None
108108

109+
def __repr__(self) -> str:
110+
r"""Return a string representation of the task."""
111+
content_preview = self.content
112+
return (
113+
f"Task(id='{self.id}', content='{content_preview}', "
114+
f"state='{self.state.value}')"
115+
)
116+
109117
@classmethod
110118
def from_message(cls, message: BaseMessage) -> "Task":
111119
r"""Create a task from a message.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# ========= Copyright 2023-2024 @ 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-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14+
import uuid
15+
from typing import List, Optional
16+
17+
from camel.logger import get_logger
18+
from camel.tasks import Task
19+
from camel.toolkits import BaseToolkit, FunctionTool
20+
21+
logger = get_logger(__name__)
22+
23+
24+
class TaskPlanningToolkit(BaseToolkit):
25+
r"""A toolkit for task decomposition and re-planning."""
26+
27+
def __init__(
28+
self,
29+
timeout: Optional[float] = None,
30+
):
31+
r"""Initialize the TaskPlanningToolkit.
32+
33+
Args:
34+
timeout (Optional[float]): The timeout for the toolkit.
35+
(default: :obj: `None`)
36+
"""
37+
super().__init__(timeout=timeout)
38+
39+
def decompose_task(
40+
self,
41+
original_task_content: str,
42+
sub_task_contents: List[str],
43+
original_task_id: Optional[str] = None,
44+
) -> List[Task]:
45+
r"""Use the tool to decompose an original task into several sub-tasks.
46+
It creates new Task objects from the provided original task content,
47+
used when the original task is complex and needs to be decomposed.
48+
49+
Args:
50+
original_task_content (str): The content of the task to be
51+
decomposed.
52+
sub_task_contents (List[str]): A list of strings, where each
53+
string is the content for a new sub-task.
54+
original_task_id (Optional[str]): The id of the task to be
55+
decomposed. If not provided, a new id will be generated.
56+
(default: :obj: `None`)
57+
58+
Returns:
59+
List[Task]: A list of newly created sub-task objects.
60+
"""
61+
# Create the original task object from its content
62+
original_task = Task(
63+
content=original_task_content,
64+
id=original_task_id if original_task_id else str(uuid.uuid4()),
65+
)
66+
67+
new_tasks: List[Task] = []
68+
for i, content in enumerate(sub_task_contents):
69+
new_task = Task(
70+
content=content,
71+
id=f"{original_task.id}.{i}",
72+
parent=original_task,
73+
)
74+
new_tasks.append(new_task)
75+
original_task.subtasks.append(new_task)
76+
77+
logger.debug(
78+
f"Decomposed task (content: '{original_task.content[:50]}...', "
79+
f"id: {original_task.id}) into {len(new_tasks)} sub-tasks: "
80+
f"{[task.id for task in new_tasks]}"
81+
)
82+
83+
return new_tasks
84+
85+
def replan_tasks(
86+
self,
87+
original_task_content: str,
88+
sub_task_contents: List[str],
89+
original_task_id: Optional[str] = None,
90+
) -> List[Task]:
91+
r"""Use the tool to re_decompose a task into several subTasks.
92+
It creates new Task objects from the provided original task content,
93+
used when the decomposed tasks are not good enough to help finish
94+
the task.
95+
96+
Args:
97+
original_task_content (str): The content of the task to be
98+
decomposed.
99+
sub_task_contents (List[str]): A list of strings, where each
100+
string is the content for a new sub-task.
101+
original_task_id (Optional[str]): The id of the task to be
102+
decomposed. (default: :obj: `None`)
103+
104+
Returns:
105+
List[Task]: Reordered or modified tasks.
106+
"""
107+
original_task = Task(
108+
content=original_task_content,
109+
id=original_task_id if original_task_id else str(uuid.uuid4()),
110+
)
111+
112+
new_tasks: List[Task] = []
113+
for i, content in enumerate(sub_task_contents):
114+
new_task = Task(
115+
content=content,
116+
id=f"{original_task.id}.{i}",
117+
parent=original_task,
118+
)
119+
new_tasks.append(new_task)
120+
original_task.subtasks.append(new_task)
121+
122+
logger.debug(
123+
f"RePlan task (content: '{original_task.content[:50]}...', "
124+
f"id: {original_task.id}) into {len(new_tasks)} sub-tasks: "
125+
f"{[task.id for task in new_tasks]}"
126+
)
127+
128+
return new_tasks
129+
130+
def get_tools(self) -> List[FunctionTool]:
131+
return [
132+
FunctionTool(self.decompose_task),
133+
FunctionTool(self.replan_tasks),
134+
]

docs/mintlify/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@
493493
"reference/camel.toolkits.slack_toolkit",
494494
"reference/camel.toolkits.stripe_toolkit",
495495
"reference/camel.toolkits.sympy_toolkit",
496+
"reference/camel.toolkits.task_planning_toolkit",
496497
"reference/camel.toolkits.terminal_toolkit",
497498
"reference/camel.toolkits.thinking_toolkit",
498499
"reference/camel.toolkits.twitter_toolkit",
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<a id="camel.toolkits.task_planning_toolkit"></a>
2+
3+
<a id="camel.toolkits.task_planning_toolkit.TaskPlanningToolkit"></a>
4+
5+
## TaskPlanningToolkit
6+
7+
```python
8+
class TaskPlanningToolkit(BaseToolkit):
9+
```
10+
11+
A toolkit for task decomposition and rePlanning.
12+
13+
<a id="camel.toolkits.task_planning_toolkit.TaskPlanningToolkit.__init__"></a>
14+
15+
### __init__
16+
17+
```python
18+
def __init__(self, timeout: Optional[float] = None):
19+
```
20+
21+
Initialize the TaskPlanningToolkit.
22+
23+
**Parameters:**
24+
25+
- **timeout** (Optional[float]): The timeout for the toolkit. (default: :obj: `None`)
26+
27+
<a id="camel.toolkits.task_planning_toolkit.TaskPlanningToolkit.decompose_task"></a>
28+
29+
### decompose_task
30+
31+
```python
32+
def decompose_task(self, original_task_content: str, sub_task_contents: List[str]):
33+
```
34+
35+
Use the tool to decompose an original task into several sub-tasks.
36+
It creates new Task objects from the provided original task content,
37+
used when the original task is complex and needs to be decomposed.
38+
39+
**Parameters:**
40+
41+
- **original_task_content** (str): The content of the task to be decomposed.
42+
- **sub_task_contents** (List[str]): A list of strings, where each string is the content for a new sub-task.
43+
44+
**Returns:**
45+
46+
List[Task]: A list of newly created sub-task objects.
47+
48+
<a id="camel.toolkits.task_planning_toolkit.TaskPlanningToolkit.replan_tasks"></a>
49+
50+
### replan_tasks
51+
52+
```python
53+
def replan_tasks(self, original_task_content: str, sub_task_contents: List[str]):
54+
```
55+
56+
Use the tool to reDecompose a task into several subTasks.
57+
It creates new Task objects from the provided original task content,
58+
used when the decomposed tasks are not good enough to help finish
59+
the task.
60+
61+
**Parameters:**
62+
63+
- **original_task_content** (str): The content of the task to be decomposed.
64+
- **sub_task_contents** (List[str]): A list of strings, where each string is the content for a new sub-task.
65+
66+
**Returns:**
67+
68+
List[Task]: Reordered or modified tasks.
69+
70+
<a id="camel.toolkits.task_planning_toolkit.TaskPlanningToolkit.get_tools"></a>
71+
72+
### get_tools
73+
74+
```python
75+
def get_tools(self):
76+
```

0 commit comments

Comments
 (0)