mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-10 00:28:31 +00:00
[FEATURE] Improve agent/task templating with Jinja2
Fixes #2650 - Add support for container types (List, Dict, Set) - Add support for standard objects (datetime) - Add support for custom objects - Add support for conditional and loop statements - Add support for filtering options - Maintain backward compatibility with existing templates - Add comprehensive tests - Add documentation with examples Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
81
tests/utilities/test_jinja_templating.py
Normal file
81
tests/utilities/test_jinja_templating.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import pytest
|
||||
import datetime
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Dict, Any
|
||||
from crewai.utilities.jinja_templating import to_jinja_template, render_template
|
||||
|
||||
class Person(BaseModel):
|
||||
name: str
|
||||
age: int
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.age})"
|
||||
|
||||
class TestJinjaTemplating:
|
||||
def test_to_jinja_template(self):
|
||||
assert to_jinja_template("Hello {name}!") == "Hello {{name}}!"
|
||||
|
||||
assert to_jinja_template("Hello {{name}}!") == "Hello {{name}}!"
|
||||
|
||||
assert to_jinja_template("Hello {name} and {{title}}!") == "Hello {{name}} and {{title}}!"
|
||||
|
||||
assert to_jinja_template("") == ""
|
||||
|
||||
assert to_jinja_template("Hello world!") == "Hello world!"
|
||||
|
||||
def test_render_template_simple_types(self):
|
||||
inputs = {"name": "John", "age": 30, "active": True, "height": 1.85}
|
||||
|
||||
assert render_template("Hello {name}!", inputs) == "Hello John!"
|
||||
assert render_template("Age: {age}", inputs) == "Age: 30"
|
||||
assert render_template("Active: {active}", inputs) == "Active: True"
|
||||
assert render_template("Height: {height}", inputs) == "Height: 1.85"
|
||||
|
||||
assert render_template("{name} is {age} years old", inputs) == "John is 30 years old"
|
||||
|
||||
def test_render_template_container_types(self):
|
||||
inputs = {
|
||||
"items": ["apple", "banana", "orange"],
|
||||
"person": {"name": "John", "age": 30}
|
||||
}
|
||||
|
||||
assert render_template("First item: {{items[0]}}", inputs) == "First item: apple"
|
||||
|
||||
assert render_template("Person name: {{person.name}}", inputs) == "Person name: John"
|
||||
|
||||
assert render_template(
|
||||
"Items: {% for item in items %}{{item}}{% if not loop.last %}, {% endif %}{% endfor %}",
|
||||
inputs
|
||||
) == "Items: apple, banana, orange"
|
||||
|
||||
assert render_template(
|
||||
"{% if items|length > 2 %}Many items{% else %}Few items{% endif %}",
|
||||
inputs
|
||||
) == "Many items"
|
||||
|
||||
def test_render_template_datetime(self):
|
||||
today = datetime.datetime.now()
|
||||
inputs = {"today": today}
|
||||
|
||||
assert render_template("Today: {{today|date}}", inputs) == f"Today: {today.strftime('%Y-%m-%d')}"
|
||||
|
||||
assert render_template("Today: {{today|date('%d/%m/%Y')}}", inputs) == f"Today: {today.strftime('%d/%m/%Y')}"
|
||||
|
||||
def test_render_template_custom_objects(self):
|
||||
person = Person(name="John", age=30)
|
||||
inputs = {"person": person}
|
||||
|
||||
assert render_template("Person: {person}", inputs) == "Person: John (30)"
|
||||
|
||||
assert render_template("Person name: {{person.name}}", inputs) == "Person name: John"
|
||||
|
||||
def test_render_template_error_handling(self):
|
||||
inputs = {"name": "John"}
|
||||
|
||||
with pytest.raises(KeyError) as excinfo:
|
||||
render_template("Hello {age}!", inputs)
|
||||
assert "Template variable 'age' not found" in str(excinfo.value)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
render_template("Hello {name}!", {})
|
||||
assert "Inputs dictionary cannot be empty" in str(excinfo.value)
|
||||
Reference in New Issue
Block a user