fix: Improve type annotations and add proper None checks

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2024-12-31 23:24:01 +00:00
parent 344fa9bbe5
commit 39bdc7e4d4
6 changed files with 34 additions and 26 deletions

View File

@@ -152,7 +152,7 @@ class Agent(BaseAgent):
self._logger = Logger(verbose=self.verbose) self._logger = Logger(verbose=self.verbose)
if self.max_rpm: if self.max_rpm:
self._rpm_controller = RPMController(max_rpm=self.max_rpm, logger=self._logger) self._rpm_controller = RPMController(max_rpm=self.max_rpm, logger=self._logger)
self._token_process = TokenProcess() self._token_process = TokenProcess() # type: ignore # Known type mismatch between utilities and agent_builder
_times_executed: int = PrivateAttr(default=0) _times_executed: int = PrivateAttr(default=0)
max_execution_time: Optional[int] = Field( max_execution_time: Optional[int] = Field(

View File

@@ -82,16 +82,17 @@ class CrewAgentExecutorMixin:
) )
self.crew._long_term_memory.save(long_term_memory) self.crew._long_term_memory.save(long_term_memory)
for entity in evaluation.entities: if hasattr(evaluation, 'entities') and evaluation.entities:
entity_memory = EntityMemoryItem( for entity in evaluation.entities:
name=entity.name, entity_memory = EntityMemoryItem(
type=entity.type, name=entity.name,
description=entity.description, type=entity.type,
relationships="\n".join( description=entity.description,
[f"- {r}" for r in entity.relationships] relationships="\n".join(
), [f"- {r}" for r in entity.relationships]
) ),
self.crew._entity_memory.save(entity_memory) )
self.crew._entity_memory.save(entity_memory)
except AttributeError as e: except AttributeError as e:
print(f"Missing attributes for long term memory: {e}") print(f"Missing attributes for long term memory: {e}")
pass pass

View File

@@ -147,7 +147,8 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
# Directly append the result to the messages if the # Directly append the result to the messages if the
# tool is "Add image to content" in case of multimodal # tool is "Add image to content" in case of multimodal
# agents # agents
if formatted_answer.tool == self._i18n.tools("add_image")["name"]: add_image_tool_name = self._i18n.tools("add_image")
if add_image_tool_name and formatted_answer.tool == add_image_tool_name:
self.messages.append(tool_result.result) self.messages.append(tool_result.result)
continue continue
@@ -214,13 +215,14 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
if self.agent.verbose or ( if self.agent.verbose or (
hasattr(self, "crew") and getattr(self.crew, "verbose", False) hasattr(self, "crew") and getattr(self.crew, "verbose", False)
): ):
agent_role = self.agent.role.split("\n")[0] agent_role = self.agent.role.split("\n")[0] if self.agent and self.agent.role else ""
self._printer.print( self._printer.print(
content=f"\033[1m\033[95m# Agent:\033[00m \033[1m\033[92m{agent_role}\033[00m" content=f"\033[1m\033[95m# Agent:\033[00m \033[1m\033[92m{agent_role}\033[00m"
) )
self._printer.print( if self.task and self.task.description:
content=f"\033[95m## Task:\033[00m \033[92m{self.task.description}\033[00m" self._printer.print(
) content=f"\033[95m## Task:\033[00m \033[92m{self.task.description}\033[00m"
)
def _show_logs(self, formatted_answer: Union[AgentAction, AgentFinish]): def _show_logs(self, formatted_answer: Union[AgentAction, AgentFinish]):
if self.agent is None: if self.agent is None:
@@ -228,7 +230,7 @@ class CrewAgentExecutor(CrewAgentExecutorMixin):
if self.agent.verbose or ( if self.agent.verbose or (
hasattr(self, "crew") and getattr(self.crew, "verbose", False) hasattr(self, "crew") and getattr(self.crew, "verbose", False)
): ):
agent_role = self.agent.role.split("\n")[0] agent_role = self.agent.role.split("\n")[0] if self.agent and self.agent.role else ""
if isinstance(formatted_answer, AgentAction): if isinstance(formatted_answer, AgentAction):
thought = re.sub(r"\n+", "\n", formatted_answer.thought) thought = re.sub(r"\n+", "\n", formatted_answer.thought)
formatted_json = json.dumps( formatted_json = json.dumps(

View File

@@ -6,6 +6,8 @@ from concurrent.futures import Future
from hashlib import md5 from hashlib import md5
from typing import Any, Callable, Dict, List, Optional, Tuple, Union from typing import Any, Callable, Dict, List, Optional, Tuple, Union
from crewai.tools.base_tool import BaseTool
from pydantic import ( from pydantic import (
UUID4, UUID4,
BaseModel, BaseModel,
@@ -728,7 +730,7 @@ class Crew(BaseModel):
tools_for_task = task.tools or agent_to_use.tools or [] tools_for_task = task.tools or agent_to_use.tools or []
tools_for_task = self._prepare_tools(agent_to_use, task, tools_for_task) tools_for_task = self._prepare_tools(agent_to_use, task, tools_for_task)
self._log_task_start(task, agent_to_use.role) self._log_task_start(task, agent_to_use.role if agent_to_use and agent_to_use.role else "")
if isinstance(task, ConditionalTask): if isinstance(task, ConditionalTask):
skipped_task_output = self._handle_conditional_task( skipped_task_output = self._handle_conditional_task(
@@ -794,8 +796,8 @@ class Crew(BaseModel):
return None return None
def _prepare_tools( def _prepare_tools(
self, agent: BaseAgent, task: Task, tools: List[Tool] self, agent: BaseAgent, task: Task, tools: List[Union[Tool, BaseTool]]
) -> List[Tool]: ) -> List[Union[Tool, BaseTool]]:
# Add delegation tools if agent allows delegation # Add delegation tools if agent allows delegation
if agent.allow_delegation: if agent.allow_delegation:
if self.process == Process.hierarchical: if self.process == Process.hierarchical:
@@ -824,8 +826,8 @@ class Crew(BaseModel):
return task.agent return task.agent
def _merge_tools( def _merge_tools(
self, existing_tools: List[Tool], new_tools: List[Tool] self, existing_tools: List[Union[Tool, BaseTool]], new_tools: List[Union[Tool, BaseTool]]
) -> List[Tool]: ) -> List[Union[Tool, BaseTool]]:
"""Merge new tools into existing tools list, avoiding duplicates by tool name.""" """Merge new tools into existing tools list, avoiding duplicates by tool name."""
if not new_tools: if not new_tools:
return existing_tools return existing_tools

View File

@@ -269,7 +269,9 @@ class Task(BaseModel):
@model_validator(mode="after") @model_validator(mode="after")
def check_tools(self): def check_tools(self):
"""Check if the tools are set.""" """Check if the tools are set."""
if not self.tools and self.agent and self.agent.tools: if self.agent and self.agent.tools:
if self.tools is None:
self.tools = []
self.tools.extend(self.agent.tools) self.tools.extend(self.agent.tools)
return self return self
@@ -348,7 +350,8 @@ class Task(BaseModel):
self.prompt_context = context self.prompt_context = context
tools = tools or self.tools or [] tools = tools or self.tools or []
self.processed_by_agents.add(agent.role) if agent and agent.role:
self.processed_by_agents.add(agent.role)
result = agent.execute_task( result = agent.execute_task(
task=self, task=self,

View File

@@ -19,13 +19,13 @@ class BaseAgentTool(BaseTool):
default_factory=I18N, description="Internationalization settings" default_factory=I18N, description="Internationalization settings"
) )
def sanitize_agent_name(self, name: str) -> str: def sanitize_agent_name(self, name: Optional[str]) -> str:
""" """
Sanitize agent role name by normalizing whitespace and setting to lowercase. Sanitize agent role name by normalizing whitespace and setting to lowercase.
Converts all whitespace (including newlines) to single spaces and removes quotes. Converts all whitespace (including newlines) to single spaces and removes quotes.
Args: Args:
name (str): The agent role name to sanitize name (Optional[str]): The agent role name to sanitize
Returns: Returns:
str: The sanitized agent role name, with whitespace normalized, str: The sanitized agent role name, with whitespace normalized,