Zum Hauptinhalt springen
Lektion 8 von 12 · Strukturierte Ausgabe: JSON und Schemata

Die Verwendung von client.chat.parse()

Lektion 8 von 12 Aktualisiert am 2. November 2026 Entwickler
Auf dieser Seite
  1. Die parse()-Methode: Das Herzstück für benutzerdefinierte strukturierte Ausgaben
  2. Ein vollständiger End-to-End-Aufruf
  3. Der automatisch angehängte Systemprompt
  4. .parsed vs .content: Zwei getrennte Verwendungszwecke
  5. Was noch fehlschlagen kann
  6. Kernaussagen

Die parse()-Methode: Das Herzstück für benutzerdefinierte strukturierte Ausgaben

client.chat.parse() ist das strukturierte Äquivalent zu client.chat.complete(). Anstatt freien Text oder rohes JSON zurückzugeben, das Sie selbst parsen müssen, liefert es ein typisiertes Objekt, das direkt Ihrem Pydantic-Modell entspricht. Der Unterschied mag auf den ersten Blick kosmetisch wirken, eliminiert aber tatsächlich eine gesamte Schicht an Code.

Der Kontrast ist am deutlichsten im direkten Vergleich. Mit complete() erhalten Sie einen String, den Sie selbst transformieren müssen. Mit parse() liegt das Objekt sofort einsatzbereit vor, während das rohe JSON weiterhin verfügbar bleibt, falls Sie es benötigen.

# JSON Mode — complete() gibt JSON-Text zurück
response = client.chat.complete(
    model="mistral-large-latest",
    messages=messages,
    response_format={"type": "json_object"}
)
raw_json: str = response.choices[0].message.content
data = json.loads(raw_json)  # Manuelles Parsen

# Custom — parse() gibt ein typisiertes Objekt zurück
response = client.chat.parse(
    model="mistral-large-latest",
    messages=messages,
    response_format=MonSchema
)
obj: MonSchema = response.choices[0].message.parsed  # Pydantic-Objekt
raw_json: str = response.choices[0].message.content   # Roher JSON-Text ebenfalls verfügbar

Der Unterschied liegt im Zugriff auf .parsed: ein direkt nutzbares Pydantic-Objekt mit IDE-Autovervollständigung und Typvalidierung.

Ein vollständiger End-to-End-Aufruf

Das folgende Beispiel führt die fünf Schritte eines echten Extraktionsvorgangs durch: Definition des Schemas mit klaren Beschreibungen, Erstellung des Clients, Aufruf von parse(), Nutzung des zurückgegebenen Objekts und Abruf der JSON-Darstellung, falls erforderlich.

from mistralai.client import Mistral
from pydantic import BaseModel, Field
from typing import Optional

# 1. Schema definieren
class BookInfo(BaseModel):
    title: str = Field(description="Titel des Buches")
    authors: list[str] = Field(description="Liste der Autoren")
    year: Optional[int] = Field(default=None, description="Erscheinungsjahr")
    genre: str = Field(description="Hauptliterarische Gattung")
    summary: str = Field(description="Zusammenfassung in 2-3 Sätzen")

# 2. Client erstellen
client = Mistral(api_key="your-api-key")

# 3. parse() aufrufen
response = client.chat.parse(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            "content": "Sie sind ein erfahrener Bibliothekar. Extrahieren Sie Informationen über das erwähnte Buch."
        },
        {
            "role": "user",
            "content": "Ich habe '1984' von George Orwell geliebt. Es ist ein dystopischer Roman, der 1949 veröffentlicht wurde und eine totalitäre Gesellschaft unter ständiger Überwachung beschreibt."
        }
    ],
    temperature=0
)

# 4. Das geparselte Objekt nutzen
book = response.choices[0].message.parsed
print(f"Titel: {book.title}")
print(f"Autoren: {', '.join(book.authors)}")
print(f"Jahr: {book.year}")
print(f"Gattung: {book.genre}")
print(f"Zusammenfassung: {book.summary}")

# 5. Der rohe JSON-Text ist ebenfalls verfügbar
raw = response.choices[0].message.content
print(f"\nRoh-JSON: {raw}")

Beachten Sie, was der Systemprompt nicht enthält: keine Beschreibung des erwarteten Formats.

Der automatisch angehängte Systemprompt

Die SDK-Implementierung übernimmt dies. Wenn Sie parse() verwenden, fügt Mistral automatisch einen Präfix zum Systemprompt hinzu:

Ihr Output sollte eine Instanz eines JSON-Objekts sein, das diesem Schema folgt: { ... }

Dieser Präfix enthält das JSON-Schema, das aus Ihrem Pydantic-Modell generiert wurde. Sie müssen das Format in Ihrem Prompt nicht beschreiben – das SDK erledigt dies für Sie. Dies befreit Ihre Systemnachricht dafür, was sie am besten kann: Geschäfts-Kontext zu liefern und Qualitätsanforderungen festzulegen, wie z. B. Präzision bei Beträgen oder das Vorgehen bei fehlenden Daten.

response = client.chat.parse(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            # Keine Notwendigkeit, das JSON-Format zu beschreiben – das ist automatisch erledigt
            # Konzentrieren Sie sich auf KONTEXT und QUALITÄT
            "content": """Sie sind ein erfahrener Finanzanalyst.
Seien Sie bei Beträgen und Prozentsätzen präzise.
Wenn Daten im Text nicht verfügbar sind, verwenden Sie null."""
        },
        {"role": "user", "content": report_text}
    ],
    response_format=FinancialReport
)

.parsed vs .content: Zwei getrennte Verwendungszwecke

Das typisierte Objekt, über .parsed zugänglich, ist das, das Sie in Ihrer Anwendungslogik manipulieren. Es stellt Attribute mit ihren Typen bereit, unterstützt Iterationen, wandelt sich mit model_dump() in ein Wörterbuch um und serialisiert sich mit model_dump_json().

book = response.choices[0].message.parsed

# Typisierter Zugriff mit IDE-Autovervollständigung
print(book.title)        # str
print(book.authors)      # list[str]
print(book.year)         # Optional[int]

# Iteration über Listen
for author in book.authors:
    print(f"  - {author}")

# Umwandlung in ein Wörterbuch
book_dict = book.model_dump()

# Serialisierung in JSON
book_json = book.model_dump_json(indent=2)

Rohes JSON ist andererseits an Systemgrenzen weiterhin nützlich: für Protokollierung, Datenbank-Speicherung oder das Weiterleiten der Antwort unverändert an eine andere API.

raw = response.choices[0].message.content

# Dies ist ein JSON-String, der nützlich ist für:
# - Protokollierung
# - Datenbank-Speicherung
# - Weiterleitung an eine andere API

import json
data = json.loads(raw)

Was noch fehlschlagen kann

Ein garantiertes Schema macht Ihren Code nicht immun gegen alles. Die API kann Netzwerk- oder Service-Fehler zurückgeben, und .parsed kann None sein, wenn die Antwort unterbrochen wurde. Das folgende Muster behandelt beide Fälle separat – SDKError für die API und ValidationError für das Schema – und wiederholt den Vorgang nur eine begrenzte Anzahl von Malen.

from mistralai.client import Mistral
from mistralai.client.errors import SDKError
from pydantic import ValidationError

client = Mistral(api_key="your-api-key")

def extract_structured(text: str, schema, max_retries: int = 2):
    """Strukturierte Extraktion mit Fehlerbehandlung."""
    for attempt in range(max_retries + 1):
        try:
            response = client.chat.parse(
                model="mistral-large-latest",
                messages=[
                    {"role": "system", "content": "Extrahieren Sie die angeforderten Informationen."},
                    {"role": "user", "content": text}
                ],
                response_format=schema,
                temperature=0,
                max_tokens=1024
            )

            parsed = response.choices[0].message.parsed
            if parsed is None:
                raise ValueError("Parsed ist None – die Antwort wurde möglicherweise abgeschnitten")

            return parsed

        except SDKError as e:
            print(f"API-Fehler (Versuch {attempt + 1}): {e}")
            if attempt == max_retries:
                raise
        except ValidationError as e:
            print(f"Validierungsfehler (Versuch {attempt + 1}): {e}")
            if attempt == max_retries:
                raise

# Nutzung
try:
    book = extract_structured("'Der kleine Prinz' von Saint-Exupéry, 1943", BookInfo)
    print(f"Extrahiert: {book.title} von {', '.join(book.authors)}")
except Exception as e:
    print(f"Endgültiger Fehler: {e}")

Die Reflex, die man mit dem JSON-Mode beobachtet, gilt hier ebenfalls: Eine Antwort, die durch max_tokens abgeschnitten wird, erzeugt ein unvollständiges oder null-Objekt, und finish_reason informiert Sie hierüber, bevor Sie es weiter unten in der Pipeline entdecken.

response = client.chat.parse(
    model="mistral-large-latest",
    messages=messages,
    response_format=MonSchema,
    max_tokens=256
)

if response.choices[0].finish_reason != "stop":
    print(f"Warnung: finish_reason = {response.choices[0].finish_reason}")
    # "length" = abgeschnittene Antwort, max_tokens erhöhen

Kernaussagen

  • client.chat.parse() ersetzt client.chat.complete() für benutzerdefinierte strukturierte Ausgaben
  • .parsed gibt ein typisiertes Pydantic-Objekt zurück; .content gibt rohes JSON zurück
  • Das Schema wird automatisch dem Systemprompt hinzugefügt – keine Notwendigkeit, das Format zu beschreiben
  • Prüfen Sie immer finish_reason und behandeln Sie SDKError- und ValidationError-Fehler
  • Verwenden Sie model_dump(), um das geparselte Objekt in ein Python-Wörterbuch umzuwandeln