LLMs & GenAI

Structured Output & Constrained Decoding

Guaranteeing 100% syntactically valid JSON, Pydantic, and SQL outputs from autoregressive LLMs.

🟡 intermediate5 min readpractical
Structured Output generation forces LLMs to emit text matching rigid formal specifications (JSON Schema, Pydantic models, SQL syntax). Traditional prompt instructions ("Respond ONLY in JSON") fail intermittently due to stochastic sampling errors. Grammar-Constrained Decoding (Outlines, Guidance, vLLM, OpenAI Structured Outputs) enforces valid syntax at the logit level: at each step, a Context-Free Grammar (CFG) or Regex State Machine sets logits of syntactically invalid tokens to -∞, guaranteeing 100% schema compliance.

The Two Approaches to Structured Output

  1. PROMPT-LEVEL INSTRUCTION (Probabilistic / Flaky)
  System: "Respond in JSON matching {'name': str, 'age': int}."
  Output: "Sure! Here is the JSON: {'name': 'Alice', 'age': 30,}"  ──► JSON.parse() CRASHES! (Trailing comma)

  2. GRAMMAR-CONSTRAINED DECODING (Deterministic / 100% Guaranteed)
  System + Pydantic Schema
  At every token step, Logit Masking sets invalid syntax tokens to -∞.
  Output: {"name": "Alice", "age": 30}                              ──► 100% VALID PARSE!

How Grammar-Constrained Decoding Works

Let $V$ be the LLM vocabulary ($32,000$ tokens).

Suppose the LLM has generated: {"name": "Alice",

The JSON schema specifies the next key MUST be "age".

  Logit Vector z [32,000]
  Token '"age"'   ──►  Logit z = 12.4  (VALID -> Retained)
  Token 'true'    ──►  Logit z = -∞    (INVALID -> Masked!)
  Token 'null'    ──►  Logit z = -∞    (INVALID -> Masked!)
  Token '}'       ──►  Logit z = -∞    (INVALID -> Masked!)

$$\text{Logit Masking: } z_i = \begin{cases} z_i & \text{if token } i \text{ matches Grammar State} \ -\infty & \text{otherwise} \end{cases}$$

After applying Softmax, probabilities for invalid tokens become exactly zero ($e^{-\infty} = 0$).

Popular Frameworks

Integration Example with Pydantic & Outlines

from pydantic import BaseModel
import outlines

class UserProfile(BaseModel):
    name: str
    age: int
    roles: list[str]

# Load model with outlines sampler
model = outlines.models.transformers("meta-llama/Meta-Llama-3-8B-Instruct")
generator = outlines.generate.json(model, UserProfile)

# Guarantees 100% valid UserProfile instance!
result: UserProfile = generator("Extract user profile from: Alice is a 30yo admin.")

Say this out loud

"Prompt instructions cannot guarantee valid JSON because stochastic sampling can pick invalid tokens like missing quotes or trailing commas. Grammar-Constrained Decoding enforces 100% schema compliance by using a Finite State Machine to mask invalid token logits to -∞ at every generation step. Tools like Outlines and OpenAI Structured Outputs enforce Pydantic schemas with zero syntax errors."

Follow-ups to expect

Check yourself

Question 1 of 3

Why do prompt-level instructions like 'Return ONLY valid JSON' fail to guarantee 100% JSON schema compliance in production LLM applications?

More in LLMs & GenAI

See all →
Pretraining → SFT → RLHF5 minFine-Tune vs RAG vs Prompt: Choosing5 minRetrieval-Augmented Generation5 min