Source code for camel.societies.babyagi_playing

# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from collections import deque
from typing import Dict, List, Optional

from camel.agents import (
    ChatAgent,
    TaskCreationAgent,
    TaskPrioritizationAgent,
    TaskSpecifyAgent,
)
from camel.agents.chat_agent import ChatAgentResponse
from camel.generators import SystemMessageGenerator
from camel.messages import BaseMessage
from camel.prompts import TextPrompt
from camel.types import RoleType, TaskType


[docs] class BabyAGI: r"""The BabyAGI Agent adapted from `"Task-driven Autonomous Agent" <https://github.com/yoheinakajima/babyagi>`_. Args: assistant_role_name (str): The name of the role played by the assistant. user_role_name (str): The name of the role played by the user. task_prompt (str, optional): A prompt for the task to be performed. (default: :obj:`""`) task_type (TaskType, optional): The type of task to perform. (default: :obj:`TaskType.AI_SOCIETY`) max_task_history (int): The maximum number of previous tasks information to include in the task agent. (default: :obj:10) assistant_agent_kwargs (Dict, optional): Additional arguments to pass to the assistant agent. (default: :obj:`None`) task_specify_agent_kwargs (Dict, optional): Additional arguments to pass to the task specify agent. (default: :obj:`None`) task_creation_agent_kwargs (Dict, optional): Additional arguments to pass to the task creation agent. (default: :obj:`None`) task_prioritization_agent_kwargs (Dict, optional): Additional arguments to pass to the task prioritization agent. (default: :obj:`None`) sys_msg_generator_kwargs (Dict, optional): Additional arguments to pass to the system message generator. (default: :obj:`None`) extend_task_specify_meta_dict (Dict, optional): A dict to extend the task specify meta dict with. (default: :obj:`None`) output_language (str, optional): The language to be output by the agents. (default: :obj:`None`) message_window_size (int, optional): The maximum number of previous messages to include in the context window. If `None`, no windowing is performed. (default: :obj:`None`) """ def __init__( self, assistant_role_name: str, user_role_name: str, task_prompt: str = "", task_type: TaskType = TaskType.AI_SOCIETY, max_task_history: int = 10, assistant_agent_kwargs: Optional[Dict] = None, task_specify_agent_kwargs: Optional[Dict] = None, task_creation_agent_kwargs: Optional[Dict] = None, task_prioritization_agent_kwargs: Optional[Dict] = None, sys_msg_generator_kwargs: Optional[Dict] = None, extend_task_specify_meta_dict: Optional[Dict] = None, output_language: Optional[str] = None, message_window_size: Optional[int] = None, ) -> None: self.task_type = task_type self.task_prompt = task_prompt self.specified_task_prompt: TextPrompt self.init_specified_task_prompt( assistant_role_name, user_role_name, task_specify_agent_kwargs, extend_task_specify_meta_dict, output_language, ) sys_msg_generator = SystemMessageGenerator( task_type=self.task_type, **(sys_msg_generator_kwargs or {}) ) init_assistant_sys_msg = sys_msg_generator.from_dicts( meta_dicts=[ dict( assistant_role=assistant_role_name, user_role=user_role_name, task=self.specified_task_prompt, ) ], role_tuples=[ (assistant_role_name, RoleType.ASSISTANT), ], ) self.assistant_agent: ChatAgent self.assistant_sys_msg: BaseMessage self.task_creation_agent: TaskCreationAgent self.task_prioritization_agent: TaskPrioritizationAgent self.init_agents( init_assistant_sys_msg[0], assistant_agent_kwargs, task_creation_agent_kwargs, task_prioritization_agent_kwargs, output_language, message_window_size, ) self.subtasks: deque = deque([]) self.solved_subtasks: List[str] = [] self.MAX_TASK_HISTORY = max_task_history
[docs] def init_specified_task_prompt( self, assistant_role_name: str, user_role_name: str, task_specify_agent_kwargs: Optional[Dict], extend_task_specify_meta_dict: Optional[Dict], output_language: Optional[str], ): r"""Use a task specify agent to generate a specified task prompt. Generated specified task prompt will be used to replace original task prompt. If there is no task specify agent, specified task prompt will not be generated. Args: assistant_role_name (str): The name of the role played by the assistant. user_role_name (str): The name of the role played by the user. task_specify_agent_kwargs (Dict, optional): Additional arguments to pass to the task specify agent. extend_task_specify_meta_dict (Dict, optional): A dict to extend the task specify meta dict with. output_language (str, optional): The language to be output by the agents. """ task_specify_meta_dict = dict() if self.task_type in [TaskType.AI_SOCIETY, TaskType.MISALIGNMENT]: task_specify_meta_dict.update( dict( assistant_role=assistant_role_name, user_role=user_role_name, ) ) task_specify_meta_dict.update(extend_task_specify_meta_dict or {}) task_specify_agent = TaskSpecifyAgent( task_type=self.task_type, output_language=output_language, **(task_specify_agent_kwargs or {}), ) self.specified_task_prompt = task_specify_agent.run( self.task_prompt, meta_dict=task_specify_meta_dict, )
[docs] def init_agents( self, init_assistant_sys_msg: BaseMessage, assistant_agent_kwargs: Optional[Dict], task_creation_agent_kwargs: Optional[Dict], task_prioritization_agent_kwargs: Optional[Dict], output_language: Optional[str], message_window_size: Optional[int] = None, ): r"""Initialize assistant and user agents with their system messages. Args: init_assistant_sys_msg (BaseMessage): Assistant agent's initial system message. assistant_agent_kwargs (Dict, optional): Additional arguments to pass to the assistant agent. task_creation_agent_kwargs (Dict, optional): Additional arguments to pass to the task creation agent. task_prioritization_agent_kwargs (Dict, optional): Additional arguments to pass to the task prioritization agent. output_language (str, optional): The language to be output by the agents. message_window_size (int, optional): The maximum number of previous messages to include in the context window. If `None`, no windowing is performed. (default: :obj:`None`) """ self.assistant_agent = ChatAgent( init_assistant_sys_msg, output_language=output_language, message_window_size=message_window_size, **(assistant_agent_kwargs or {}), ) self.assistant_sys_msg = self.assistant_agent.system_message self.assistant_agent.reset() self.task_creation_agent = TaskCreationAgent( objective=self.specified_task_prompt, role_name=self.assistant_sys_msg.role_name, output_language=output_language, message_window_size=message_window_size, **(task_creation_agent_kwargs or {}), ) self.task_creation_agent.reset() self.task_prioritization_agent = TaskPrioritizationAgent( objective=self.specified_task_prompt, output_language=output_language, message_window_size=message_window_size, **(task_prioritization_agent_kwargs or {}), ) self.task_prioritization_agent.reset()
[docs] def step(self) -> ChatAgentResponse: r"""BabyAGI agent would pull the first task from the task list, complete the task based on the context, then creates new tasks and re-prioritizes the task list based on the objective and the result of the previous task. It returns assistant message. Returns: ChatAgentResponse: it contains the resulting assistant message, whether the assistant agent terminated the conversation, and any additional assistant information. """ if not self.subtasks: new_subtask_list = self.task_creation_agent.run(task_list=[]) prioritized_subtask_list = self.task_prioritization_agent.run( new_subtask_list ) self.subtasks = deque(prioritized_subtask_list) task_name = self.subtasks.popleft() assistant_msg_msg = BaseMessage.make_user_message( role_name=self.assistant_sys_msg.role_name, content=f"{task_name}" ) assistant_response = self.assistant_agent.step(assistant_msg_msg) assistant_msg = assistant_response.msgs[0] self.solved_subtasks.append(task_name) past_tasks = self.solved_subtasks + list(self.subtasks) new_subtask_list = self.task_creation_agent.run( task_list=past_tasks[-self.MAX_TASK_HISTORY :] ) if new_subtask_list: self.subtasks.extend(new_subtask_list) prioritized_subtask_list = self.task_prioritization_agent.run( task_list=list(self.subtasks)[-self.MAX_TASK_HISTORY :] ) self.subtasks = deque(prioritized_subtask_list) else: print("no new tasks") assistant_response.info['task_name'] = task_name assistant_response.info['subtasks'] = list(self.subtasks) if not self.subtasks: terminated = True assistant_response.info['termination_reasons'] = ( "All tasks are solved" ) return ChatAgentResponse( msgs=[assistant_msg], terminated=terminated, info=assistant_response.info, ) return ChatAgentResponse( msgs=[assistant_msg], terminated=assistant_response.terminated, info=assistant_response.info, )