-
Notifications
You must be signed in to change notification settings - Fork 156
Description
Python -VV
Python 3.13.7 (main, Sep 25 2025, 21:20:20) [Clang 17.0.0 (clang-1700.3.19.1)]Pip Freeze
aiofiles==25.1.0
alembic==1.17.2
annotated-doc==0.0.4
annotated-types==0.7.0
anyio==4.11.0
appdirs==1.4.4
APScheduler==3.11.1
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
async-property==0.2.2
certifi==2025.8.3
cffi==2.0.0
charset-normalizer==3.4.3
click==8.3.0
cryptography==46.0.1
debugpy==1.8.19
Deprecated==1.2.18
deprecation==2.1.0
distro==1.9.0
dnspython==2.8.0
ecdsa==0.19.1
elementpath==5.0.4
email-validator==2.3.0
eval_type_backport==0.2.2
fastapi==0.121.3
frozendict==2.4.6
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.10
img2pdf==0.6.1
iniconfig==2.3.0
invoke==2.2.1
Jinja2==3.1.6
jwcrypto==1.5.6
lxml==6.0.2
Mako==1.3.10
markdown-it-py==4.0.0
MarkupSafe==3.0.3
mdurl==0.1.2
minio==7.2.18
mistralai==1.9.11
mollie-api-python==3.9.1
oauthlib==3.3.1
ocrmypdf==16.11.0
packaging==25.0
pdfminer.six==20250506
pi_heif==1.1.0
pikepdf==9.11.0
pillow==11.3.0
pluggy==1.6.0
pyasn1==0.6.1
pycparser==2.23
pycryptodome==3.23.0
pydantic==2.11.10
pydantic-settings==2.12.0
pydantic-xml==2.18.0
pydantic_core==2.33.2
Pygments==2.19.2
pyschematron==1.1.13
pytest==9.0.1
pytest-asyncio==1.3.0
python-dateutil==2.9.0.post0
python-dotenv==1.2.1
python-jose==3.5.0
python-keycloak==5.8.1
python-multipart==0.0.20
PyYAML==6.0.3
requests==2.32.5
requests-oauthlib==2.0.0
requests-toolbelt==1.0.0
rich==14.1.0
rsa==4.9.1
ruyaml==0.91.0
setuptools==80.9.0
shellingham==1.5.4
six==1.17.0
sniffio==1.3.1
SQLAlchemy==2.0.43
sqlmodel==0.0.27
starlette==0.48.0
typer==0.19.2
typing-inspection==0.4.2
typing_extensions==4.15.0
tzlocal==5.3.1
urllib3==2.5.0
uvicorn==0.38.0
wrapt==1.17.3
xmlschema==4.1.0Reproduction Steps
- Create a simple Pydantic model:
from mistralai.extra import response_format_from_pydantic_model
from pydantic import BaseModel, Field
import json
class TestModel(BaseModel):
name: str = Field(description="A name field")
value: int = Field(description="A value field")- Generate a ResponseFormat using the SDK function:
response_format = response_format_from_pydantic_model(TestModel)- Serialize using
model_dump()withoutby_alias=True:
serialized = response_format.model_dump(mode='json')
print(json.dumps(serialized, indent=2))-
Observe that
json_schema.schemaisnullinstead of containing the schema definition. -
Compare with
model_dump(by_alias=True):
serialized_with_alias = response_format.model_dump(mode='json', by_alias=True)
print(json.dumps(serialized_with_alias, indent=2))Expected Behavior
hen calling model_dump() on a ResponseFormat object created with response_format_from_pydantic_model(), the json_schema.schema field should contain the actual JSON schema definition, not null. The serialization should work consistently regardless of whether by_alias=True is used.
The expected output should be:
{
"type": "json_schema",
"json_schema": {
"name": "TestModel",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "A name field"},
"value": {"type": "integer", "description": "A value field"}
},
"required": ["name", "value"],
"additionalProperties": false
},
"strict": true
}
}Additional Context
Current Behavior:
model_dump()showsschema: nullmodel_dump(by_alias=True)correctly shows the schema- Actual API calls succeed because the SDK's
marshal_json()function (used for HTTP requests) internally callsmodel_dump(by_alias=True)
Root Cause:
The issue is in JSONSchema.model_serializer (located in mistralai/models/jsonschema.py). The serializer attempts to retrieve the schema_definition field using its alias "schema", but handler(self) returns a dict with the field name "schema_definition" instead of the alias when by_alias=False:
@model_serializer(mode="wrap")
def serialize_model(self, handler):
serialized = handler(self) # Returns {"schema_definition": {...}, ...}
for n, f in type(self).model_fields.items():
k = f.alias or n # k = "schema" (alias)
val = serialized.get(k) # Returns None because key is "schema_definition", not "schema"Impact:
While API calls work, this inconsistency causes confusion for:
- Debugging/inspecting serialized data
- Logging request payloads
- Testing code that relies on
model_dump() - Potential breakage if HTTP serialization method changes
Suggested Solutions
Suggested Fix:
The JSONSchema.model_serializer should check for both the alias key and the field name:
@model_serializer(mode="wrap")
def serialize_model(self, handler):
serialized = handler(self)
for n, f in type(self).model_fields.items():
k = f.alias or n
# Try alias first, then field name as fallback
val = serialized.get(k) or serialized.get(n)
# ... rest of logic ...