mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-26 16:48:13 +00:00
feat(files): use FileInput type for all input_files parameters
This commit is contained in:
@@ -8,6 +8,7 @@ from hashlib import md5
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import (
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
cast,
|
cast,
|
||||||
)
|
)
|
||||||
@@ -31,6 +32,10 @@ from rich.console import Console
|
|||||||
from rich.panel import Panel
|
from rich.panel import Panel
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from crewai_files import FileInput
|
||||||
|
|
||||||
from crewai.agent import Agent
|
from crewai.agent import Agent
|
||||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||||
from crewai.agents.cache.cache_handler import CacheHandler
|
from crewai.agents.cache.cache_handler import CacheHandler
|
||||||
@@ -679,7 +684,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
def kickoff(
|
def kickoff(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> CrewOutput | CrewStreamingOutput:
|
) -> CrewOutput | CrewStreamingOutput:
|
||||||
"""Execute the crew's workflow.
|
"""Execute the crew's workflow.
|
||||||
|
|
||||||
@@ -751,7 +756,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
def kickoff_for_each(
|
def kickoff_for_each(
|
||||||
self,
|
self,
|
||||||
inputs: list[dict[str, Any]],
|
inputs: list[dict[str, Any]],
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> list[CrewOutput | CrewStreamingOutput]:
|
) -> list[CrewOutput | CrewStreamingOutput]:
|
||||||
"""Executes the Crew's workflow for each input and aggregates results.
|
"""Executes the Crew's workflow for each input and aggregates results.
|
||||||
|
|
||||||
@@ -787,7 +792,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
async def kickoff_async(
|
async def kickoff_async(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> CrewOutput | CrewStreamingOutput:
|
) -> CrewOutput | CrewStreamingOutput:
|
||||||
"""Asynchronous kickoff method to start the crew execution.
|
"""Asynchronous kickoff method to start the crew execution.
|
||||||
|
|
||||||
@@ -834,7 +839,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
async def kickoff_for_each_async(
|
async def kickoff_for_each_async(
|
||||||
self,
|
self,
|
||||||
inputs: list[dict[str, Any]],
|
inputs: list[dict[str, Any]],
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> list[CrewOutput | CrewStreamingOutput] | CrewStreamingOutput:
|
) -> list[CrewOutput | CrewStreamingOutput] | CrewStreamingOutput:
|
||||||
"""Executes the Crew's workflow for each input asynchronously.
|
"""Executes the Crew's workflow for each input asynchronously.
|
||||||
|
|
||||||
@@ -860,7 +865,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
async def akickoff(
|
async def akickoff(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> CrewOutput | CrewStreamingOutput:
|
) -> CrewOutput | CrewStreamingOutput:
|
||||||
"""Native async kickoff method using async task execution throughout.
|
"""Native async kickoff method using async task execution throughout.
|
||||||
|
|
||||||
@@ -936,7 +941,7 @@ class Crew(FlowTrackable, BaseModel):
|
|||||||
async def akickoff_for_each(
|
async def akickoff_for_each(
|
||||||
self,
|
self,
|
||||||
inputs: list[dict[str, Any]],
|
inputs: list[dict[str, Any]],
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> list[CrewOutput | CrewStreamingOutput] | CrewStreamingOutput:
|
) -> list[CrewOutput | CrewStreamingOutput] | CrewStreamingOutput:
|
||||||
"""Native async execution of the Crew's workflow for each input.
|
"""Native async execution of the Crew's workflow for each input.
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ except ImportError:
|
|||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from crewai_files import FileInput
|
||||||
|
|
||||||
from crewai.crew import Crew
|
from crewai.crew import Crew
|
||||||
|
|
||||||
|
|
||||||
@@ -225,7 +227,7 @@ def _extract_files_from_inputs(inputs: dict[str, Any]) -> dict[str, Any]:
|
|||||||
def prepare_kickoff(
|
def prepare_kickoff(
|
||||||
crew: Crew,
|
crew: Crew,
|
||||||
inputs: dict[str, Any] | None,
|
inputs: dict[str, Any] | None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> dict[str, Any] | None:
|
) -> dict[str, Any] | None:
|
||||||
"""Prepare crew for kickoff execution.
|
"""Prepare crew for kickoff execution.
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ from crewai.flow.utils import (
|
|||||||
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from crewai_files import FileInput
|
||||||
|
|
||||||
from crewai.flow.async_feedback.types import PendingFeedbackContext
|
from crewai.flow.async_feedback.types import PendingFeedbackContext
|
||||||
from crewai.flow.human_feedback import HumanFeedbackResult
|
from crewai.flow.human_feedback import HumanFeedbackResult
|
||||||
from crewai.llms.base_llm import BaseLLM
|
from crewai.llms.base_llm import BaseLLM
|
||||||
@@ -1414,7 +1416,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
|||||||
def kickoff(
|
def kickoff(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> Any | FlowStreamingOutput:
|
) -> Any | FlowStreamingOutput:
|
||||||
"""Start the flow execution in a synchronous context.
|
"""Start the flow execution in a synchronous context.
|
||||||
|
|
||||||
@@ -1475,7 +1477,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
|||||||
async def kickoff_async(
|
async def kickoff_async(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> Any | FlowStreamingOutput:
|
) -> Any | FlowStreamingOutput:
|
||||||
"""Start the flow execution asynchronously.
|
"""Start the flow execution asynchronously.
|
||||||
|
|
||||||
@@ -1720,7 +1722,7 @@ class Flow(Generic[T], metaclass=FlowMeta):
|
|||||||
async def akickoff(
|
async def akickoff(
|
||||||
self,
|
self,
|
||||||
inputs: dict[str, Any] | None = None,
|
inputs: dict[str, Any] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> Any | FlowStreamingOutput:
|
) -> Any | FlowStreamingOutput:
|
||||||
"""Native async method to start the flow execution. Alias for kickoff_async.
|
"""Native async method to start the flow execution. Alias for kickoff_async.
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from collections.abc import Callable
|
|||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
from typing import (
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
Literal,
|
Literal,
|
||||||
cast,
|
cast,
|
||||||
@@ -23,6 +24,10 @@ from pydantic import (
|
|||||||
)
|
)
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from crewai_files import FileInput
|
||||||
|
|
||||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||||
from crewai.agents.agent_builder.utilities.base_token_process import TokenProcess
|
from crewai.agents.agent_builder.utilities.base_token_process import TokenProcess
|
||||||
from crewai.agents.cache.cache_handler import CacheHandler
|
from crewai.agents.cache.cache_handler import CacheHandler
|
||||||
@@ -296,7 +301,7 @@ class LiteAgent(FlowTrackable, BaseModel):
|
|||||||
self,
|
self,
|
||||||
messages: str | list[LLMMessage],
|
messages: str | list[LLMMessage],
|
||||||
response_format: type[BaseModel] | None = None,
|
response_format: type[BaseModel] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> LiteAgentOutput:
|
) -> LiteAgentOutput:
|
||||||
"""Execute the agent with the given messages.
|
"""Execute the agent with the given messages.
|
||||||
|
|
||||||
@@ -470,7 +475,7 @@ class LiteAgent(FlowTrackable, BaseModel):
|
|||||||
self,
|
self,
|
||||||
messages: str | list[LLMMessage],
|
messages: str | list[LLMMessage],
|
||||||
response_format: type[BaseModel] | None = None,
|
response_format: type[BaseModel] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> LiteAgentOutput:
|
) -> LiteAgentOutput:
|
||||||
"""Execute the agent asynchronously with the given messages.
|
"""Execute the agent asynchronously with the given messages.
|
||||||
|
|
||||||
@@ -492,7 +497,7 @@ class LiteAgent(FlowTrackable, BaseModel):
|
|||||||
self,
|
self,
|
||||||
messages: str | list[LLMMessage],
|
messages: str | list[LLMMessage],
|
||||||
response_format: type[BaseModel] | None = None,
|
response_format: type[BaseModel] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> LiteAgentOutput:
|
) -> LiteAgentOutput:
|
||||||
"""Async version of kickoff. Alias for kickoff_async.
|
"""Async version of kickoff. Alias for kickoff_async.
|
||||||
|
|
||||||
@@ -548,7 +553,7 @@ class LiteAgent(FlowTrackable, BaseModel):
|
|||||||
self,
|
self,
|
||||||
messages: str | list[LLMMessage],
|
messages: str | list[LLMMessage],
|
||||||
response_format: type[BaseModel] | None = None,
|
response_format: type[BaseModel] | None = None,
|
||||||
input_files: dict[str, Any] | None = None,
|
input_files: dict[str, FileInput] | None = None,
|
||||||
) -> list[LLMMessage]:
|
) -> list[LLMMessage]:
|
||||||
"""Format messages for the LLM.
|
"""Format messages for the LLM.
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import threading
|
import threading
|
||||||
from typing import (
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
ClassVar,
|
ClassVar,
|
||||||
cast,
|
cast,
|
||||||
@@ -30,6 +31,10 @@ from pydantic import (
|
|||||||
from pydantic_core import PydanticCustomError
|
from pydantic_core import PydanticCustomError
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from crewai_files import FileInput
|
||||||
|
|
||||||
from crewai.agents.agent_builder.base_agent import BaseAgent
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
||||||
from crewai.events.event_bus import crewai_event_bus
|
from crewai.events.event_bus import crewai_event_bus
|
||||||
from crewai.events.types.task_events import (
|
from crewai.events.types.task_events import (
|
||||||
@@ -52,10 +57,7 @@ from crewai.utilities.file_store import (
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from crewai_files import (
|
from crewai_files import FilePath
|
||||||
FilePath,
|
|
||||||
normalize_input_files,
|
|
||||||
)
|
|
||||||
|
|
||||||
HAS_CREWAI_FILES = True
|
HAS_CREWAI_FILES = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -158,9 +160,9 @@ class Task(BaseModel):
|
|||||||
default_factory=list,
|
default_factory=list,
|
||||||
description="Tools the agent is limited to use for this task.",
|
description="Tools the agent is limited to use for this task.",
|
||||||
)
|
)
|
||||||
input_files: list[Any] = Field(
|
input_files: dict[str, FileInput] = Field(
|
||||||
default_factory=list,
|
default_factory=dict,
|
||||||
description="List of input files for this task. Accepts paths, bytes, or File objects.",
|
description="Named input files for this task. Keys are reference names, values are paths or File objects.",
|
||||||
)
|
)
|
||||||
security_config: SecurityConfig = Field(
|
security_config: SecurityConfig = Field(
|
||||||
default_factory=SecurityConfig,
|
default_factory=SecurityConfig,
|
||||||
@@ -379,7 +381,7 @@ class Task(BaseModel):
|
|||||||
|
|
||||||
@field_validator("input_files", mode="before")
|
@field_validator("input_files", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def _normalize_input_files(cls, v: list[Any]) -> list[Any]:
|
def _normalize_input_files(cls, v: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Convert string paths to FilePath objects."""
|
"""Convert string paths to FilePath objects."""
|
||||||
if not v:
|
if not v:
|
||||||
return v
|
return v
|
||||||
@@ -387,12 +389,12 @@ class Task(BaseModel):
|
|||||||
if not HAS_CREWAI_FILES:
|
if not HAS_CREWAI_FILES:
|
||||||
return v
|
return v
|
||||||
|
|
||||||
result = []
|
result = {}
|
||||||
for item in v:
|
for key, value in v.items():
|
||||||
if isinstance(item, str):
|
if isinstance(value, str):
|
||||||
result.append(FilePath(path=Path(item)))
|
result[key] = FilePath(path=Path(value))
|
||||||
else:
|
else:
|
||||||
result.append(item)
|
result[key] = value
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@field_validator("output_file")
|
@field_validator("output_file")
|
||||||
@@ -1038,16 +1040,11 @@ Follow these guidelines:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def _store_input_files(self) -> None:
|
def _store_input_files(self) -> None:
|
||||||
"""Store task input files in the file store.
|
"""Store task input files in the file store."""
|
||||||
|
|
||||||
Converts input_files list to a named dict and stores under task ID.
|
|
||||||
"""
|
|
||||||
if not HAS_CREWAI_FILES or not self.input_files:
|
if not HAS_CREWAI_FILES or not self.input_files:
|
||||||
return
|
return
|
||||||
|
|
||||||
files_dict = normalize_input_files(self.input_files)
|
store_task_files(self.id, self.input_files)
|
||||||
if files_dict:
|
|
||||||
store_task_files(self.id, files_dict)
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"Task(description={self.description}, expected_output={self.expected_output})"
|
return f"Task(description={self.description}, expected_output={self.expected_output})"
|
||||||
|
|||||||
Reference in New Issue
Block a user