Compare commits

...

15 Commits

Author SHA1 Message Date
Devin AI
f26833f751 fix: Sort imports using ruff --fix
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:33:16 +00:00
Devin AI
5fe15a8dba fix: Resolve merge conflict and maintain organized imports
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:31:39 +00:00
Devin AI
d8f5a9fb71 fix: Apply ruff automatic import sorting
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:29:13 +00:00
Devin AI
55883c6083 fix: Consolidate imports and fix formatting
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:26:47 +00:00
Devin AI
072f0cbef6 fix: Reorganize imports using ruff --fix
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:25:37 +00:00
Devin AI
7beb511206 fix: Sort imports to fix lint issues
Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:22:11 +00:00
Devin AI
5b2e41b8eb feat: Add interpolate_only method and improve error handling
- Add interpolate_only method for string interpolation while preserving JSON structure
- Add comprehensive test coverage for interpolate_only
- Add proper type annotation for logger using ClassVar
- Improve error handling and documentation for _save_file method

Co-Authored-By: Joe Moura <joao@crewai.com>
2024-12-22 04:19:47 +00:00
Brandon Hancock (bhancock_ai)
e6f620877d Merge branch 'main' into main 2024-12-20 10:34:39 -05:00
Frieda (Jingying) Huang
43cb2d1f66 Fixed yaml config is not escaped properly for output requirements 2024-12-15 13:28:17 -05:00
Frieda Huang
4e9b70201e Merge branch 'crewAIInc:main' into main 2024-12-15 11:30:27 -05:00
Frieda Huang
059b0cf5b4 Merge branch 'crewAIInc:main' into main 2024-12-10 22:48:49 -05:00
Frieda Huang
652ddcc1c5 Merge branch 'crewAIInc:main' into main 2024-12-10 07:40:02 -05:00
Brandon Hancock (bhancock_ai)
964d4bfdbf Merge branch 'main' into main 2024-12-09 09:54:20 -05:00
Frieda (Jingying) Huang
c103d7eab7 Merge branch 'main' of https://github.com/frieda-huang/crewAI 2024-12-08 09:25:06 -05:00
Frieda (Jingying) Huang
4fe9f5d8bd Fixed output_file not respecting system path 2024-12-08 09:21:12 -05:00
2 changed files with 90 additions and 13 deletions

View File

@@ -1,13 +1,25 @@
import datetime
import inspect
import json
import logging
import threading
import uuid
from concurrent.futures import Future
from copy import copy
from hashlib import md5
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
from typing import (
Any,
Callable,
ClassVar,
Dict,
List,
Optional,
Set,
Tuple,
Type,
Union,
)
from opentelemetry.trace import Span
from pydantic import (
@@ -51,6 +63,7 @@ class Task(BaseModel):
"""
__hash__ = object.__hash__ # type: ignore
logger: ClassVar[logging.Logger] = logging.getLogger(__name__)
used_tools: int = 0
tools_errors: int = 0
delegations: int = 0
@@ -389,7 +402,18 @@ class Task(BaseModel):
if inputs:
self.description = self._original_description.format(**inputs)
self.expected_output = self._original_expected_output.format(**inputs)
self.expected_output = self.interpolate_only(
input_string=self._original_expected_output, 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."""
escaped_string = input_string.replace("{", "{{").replace("}", "}}")
for key in inputs.keys():
escaped_string = escaped_string.replace(f"{{{{{key}}}}}", f"{{{key}}}")
return escaped_string.format(**inputs)
def increment_tools_errors(self) -> None:
"""Increment the tools errors counter."""
@@ -471,22 +495,33 @@ class Task(BaseModel):
return OutputFormat.RAW
def _save_file(self, result: Any) -> None:
"""Save task output to a file.
Args:
result: The result to save to the file. Can be a dict or any stringifiable object.
Raises:
ValueError: If output_file is not set
RuntimeError: If there is an error writing to the file
"""
if self.output_file is None:
raise ValueError("output_file is not set.")
resolved_path = Path(self.output_file).expanduser().resolve()
directory = resolved_path.parent
try:
resolved_path = Path(self.output_file).expanduser().resolve()
directory = resolved_path.parent
if not directory.exists():
directory.mkdir(parents=True, exist_ok=True)
if not directory.exists():
directory.mkdir(parents=True, exist_ok=True)
with resolved_path.open("w", encoding="utf-8") as file:
if isinstance(result, dict):
import json
json.dump(result, file, ensure_ascii=False, indent=2)
else:
file.write(str(result))
with resolved_path.open("w", encoding="utf-8") as file:
if isinstance(result, dict):
import json
json.dump(result, file, ensure_ascii=False, indent=2)
else:
file.write(str(result))
except (OSError, IOError) as e:
raise RuntimeError(f"Failed to save output file: {e}")
return None
def __repr__(self):

View File

@@ -736,6 +736,48 @@ def test_interpolate_inputs():
assert task.expected_output == "Bullet point list of 5 interesting ideas about ML."
def test_interpolate_only():
"""Test the interpolate_only method for various scenarios including JSON structure preservation."""
task = Task(
description="Unused in this test",
expected_output="Unused in this test"
)
# Test JSON structure preservation
json_string = '{"info": "Look at {placeholder}", "nested": {"val": "{nestedVal}"}}'
result = task.interpolate_only(
input_string=json_string,
inputs={"placeholder": "the data", "nestedVal": "something else"}
)
assert '"info": "Look at the data"' in result
assert '"val": "something else"' in result
assert "{placeholder}" not in result
assert "{nestedVal}" not in result
# Test normal string interpolation
normal_string = "Hello {name}, welcome to {place}!"
result = task.interpolate_only(
input_string=normal_string,
inputs={"name": "John", "place": "CrewAI"}
)
assert result == "Hello John, welcome to CrewAI!"
# Test empty string
result = task.interpolate_only(
input_string="",
inputs={"unused": "value"}
)
assert result == ""
# Test string with no placeholders
no_placeholders = "Hello, this is a test"
result = task.interpolate_only(
input_string=no_placeholders,
inputs={"unused": "value"}
)
assert result == no_placeholders
def test_task_output_str_with_pydantic():
from crewai.tasks.output_format import OutputFormat