mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-14 10:38:29 +00:00
Hierarchical process (#206)
* Hierarchical process + Docs Co-authored-by: João Moura <joaomdmoura@gmail.com>
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
import uuid
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.agents.agent import RunnableAgent
|
||||
from langchain.agents.format_scratchpad import format_log_to_str
|
||||
from langchain.memory import ConversationSummaryMemory
|
||||
from langchain.tools.render import render_text_description
|
||||
from langchain_core.runnables.config import RunnableConfig
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from pydantic import (
|
||||
UUID4,
|
||||
BaseModel,
|
||||
@@ -171,7 +170,7 @@ class Agent(BaseModel):
|
||||
"""
|
||||
self.cache_handler = cache_handler
|
||||
self.tools_handler = ToolsHandler(cache=self.cache_handler)
|
||||
self.__create_agent_executor()
|
||||
self._create_agent_executor()
|
||||
|
||||
def set_rpm_controller(self, rpm_controller: RPMController) -> None:
|
||||
"""Set the rpm controller for the agent.
|
||||
@@ -181,9 +180,9 @@ class Agent(BaseModel):
|
||||
"""
|
||||
if not self._rpm_controller:
|
||||
self._rpm_controller = rpm_controller
|
||||
self.__create_agent_executor()
|
||||
self._create_agent_executor()
|
||||
|
||||
def __create_agent_executor(self) -> None:
|
||||
def _create_agent_executor(self) -> None:
|
||||
"""Create an agent executor for the agent.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -142,18 +142,26 @@ class Crew(BaseModel):
|
||||
agent.i18n = I18N(language=self.language)
|
||||
|
||||
if self.process == Process.sequential:
|
||||
return self._sequential_loop()
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"The process '{self.process}' is not implemented yet."
|
||||
)
|
||||
return self._run_sequential_process()
|
||||
if self.process == Process.hierarchical:
|
||||
return self._run_hierarchical_process()
|
||||
|
||||
def _sequential_loop(self) -> str:
|
||||
raise NotImplementedError(
|
||||
f"The process '{self.process}' is not implemented yet."
|
||||
)
|
||||
|
||||
def _run_sequential_process(self) -> str:
|
||||
"""Executes tasks sequentially and returns the final output."""
|
||||
task_output = ""
|
||||
for task in self.tasks:
|
||||
self._prepare_and_execute_task(task)
|
||||
task_output = task.execute(task_output)
|
||||
if task.agent is not None and task.agent.allow_delegation:
|
||||
task.tools += AgentTools(agents=self.agents).tools()
|
||||
|
||||
role = task.agent.role if task.agent is not None else "None"
|
||||
self._logger.log("debug", f"Working Agent: {role}")
|
||||
self._logger.log("info", f"Starting Task: {task.description}")
|
||||
|
||||
task_output = task.execute(context=task_output)
|
||||
|
||||
role = task.agent.role if task.agent is not None else "None"
|
||||
self._logger.log("debug", f"[{role}] Task output: {task_output}\n\n")
|
||||
@@ -163,15 +171,29 @@ class Crew(BaseModel):
|
||||
|
||||
return task_output
|
||||
|
||||
def _prepare_and_execute_task(self, task: Task) -> None:
|
||||
"""Prepares and logs information about the task being executed.
|
||||
def _run_hierarchical_process(self) -> str:
|
||||
"""Creates and assigns a manager agent to make sure the crew completes the tasks."""
|
||||
|
||||
Args:
|
||||
task: The task to be executed.
|
||||
"""
|
||||
if task.agent is not None and task.agent.allow_delegation:
|
||||
task.tools += AgentTools(agents=self.agents).tools()
|
||||
i18n = I18N(language=self.language)
|
||||
manager = Agent(
|
||||
role=i18n.retrieve("hierarchical_manager_agent", "role"),
|
||||
goal=i18n.retrieve("hierarchical_manager_agent", "goal"),
|
||||
backstory=i18n.retrieve("hierarchical_manager_agent", "backstory"),
|
||||
tools=AgentTools(agents=self.agents).tools(),
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
role = task.agent.role if task.agent is not None else "None"
|
||||
self._logger.log("debug", f"Working Agent: {role}")
|
||||
self._logger.log("info", f"Starting Task: {task.description}")
|
||||
task_output = ""
|
||||
for task in self.tasks:
|
||||
self._logger.log("info", f"Starting Task: {task.description}")
|
||||
|
||||
task_output = task.execute(agent=manager, context=task_output)
|
||||
|
||||
self._logger.log(
|
||||
"debug", f"[{manager.role}] Task output: {task_output}\n\n"
|
||||
)
|
||||
|
||||
if self.max_rpm:
|
||||
self._rpm_controller.stop_rpm_counter()
|
||||
|
||||
return task_output
|
||||
|
||||
@@ -7,5 +7,5 @@ class Process(str, Enum):
|
||||
"""
|
||||
|
||||
sequential = "sequential"
|
||||
hierarchical = "hierarchical"
|
||||
# TODO: consensual = 'consensual'
|
||||
# TODO: hierarchical = 'hierarchical'
|
||||
|
||||
@@ -19,7 +19,7 @@ class Task(BaseModel):
|
||||
description="Callback to be executed after the task is completed.", default=None
|
||||
)
|
||||
agent: Optional[Agent] = Field(
|
||||
description="Agent responsible for executiong the task.", default=None
|
||||
description="Agent responsible for execution the task.", default=None
|
||||
)
|
||||
expected_output: Optional[str] = Field(
|
||||
description="Clear definition of expected output for the task.",
|
||||
@@ -53,18 +53,20 @@ class Task(BaseModel):
|
||||
self.tools.extend(self.agent.tools)
|
||||
return self
|
||||
|
||||
def execute(self, context: Optional[str] = None) -> str:
|
||||
def execute(self, agent: Agent | None = None, context: Optional[str] = None) -> str:
|
||||
"""Execute the task.
|
||||
|
||||
Returns:
|
||||
Output of the task.
|
||||
"""
|
||||
if not self.agent:
|
||||
|
||||
agent = agent or self.agent
|
||||
if not agent:
|
||||
raise Exception(
|
||||
f"The task '{self.description}' has no agent assigned, therefore it can't be executed directly and should be executed in a Crew using a specific process that support that, either consensual or hierarchical."
|
||||
f"The task '{self.description}' has no agent assigned, therefore it can't be executed directly and should be executed in a Crew using a specific process that support that, like hierarchical."
|
||||
)
|
||||
|
||||
result = self.agent.execute_task(
|
||||
result = agent.execute_task(
|
||||
task=self._prompt(), context=context, tools=self.tools
|
||||
)
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@ class AgentTools(BaseModel):
|
||||
|
||||
def delegate_work(self, command):
|
||||
"""Useful to delegate a specific task to a coworker."""
|
||||
return self.__execute(command)
|
||||
return self._execute(command)
|
||||
|
||||
def ask_question(self, command):
|
||||
"""Useful to ask a question, opinion or take from a coworker."""
|
||||
return self.__execute(command)
|
||||
return self._execute(command)
|
||||
|
||||
def __execute(self, command):
|
||||
def _execute(self, command):
|
||||
"""Execute the command."""
|
||||
try:
|
||||
agent, task, context = command.split("|")
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"hierarchical_manager_agent": {
|
||||
"role": "Διευθυντής Ομάδας",
|
||||
"goal": "Διαχειρίσου την ομάδα σου για να ολοκληρώσει την εργασία με τον καλύτερο δυνατό τρόπο.",
|
||||
"backstory": "Είσαι ένας έμπειρος διευθυντής με την ικανότητα να βγάζεις το καλύτερο από την ομάδα σου.\nΕίσαι επίσης γνωστός για την ικανότητά σου να αναθέτεις εργασίες στους σωστούς ανθρώπους και να κάνεις τις σωστές ερωτήσεις για να πάρεις το καλύτερο από την ομάδα σου.\nΑκόμα κι αν δεν εκτελείς εργασίες μόνος σου, έχεις πολλή εμπειρία στον τομέα, που σου επιτρέπει να αξιολογείς σωστά τη δουλειά των μελών της ομάδας σου."
|
||||
},
|
||||
"slices": {
|
||||
"observation": "\nΠαρατήρηση",
|
||||
"task": "Αρχή! Αυτό είναι ΠΟΛΥ σημαντικό για εσάς, η δουλειά σας εξαρτάται από αυτό!\n\nΤρέχουσα εργασία: {input}",
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"hierarchical_manager_agent": {
|
||||
"role": "Crew Manager",
|
||||
"goal": "Manage the team to complete the task in the best way possible.",
|
||||
"backstory": "You are a seasoned manager with a knack for getting the best out of your team.\nYou are also known for your ability to delegate work to the right people, and to ask the right questions to get the best out of your team.\nEven though you don't perform tasks by yourself, you have a lot of experience in the field, which allows you to properly evaluate the work of your team members."
|
||||
},
|
||||
"slices": {
|
||||
"observation": "\nObservation",
|
||||
"task": "Begin! This is VERY important to you, your job depends on it!\n\nCurrent Task: {input}",
|
||||
@@ -18,4 +23,4 @@
|
||||
"delegate_work": "Useful to delegate a specific task to one of the following co-workers: {coworkers}.\nThe input to this tool should be a pipe (|) separated text of length 3 (three), representing the co-worker you want to ask it to (one of the options), the task and all actual context you have for the task.\nFor example, `coworker|task|context`.",
|
||||
"ask_question": "Useful to ask a question, opinion or take from on of the following co-workers: {coworkers}.\nThe input to this tool should be a pipe (|) separated text of length 3 (three), representing the co-worker you want to ask it to (one of the options), the question and all actual context you have for the question.\n For example, `coworker|question|context`."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user