Learn how to create structured outputs using OpenAI's JSON schema capabilities and Pydantic models. These techniques ensure consistent responses, enable type validation, and improve reliability for AI-driven workflows.
Prerequisites for Implementing Structured Outputs
Before starting, ensure the following setup is complete:
prerequisites
- Python: Install Python 3.8 or newer.
- OpenAI Python package: Update your OpenAI library using
pip install openai --upgrade. - Access: Ensure you have access to the GPT-4 API in OpenAI.
- Pydantic: Install the Pydantic library via
pip install pydantic.
Introduction to Structured Outputs in OpenAI
Structured outputs allow developers to define a schema for expected responses, ensuring reliability and consistent formatting. Unlike plain JSON mode, structured outputs verify both the format and content against predefined constraints, eliminating risks like hallucinated responses. This method is ideal for systems requiring type safety, explicit refusals, or complex multi-field outputs.
Implementing Structured Outputs Using JSON Schema
The first method involves defining and using a JSON schema directly with the OpenAI API.
Defining and Using JSON Schema
Below is a Python example for a customer service scenario:
import openai
import json
# Update your API key with the correct value
openai.api_key = "your_openai_api_key"
schema = {
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {"type": "string"},
"action": {"type": "string"}
},
"required": ["description", "action"]
}
},
"final_resolution": {"type": "string"}
},
"required": ["steps", "final_resolution"]
}
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": "Provide steps and resolution for resolving customer issues."},
{"role": "user", "content": "I want to return an item I bought recently."}
],
response_format={"type": "json_schema", "schema": schema}
)
structured_output = json.loads(response.choices[0].message.content)
# Printing the structured response
for step in structured_output["steps"]:
print(f"Step Description: {step['description']}, Action: {step['action']}")
print(f"Final Resolution: {structured_output['final_resolution']}")This code defines an explicit JSON schema and uses it to enforce strict adherence in responses.
Using Pydantic Models for Structured Outputs
The recommended, simpler approach involves using Pydantic models. Pydantic streamlines schema definition and integrates validation directly into the model.
Defining and Using Pydantic Models
Here is an alternative setup for the same task using Pydantic:
import openai
from pydantic import BaseModel, Field
# Update your API key with the correct value
openai.api_key = "your_openai_api_key"
# Define Pydantic Model
class Step(BaseModel):
description: str = Field(..., description="A summary of the action needed.")
action: str = Field(..., description="The related action to be performed.")
class TicketResolution(BaseModel):
steps: list[Step] = Field(..., description="Steps required to resolve the issue.")
final_resolution: str = Field(..., description="Final message for the customer.")
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": "Provide steps and resolution for resolving customer issues."},
{"role": "user", "content": "I want to return an item I bought recently."}
],
response_format={"type": "pydantic", "model": TicketResolution}
)
parsed_response = response["choices"][0].message
# Print the parsed output
print(parsed_response.steps)
print(parsed_response.final_resolution)Using Pydantic reduces complexity and integrates description-based prompt engineering directly into a data model.
Handling Schema Mismatches and Model Refusals
Handling Validation Errors
- Schema mismatches: Use OpenAI's refusal signals to detect when the model cannot comply with constraints.
- Validation limits: Avoid unsupported validation rules (e.g.,
minormaxfields for floats in certain schemas). - Fallback strategies: Combine structured outputs with failover tools like instructors or secondary validators for critical tasks.
Embedding Structured Outputs in System Design
Structured outputs enable advanced system integration:
- Use enums for decisions requiring routing or pipeline management.
- Include flags like booleans for confidence scoring and escalation paths.
- Combine user-facing interactions with internal metadata storage for long-term analysis.
Summary and Best Practices for Structured Outputs
FAQ
What are structured outputs in OpenAI?
Structured outputs use JSON schema or Pydantic models to define strict response formatting, ensuring reliable type and content validation.
How do I handle OpenAI refusal errors?
Refusal errors typically occur when the inputs or constraints contradict the schema. Handle refusals by programmatically detecting them and applying fallback logic.
Should I use JSON schema or Pydantic models?
Pydantic models are recommended for their simplicity, validation capabilities, and ease of extension compared to JSON schemas.
Official reference: OpenAI structured outputs guide.