fix: fix and add comments for all type checking errors

This commit is contained in:
Eduardo Chiarotti
2024-07-04 23:21:36 -03:00
parent 7fbddc32b4
commit 109e41f0ef
8 changed files with 49 additions and 66 deletions

View File

@@ -20,7 +20,7 @@ from crewai.utilities.training_handler import CrewTrainingHandler
agentops = None agentops = None
try: try:
import agentops import agentops # type: ignore # Name "agentops" already defined on line 21
from agentops import track_agent from agentops import track_agent
except ImportError: except ImportError:
@@ -60,8 +60,8 @@ class Agent(BaseAgent):
default=None, default=None,
description="Maximum execution time for an agent to execute a task", description="Maximum execution time for an agent to execute a task",
) )
agent_ops_agent_name: str = None agent_ops_agent_name: str = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
agent_ops_agent_id: str = None agent_ops_agent_id: str = None # type: ignore # Incompatible types in assignment (expression has type "None", variable has type "str")
cache_handler: InstanceOf[CacheHandler] = Field( cache_handler: InstanceOf[CacheHandler] = Field(
default=None, description="An instance of the CacheHandler class." default=None, description="An instance of the CacheHandler class."
) )
@@ -148,8 +148,7 @@ class Agent(BaseAgent):
Output of the agent Output of the agent
""" """
if self.tools_handler: if self.tools_handler:
# type: ignore # Incompatible types in assignment (expression has type "dict[Never, Never]", variable has type "ToolCalling") self.tools_handler.last_used_tool = {} # type: ignore # Incompatible types in assignment (expression has type "dict[Never, Never]", variable has type "ToolCalling")
self.tools_handler.last_used_tool = {}
task_prompt = task.prompt() task_prompt = task.prompt()
@@ -169,8 +168,8 @@ class Agent(BaseAgent):
task_prompt += self.i18n.slice("memory").format(memory=memory) task_prompt += self.i18n.slice("memory").format(memory=memory)
tools = tools or self.tools tools = tools or self.tools
# type: ignore # Argument 1 to "_parse_tools" of "Agent" has incompatible type "list[Any] | None"; expected "list[Any]"
parsed_tools = self._parse_tools(tools or []) parsed_tools = self._parse_tools(tools or []) # type: ignore # Argument 1 to "_parse_tools" of "Agent" has incompatible type "list[Any] | None"; expected "list[Any]"
self.create_agent_executor(tools=tools) self.create_agent_executor(tools=tools)
self.agent_executor.tools = parsed_tools self.agent_executor.tools = parsed_tools
self.agent_executor.task = task self.agent_executor.task = task
@@ -196,7 +195,7 @@ class Agent(BaseAgent):
# If there was any tool in self.tools_results that had result_as_answer # If there was any tool in self.tools_results that had result_as_answer
# set to True, return the results of the last tool that had # set to True, return the results of the last tool that had
# result_as_answer set to True # result_as_answer set to True
for tool_result in self.tools_results: for tool_result in self.tools_results: # type: ignore # Item "None" of "list[Any] | None" has no attribute "__iter__" (not iterable)
if tool_result.get("result_as_answer", False): if tool_result.get("result_as_answer", False):
result = tool_result["result"] result = tool_result["result"]
@@ -300,7 +299,7 @@ class Agent(BaseAgent):
def get_output_converter(self, llm, text, model, instructions): def get_output_converter(self, llm, text, model, instructions):
return Converter(llm=llm, text=text, model=model, instructions=instructions) return Converter(llm=llm, text=text, model=model, instructions=instructions)
def _parse_tools(self, tools: List[Any]) -> List[LangChainTool]: def _parse_tools(self, tools: List[Any]) -> List[LangChainTool]: # type: ignore # Function "langchain_core.tools.tool" is not valid as a type
"""Parse tools to be used for the task.""" """Parse tools to be used for the task."""
tools_list = [] tools_list = []
try: try:

View File

@@ -191,7 +191,7 @@ class BaseAgent(ABC, BaseModel):
"""Get the converter class for the agent to create json/pydantic outputs.""" """Get the converter class for the agent to create json/pydantic outputs."""
pass pass
def copy(self: T) -> T: def copy(self: T) -> T: # type: ignore # Signature of "copy" incompatible with supertype "BaseModel"
"""Create a deep copy of the Agent.""" """Create a deep copy of the Agent."""
exclude = { exclude = {
"id", "id",

View File

@@ -1,6 +1,8 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import List, Optional, Union from typing import List, Optional, Union
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from crewai.agents.agent_builder.base_agent import BaseAgent from crewai.agents.agent_builder.base_agent import BaseAgent
from crewai.task import Task from crewai.task import Task
from crewai.utilities import I18N from crewai.utilities import I18N
@@ -53,7 +55,7 @@ class BaseAgentTools(BaseModel, ABC):
# {"task": "....", "coworker": "...."} # {"task": "....", "coworker": "...."}
agent_name = agent.casefold().replace('"', "").replace("\n", "") agent_name = agent.casefold().replace('"', "").replace("\n", "")
agent = [ agent = [ # type: ignore # Incompatible types in assignment (expression has type "list[BaseAgent]", variable has type "str | None")
available_agent available_agent
for available_agent in self.agents for available_agent in self.agents
if available_agent.role.casefold().replace("\n", "") == agent_name if available_agent.role.casefold().replace("\n", "") == agent_name
@@ -73,9 +75,9 @@ class BaseAgentTools(BaseModel, ABC):
) )
agent = agent[0] agent = agent[0]
task = Task( task = Task( # type: ignore # Incompatible types in assignment (expression has type "Task", variable has type "str")
description=task, description=task,
agent=agent, agent=agent,
expected_output="Your best answer to your coworker asking you this, accounting for the context shared.", expected_output="Your best answer to your coworker asking you this, accounting for the context shared.",
) )
return agent.execute_task(task, context) return agent.execute_task(task, context) # type: ignore # "str" has no attribute "execute_task"

View File

@@ -1,7 +1,6 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Optional from typing import Any, Optional
from pydantic import BaseModel, Field, PrivateAttr from pydantic import BaseModel, Field, PrivateAttr
@@ -42,7 +41,7 @@ class OutputConverter(BaseModel, ABC):
"""Convert text to json.""" """Convert text to json."""
pass pass
@abstractmethod @abstractmethod # type: ignore # Name "_is_gpt" already defined on line 25
def _is_gpt(self, llm): def _is_gpt(self, llm): # type: ignore # Name "_is_gpt" already defined on line 25
"""Return if llm provided is of gpt from openai.""" """Return if llm provided is of gpt from openai."""
pass pass

View File

@@ -15,19 +15,18 @@ from langchain.agents.agent import ExceptionTool
from langchain.callbacks.manager import CallbackManagerForChainRun from langchain.callbacks.manager import CallbackManagerForChainRun
from langchain_core.agents import AgentAction, AgentFinish, AgentStep from langchain_core.agents import AgentAction, AgentFinish, AgentStep
from langchain_core.exceptions import OutputParserException from langchain_core.exceptions import OutputParserException
from langchain_core.tools import BaseTool from langchain_core.tools import BaseTool
from langchain_core.utils.input import get_color_mapping from langchain_core.utils.input import get_color_mapping
from pydantic import InstanceOf from pydantic import InstanceOf
from crewai.agents.agent_builder.base_agent_executor_mixin import ( from crewai.agents.agent_builder.base_agent_executor_mixin import (
CrewAgentExecutorMixin, CrewAgentExecutorMixin,
) )
from crewai.agents.tools_handler import ToolsHandler from crewai.agents.tools_handler import ToolsHandler
from crewai.tools.tool_usage import ToolUsage, ToolUsageErrorException from crewai.tools.tool_usage import ToolUsage, ToolUsageErrorException
from crewai.utilities import I18N
from crewai.utilities.constants import TRAINING_DATA_FILE from crewai.utilities.constants import TRAINING_DATA_FILE
from crewai.utilities.training_handler import CrewTrainingHandler from crewai.utilities.training_handler import CrewTrainingHandler
from crewai.utilities import I18N
class CrewAgentExecutor(AgentExecutor, CrewAgentExecutorMixin): class CrewAgentExecutor(AgentExecutor, CrewAgentExecutorMixin):
@@ -46,7 +45,7 @@ class CrewAgentExecutor(AgentExecutor, CrewAgentExecutorMixin):
tools_handler: Optional[InstanceOf[ToolsHandler]] = None tools_handler: Optional[InstanceOf[ToolsHandler]] = None
max_iterations: Optional[int] = 15 max_iterations: Optional[int] = 15
have_forced_answer: bool = False have_forced_answer: bool = False
force_answer_max_iterations: Optional[int] = None force_answer_max_iterations: Optional[int] = None # type: ignore # Incompatible types in assignment (expression has type "int | None", base class "CrewAgentExecutorMixin" defined the type as "int")
step_callback: Optional[Any] = None step_callback: Optional[Any] = None
system_template: Optional[str] = None system_template: Optional[str] = None
prompt_template: Optional[str] = None prompt_template: Optional[str] = None

View File

@@ -232,7 +232,7 @@ class Crew(BaseModel):
if task.agent is None: if task.agent is None:
raise PydanticCustomError( raise PydanticCustomError(
"missing_agent_in_task", "missing_agent_in_task",
f"Sequential process error: Agent is missing in the task with the following description: {task.description}", # type: ignore Argument of type "str" cannot be assigned to parameter "message_template" of type "LiteralString" f"Sequential process error: Agent is missing in the task with the following description: {task.description}", # type: ignore # Argument of type "str" cannot be assigned to parameter "message_template" of type "LiteralString"
{}, {},
) )
@@ -318,26 +318,25 @@ class Crew(BaseModel):
) -> Union[str, Dict[str, Any]]: ) -> Union[str, Dict[str, Any]]:
"""Starts the crew to work on its assigned tasks.""" """Starts the crew to work on its assigned tasks."""
self._execution_span = self._telemetry.crew_execution_span(self, inputs) self._execution_span = self._telemetry.crew_execution_span(self, inputs)
# type: ignore # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
self._interpolate_inputs(inputs) self._interpolate_inputs(inputs) # type: ignore # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
self._set_tasks_callbacks() self._set_tasks_callbacks()
i18n = I18N(prompt_file=self.prompt_file) i18n = I18N(prompt_file=self.prompt_file)
for agent in self.agents: for agent in self.agents:
# type: ignore # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
agent.i18n = i18n agent.i18n = i18n
# type: ignore[attr-defined] # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]" # type: ignore[attr-defined] # Argument 1 to "_interpolate_inputs" of "Crew" has incompatible type "dict[str, Any] | None"; expected "dict[str, Any]"
agent.crew = self # type: ignore[attr-defined] agent.crew = self # type: ignore[attr-defined]
# TODO: Create an AgentFunctionCalling protocol for future refactoring # TODO: Create an AgentFunctionCalling protocol for future refactoring
if not agent.function_calling_llm: if not agent.function_calling_llm: # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
agent.function_calling_llm = self.function_calling_llm agent.function_calling_llm = self.function_calling_llm # type: ignore # "BaseAgent" has no attribute "function_calling_llm"
if agent.allow_code_execution: if agent.allow_code_execution: # type: ignore # BaseAgent" has no attribute "allow_code_execution"
agent.tools += agent.get_code_execution_tools() agent.tools += agent.get_code_execution_tools() # type: ignore # "BaseAgent" has no attribute "get_code_execution_tools"; maybe "get_delegation_tools"?
if not agent.step_callback: if not agent.step_callback: # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.step_callback = self.step_callback agent.step_callback = self.step_callback # type: ignore # "BaseAgent" has no attribute "step_callback"
agent.create_agent_executor() agent.create_agent_executor()
@@ -346,7 +345,7 @@ class Crew(BaseModel):
if self.process == Process.sequential: if self.process == Process.sequential:
result = self._run_sequential_process() result = self._run_sequential_process()
elif self.process == Process.hierarchical: elif self.process == Process.hierarchical:
result, manager_metrics = self._run_hierarchical_process() result, manager_metrics = self._run_hierarchical_process() # type: ignore # Incompatible types in assignment (expression has type "str | dict[str, Any]", variable has type "str")
metrics.append(manager_metrics) metrics.append(manager_metrics)
else: else:
raise NotImplementedError( raise NotImplementedError(
@@ -432,7 +431,7 @@ class Crew(BaseModel):
agent for agent in self.agents if agent != task.agent agent for agent in self.agents if agent != task.agent
] ]
if len(self.agents) > 1 and len(agents_for_delegation) > 0: if len(self.agents) > 1 and len(agents_for_delegation) > 0:
task.tools += task.agent.get_delegation_tools(agents_for_delegation) task.tools += task.agent.get_delegation_tools(agents_for_delegation) # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_delegation_tools"
role = task.agent.role if task.agent is not None else "None" role = task.agent.role if task.agent is not None else "None"
self._logger.log("debug", f"== Working Agent: {role}", color="bold_purple") self._logger.log("debug", f"== Working Agent: {role}", color="bold_purple")
@@ -459,8 +458,7 @@ class Crew(BaseModel):
token_usage = self.calculate_usage_metrics() token_usage = self.calculate_usage_metrics()
# type: ignore # Incompatible return value type (got "tuple[str, Any]", expected "str") return self._format_output(task_output, token_usage) # type: ignore # Incompatible return value type (got "tuple[str, Any]", expected "str")
return self._format_output(task_output, token_usage)
def _run_hierarchical_process( def _run_hierarchical_process(
self, self,

View File

@@ -190,16 +190,13 @@ class Task(BaseModel):
) )
if self.context: if self.context:
# type: ignore # Incompatible types in assignment (expression has type "list[Never]", variable has type "str | None") context = [] # type: ignore # Incompatible types in assignment (expression has type "list[Never]", variable has type "str | None")
context = []
for task in self.context: for task in self.context:
if task.async_execution: if task.async_execution:
task.wait_for_completion() task.wait_for_completion()
if task.output: if task.output:
# type: ignore # Item "str" of "str | None" has no attribute "append" context.append(task.output.raw_output) # type: ignore # Item "str" of "str | None" has no attribute "append"
context.append(task.output.raw_output) context = "\n".join(context) # type: ignore # Argument 1 to "join" of "str" has incompatible type "str | None"; expected "Iterable[str]"
# type: ignore # Argument 1 to "join" of "str" has incompatible type "str | None"; expected "Iterable[str]"
context = "\n".join(context)
self.prompt_context = context self.prompt_context = context
tools = tools or self.tools tools = tools or self.tools
@@ -226,8 +223,7 @@ class Task(BaseModel):
) )
exported_output = self._export_output(result) exported_output = self._export_output(result)
# type: ignore # the responses are usually str but need to figure out a more elegant solution here self.output = TaskOutput( # type: ignore # the responses are usually str but need to figure out a more elegant solution here
self.output = TaskOutput(
description=self.description, description=self.description,
exported_output=exported_output, exported_output=exported_output,
raw_output=result, raw_output=result,
@@ -276,7 +272,7 @@ class Task(BaseModel):
"""Increment the delegations counter.""" """Increment the delegations counter."""
self.delegations += 1 self.delegations += 1
def copy(self, agents: Optional[List["BaseAgent"]] = None) -> "Task": def copy(self, agents: Optional[List["BaseAgent"]] = None) -> "Task": # type: ignore # Signature of "copy" incompatible with supertype "BaseModel"
"""Create a deep copy of the Task.""" """Create a deep copy of the Task."""
exclude = { exclude = {
"id", "id",
@@ -293,7 +289,7 @@ class Task(BaseModel):
) )
def get_agent_by_role(role: str) -> Union["BaseAgent", None]: def get_agent_by_role(role: str) -> Union["BaseAgent", None]:
return next((agent for agent in agents if agent.role == role), None) return next((agent for agent in agents if agent.role == role), None) # type: ignore # Item "None" of "list[BaseAgent] | None" has no attribute "__iter__" (not iterable)
cloned_agent = get_agent_by_role(self.agent.role) if self.agent else None cloned_agent = get_agent_by_role(self.agent.role) if self.agent else None
cloned_tools = copy(self.tools) if self.tools else [] cloned_tools = copy(self.tools) if self.tools else []
@@ -316,34 +312,28 @@ class Task(BaseModel):
# try to convert task_output directly to pydantic/json # try to convert task_output directly to pydantic/json
try: try:
# type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "model_validate_json" exported_result = model.model_validate_json(result) # type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "model_validate_json"
exported_result = model.model_validate_json(result)
if self.output_json: if self.output_json:
# type: ignore # "str" has no attribute "model_dump" return exported_result.model_dump() # type: ignore # "str" has no attribute "model_dump"
return exported_result.model_dump()
return exported_result return exported_result
except Exception: except Exception:
# sometimes the response contains valid JSON in the middle of text # sometimes the response contains valid JSON in the middle of text
match = re.search(r"({.*})", result, re.DOTALL) match = re.search(r"({.*})", result, re.DOTALL)
if match: if match:
try: try:
# type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "model_validate_json" exported_result = model.model_validate_json(match.group(0)) # type: ignore # Item "None" of "type[BaseModel] | None" has no attribute "model_validate_json"
exported_result = model.model_validate_json(match.group(0))
if self.output_json: if self.output_json:
# type: ignore # "str" has no attribute "model_dump" return exported_result.model_dump() # type: ignore # "str" has no attribute "model_dump"
return exported_result.model_dump()
return exported_result return exported_result
except Exception: except Exception:
pass pass
# type: ignore # Item "None" of "BaseAgent | None" has no attribute "function_calling_llm" llm = getattr(self.agent, "function_calling_llm", None) or self.agent.llm # type: ignore # Item "None" of "BaseAgent | None" has no attribute "function_calling_llm"
llm = getattr(self.agent, "function_calling_llm", None) or self.agent.llm
if not self._is_gpt(llm): if not self._is_gpt(llm):
# type: ignore # Argument "model" to "PydanticSchemaParser" has incompatible type "type[BaseModel] | None"; expected "type[BaseModel]" model_schema = PydanticSchemaParser(model=model).get_schema() # type: ignore # Argument "model" to "PydanticSchemaParser" has incompatible type "type[BaseModel] | None"; expected "type[BaseModel]"
model_schema = PydanticSchemaParser(model=model).get_schema()
instructions = f"{instructions}\n\nThe json should have the following structure, with the following keys:\n{model_schema}" instructions = f"{instructions}\n\nThe json should have the following structure, with the following keys:\n{model_schema}"
converter = self.agent.get_output_converter( converter = self.agent.get_output_converter( # type: ignore # Item "None" of "BaseAgent | None" has no attribute "get_output_converter"
llm=llm, text=result, model=model, instructions=instructions llm=llm, text=result, model=model, instructions=instructions
) )
@@ -361,10 +351,9 @@ class Task(BaseModel):
if self.output_file: if self.output_file:
content = ( content = (
# type: ignore # "str" has no attribute "json"
exported_result exported_result
if not self.output_pydantic if not self.output_pydantic
else exported_result.model_dump_json() else exported_result.model_dump_json() # type: ignore # "str" has no attribute "json"
) )
self._save_file(content) self._save_file(content)
@@ -374,14 +363,12 @@ class Task(BaseModel):
return isinstance(llm, ChatOpenAI) and llm.openai_api_base is None return isinstance(llm, ChatOpenAI) and llm.openai_api_base is None
def _save_file(self, result: Any) -> None: def _save_file(self, result: Any) -> None:
# type: ignore # Value of type variable "AnyOrLiteralStr" of "dirname" cannot be "str | None" directory = os.path.dirname(self.output_file) # type: ignore # Value of type variable "AnyOrLiteralStr" of "dirname" cannot be "str | None"
directory = os.path.dirname(self.output_file)
if directory and not os.path.exists(directory): if directory and not os.path.exists(directory):
os.makedirs(directory) os.makedirs(directory)
# type: ignore # Argument 1 to "open" has incompatible type "str | None"; expected "int | str | bytes | PathLike[str] | PathLike[bytes]" with open(self.output_file, "w", encoding="utf-8") as file: # type: ignore # Argument 1 to "open" has incompatible type "str | None"; expected "int | str | bytes | PathLike[str] | PathLike[bytes]"
with open(self.output_file, "w", encoding="utf-8") as file:
file.write(result) file.write(result)
return None return None

View File

@@ -11,11 +11,10 @@ from crewai.telemetry import Telemetry
from crewai.tools.tool_calling import InstructorToolCalling, ToolCalling from crewai.tools.tool_calling import InstructorToolCalling, ToolCalling
from crewai.utilities import I18N, Converter, ConverterError, Printer from crewai.utilities import I18N, Converter, ConverterError, Printer
agentops = None
try: try:
import agentops import agentops
except ImportError: except ImportError:
pass agentops = None
OPENAI_BIGGER_MODELS = ["gpt-4"] OPENAI_BIGGER_MODELS = ["gpt-4"]
@@ -216,7 +215,7 @@ class ToolUsage:
hasattr(original_tool, "result_as_answer") hasattr(original_tool, "result_as_answer")
and original_tool.result_as_answer # type: ignore # Item "None" of "Any | None" has no attribute "cache_function" and original_tool.result_as_answer # type: ignore # Item "None" of "Any | None" has no attribute "cache_function"
): ):
result_as_answer = original_tool.result_as_answer result_as_answer = original_tool.result_as_answer # type: ignore # Item "None" of "Any | None" has no attribute "result_as_answer"
data["result_as_answer"] = result_as_answer data["result_as_answer"] = result_as_answer
self.agent.tools_results.append(data) self.agent.tools_results.append(data)