
In veel AI toepassingen hebben we betrouwbare, machine-leesbare output nodig in plaats van vrije tekst.
Met structured outputs laten laat je als AI Engineer het AI model JSON of objecten teruggeven die een vast schema volgen.
Dit maakt koppeling met andere systemen eenvoudiger en zorgt voor automatische validatie.
In dit notebook behandelen we het volgende:
- Waarom structured outputs?
- Voorbeeld zonder structured output
- Hoe gebruik ik structured outputs? (voorbeeld Python & OpenAI)
- Aanpassen system prompt
- Omzetten JSON string naar dictionary
- Afdwingen van datatype met parameter
response_format - Herhaaldelijk gebruik
In onderstaande code doen we het volgende: het aanmaken van een OpenAI client voor de OpenIA API verbinding. Als je mee wilt doen dien je een eigen API key aan te maken.
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv("api_key.env")
OPENAI_API_KEY = os.getenv("OPEN_AI_API_KEY")
print(f"Length API key: {len(OPENAI_API_KEY)}")
print(f"Last characters: ...{OPENAI_API_KEY[-30:]}")
client = OpenAI(api_key=OPENAI_API_KEY, base_url="https://api.openai.com/v1/")
print(client)Length API key: 164
Last characters: ...xtvqYjTUfLU8_RN4xfoZMy0nQDfCkA
1. Waarom structured outputs?
In veel AI-toepassingen is vrije tekst niet voldoende.
Zodra de output verder verwerkt moet worden in code, door AI agents, pipelines of andere systemen, heb je betrouwbare en machine-leesbare output nodig.
Standaard geven taalmodellen tekst terug die bedoeld is voor mensen. Dat is flexibel en leesbaar, maar moeilijk te gebruiken in software. Kleine variaties in formulering, hoofdletters of volgorde zorgen er al voor dat parsing fout gaat of dat applicaties onverwacht gedrag vertonen.
Met structured outputs dwing je een vast outputformaat af, meestal JSON met vooraf bepaalde sleutels en waarden. Hierdoor wordt de output voorspelbaar en eenvoudig te valideren. De AI-output kan dan behandeld worden als gewone data, in plaats van als tekst die eerst geïnterpreteerd moet worden.
Dit is vooral belangrijk in productie-omgevingen, waar AI-output onderdeel is van een groter geheel. Denk aan automatische classificatie, data-extractie of het aansturen van andere services. Zonder structured output ontstaat er snel fragiele logica die alleen werkt zolang het model exact hetzelfde blijft antwoorden.
In de rest van dit blog laten we zien hoe structured output dit probleem oplost en hoe je dit praktisch toepast met de OpenAI API.
2. Voorbeeld zonder structured outputs
Standaard krijg je vrije tekst terug als antwoord.
Dit is niet altijd handig om vervolgens vanuit code verder te kunnen gebruiken.
We bekijken een voorbeeld waarbij we klantenservice-tickets willen classificeren op verschillende gebieden.
In onderstaande code doen we het volgende:
- Aanmaken van een system prompt.
- Aanmaken van een ticket tekst.
- Genereren van een antwoord.
system_prompt = "You are a classifier for customer service tickets: category, issue_type, priority, department."
ticket_text = "My order from last week still hasn’t been delivered, even though it said 3-day shipping."
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": ticket_text,
},
],
temperature=.2,
)
answer = response.choices[0].message.content
print(answer)Category: Order Inquiry
Issue Type: Shipping Delay
Priority: High
Department: Shipping & DeliveryHet antwoord is nu dus vrije tekst.
Je kunt hier nu niet direct/gemakkelijk de waarde van een categorie uit ophalen, bijvoorbeeld:
answer["Category"]Output:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 1
----> 1 answer["Category"]
TypeError: string indices must be integers, not 'str'Dit kunnen we oplossen met structured output.

3. Hoe gebruik ik structured outputs? (voorbeeld Python & OpenAI)
Door een prompt aan te passen kun je structured output verkrijgen.
3.1. Aanpassen system prompt
Door het system promt aan te passen dwingen we af dat de output in JSON formaat moet zijn.
In onderstaande code doen we het volgende:
- Doorvoeren van aanpassingen in het system prompt.
- Hierin vragen we uitdrukkelijk om JSON formaat.
system_prompt = (
"You are a classifier for customer service tickets. "
"Return ONLY valid JSON with keys: category, issue_type, priority, department. "
"Use concise lowercase strings. Priority is one of: low, normal, high."
)
ticket_text = "My order from last week still hasn’t been delivered, even though it said 3-day shipping."
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": ticket_text,
},
],
temperature=.2,
)
answer = response.choices[0].message.content
print(answer){
"category": "order",
"issue_type": "delivery delay",
"priority": "high",
"department": "shipping"
}Dit ziet er goed gestructureerd uit, als een JSON object.
Echter, het is nog altijd een string:
type(answer)str3.2. Omzetten JSON string naar dictionary
We moeten de JSON string omzetten naar dictionary formaat.
In onderstaande code doen we het volgende:
- Importeren module
json. - Omzetten van de JSON string naar dictionary met
json.loads(). - Bekijken het datatype en halen een waarde op.
import json
data = json.loads(answer)
print(type(data))
data["category"]
'order' Je ziet nu dat we gestructureerde output hebben die gemakkelijk verder verwerkt kan worden.
3.3. Afdwingen van datatype met parameter response_format
Om er zeker van te zijn dat het output-formaat JSON is, kunnen we gebruik maken van API parameter response_format.
In onderstaande code doen we het volgende:
- Toevoegen van
response_format={"type": "json_object"},.
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": ticket_text,
},
],
temperature=.2,
response_format={"type": "json_object"},
)
answer = response.choices[0].message.content
print(answer){
"category": "order",
"issue_type": "delivery delay",
"priority": "high",
"department": "shipping"
}We zien wederom een goed resultaat.
3.4. Herhaaldelijk gebruik
Het gebruik van structured output kan vooral ook handig zijn als iets meerdere keren moet doen.
Bijvoorbeeld het classificeren van meerdere klantenservice-tickets.
In onderstaande code doen we het volgende:
- Aanmaken van een lijst met tickets.
- Aanmaken van een functie voor het classificeren van een ticket.
- Toepassen van de functie, en met list comprehension de resultaten in een list bewaren.
import json
system_instructions = (
"You are a classifier for customer service tickets. "
"Return ONLY valid JSON with keys: category, issue_type, priority, department. "
"Use concise lowercase strings. Priority is one of: low, normal, high."
)
ticket_texts = [
"My order from last week still hasn’t been delivered, even though it said 3-day shipping.",
"The product I received is defective, the screen won’t turn on.",
"I would like to upgrade my subscription to the Premium plan.",
"The invoice I got is incorrect, it shows a higher amount than expected.",
"I forgot my password and can’t log into my account anymore."
]
def classify_ticket(ticket_text: str) -> dict:
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_instructions},
{"role": "user", "content": ticket_text},
],
temperature=0.2,
response_format={"type": "json_object"},
)
json_text = resp.choices[0].message.content
return json.loads(json_text)
results = [classify_ticket(ticket_text) for ticket_text in ticket_texts]
results[{'category': 'order',
'issue_type': 'delivery delay',
'priority': 'high',
'department': 'shipping'},
{'category': 'product issue',
'issue_type': 'defective item',
'priority': 'high',
'department': 'support'},
{'category': 'subscription',
'issue_type': 'upgrade request',
'priority': 'normal',
'department': 'billing'},
{'category': 'billing',
'issue_type': 'invoice discrepancy',
'priority': 'normal',
'department': 'finance'},
{'category': 'account',
'issue_type': 'password reset',
'priority': 'normal',
'department': 'support'}]We zien nu dat we een list hebben met daarin voor elk ticket de classificaties.
Dit kunnen we eenvoudig omzetten in een Pandas DataFrame:
import pandas as pd
df = pd.DataFrame(results)
df["ticket_text"] = ticket_texts
df| category | issue_type | priority | department | ticket_text | |
|---|---|---|---|---|---|
| 0 | order | delivery delay | high | shipping | My order from last week still hasn’t been deli... |
| 1 | product issue | defective item | high | support | The product I received is defective, the scree... |
| 2 | subscription | upgrade request | normal | billing | I would like to upgrade my subscription to the... |
| 3 | billing | invoice discrepancy | normal | finance | The invoice I got is incorrect, it shows a hig... |
| 4 | account | password reset | normal | support | I forgot my password and can’t log into my acc... |
En we kunnen er bijvoorbeeld ook eenvoudig een grafiek van maken:
df["priority"].value_counts().plot.pie(
title="Distribution of Priority",
ylabel="",
autopct="%.0f%%",
)
Wil je AI expert worden?
Tijdens onze 5-daagse AI Opleiding of 7-daagse AI Engineer Opleiding leer je het hele AI spectrum kennen; van klassieke machine learning modellen tot generative AI met o.a. ChatGPT. Je leert programmeren in Python zodat je op uiteenlopende vlakken aan de slag kunt met AI. Of ben je op zoek naar een introductie in AI? Bekijk dan onze AI cursus basis eens. We bieden ook AI consultancy aan op allerlei thema’s.










