From 53697744befe135cb334f7aef922f4692c67b220 Mon Sep 17 00:00:00 2001 From: Brandon Hancock Date: Wed, 9 Oct 2024 14:58:24 -0400 Subject: [PATCH 1/4] Trying to fix linting --- src/crewai/agents/crew_agent_executor.py | 37 +++++++++++++----------- src/crewai/crew.py | 3 ++ src/crewai/flow/flow.py | 2 +- src/crewai/project/annotations.py | 7 +++-- src/crewai/project/crew_base.py | 4 +-- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/crewai/agents/crew_agent_executor.py b/src/crewai/agents/crew_agent_executor.py index 8b3db9d85f..b11d032761 100644 --- a/src/crewai/agents/crew_agent_executor.py +++ b/src/crewai/agents/crew_agent_executor.py @@ -3,7 +3,13 @@ from typing import Any, Dict, List, Union from crewai.agents.agent_builder.base_agent_executor_mixin import CrewAgentExecutorMixin -from crewai.agents.parser import CrewAgentParser +from crewai.agents.parser import ( + FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE, + AgentAction, + AgentFinish, + CrewAgentParser, + OutputParserException, +) from crewai.agents.tools_handler import ToolsHandler from crewai.tools.tool_usage import ToolUsage, ToolUsageErrorException from crewai.utilities import I18N, Printer @@ -13,12 +19,6 @@ ) from crewai.utilities.logger import Logger from crewai.utilities.training_handler import CrewTrainingHandler -from crewai.agents.parser import ( - AgentAction, - AgentFinish, - OutputParserException, - FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE, -) class CrewAgentExecutor(CrewAgentExecutorMixin): @@ -307,17 +307,20 @@ def _handle_crew_training_output( ) -> None: """Function to handle the process of the training data.""" agent_id = str(self.agent.id) - if ( - CrewTrainingHandler(TRAINING_DATA_FILE).load() - and not self.ask_for_human_input - ): - training_data = CrewTrainingHandler(TRAINING_DATA_FILE).load() - if training_data.get(agent_id): + + # Load training data + training_handler = CrewTrainingHandler(TRAINING_DATA_FILE) + training_data = training_handler.load() + + # Check if training data exists and human input is not requested + if training_data and not self.ask_for_human_input: + if agent_id in training_data: training_data[agent_id][self.crew._train_iteration][ "improved_output" ] = result.output - CrewTrainingHandler(TRAINING_DATA_FILE).save(training_data) + training_handler.save(training_data) + # Handle human feedback if requested if self.ask_for_human_input and human_feedback is not None: training_data = { "initial_output": result.output, @@ -325,12 +328,12 @@ def _handle_crew_training_output( "agent": agent_id, "agent_role": self.agent.role, } + + # Ensure crew and _train_iteration are valid if self.crew is not None and hasattr(self.crew, "_train_iteration"): train_iteration = self.crew._train_iteration if isinstance(train_iteration, int): - CrewTrainingHandler(TRAINING_DATA_FILE).append( - train_iteration, agent_id, training_data - ) + training_handler.append(train_iteration, agent_id, training_data) else: self._logger.log( "error", diff --git a/src/crewai/crew.py b/src/crewai/crew.py index 91b75c6cef..8ed58b8911 100644 --- a/src/crewai/crew.py +++ b/src/crewai/crew.py @@ -2,6 +2,7 @@ import json import os import uuid +import warnings from concurrent.futures import Future from hashlib import md5 from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union @@ -57,6 +58,8 @@ if TYPE_CHECKING: from crewai.pipeline.pipeline import Pipeline +warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd") + class Crew(BaseModel): """ diff --git a/src/crewai/flow/flow.py b/src/crewai/flow/flow.py index 34e4955fc5..d44d7a5e99 100644 --- a/src/crewai/flow/flow.py +++ b/src/crewai/flow/flow.py @@ -149,7 +149,7 @@ class Flow(Generic[T], metaclass=FlowMeta): _router_paths: Dict[str, List[str]] = {} initial_state: Union[Type[T], T, None] = None - def __class_getitem__(cls, item: Type[T]) -> Type["Flow"]: + def __class_getitem__(cls: Type["Flow"], item: Type[T]) -> Type["Flow"]: class _FlowGeneric(cls): _initial_state_T: Type[T] = item diff --git a/src/crewai/project/annotations.py b/src/crewai/project/annotations.py index e95909827f..42640b5153 100644 --- a/src/crewai/project/annotations.py +++ b/src/crewai/project/annotations.py @@ -1,7 +1,8 @@ from functools import wraps +from typing import Callable -from crewai.project.utils import memoize from crewai import Crew +from crewai.project.utils import memoize def task(func): @@ -73,8 +74,8 @@ def pipeline(func): return memoize(func) -def crew(func) -> "Crew": - def wrapper(self, *args, **kwargs): +def crew(func) -> Callable[..., Crew]: + def wrapper(self, *args, **kwargs) -> Crew: instantiated_tasks = [] instantiated_agents = [] diff --git a/src/crewai/project/crew_base.py b/src/crewai/project/crew_base.py index 2ecf50e13d..ac2a6c4d87 100644 --- a/src/crewai/project/crew_base.py +++ b/src/crewai/project/crew_base.py @@ -10,8 +10,8 @@ T = TypeVar("T", bound=Type[Any]) -def CrewBase(cls: T) -> T: - class WrappedClass(cls): +def CrewBase(cls: Type[T]) -> Type[T]: + class WrappedClass(cls): # Use cls as a base class is_crew_class: bool = True # type: ignore # Get the directory of the class being decorated From 3c88c50820a05f7dfbf7192c7409d053cfd52905 Mon Sep 17 00:00:00 2001 From: Brandon Hancock Date: Thu, 10 Oct 2024 10:15:17 -0400 Subject: [PATCH 2/4] fixing more type issues --- src/crewai/agents/crew_agent_executor.py | 27 ++++++------------------ src/crewai/flow/flow.py | 4 ++-- src/crewai/project/crew_base.py | 2 +- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/crewai/agents/crew_agent_executor.py b/src/crewai/agents/crew_agent_executor.py index b11d032761..dd164a657f 100644 --- a/src/crewai/agents/crew_agent_executor.py +++ b/src/crewai/agents/crew_agent_executor.py @@ -312,32 +312,19 @@ def _handle_crew_training_output( training_handler = CrewTrainingHandler(TRAINING_DATA_FILE) training_data = training_handler.load() - # Check if training data exists and human input is not requested + # Check if training data exists, human input is not requested, and self.crew is valid if training_data and not self.ask_for_human_input: - if agent_id in training_data: - training_data[agent_id][self.crew._train_iteration][ - "improved_output" - ] = result.output - training_handler.save(training_data) - - # Handle human feedback if requested - if self.ask_for_human_input and human_feedback is not None: - training_data = { - "initial_output": result.output, - "human_feedback": human_feedback, - "agent": agent_id, - "agent_role": self.agent.role, - } - - # Ensure crew and _train_iteration are valid if self.crew is not None and hasattr(self.crew, "_train_iteration"): train_iteration = self.crew._train_iteration - if isinstance(train_iteration, int): - training_handler.append(train_iteration, agent_id, training_data) + if agent_id in training_data and isinstance(train_iteration, int): + training_data[agent_id][train_iteration][ + "improved_output" + ] = result.output + training_handler.save(training_data) else: self._logger.log( "error", - "Invalid train iteration type. Expected int.", + "Invalid train iteration type or agent_id not in training data.", color="red", ) else: diff --git a/src/crewai/flow/flow.py b/src/crewai/flow/flow.py index d44d7a5e99..66fa496595 100644 --- a/src/crewai/flow/flow.py +++ b/src/crewai/flow/flow.py @@ -150,8 +150,8 @@ class Flow(Generic[T], metaclass=FlowMeta): initial_state: Union[Type[T], T, None] = None def __class_getitem__(cls: Type["Flow"], item: Type[T]) -> Type["Flow"]: - class _FlowGeneric(cls): - _initial_state_T: Type[T] = item + class _FlowGeneric(cls): # type: ignore + _initial_state_T = item # type: ignore _FlowGeneric.__name__ = f"{cls.__name__}[{item.__name__}]" return _FlowGeneric diff --git a/src/crewai/project/crew_base.py b/src/crewai/project/crew_base.py index ac2a6c4d87..13a3097725 100644 --- a/src/crewai/project/crew_base.py +++ b/src/crewai/project/crew_base.py @@ -11,7 +11,7 @@ def CrewBase(cls: Type[T]) -> Type[T]: - class WrappedClass(cls): # Use cls as a base class + class WrappedClass(cls): # type: ignore is_crew_class: bool = True # type: ignore # Get the directory of the class being decorated From 1c609e71bf9a3b66c8b1e941686b6f0b144c8abe Mon Sep 17 00:00:00 2001 From: Brandon Hancock Date: Thu, 10 Oct 2024 16:31:52 -0400 Subject: [PATCH 3/4] clean up ci --- src/crewai/project/annotations.py | 75 ++++++++++++++----------------- src/crewai/project/crew_base.py | 6 +-- 2 files changed, 36 insertions(+), 45 deletions(-) diff --git a/src/crewai/project/annotations.py b/src/crewai/project/annotations.py index 42640b5153..5bbf8dd1c9 100644 --- a/src/crewai/project/annotations.py +++ b/src/crewai/project/annotations.py @@ -6,8 +6,7 @@ def task(func): - if not hasattr(task, "registration_order"): - task.registration_order = [] + func.is_task = True @wraps(func) def wrapper(*args, **kwargs): @@ -16,9 +15,6 @@ def wrapper(*args, **kwargs): result.name = func.__name__ return result - setattr(wrapper, "is_task", True) - task.registration_order.append(func.__name__) - return memoize(wrapper) @@ -78,46 +74,41 @@ def crew(func) -> Callable[..., Crew]: def wrapper(self, *args, **kwargs) -> Crew: instantiated_tasks = [] instantiated_agents = [] - agent_roles = set() - all_functions = { - name: getattr(self, name) - for name in dir(self) - if callable(getattr(self, name)) - } - tasks = { - name: func - for name, func in all_functions.items() - if hasattr(func, "is_task") - } - agents = { - name: func - for name, func in all_functions.items() - if hasattr(func, "is_agent") - } - - # Sort tasks by their registration order - sorted_task_names = sorted( - tasks, key=lambda name: task.registration_order.index(name) - ) - - # Instantiate tasks in the order they were defined - for task_name in sorted_task_names: - task_instance = tasks[task_name]() + + # Collect methods from crew in order + all_functions = [ + (name, getattr(self, name)) + for name, attr in self.__class__.__dict__.items() + if callable(attr) + ] + tasks = [ + (name, method) + for name, method in all_functions + if hasattr(method, "is_task") + ] + + agents = [ + (name, method) + for name, method in all_functions + if hasattr(method, "is_agent") + ] + + # Instantiate tasks in order + for task_name, task_method in tasks: + task_instance = task_method() instantiated_tasks.append(task_instance) agent_instance = getattr(task_instance, "agent", None) - if agent_instance is not None: - agent_instance = task_instance.agent - if agent_instance.role not in agent_roles: - instantiated_agents.append(agent_instance) - agent_roles.add(agent_instance.role) - - # Instantiate any additional agents not already included by tasks - for agent_name in agents: - temp_agent_instance = agents[agent_name]() - if temp_agent_instance.role not in agent_roles: - instantiated_agents.append(temp_agent_instance) - agent_roles.add(temp_agent_instance.role) + if agent_instance and agent_instance.role not in agent_roles: + instantiated_agents.append(agent_instance) + agent_roles.add(agent_instance.role) + + # Instantiate agents not included by tasks + for agent_name, agent_method in agents: + agent_instance = agent_method() + if agent_instance.role not in agent_roles: + instantiated_agents.append(agent_instance) + agent_roles.add(agent_instance.role) self.agents = instantiated_agents self.tasks = instantiated_tasks diff --git a/src/crewai/project/crew_base.py b/src/crewai/project/crew_base.py index 13a3097725..cf7778fd9a 100644 --- a/src/crewai/project/crew_base.py +++ b/src/crewai/project/crew_base.py @@ -1,16 +1,16 @@ import inspect from pathlib import Path -from typing import Any, Callable, Dict, Type, TypeVar +from typing import Any, Callable, Dict, TypeVar import yaml from dotenv import load_dotenv load_dotenv() -T = TypeVar("T", bound=Type[Any]) +T = TypeVar("T", bound=type) -def CrewBase(cls: Type[T]) -> Type[T]: +def CrewBase(cls: T) -> T: class WrappedClass(cls): # type: ignore is_crew_class: bool = True # type: ignore From bc9a9abcf9042e3659cebcf51b541a5063db06a4 Mon Sep 17 00:00:00 2001 From: Brandon Hancock Date: Thu, 10 Oct 2024 16:39:31 -0400 Subject: [PATCH 4/4] more ci fixes --- src/crewai/project/crew_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crewai/project/crew_base.py b/src/crewai/project/crew_base.py index cf7778fd9a..6ad8a8c3ca 100644 --- a/src/crewai/project/crew_base.py +++ b/src/crewai/project/crew_base.py @@ -1,6 +1,6 @@ import inspect from pathlib import Path -from typing import Any, Callable, Dict, TypeVar +from typing import Any, Callable, Dict, TypeVar, cast import yaml from dotenv import load_dotenv @@ -180,4 +180,4 @@ def _map_task_variables( callback_functions[callback]() for callback in callbacks ] - return WrappedClass + return cast(T, WrappedClass)