Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement babyagi_agent and integrate it into multimodel role playing #210

Merged
merged 70 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
c639075
pr_test
hychen-naza Jul 7, 2023
dcfc5ff
babyagi_pr_test
hychen-naza Jul 7, 2023
034727c
babyagi_pr_test
hychen-naza Jul 7, 2023
2e17f7a
update test
hychen-naza Jul 15, 2023
a5447c5
babyagi
hychen-naza Jul 15, 2023
4602a85
babyagi
hychen-naza Jul 15, 2023
3101a79
babyagi
hychen-naza Jul 15, 2023
2d85411
babyagi
hychen-naza Jul 15, 2023
e67e10d
babyagi
hychen-naza Jul 15, 2023
595c640
babyagi
hychen-naza Jul 15, 2023
a181484
babyagi
hychen-naza Jul 15, 2023
17e1dee
babyagi
hychen-naza Jul 15, 2023
553c46d
babyagi
hychen-naza Jul 15, 2023
20c821c
babyagi
hychen-naza Jul 15, 2023
4ad7299
babyagi
hychen-naza Jul 15, 2023
eced189
babyagi
hychen-naza Jul 15, 2023
67caaaf
babyagi
hychen-naza Jul 15, 2023
50c5ff3
babyagi
hychen-naza Jul 15, 2023
18c6a20
babyagi
hychen-naza Jul 15, 2023
e05848f
babyagi
hychen-naza Jul 15, 2023
eec1801
babyagi
hychen-naza Jul 15, 2023
b250e72
babyagi
hychen-naza Jul 15, 2023
0e622ac
package
hychen-naza Jul 18, 2023
99ef6b2
Merge branch 'master' into new_agents
hychen-naza Jul 18, 2023
259a0ee
pyproject update
hychen-naza Jul 18, 2023
4afb6e8
Update __init__.py
hychen-naza Jul 23, 2023
245a767
delete old babyagi
hychen-naza Jul 23, 2023
445e9a6
Merge branch 'new_agents' of https://github.com/camel-ai/camel into n…
hychen-naza Jul 23, 2023
268ac03
Update __init__.py
hychen-naza Jul 23, 2023
c6b44b1
Merge branch 'new_agents' of https://github.com/camel-ai/camel into n…
hychen-naza Jul 23, 2023
14951db
remove duplicate multi model roleplaying
hychen-naza Jul 23, 2023
35dd806
remove old babyagi test
hychen-naza Jul 23, 2023
9f01c79
Merge branch 'master' into new_agents
hychen-naza Jul 23, 2023
f1370e2
remove babyagi play
hychen-naza Jul 23, 2023
56cb6ee
split babyagi to task agent
hychen-naza Jul 23, 2023
31c8fed
split babyagi to task agent
hychen-naza Jul 23, 2023
2f53bde
split babyagi to task agent
hychen-naza Jul 23, 2023
73b5b51
split babyagi to task agent
hychen-naza Jul 23, 2023
46eed90
split babyagi to task agent
hychen-naza Jul 23, 2023
9751b43
Merge branch 'master' into new_agents
hychen-naza Jul 23, 2023
98d397d
Update camel/agents/task_agent.py
hychen-naza Jul 24, 2023
392d9f7
Update test/agents/test_task_agent.py
hychen-naza Jul 24, 2023
ac00d54
Update camel/agents/task_agent.py
hychen-naza Jul 24, 2023
29d96eb
Update camel/agents/task_agent.py
hychen-naza Jul 24, 2023
a60d9dd
Update camel/agents/task_agent.py
hychen-naza Jul 24, 2023
f9068be
Update camel/agents/task_agent.py
hychen-naza Jul 24, 2023
5af6c27
resolve comments
hychen-naza Jul 24, 2023
0807d19
resolve comments
hychen-naza Jul 26, 2023
389dba2
resolve comments
hychen-naza Jul 26, 2023
bd7c859
remove packages
hychen-naza Jul 26, 2023
1495e41
resolve minor comments
hychen-naza Jul 26, 2023
6e2f21d
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
e2f4654
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
ea569e8
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
b3a6a32
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
3c23613
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
d4e0e74
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
7a24cb5
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
8bf59c4
Update camel/utils/functions.py
hychen-naza Jul 27, 2023
9f94d07
Update camel/utils/functions.py
hychen-naza Jul 27, 2023
0d914ce
Update camel/agents/task_agent.py
hychen-naza Jul 27, 2023
d51f959
add test for utils function
hychen-naza Jul 27, 2023
d7a17b9
Minor update in naming, test and docs
lightaime Jul 31, 2023
d2a3fc4
Merge branch 'master' into new_agents
lightaime Jul 31, 2023
a9d75cc
update
lightaime Jul 31, 2023
5145469
Merge branch 'new_agents' of https://github.com/camel-ai/camel into n…
lightaime Jul 31, 2023
ae367f9
fix
lightaime Jul 31, 2023
0e3588b
update
lightaime Jul 31, 2023
3543104
update
lightaime Jul 31, 2023
ea85c62
update
lightaime Jul 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion camel/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from .base import BaseAgent
from .chat_agent import ChatAgent, ChatAgentResponse
from .task_agent import TaskPlannerAgent, TaskSpecifyAgent
from .task_agent import (
TaskSpecifyAgent,
TaskPlannerAgent,
TaskCreationAgent,
TaskPrioritizationAgent,
)
from .critic_agent import CriticAgent
from .tool_agents.base import BaseToolAgent
from .tool_agents.hugging_face_tool_agent import HuggingFaceToolAgent
Expand All @@ -25,6 +30,8 @@
'ChatAgentResponse',
'TaskSpecifyAgent',
'TaskPlannerAgent',
'TaskCreationAgent',
'TaskPrioritizationAgent',
'CriticAgent',
'BaseToolAgent',
'HuggingFaceToolAgent',
Expand Down
248 changes: 221 additions & 27 deletions camel/agents/task_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from typing import Any, Dict, Optional, Union
from typing import Any, Dict, List, Optional, Union

from camel.agents import ChatAgent
from camel.configs import ChatGPTConfig
from camel.messages import BaseMessage
from camel.prompts import PromptTemplateGenerator, TextPrompt
from camel.typing import ModelType, RoleType, TaskType
from camel.utils import get_task_list


class TaskSpecifyAgent(ChatAgent):
Expand All @@ -29,15 +30,15 @@ class TaskSpecifyAgent(ChatAgent):
task_specify_prompt (TextPrompt): The prompt for specifying the task.

Args:
model (ModelType): The type of model to use for the agent.
model (ModelType, optional): The type of model to use for the agent.
(default: :obj:`ModelType.GPT_3_5_TURBO`)
task_type (TaskType): The type of task for which to generate a prompt.
(default: :obj:`TaskType.AI_SOCIETY`)
model_config (Any): The configuration for the model.
task_type (TaskType, optional): The type of task for which to generate
a prompt. (default: :obj:`TaskType.AI_SOCIETY`)
model_config (Any, optional): The configuration for the model.
(default: :obj:`None`)
task_specify_prompt (Optional[TextPrompt]): The prompt for specifying
the task. (default: :obj:`None`)
word_limit (int): The word limit for the task prompt.
task_specify_prompt (Union[str, TextPrompt], optional): The prompt for
specifying the task. (default: :obj:`None`)
word_limit (int, optional): The word limit for the task prompt.
(default: :obj:`50`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
Expand Down Expand Up @@ -86,26 +87,23 @@ def run(
Args:
task_prompt (Union[str, TextPrompt]): The original task
prompt.
meta_dict (Optional[Dict[str, Any]]): A dictionary containing
meta_dict (Dict[str, Any], optional): A dictionary containing
additional information to include in the prompt.
(default: :obj:`None`)

Returns:
TextPrompt: The specified task prompt.
"""
self.reset()
self.task_specify_prompt = self.task_specify_prompt.format(
task=task_prompt)
task_specify_prompt = self.task_specify_prompt.format(task=task_prompt)

if meta_dict is not None:
self.task_specify_prompt = (self.task_specify_prompt.format(
**meta_dict))
task_specify_prompt = (task_specify_prompt.format(**meta_dict))

task_msg = BaseMessage.make_user_message(
role_name="Task Specifier", content=self.task_specify_prompt)
task_msg = BaseMessage.make_user_message(role_name="Task Specifier",
content=task_specify_prompt)
specifier_response = self.step(task_msg)
if (specifier_response.msgs is None
or len(specifier_response.msgs) == 0):
if len(specifier_response.msgs) == 0:
raise RuntimeError("Task specification failed.")
specified_task_msg = specifier_response.msgs[0]

Expand All @@ -124,9 +122,9 @@ class TaskPlannerAgent(ChatAgent):
the task into subtasks.

Args:
model (ModelType): The type of model to use for the agent.
model (ModelType, optional: The type of model to use for the agent.
(default: :obj:`ModelType.GPT_3_5_TURBO`)
model_config (Any): The configuration for the model.
model_config (Any, optional): The configuration for the model.
(default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
Expand All @@ -135,13 +133,12 @@ class TaskPlannerAgent(ChatAgent):
def __init__(
self,
model: Optional[ModelType] = None,
model_config: Any = None,
model_config: Optional[Any] = None,
output_language: Optional[str] = None,
) -> None:

self.task_planner_prompt = TextPrompt(
"Divide this task into subtasks: {task}. Be concise.")

system_message = BaseMessage(
role_name="Task Planner",
role_type=RoleType.ASSISTANT,
Expand All @@ -167,17 +164,214 @@ def run(
"""
# TODO: Maybe include roles information.
self.reset()
self.task_planner_prompt = self.task_planner_prompt.format(
task=task_prompt)
task_planner_prompt = self.task_planner_prompt.format(task=task_prompt)

task_msg = BaseMessage.make_user_message(role_name="Task Planner",
content=task_planner_prompt)

task_msg = BaseMessage.make_user_message(
role_name="Task Planner", content=self.task_planner_prompt)
task_response = self.step(task_msg)

if task_response.msgs is None:
raise RuntimeError("Got None Subtasks messages.")
if len(task_response.msgs) == 0:
raise RuntimeError("Got no task planning messages.")
if task_response.terminated:
raise RuntimeError("Task planning failed.")

sub_tasks_msg = task_response.msgs[0]
return TextPrompt(sub_tasks_msg.content)


class TaskCreationAgent(ChatAgent):
r"""An agent that helps create new tasks based on the objective
and last completed task. Compared to :obj:`TaskPlannerAgent`,
it's still a task planner, but it has more context information
like last task and incomplete task list. Modified from
`BabyAGI <https://github.com/yoheinakajima/babyagi>`_.

Attributes:
task_creation_prompt (TextPrompt): A prompt for the agent to create
new tasks.

Args:
objective (Union[str, TextPrompt]): The objective of the Agent to
perform the task.
model (ModelType, optional): The type of model to use for the agent.
(default: :obj:`ModelType.GPT_3_5_TURBO`)
model_config (Any, optional): The configuration for the model.
(default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
"""

def __init__(
self,
objective: Union[str, TextPrompt],
model: Optional[ModelType] = None,
model_config: Optional[Any] = None,
output_language: Optional[str] = None,
) -> None:

task_creation_prompt = TextPrompt(
"""Create new tasks with the following objective: {objective}.
The last completed task has the result:
{task_result}.
This result was based on this task: {task}.
Based on the result, return a list of tasks to be completed in order to meet \
the objective.

{unsolved_tasks}

Return one task per line in your response.
The result must be a numbered list in the format:

1. First task
2. Second task

The number of each entry must be followed by a period. Be concise.""")

self.task_creation_prompt = task_creation_prompt.format(
objective=objective)
self.objective = objective

system_message = BaseMessage(
role_name="Task Creator",
role_type=RoleType.ASSISTANT,
meta_dict=None,
content="You are a helpful task creator.",
)

super().__init__(system_message, model, model_config,
output_language=output_language)

def run(
self,
previous_task: Union[str, TextPrompt],
task_result: Union[str, TextPrompt],
task_list: Optional[List[str]] = None,
) -> List[str]:
r"""Generate subtasks based on the previous task results and
incomplete task list.

Args:
previous_task (Union[str, TextPrompt]): The last completed task to
be used to create future plans.
task_result (Union[str, TextPrompt]): The result of last completed
task to be used to create future plans.
task_list (List[str], optional): The incomplete task list
which should not overlap with new created tasks.
(default: :obj:`None`)
Returns:
List[str]: The new task list generated by the Agent.
"""
self.reset()
task_creation_prompt = self.task_creation_prompt.format(
task=previous_task, task_result=task_result)
if task_list is not None:
unsolved = (
f"These are unsolved tasks: {task_list}.\n"
"These new tasks must not overlap with incomplete tasks.")

task_creation_prompt = task_creation_prompt.format(
unsolved_tasks=unsolved)
else:
task_creation_prompt = task_creation_prompt.format(
unsolved_tasks="")

task_msg = BaseMessage.make_user_message(role_name="Task Creator",
content=task_creation_prompt)

task_response = self.step(task_msg)

if len(task_response.msgs) == 0:
raise RuntimeError("Got no task creation messages.")
if task_response.terminated:
raise RuntimeError("Task creation failed.")

sub_tasks_msg = task_response.msgs[0]
return get_task_list(sub_tasks_msg.content)


class TaskPrioritizationAgent(ChatAgent):
r"""An agent that helps re-prioritize the task list and
returns numbered prioritized list. Modified from
`BabyAGI <https://github.com/yoheinakajima/babyagi>`_.

Attributes:
task_prioritization_prompt (TextPrompt): A prompt for the agent to
prioritize tasks.

Args:
objective (Union[str, TextPrompt]): The objective of the Agent to
perform the task.
model (ModelType, optional): The type of model to use for the agent.
(default: :obj:`ModelType.GPT_3_5_TURBO`)
model_config (Any, optional): The configuration for the model.
(default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
"""

def __init__(
self,
objective: Union[str, TextPrompt],
model: Optional[ModelType] = None,
model_config: Optional[Any] = None,
output_language: Optional[str] = None,
) -> None:

task_prioritization_prompt = TextPrompt(
"""Prioritize the following tasks : {task_list}.
Consider the ultimate objective of you: {objective}.
Tasks should be sorted from highest to lowest priority,
where higher-priority tasks are those that act as pre-requisites \
or are more essential for meeting the objective.
Return one task per line in your response. Do not remove any tasks.
The result must be a numbered list in the format:

1. First task
2. Second task

The entries must be consecutively numbered, starting with 1.
The number of each entry must be followed by a period.
Be concise.""")

self.task_prioritization_prompt = task_prioritization_prompt.format(
objective=objective)
self.objective = objective

system_message = BaseMessage(
role_name="Task Prioritizer",
role_type=RoleType.ASSISTANT,
meta_dict=None,
content="You are a helpful task prioritizer.",
)

super().__init__(system_message, model, model_config,
output_language=output_language)

def run(
self,
task_list: List[str],
) -> List[str]:
r"""Prioritize the task list given the agent objective.

Args:
task_list (List[str]): The un-prioritized task list of agent.
Returns:
List[str]: The new prioritized task list generated by the Agent.
"""
self.reset()
task_prioritization_prompt = self.task_prioritization_prompt.format(
task_list=task_list)

task_msg = BaseMessage.make_user_message(
role_name="Task Prioritizer", content=task_prioritization_prompt)

task_response = self.step(task_msg)

if len(task_response.msgs) == 0:
raise RuntimeError("Got no task prioritization messages.")
if task_response.terminated:
raise RuntimeError("Task prioritization failed.")

sub_tasks_msg = task_response.msgs[0]
return get_task_list(sub_tasks_msg.content)
2 changes: 2 additions & 0 deletions camel/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
get_first_int,
download_tasks,
parse_doc,
get_task_list,
)

__all__ = [
Expand All @@ -35,4 +36,5 @@
'download_tasks',
'PythonInterpreter',
'parse_doc',
'get_task_list',
]
23 changes: 23 additions & 0 deletions camel/utils/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,26 @@ def parse_doc(func: Callable) -> Dict[str, Any]:
}

return function_dict


def get_task_list(task_response: str) -> List[str]:
r"""Parse the response of the Agent and return task list.

Args:
task_response (str): The string response of the Agent.

hychen-naza marked this conversation as resolved.
Show resolved Hide resolved
Returns:
List[str]: A list of the string tasks.
"""

new_tasks_list = []
task_string_list = task_response.strip().split('\n')
# each task starts with #.
for task_string in task_string_list:
task_parts = task_string.strip().split(".", 1)
if len(task_parts) == 2:
task_id = ''.join(s for s in task_parts[0] if s.isnumeric())
task_name = re.sub(r'[^\w\s_]+', '', task_parts[1]).strip()
if task_name.strip() and task_id.isnumeric():
new_tasks_list.append(task_name)
return new_tasks_list
Loading