Structured Outputs

Structured Output

{
    "model": "gpt-5.4",
    "input": "Tell me a three sentence bedtime story about a unicorn.",
    ...
    "text": {
        "format": {
            "type": "json_schema",
            "name": "..."
            "strict": true,
            "schema": ...
        }
    }
}
  • Pydantic Example
from openai import OpenAI
from pydantic import BaseModel
 
client = OpenAI()
 
class CalendarEvent(BaseModel):
    name: str
    date: str
    participants: list[str]
 
response = client.responses.parse(
    model="gpt-5.5",
    input=[
        {"role": "system", "content": "Extract the event information."},
        {
            "role": "user",
            "content": "Alice and Bob are going to a science fair on Friday.",
        },
    ],
    text_format=CalendarEvent,
)
 
event = response.output_parsed
  • Use cases
# Chain of thought
class Step(BaseModel):
    explanation: str
    output: str
 
class MathReasoning(BaseModel):
    steps: list[Step]
    final_answer: str
 
 
# Structured data extraction
class ResearchPaperExtraction(BaseModel):
    title: str
    authors: list[str]
    abstract: str
    keywords: list[str]
 
 
# Moderation
class Category(str, Enum):
    violence = "violence"
    sexual = "sexual"
    self_harm = "self_harm"
 
class ContentCompliance(BaseModel):
    is_violating: bool
    category: Optional[Category]
    explanation_if_violating: Optional[str]

JSON Mode

  • Compared to Structured Output, JSON Mode just checks if the output is valid JSON
  • Create Response API Body
{
    "model": "gpt-3.5-turbo",
    "input": "Tell me a three sentence bedtime story about a unicorn.",
    ...
    "text": {
        "format": {
            "type": "json_object"
        }
    }
}

Langchain Output Parser

from langchain_ollama import ChatOllama
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
 
class Cricketer(BaseModel) :
    name: str = Field(description="Name of Cricketer")
    records: list = Field(description="Python list of records")
 
parser = PydanticOutputParser(pydantic_object=Cricketer)
 
# This prepares the instructions for json schema
# We inject these instructions at the end of our message
print(parser.get_format_instructions())
 
model = ChatOllama(
    model="qwen2.5:7b",
    temperature=0
)
 
messages = [
    (
        "user",
        f"Tell me about a cricketer\n{parser.get_format_instructions()}",
    )
]
 
response = model.invoke(messages)
 
# We should be able to parse the response into pydantic object
cricketer: Cricketer = parser.parse(response.content)
 
print(cricketer)