mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-05-02 15:52:34 +00:00
fixes interpolation issues when inputs are type dict,list specifically when defined on expected_output
This commit is contained in:
@@ -431,7 +431,9 @@ class Task(BaseModel):
|
|||||||
content = (
|
content = (
|
||||||
json_output
|
json_output
|
||||||
if json_output
|
if json_output
|
||||||
else pydantic_output.model_dump_json() if pydantic_output else result
|
else pydantic_output.model_dump_json()
|
||||||
|
if pydantic_output
|
||||||
|
else result
|
||||||
)
|
)
|
||||||
self._save_file(content)
|
self._save_file(content)
|
||||||
|
|
||||||
@@ -452,7 +454,7 @@ class Task(BaseModel):
|
|||||||
return "\n".join(tasks_slices)
|
return "\n".join(tasks_slices)
|
||||||
|
|
||||||
def interpolate_inputs_and_add_conversation_history(
|
def interpolate_inputs_and_add_conversation_history(
|
||||||
self, inputs: Dict[str, Union[str, int, float]]
|
self, inputs: Dict[str, Union[str, int, float, dict, list]]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Interpolate inputs into the task description, expected output, and output file path.
|
"""Interpolate inputs into the task description, expected output, and output file path.
|
||||||
Add conversation history if present.
|
Add conversation history if present.
|
||||||
@@ -524,7 +526,9 @@ class Task(BaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def interpolate_only(
|
def interpolate_only(
|
||||||
self, input_string: Optional[str], inputs: Dict[str, Union[str, int, float]]
|
self,
|
||||||
|
input_string: Optional[str],
|
||||||
|
inputs: Dict[str, Union[str, int, float, dict, list]],
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Interpolate placeholders (e.g., {key}) in a string while leaving JSON untouched.
|
"""Interpolate placeholders (e.g., {key}) in a string while leaving JSON untouched.
|
||||||
|
|
||||||
@@ -551,14 +555,16 @@ class Task(BaseModel):
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Inputs dictionary cannot be empty when interpolating variables"
|
"Inputs dictionary cannot be empty when interpolating variables"
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate input types
|
# Validate input types
|
||||||
for key, value in inputs.items():
|
for key, value in inputs.items():
|
||||||
if not isinstance(value, (str, int, float)):
|
print("key", key, value)
|
||||||
|
if not isinstance(value, (str, int, float, dict, list)):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Value for key '{key}' must be a string, integer, or float, got {type(value).__name__}"
|
f"Value for key '{key}' must be a string, integer, float, dict, or list, got {type(value).__name__}"
|
||||||
)
|
)
|
||||||
|
if isinstance(value, (dict, list)):
|
||||||
|
inputs[key] = json.dumps(value, ensure_ascii=False)
|
||||||
|
|
||||||
escaped_string = input_string.replace("{", "{{").replace("}", "}}")
|
escaped_string = input_string.replace("{", "{{").replace("}", "}}")
|
||||||
|
|
||||||
|
|||||||
@@ -441,9 +441,9 @@ def test_output_pydantic_to_another_task():
|
|||||||
crew = Crew(agents=[scorer], tasks=[task1, task2], verbose=True)
|
crew = Crew(agents=[scorer], tasks=[task1, task2], verbose=True)
|
||||||
result = crew.kickoff()
|
result = crew.kickoff()
|
||||||
pydantic_result = result.pydantic
|
pydantic_result = result.pydantic
|
||||||
assert isinstance(
|
assert isinstance(pydantic_result, ScoreOutput), (
|
||||||
pydantic_result, ScoreOutput
|
"Expected pydantic result to be of type ScoreOutput"
|
||||||
), "Expected pydantic result to be of type ScoreOutput"
|
)
|
||||||
assert pydantic_result.score == 5
|
assert pydantic_result.score == 5
|
||||||
|
|
||||||
|
|
||||||
@@ -779,6 +779,43 @@ def test_interpolate_only():
|
|||||||
assert result == no_placeholders
|
assert result == no_placeholders
|
||||||
|
|
||||||
|
|
||||||
|
def test_interpolate_only_with_dict_inside_expected_output():
|
||||||
|
"""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: {questions}",
|
||||||
|
)
|
||||||
|
|
||||||
|
json_string = '{"questions": {"main_question": "What is the user\'s name?", "secondary_question": "What is the user\'s age?"}}'
|
||||||
|
result = task.interpolate_only(
|
||||||
|
input_string=json_string,
|
||||||
|
inputs={
|
||||||
|
"questions": {
|
||||||
|
"main_question": "What is the user's name?",
|
||||||
|
"secondary_question": "What is the user's age?",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert '"main_question": "What is the user\'s name?"' in result
|
||||||
|
assert '"secondary_question": "What is the user\'s age?"' in result
|
||||||
|
assert result == json_string
|
||||||
|
|
||||||
|
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!"
|
||||||
|
|
||||||
|
result = task.interpolate_only(input_string="", inputs={"unused": "value"})
|
||||||
|
assert result == ""
|
||||||
|
|
||||||
|
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():
|
def test_task_output_str_with_pydantic():
|
||||||
from crewai.tasks.output_format import OutputFormat
|
from crewai.tasks.output_format import OutputFormat
|
||||||
|
|
||||||
@@ -870,9 +907,9 @@ def test_key():
|
|||||||
assert task.key == hash, "The key should be the hash of the description."
|
assert task.key == hash, "The key should be the hash of the description."
|
||||||
|
|
||||||
task.interpolate_inputs_and_add_conversation_history(inputs={"topic": "AI"})
|
task.interpolate_inputs_and_add_conversation_history(inputs={"topic": "AI"})
|
||||||
assert (
|
assert task.key == hash, (
|
||||||
task.key == hash
|
"The key should be the hash of the non-interpolated description."
|
||||||
), "The key should be the hash of the non-interpolated description."
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_output_file_validation():
|
def test_output_file_validation():
|
||||||
|
|||||||
Reference in New Issue
Block a user