Structured output
Typed responses with json_schema
Pass a JSON schema in response_format and the model is constrained to return JSON that matches. Strict mode rejects unknown fields; in non-strict mode the model still tries to match but can drift on edge cases.
Python
python
import os, json
from openai import OpenAI
client = OpenAI(
base_url="https://api.quicksilverpro.io/v1",
api_key=os.environ["QSP_KEY"],
)
resp = client.chat.completions.create(
model="deepseek-v3",
messages=[{
"role": "user",
"content": "Extract the city and temperature from: It was 18C in Paris today.",
}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "weather_reading",
"strict": True,
"schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"temp_c": {"type": "number"},
},
"required": ["city", "temp_c"],
"additionalProperties": False,
},
},
},
)
data = json.loads(resp.choices[0].message.content)
print(data["city"], data["temp_c"]) # Paris 18Strict vs non-strict
- Strict (
strict: true): output is constrained at decode time to match the schema. Unknown keys are impossible.additionalProperties: falseis required on every object in the schema. Recommended for production. - Non-strict (
json_object): output is JSON but not schema-constrained. The model tries to match but can drift on long-tail prompts. Use only for prototyping.
Schema rules
Strict mode has a few constraints to be aware of:
- Every object must have
additionalProperties: falseandrequiredlisting every property. enum,const,oneOfare supported. Recursive schemas via$refare also supported.- Defaults aren't enforced — if you need a default, post-process the parsed JSON in your client.
When to use
- Structured extraction — pulling typed fields from free-form text.
- Form-filling agents — guaranteeing the agent emits keys your downstream code can consume.
- Pipelines— when the model's output is the input to the next stage, schema-constrained output eliminates a class of parse errors.
For function/tool calling, the same constraint mechanism is available via the tools[].function.parameters field. See Tool calling.