Vergleich strukturierter Ausgaben bei führenden LLM-Anbietern – OpenAI, Gemini, Anthropic, Mistral und AWS Bedrock
„Sich leicht unterscheidende APIs erfordern einen besonderen Ansatz.“
Hier ist ein direkter Vergleich der Unterstützung für strukturierte Ausgabe (verlässliche Rückgabe von JSON) bei populären LLM-Anbietern, ergänzt um minimale Python-Beispiele.

Wir haben bereits untersucht, wie man strukturierte Ausgabe von einem auf Ollama gehosteten LLM anfordert. Sobald JSON über die Leitung zurückkommt, erläutert Validierung der strukturierten LLM-Ausgabe in Python, die standhält, den Prozess des Parsens, Pydantic-Checks, Wiederholungsversuchen (Retries) und Tests in Ihrer Service-Schicht. Hierüber hinaus prüfen wir, wie dieselbe Anforderung bei anderen Anbietern gestellt wird.
TL;DR Matrix
| Anbieter | Nativer „JSON-Modus“ | Durchsetzung des JSON-Schemas | Typischer Parameter | Anmerkungen |
|---|---|---|---|---|
| OpenAI | Ja | Ja (Erstkategorie) | response_format={"type":"json_schema", ...} |
Funktioniert über die Responses API oder Chat Completions; ermöglicht auch Function Calling. |
| Google Gemini | Ja | Ja (Erstkategorie) | response_schema= + response_mime_type="application/json" |
Gibt streng validiertes JSON zurück, wenn ein Schema gesetzt ist. |
| Anthropic (Claude) | Indirekt | Ja (über Tool Use mit JSON-Schema) | tools=[{input_schema=...}] + tool_choice |
Erzwingt, dass das Modell Ihr schema-definiertes Tool „aufruft“; liefert Argumente in der Schema-Struktur. |
| Mistral | Ja | Teilweise (nur JSON; kein serverseitiges Schema) | response_format={"type":"json_object"} |
Stellt JSON sicher, die Validierung gegen Ihr Schema erfolgt jedoch clientseitig. |
| AWS Bedrock (Plattform) | Je nach Modell | Ja (über Tool/Converse-Schema) | toolConfig.tools[].toolSpec.inputSchema |
Die Converse API von Bedrock validiert Tool-Eingaben gegen ein JSON-Schema. |
Strukturierte LLM-Ausgabe – Allgemeine Informationen
Strukturierte LLM-Ausgabe bezieht sich auf die Fähigkeit großer Sprachmodelle (LLMs), Antworten zu generieren, die strikt einem vordefinierten, spezifischen Format oder einer Struktur folgen, anstatt freien Text zu produzieren. Diese strukturierte Ausgabe kann Formate wie JSON, XML, Tabellen oder Templates annehmen, was die Daten maschinenlesbar, konsistent und leicht für Software in verschiedenen Anwendungen parsebar macht.
Strukturierte Ausgaben unterscheiden sich von traditionellen LLM-Ausgaben, die typischerweise offenen, natürlichen Text generieren. Stattdessen erzwingen strukturierte Ausgaben ein Schema oder Format, wie z. B. JSON-Objekte mit definierten Schlüsseln und Wertetypen oder spezifische Klassen in der Ausgabe (z. B. Multiple-Choice-Antworten, Sentiment-Klassen oder Datenbankzeilenformate). Dieser Ansatz verbessert die Zuverlässigkeit, reduziert Fehler und Halluzinationen und vereinfacht die Integration in Systeme wie Datenbanken, APIs oder Workflows.
Die Generierung strukturierten Outputs in LLMs beinhaltet oft Techniken wie:
- Das Festlegen detaillierter Prompt-Anweisungen, um das Modell zur Ausgabe im gewünschten Format zu führen.
- Die Verwendung von Validierungs- und Parsing-Tools wie Pydantic in Python, um sicherzustellen, dass die Ausgabe dem Schema entspricht.
- Gelegentliches Erzwingen von Decodierungseinschränkungen basierend auf Grammatik oder endlichen Automaten, um die Token-Ebene-Konformität mit dem Format sicherzustellen.
Vorteile strukturierten LLM-Outputs umfassen:
- Maschinenlesbarkeit und einfache Integration.
- Reduzierte Variabilität und Fehler.
- Verbesserte Vorhersagbarkeit und Verifizierbarkeit für Aufgaben, die konsistente Datenformate erfordern.
Herausforderungen beinhalten das Entwerfen effektiver Schemata, die Handhabung komplexer verschachtelter Daten und potenzielle Einschränkungen in den Reasoning-Fähigkeiten im Vergleich zur Generierung freien Texts.
Insgesamt ermöglicht strukturierte Ausgabe LLMs, in Anwendungen nützlicher zu sein, die präzise, formatierte Daten erfordern, anstatt ausschließlich menschenlesbaren Text.
Beispiele für strukturierte Ausgabe in Python
Alle Snippets extrahieren Event-Informationen als JSON: {title, date, location}. Passen Sie Schlüssel/Modelle nach Belieben an.
1) OpenAI — JSON Schema (strikt)
from openai import OpenAI
import json
client = OpenAI()
schema = {
"name": "Event",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string", "description": "YYYY-MM-DD"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
},
"strict": True
}
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}
],
response_format={"type": "json_schema", "json_schema": schema},
)
data = json.loads(resp.choices[0].message.content)
print(data)
OpenAIs Feature Structured Outputs erzwingt dieses Schema auf der Serverseite.
2) Google Gemini — Response Schema + JSON MIME
import google.generativeai as genai
from google.genai import types
# Konfigurieren Sie mit Ihrem API-Schlüssel
# genai.configure(api_key="your-api-key")
schema = types.Schema(
type=types.Type.OBJECT,
properties={
"title": types.Schema(type=types.Type.STRING),
"date": types.Schema(type=types.Type.STRING),
"location": types.Schema(type=types.Type.STRING),
},
required=["title", "date", "location"],
additional_properties=False,
)
resp = genai.generate_content(
model="gemini-2.0-flash",
contents="Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'",
generation_config=genai.GenerationConfig(
response_mime_type="application/json",
response_schema=schema,
),
)
print(resp.text) # bereits valides JSON gemäß Schema
Gemini wird striktes JSON zurückgeben, das dem response_schema entspricht.
3) Anthropic (Claude) — Tool Use mit JSON-Schema
from anthropic import Anthropic
import json
client = Anthropic()
tool = {
"name": "extract_event",
"description": "Return event details.",
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
}
}
msg = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=256,
tools=[tool],
tool_choice={"type": "tool", "name": "extract_event"}, # Schema erzwingen
messages=[{"role": "user", "content":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
)
# Claude wird das Tool „aufrufen“; holen Sie sich die Argumente (die Ihrem Schema entsprechen)
tool_use = next(b for b in msg.content if b.type == "tool_use")
print(json.dumps(tool_use.input, indent=2))
Claude verfügt nicht über einen generischen „JSON-Modus“-Schalter; stattdessen gibt Ihnen Tool Use mit einem input_schema validierte, schema-geformte Argumente (und Sie können dessen Nutzung erzwingen).
4) Mistral — JSON-Modus (Validierung clientseitig)
from mistralai import Mistral
import json
client = Mistral()
resp = client.chat.complete(
model="mistral-large-latest",
messages=[{"role":"user","content":
"Return JSON with keys title, date (YYYY-MM-DD), location for: "
"'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}],
response_format={"type": "json_object"} # garantiert valides JSON
)
data = json.loads(resp.choices[0].message.content)
print(data)
# Tipp: Validieren Sie `data` lokal gegen Ihr Pydantic-/JSON-Schema.
Mistrals json_object erzwingt die JSON-Struktur (nicht Ihr exaktes Schema) – validieren Sie clientseitig.
5) AWS Bedrock — Converse API Tool-Schema (modellagnostisch)
import boto3, json
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"
tools = [{
"toolSpec": {
"name": "extract_event",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title","date","location"],
"additionalProperties": False
}
}
}
}]
resp = bedrock.converse(
modelId=model_id,
toolConfig={"tools": tools},
toolChoice={"tool": {"name": "extract_event"}}, # Schema erzwingen
messages=[{"role":"user","content":[{"text":
"Extract the event from: 'PyData Sydney is on 2025-11-03 at Darling Harbour.'"}]}],
)
# Hole toolUse-Inhalt
tool_use = next(
c["toolUse"] for c in resp["output"]["message"]["content"] if "toolUse" in c
)
print(json.dumps(tool_use["input"], indent=2))
Bedrock validiert Tool-Eingaben gegen Ihr JSON-Schema und viele gehostete Modelle (z. B. Claude) unterstützen dies über Converse.
Praktische Anleitung und Validierung
- Wenn Sie die stärksten serverseitigen Garantien wünschen: OpenAI Structured Outputs oder Gemini Response Schema.
- Wenn Sie bereits Claude/Bedrock nutzen: Definieren Sie ein Tool mit einem JSON-Schema und erzwingen Sie dessen Nutzung; lesen Sie die Argumente des Tools als Ihr typisiertes Objekt.
- Wenn Sie Mistral nutzen: Aktivieren Sie
json_objectund validieren Sie lokal (z. B. mit Pydantic).
Validierungsmuster (funktioniert für alle)
from pydantic import BaseModel, ValidationError
class Event(BaseModel):
title: str
date: str
location: str
try:
event = Event.model_validate(data) # `data` von beliebigem Anbieter
except ValidationError as e:
# behandeln / wiederholen / Modell bitten, mit e.errors() zu korrigieren
print(e)
Nützliche Links
- https://platform.openai.com/docs/guides/structured-outputs
- https://ai.google.dev/gemini-api/docs/structured-output
- https://docs.mistral.ai/capabilities/structured-output/json_mode/
- https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use
- https://github.com/aws-samples/anthropic-on-aws/blob/main/complex-schema-tool-use/README.md
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
- Wie man strukturierte Ausgabe vom auf Ollama gehosteten LLM anfordert
- Python Cheatsheet
- AWS SAM + AWS SQS + Python PowerTools
- AWS Lambda Performance-Vergleich: JavaScript vs. Python vs. Golang