Structured Outputs, JSON Schema & Pydantic
In production software, connecting LLM outputs to databases, UI components, and API webhooks requires 100% deterministic schema conformity. Asking nicely with "Please return valid JSON" fails under load. In this chapter, learn how modern Constrained Decoding and Strict JSON Schemamathematically guarantee zero syntax errors.
1. The Evolution of Structured Generation
Instruction: "Respond only with JSON."
Failure: Model wraps responses in markdown fences (```json), omits quotes, or includes conversational pleasantries ("Here is your data:").
Parameter: response_format={ "type": "json_object" }
Limitation: Guarantees valid JSON syntax, but does NOT guarantee that required fields, types (strings vs integers), or enums match your schema.
Parameter: strict: true with JSON Schema.
Guarantee: 100% adherence to all required fields, nested types, and enums via Context-Free Grammar (CFG) token masking.
2. How Constrained Decoding Works Under the Hood
When strict: true is enabled, the inference engine (such as OpenAI's infrastructure, Outlines, or SGLang) converts your JSON Schema into a Deterministic Finite Automaton (DFA):
// Logit Masking Mechanics:
State: Inside key `"age": `
Permitted Tokens: [0-9] | Prohibited: [a-z, Quotes, Braces, Symbols]
At each sampling step, logits for all invalid tokens that would violate the grammar are set to negative infinity (-inf). It is literally impossible for the model to emit a trailing comma, missing bracket, or unexpected string!
3. Production Pydantic Extraction with OpenAI
By leveraging OpenAI's client.beta.chat.completions.parse() method, you can pass native Pydantic models and receive fully typed, validated Python objects:
from typing import List, Optional
from pydantic import BaseModel, Field
from openai import OpenAI
client = OpenAI()
# 1. Define Strict Pydantic Schema
class InvoiceItem(BaseModel):
description: str = Field(description="Name or description of the product/service")
quantity: int = Field(description="Number of units purchased", ge=1)
unit_price: float = Field(description="Price per single unit in USD")
total: float = Field(description="Line item subtotal (quantity * unit_price)")
class InvoiceExtraction(BaseModel):
invoice_number: str
vendor_name: str
date: str
items: List[InvoiceItem]
tax_amount: Optional[float] = 0.0
total_amount: float
# 2. Extract from Raw Unstructured Text
raw_email = """
Thanks for your business! Invoice #INV-2026-9812
From: CloudTech Solutions LLC
Date: October 14, 2026
Items:
- Enterprise Kubernetes Cluster (qty: 2) at $1,250.00 each -> $2,500.00
- Dedicated Support SLA (qty: 1) at $500.00 -> $500.00
Tax: $150.00
Total Due: $3,150.00
"""
completion = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "Extract invoice details into the structured format."},
{"role": "user", "content": raw_email}
],
response_format=InvoiceExtraction
)
# 3. Access strongly-typed properties with full IDE autocomplete!
invoice_data: InvoiceExtraction = completion.choices[0].message.parsed
print(f"Vendor: {invoice_data.vendor_name}")
print(f"Total Amount: ${invoice_data.total_amount:,.2f}")
for item in invoice_data.items:
print(f" - {item.description}: {item.quantity} x ${item.unit_price} = ${item.total}")4. Best Practices for Strict Schemas
| Practice | Why It Matters | Recommendation |
|---|---|---|
Always provide description | The model uses Pydantic field descriptions as semantic in-context guidance. | Add clear, concise descriptions explaining units, formats, and expectations. |
Set additionalProperties: false | Required by OpenAI Strict Mode to prevent the model from generating hallucinated extra keys. | Native client.beta.chat.completions.parse configures this automatically. |
| Use Enums for Categories | Constrains output strictly to a predefined list of valid string literals. | Use Python's enum.Enum for statuses, priority tags, and currency codes. |
Adversarial Injections & Security
Continue to the next hands-on prompt engineering guide in this series.
Explore Related Tools
Hand-picked utilities and calculators related to this tool.
