Strukturierter Output-Vergleich bei beliebten LLM-Anbietern - OpenAI, Gemini, Anthropic, Mistral und AWS Bedrock

Leicht unterschiedliche APIs erfordern einen speziellen Ansatz.

Inhaltsverzeichnis

Hier ist ein Seitenvergleich der Unterstützung für strukturierte Ausgaben (zuverlässige JSON-Rückgabe) bei beliebten LLM-Anbietern, plus minimale Python-Beispiele

farbige Balken stehen

Wir haben bereits untersucht, wie man strukturierte Ausgaben vom auf Ollama gehosteten LLM anfordert. Hier überprüfen wir, wie man dasselbe von anderen Anbietern anfordert.

TL;DR-Matrix

Anbieter Nativer „JSON-Modus“ JSON Schema-Erzwingung Typischer Regler Hinweise
OpenAI Ja Ja (erster Klasse) response_format={"type":"json_schema", ...} Funktioniert über die Responses API oder Chat Completions; kann auch Funktionaufrufe durchführen.
Google Gemini Ja Ja (erster Klasse) response_schema= + response_mime_type="application/json" Gibt streng validiertes JSON zurück, wenn ein Schema festgelegt 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“; ergibt schemaförmige Argumente.
Mistral Ja Teilweise (JSON-only; kein serverseitiges Schema) response_format={"type":"json_object"} Gewährleistet JSON, aber Sie validieren gegen Ihr Schema clientseitig.
AWS Bedrock (Plattform) Variiert je nach Modell Ja (über Tool/Converse-Schema) toolConfig.tools[].toolSpec.inputSchema Bedrocks Converse-API validiert Tool-Eingaben gegen ein JSON-Schema.

LLM-Strukturierte Ausgaben - Allgemeine Informationen

LLM-Strukturierte Ausgaben beziehen sich auf die Fähigkeit großer Sprachmodelle (LLMs), Antworten zu generieren, die streng einem vordefinierten, spezifischen Format oder einer Struktur folgen, anstatt frei formulierten Text zu produzieren. Diese strukturierten Ausgaben können in Formaten wie JSON, XML, Tabellen oder Vorlagen vorliegen und machen die Daten maschinenlesbar, konsistent und einfach für Software parsbar, um sie in verschiedenen Anwendungen zu nutzen.

Strukturierte Ausgaben unterscheiden sich von traditionellen LLM-Ausgaben, die typischerweise offenen, natürlichen Sprachtext generieren. Stattdessen erzwingen strukturierte Ausgaben ein Schema oder Format, wie z. B. JSON-Objekte mit definierten Schlüsseln und Werttypen 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 Erzeugung strukturierter Ausgaben in LLMs umfasst oft Techniken wie:

  • Spezifizierung detaillierter Prompt-Anweisungen, um das Modell anzuleiten, die Ausgabe im gewünschten Format zu produzieren.
  • Verwendung von Validierungs- und Parsing-Tools wie Pydantic in Python, um sicherzustellen, dass die Ausgabe dem Schema entspricht.
  • Manchmal Erzwingung von Decodierungsbeschränkungen basierend auf Grammatik oder endlichen Automaten, um die Token-Ebene-Konformität mit dem Format sicherzustellen.

Vorteile strukturierter LLM-Ausgaben sind:

  • Maschinenlesbarkeit und einfache Integration.
  • Reduzierte Variabilität und Fehler.
  • Verbesserte Vorhersehbarkeit und Überprüfbarkeit für Aufgaben, die konsistente Datenformate erfordern.

Herausforderungen umfassen das Design effektiver Schemata, das Handling komplexer verschachtelter Daten und potenzielle Einschränkungen in den Denkfähigkeiten im Vergleich zur Erzeugung von frei formuliertem Text.

Insgesamt ermöglichen strukturierte Ausgaben LLMs, in Anwendungen nützlicher zu sein, die präzise, formatierte Daten erfordern, anstatt nur menschenlesbaren Text.

Python-Beispiele für strukturierte Ausgaben

Alle Code-Snippets extrahieren Event-Informationen als JSON: {title, date, location}. Ersetzen Sie die Schlüssel/Modelle nach Belieben.

1) OpenAI — JSON-Schema (streng)

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": "Extrahieren Sie das Event aus: 'PyData Sydney findet am 2025-11-03 im Darling Harbour statt.'"}
    ],
    response_format={"type": "json_schema", "json_schema": schema},
)

data = json.loads(resp.choices[0].message.content)
print(data)

OpenAIs Strukturierte Ausgaben-Funktion erzwingt dieses Schema auf 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="Extrahieren Sie das Event aus: 'PyData Sydney findet am 2025-11-03 im Darling Harbour statt.'",
    generation_config=genai.GenerationConfig(
        response_mime_type="application/json",
        response_schema=schema,
    ),
)

print(resp.text)  # bereits gültiges JSON gemäß Schema

Gemini gibt strenges JSON zurück, 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": "Gibt Event-Details zurück.",
    "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":
        "Extrahieren Sie das Event aus: 'PyData Sydney findet am 2025-11-03 im Darling Harbour statt.'"}],
)

# 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 hat keinen generischen „JSON-Modus“-Schalter; stattdessen gibt Tool Use mit einem input_schema Ihnen validierte, schemaförmige Argumente (und Sie können dessen Verwendung erzwingen).


4) Mistral — JSON-Modus (clientseitige Validierung)

from mistralai import Mistral
import json

client = Mistral()

resp = client.chat.complete(
    model="mistral-large-latest",
    messages=[{"role":"user","content":
        "Geben Sie JSON mit den Schlüsseln title, date (YYYY-MM-DD), location für: "
        "'PyData Sydney findet am 2025-11-03 im Darling Harbour statt.'"}],
    response_format={"type": "json_object"}  # garantiert gültiges JSON
)

data = json.loads(resp.choices[0].message.content)
print(data)
# Tipp: Validieren Sie `data` gegen Ihr Pydantic/JSON-Schema lokal.

Mistrals json_object erzwingt JSON-Form (nicht Ihr genaues Schema) — validieren Sie clientseitig.


5) AWS Bedrock — Converse API Tool-Schema (modellunabhängig)

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":
        "Extrahieren Sie das Event aus: 'PyData Sydney findet am 2025-11-03 im Darling Harbour statt.'"}]}],
)

# ToolUse-Inhalt abrufen
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-Strukturierte Ausgaben oder Gemini-Response-Schema.
  • Wenn Sie bereits Claude/Bedrock verwenden: Definieren Sie ein Tool mit einem JSON-Schema und erzwingen Sie dessen Verwendung; lesen Sie die Argumente des Tools als Ihr typisiertes Objekt.
  • Wenn Sie Mistral verwenden: Aktivieren Sie json_object und 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 jedem Anbieter
except ValidationError as e:
    # behandeln / wiederholen / bitten Sie das Modell, mit e.errors() zu reparieren
    print(e)