From c871d729e701246df8c2065c33c43a827093b5a0 Mon Sep 17 00:00:00 2001 From: abdelhadi703 Date: Mon, 2 Mar 2026 21:49:41 +0100 Subject: [PATCH] fix(extra): explicitly pass by_alias=True to model_json_schema in response_format Ensures Pydantic field aliases are explicitly respected when generating JSON schemas via response_format_from_pydantic_model(). While Pydantic v2 uses aliases by default in model_json_schema(), adding by_alias=True makes the intent explicit and guards against potential future behavior changes. Related to #310 Co-Authored-By: Claude Opus 4.6 --- src/mistralai/extra/utils/response_format.py | 2 +- tests/test_response_format_alias.py | 47 ++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/test_response_format_alias.py diff --git a/src/mistralai/extra/utils/response_format.py b/src/mistralai/extra/utils/response_format.py index 2378b562..31f6664f 100644 --- a/src/mistralai/extra/utils/response_format.py +++ b/src/mistralai/extra/utils/response_format.py @@ -11,7 +11,7 @@ def response_format_from_pydantic_model( model: type[CustomPydanticModel], ) -> ResponseFormat: """Generate a strict JSON schema from a pydantic model.""" - model_schema = rec_strict_json_schema(model.model_json_schema()) + model_schema = rec_strict_json_schema(model.model_json_schema(by_alias=True)) json_schema = JSONSchema.model_validate( {"name": model.__name__, "schema": model_schema, "strict": True} ) diff --git a/tests/test_response_format_alias.py b/tests/test_response_format_alias.py new file mode 100644 index 00000000..ed9fc60d --- /dev/null +++ b/tests/test_response_format_alias.py @@ -0,0 +1,47 @@ +"""Test that response_format_from_pydantic_model respects Pydantic field aliases.""" + +from pydantic import BaseModel, Field + +from mistralai.extra.utils.response_format import response_format_from_pydantic_model + + +class AliasedModel(BaseModel): + full_name: str = Field(alias="fullName") + phone_number: str = Field(alias="phoneNumber") + + +class NoAliasModel(BaseModel): + name: str + age: int + + +def test_response_format_uses_alias_keys(): + """Schema properties should use alias names, not Python field names.""" + result = response_format_from_pydantic_model(AliasedModel) + schema = result.json_schema.schema_definition + + props = schema["properties"] + assert "fullName" in props, f"Expected 'fullName' in properties, got {list(props)}" + assert "phoneNumber" in props, f"Expected 'phoneNumber' in properties, got {list(props)}" + assert "full_name" not in props, "Python field name 'full_name' should not appear" + assert "phone_number" not in props, "Python field name 'phone_number' should not appear" + + +def test_response_format_required_uses_aliases(): + """Required field list should use alias names.""" + result = response_format_from_pydantic_model(AliasedModel) + schema = result.json_schema.schema_definition + + required = schema["required"] + assert "fullName" in required + assert "phoneNumber" in required + + +def test_response_format_without_aliases_unchanged(): + """Models without aliases should work as before.""" + result = response_format_from_pydantic_model(NoAliasModel) + schema = result.json_schema.schema_definition + + props = schema["properties"] + assert "name" in props + assert "age" in props