Fix Pydantic field alias consistency in structured output (#1099)
This commit is contained in:
parent
906ceea388
commit
5c9cf290d8
2 changed files with 46 additions and 1 deletions
|
|
@ -111,7 +111,7 @@ class FuncMetadata(BaseModel):
|
|||
|
||||
assert self.output_model is not None, "Output model must be set if output schema is defined"
|
||||
validated = self.output_model.model_validate(result)
|
||||
structured_content = validated.model_dump(mode="json")
|
||||
structured_content = validated.model_dump(mode="json", by_alias=True)
|
||||
|
||||
return (unstructured_content, structured_content)
|
||||
|
||||
|
|
|
|||
|
|
@ -839,3 +839,48 @@ def test_structured_output_unserializable_type_error():
|
|||
func_metadata(func_returning_namedtuple, structured_output=True)
|
||||
assert "is not serializable for structured output" in str(exc_info.value)
|
||||
assert "Point" in str(exc_info.value)
|
||||
|
||||
|
||||
def test_structured_output_aliases():
|
||||
"""Test that field aliases are consistent between schema and output"""
|
||||
|
||||
class ModelWithAliases(BaseModel):
|
||||
field_first: str | None = Field(default=None, alias="first", description="The first field.")
|
||||
field_second: str | None = Field(default=None, alias="second", description="The second field.")
|
||||
|
||||
def func_with_aliases() -> ModelWithAliases:
|
||||
# When aliases are defined, we must use the aliased names to set values
|
||||
return ModelWithAliases(**{"first": "hello", "second": "world"})
|
||||
|
||||
meta = func_metadata(func_with_aliases)
|
||||
|
||||
# Check that schema uses aliases
|
||||
assert meta.output_schema is not None
|
||||
assert "first" in meta.output_schema["properties"]
|
||||
assert "second" in meta.output_schema["properties"]
|
||||
assert "field_first" not in meta.output_schema["properties"]
|
||||
assert "field_second" not in meta.output_schema["properties"]
|
||||
|
||||
# Check that the actual output uses aliases too
|
||||
result = ModelWithAliases(**{"first": "hello", "second": "world"})
|
||||
unstructured_content, structured_content = meta.convert_result(result)
|
||||
|
||||
# The structured content should use aliases to match the schema
|
||||
assert "first" in structured_content
|
||||
assert "second" in structured_content
|
||||
assert "field_first" not in structured_content
|
||||
assert "field_second" not in structured_content
|
||||
assert structured_content["first"] == "hello"
|
||||
assert structured_content["second"] == "world"
|
||||
|
||||
# Also test the case where we have a model with defaults to ensure aliases work in all cases
|
||||
result_with_defaults = ModelWithAliases() # Uses default None values
|
||||
unstructured_content_defaults, structured_content_defaults = meta.convert_result(result_with_defaults)
|
||||
|
||||
# Even with defaults, should use aliases in output
|
||||
assert "first" in structured_content_defaults
|
||||
assert "second" in structured_content_defaults
|
||||
assert "field_first" not in structured_content_defaults
|
||||
assert "field_second" not in structured_content_defaults
|
||||
assert structured_content_defaults["first"] is None
|
||||
assert structured_content_defaults["second"] is None
|
||||
|
|
|
|||
Loading…
Reference in a new issue