Structured outputs guarantee the model's response conforms to a specific JSON schema. Combined with vision, you can extract structured data from PDFs and documents.
Pydantic with Responses API
Structured output schema limits: max 5,000 properties, 10 nesting levels, 1,000 enum values, and 120,000 characters total.
One pipeline replaces three
The pre-input_file pattern was: pdfplumber → text extraction → chunking → embedding → vector search → prompt assembly → JSON parsing. input_file + response_format collapses that into one API call. Pass the PDF; get back a typed Pydantic instance.
Caveat: input_file processes the whole PDF in one pass, so very long documents (100+ pages) hit context-window limits. For those, you still want chunking. For invoices, reports, contracts, single-page forms — input_file is the canonical shape.
Code
Sending a PDF via input_file·python
completion = client.chat.completions.create(
model="gpt-5.4",
messages=[{"role": "user", "content": "Return a JSON with name and age for 'Alice, 30'"}],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": True,
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"required": ["name", "age"],
"additionalProperties": False,
}
}
}
)
import json
person = json.loads(completion.choices[0].message.content)
Structured extraction with response_format·python
from pydantic import BaseModel
class InvoiceData(BaseModel):
vendor: str
total: float
items: list[str]
date: str
response = client.responses.parse(
model="gpt-5.4",
input=[{
"role": "user",
"content": [
{"type": "input_text", "text": "Extract invoice data from this PDF:"},
{"type": "input_file", "file_id": "file-abc123"},
]
}],
text_format=InvoiceData,
)
invoice = response.output_parsed # typed InvoiceData object
Pick a PDF invoice (or generate one). Extract {vendor, invoice_number, total, currency, line_items[]} via input_file + response_format. Run on 5 different PDFs and measure which fields fail most.
Progress
Progress is local-only — sign in to sync across devices.