From 8871d9a6cda9e855874540cbc23cf690cd85db29 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 29 Dec 2024 02:40:37 +0000 Subject: [PATCH] fix: interpolate output_file attribute from YAML Co-Authored-By: Joe Moura --- src/crewai/task.py | 18 +++++++++++++++--- tests/task_test.py | 7 +++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/crewai/task.py b/src/crewai/task.py index 30ab79c00..4817419a4 100644 --- a/src/crewai/task.py +++ b/src/crewai/task.py @@ -213,8 +213,14 @@ class Task(BaseModel): @field_validator("output_file") @classmethod - def output_file_validation(cls, value: str) -> str: - """Validate the output file path by removing the / from the beginning of the path.""" + def output_file_validation(cls, value: Optional[str]) -> Optional[str]: + """Validate the output file path.""" + if value is None: + return None + # Don't strip leading slash if it's a template path with variables + if "{" in value or "}" in value: + return value + # Strip leading slash for regular paths if value.startswith("/"): return value[1:] return value @@ -394,17 +400,23 @@ class Task(BaseModel): return "\n".join(tasks_slices) def interpolate_inputs(self, inputs: Dict[str, Any]) -> None: - """Interpolate inputs into the task description and expected output.""" + """Interpolate inputs into the task description, expected output, and output file path.""" if self._original_description is None: self._original_description = self.description if self._original_expected_output is None: self._original_expected_output = self.expected_output + if self.output_file is not None and not hasattr(self, "_original_output_file"): + self._original_output_file = self.output_file if inputs: self.description = self._original_description.format(**inputs) self.expected_output = self.interpolate_only( input_string=self._original_expected_output, inputs=inputs ) + if self.output_file is not None: + self.output_file = self.interpolate_only( + input_string=self._original_output_file, inputs=inputs + ) def interpolate_only(self, input_string: str, inputs: Dict[str, Any]) -> str: """Interpolate placeholders (e.g., {key}) in a string while leaving JSON untouched.""" diff --git a/tests/task_test.py b/tests/task_test.py index 40eb98e54..e9edf927f 100644 --- a/tests/task_test.py +++ b/tests/task_test.py @@ -719,21 +719,24 @@ def test_interpolate_inputs(): task = Task( description="Give me a list of 5 interesting ideas about {topic} to explore for an article, what makes them unique and interesting.", expected_output="Bullet point list of 5 interesting ideas about {topic}.", + output_file="/tmp/{topic}/output_{date}.txt" ) - task.interpolate_inputs(inputs={"topic": "AI"}) + task.interpolate_inputs(inputs={"topic": "AI", "date": "2024"}) assert ( task.description == "Give me a list of 5 interesting ideas about AI to explore for an article, what makes them unique and interesting." ) assert task.expected_output == "Bullet point list of 5 interesting ideas about AI." + assert task.output_file == "/tmp/AI/output_2024.txt" - task.interpolate_inputs(inputs={"topic": "ML"}) + task.interpolate_inputs(inputs={"topic": "ML", "date": "2025"}) assert ( task.description == "Give me a list of 5 interesting ideas about ML to explore for an article, what makes them unique and interesting." ) assert task.expected_output == "Bullet point list of 5 interesting ideas about ML." + assert task.output_file == "/tmp/ML/output_2025.txt" def test_interpolate_only():