fix: allow booleans, numbers, etc. in root-level tweaks (#12605)

fix: allow booleans, numbers, etc. in root-level tweaks (#11830)

Widen the Tweaks schema to accept bool, int, and float values alongside
str and dict, so scalar tweaks like {"stream": false} are no longer
rejected by Pydantic validation.

bool is listed before int in the union to prevent Pydantic from coercing
booleans to integers (since bool is a subclass of int).

Adds unit tests for boolean and numeric root-level tweaks, as well as
direct Tweaks Pydantic model validation tests.

Co-authored-by: Alex Kuligowski <alekuligowski@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eric Hare
2026-04-13 11:10:36 -07:00
committed by GitHub
parent 7e786a728f
commit faac7ad007
2 changed files with 156 additions and 1 deletions

View File

@ -310,6 +310,159 @@ async def test_load_langchain_object_with_cached_session(basic_graph_data):
# assert graph1 == graph2
def test_tweak_no_node_id_boolean():
"""Test that boolean tweaks at root level are applied to all matching nodes."""
graph_data = {
"data": {
"nodes": [
{
"id": "node1",
"data": {
"node": {
"template": {
"enabled": {"value": True, "type": "bool"},
"param1": {"value": "hello", "type": "str"},
}
}
},
},
{
"id": "node2",
"data": {
"node": {
"template": {
"enabled": {"value": True, "type": "bool"},
}
}
},
},
]
}
}
tweaks = {"enabled": False}
expected_result = {
"data": {
"nodes": [
{
"id": "node1",
"data": {
"node": {
"template": {
"enabled": {"value": False, "type": "bool"},
"param1": {"value": "hello", "type": "str"},
}
}
},
},
{
"id": "node2",
"data": {
"node": {
"template": {
"enabled": {"value": False, "type": "bool"},
}
}
},
},
]
}
}
result = process_tweaks(graph_data, tweaks)
assert result == expected_result
def test_tweak_no_node_id_numeric():
"""Test that numeric tweaks at root level are applied to all matching nodes."""
graph_data = {
"data": {
"nodes": [
{
"id": "node1",
"data": {
"node": {
"template": {
"temperature": {"value": 1.0, "type": "float"},
"max_tokens": {"value": 100, "type": "int"},
}
}
},
},
{
"id": "node2",
"data": {
"node": {
"template": {
"temperature": {"value": 1.0, "type": "float"},
}
}
},
},
]
}
}
tweaks = {"temperature": 0.7, "max_tokens": 256}
expected_result = {
"data": {
"nodes": [
{
"id": "node1",
"data": {
"node": {
"template": {
"temperature": {"value": 0.7, "type": "float"},
"max_tokens": {"value": 256, "type": "int"},
}
}
},
},
{
"id": "node2",
"data": {
"node": {
"template": {
"temperature": {"value": 0.7, "type": "float"},
}
}
},
},
]
}
}
result = process_tweaks(graph_data, tweaks)
assert result == expected_result
def test_tweaks_schema_accepts_bool():
"""Tweaks model must accept boolean root-level values without coercion."""
from lfx.schema.graph import Tweaks
tweaks = Tweaks(root={"stream": False, "enabled": True})
assert tweaks.root["stream"] is False
assert tweaks.root["enabled"] is True
# Verify bool is preserved and not coerced to int
assert isinstance(tweaks.root["stream"], bool)
assert isinstance(tweaks.root["enabled"], bool)
def test_tweaks_schema_accepts_numerics():
"""Tweaks model must accept int and float root-level values."""
from lfx.schema.graph import Tweaks
tweaks = Tweaks(root={"temperature": 0.7, "max_tokens": 256})
assert tweaks.root["temperature"] == 0.7
assert tweaks.root["max_tokens"] == 256
def test_tweaks_schema_rejects_invalid():
"""Tweaks model should still reject unsupported value types."""
import pytest
from lfx.schema.graph import Tweaks
from pydantic import ValidationError
with pytest.raises(ValidationError):
Tweaks(root={"param": [1, 2, 3]})
def test_apply_tweaks_code_override_prevention():
"""Test that code tweaks are prevented and logged as warning."""
from unittest.mock import patch

View File

@ -16,7 +16,7 @@ class InputValue(BaseModel):
class Tweaks(RootModel):
root: dict[str, str | dict[str, Any]] = Field(
root: dict[str, bool | int | float | str | dict[str, Any]] = Field(
description="A dictionary of tweaks to adjust the flow's execution. "
"Allows customizing flow behavior dynamically. "
"All tweaks are overridden by the input values.",
@ -26,6 +26,8 @@ class Tweaks(RootModel):
"examples": [
{
"parameter_name": "value",
"stream": False,
"temperature": 0.7,
"Component Name": {"parameter_name": "value"},
"component_id": {"parameter_name": "value"},
}