Structured output¶
Here, we introduce how to get structured output from OpenAI's API, which is extremely handy if you have to process large amounts of data programmatically.
Many LLMs providers support structured output now, which would produce structured output that's easy for programs to parse. Here, we will focus on OpenAI's API.
Setup¶
Install the dependencies and configure your API key.
On Google Colab, store your key in Colab Secrets first: click the key icon in the left sidebar, add a secret named OPENAI_API_KEY, and enable notebook access. Running locally, put the key in a .env file or in the OPENAI_API_KEY environment variable (see handling API keys).
%pip install -q openai pydantic python-dotenv
import os
from dotenv import load_dotenv
load_dotenv() # loads a .env file from the working directory, if there is one
if "OPENAI_API_KEY" not in os.environ:
try:
# On Google Colab, read the key from Colab Secrets
from google.colab import userdata
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY")
except ImportError:
raise RuntimeError("Set OPENAI_API_KEY in your environment or in a .env file")
Getting structured output¶
Let's modify our basic script for sentiment analysis and demonstrate the use of structured output.
There are two things we need to do. First, we need to modify the prompt to instruct the model to return the output in JSON format and specify the schema.
text_message = "The service here is very good!"
system_prompt = "You are an expert on sentiment analysis. Your job is to evaluate the sentiment of the given text message."
user_instruction = f"""
Given the following text message: '{text_message}', please evaluate its sentiment by giving a score in the range of -1 to 1, where -1 means negative and 1 means positive.
Also explain why.
"""
Second, we need to define the schema of the output in the prompt.
The ge and le arguments add a range constraint to the schema, so the model is constrained to return a score between -1 and 1, and Pydantic rejects anything outside that range.
from pydantic import BaseModel, Field
class Sentiment(BaseModel):
score: float = Field(
ge=-1,
le=1,
description="Sentiment score in the range of -1 to 1, where -1 means negative and 1 means positive.",
)
explanation: str = Field(description="Explanation of the sentiment score.")
Now we are ready to query the API.
from openai import OpenAI
client = OpenAI()
response = client.responses.parse(
model="gpt-5.6-luna",
instructions=system_prompt,
input=user_instruction,
text_format=Sentiment,
)
The output of the response will be automatically parsed into the Pydantic model we defined.
You can access the parsed output by calling response.output_parsed.
parsed_output = response.output_parsed
# Print the result as a dictionary
print(parsed_output.model_dump())
# You can get the score and explanation directly
print(f"Score: {parsed_output.score}")
print(f"Explanation: {parsed_output.explanation}")
{'score': 0.95, 'explanation': 'The message expresses strong positive sentiment, praising the service as “very good.”'}
Score: 0.95
Explanation: The message expresses strong positive sentiment, praising the service as “very good.”
Alternative: provide a JSON schema directly¶
Alternatively, you can also use the JSON schema to get the output as a string and parse it yourself. Note that the API has some requirements on the schema. I would suggest trying it out in the Playground first.
sentiment_json_schema = {
"type": "object",
"title": "Sentiment",
"required": ["score", "explanation"],
"properties": {
"score": {
"type": "number",
"title": "Score",
"minimum": -1,
"maximum": 1,
"description": "Sentiment score in the range of -1 to 1, where -1 means negative and 1 means positive.",
},
"explanation": {
"type": "string",
"title": "Explanation",
"description": "Explanation of the sentiment score.",
},
},
"additionalProperties": False,
}
response = client.responses.parse(
model="gpt-5.6-luna",
instructions=system_prompt,
input=user_instruction,
text={
"format": {
"type": "json_schema",
"name": "sentiment",
"strict": True,
"schema": sentiment_json_schema,
}
},
)
Note that the output won't be parsed automatically this time; you parse the JSON string yourself.
import json
text_output = response.output_text
print(text_output)
parsed_output = json.loads(text_output)
print(f"Score: {parsed_output['score']}")
print(f"Explanation: {parsed_output['explanation']}")
{"score":0.95,"explanation":"The message expresses strong positive sentiment, praising the quality of the service as “very good.”"}
Score: 0.95
Explanation: The message expresses strong positive sentiment, praising the quality of the service as “very good.”
Additional tips¶
If you are using the API from a provider that doesn't support structured output, you can still use the JSON mode to get a JSON string and parse it yourself.
A particular useful tool I found is json_repair, which can repair invalid JSON strings.
With a valid JSON string, you could do so by using the json module in Python to parse the output and check each field in the schema yourself.
But I suggest using pydantic for this purpose.