Zum Inhalt springen
Projekt besprechen

20. Oktober 2026

Structured Output ist keine Garantie: Nach dem Parsen selbst validieren

AILLMEngineering

Was der Schema-Modus tatsächlich absichert

LLM Structured Output und ein JSON Schema LLM lösen ein konkretes Problem: Das Modell soll Daten in einer vorhersehbaren Struktur zurückgeben. Statt frei formuliertem Text erhält die Anwendung beispielsweise ein Objekt mit Feldern für Datum, Status und Referenz-ID. Das reduziert Fehler beim Parsen und vereinfacht die Weiterverarbeitung.

Das ist wertvoll, aber die Zusage ist begrenzt: Das Ergebnis passt zur Form. Ob die enthaltenen Werte fachlich korrekt, aktuell oder im eigenen System überhaupt gültig sind, folgt daraus nicht.

Ein Feld vom Typ String kann jede Zeichenkette enthalten, die der erwarteten Form entspricht. Ein Datum kann syntaktisch korrekt sein und dennoch in der Zukunft liegen. Eine ID kann das erwartete Muster haben, aber in der Datenbank nicht existieren. Ein Betrag kann eine Zahl sein, die gegen eine Preisregel oder einen zulässigen Wertebereich verstößt.

Schema-konform, aber fachlich falsch

Angenommen, ein Modell extrahiert eine Bestelländerung aus einer Nachricht. Das Ausgabeformat verlangt eine Bestell-ID und ein gewünschtes Lieferdatum.

{
  "orderId": "ORD-4711",
  "deliveryDate": "2032-05-14"
}

Diese Antwort kann vollständig schema-konform sein: Beide Felder sind vorhanden, beide sind Strings, und das Datum hat ein plausibles Format. Trotzdem bleiben mehrere Fragen offen:

  • Gibt es die Bestellung ORD-4711?
  • Darf diese Bestellung überhaupt geändert werden?
  • Ist das Lieferdatum für diesen Vorgang zulässig?
  • Liegt es innerhalb des erlaubten Zeitraums?
  • Wurde aus der ursprünglichen Nachricht vielleicht ein anderes Datum abgeleitet?

JSON Schema kann einige einfache Regeln ausdrücken, etwa Pflichtfelder, Typen oder Muster. Die Bedeutung der Daten kennt es jedoch nicht automatisch. Auch das LLM kennt weder den aktuellen Zustand des eigenen Systems noch interne Geschäftsregeln, sofern diese nicht zuverlässig als Kontext verfügbar sind.

LLM Validierung beginnt nach dem Parsen

Die Anwendung sollte eine Antwort deshalb wie externen, nicht vertrauenswürdigen Input behandeln. Der Ablauf besteht mindestens aus drei Ebenen:

  1. Struktur prüfen: Lässt sich die Antwort parsen und entspricht sie dem erwarteten Schema?
  2. Fachliche Werte prüfen: Liegen Daten, Mengen, Statuswerte und Wertebereiche im erlaubten Rahmen?
  3. Referenzen und Geschäftsregeln prüfen: Existieren IDs? Sind Zustandsübergänge erlaubt? Passt die Aktion zum angemeldeten Nutzer und zum Vorgang?

Ein möglicher TypeScript-Ausschnitt zeigt die Trennung. Die konkrete Implementierung der Datenabfrage hängt vom jeweiligen System ab.

type ChangeRequest = {
  orderId: string;
  deliveryDate: string;
};
 
async function validateChangeRequest(input: ChangeRequest) {
  const date = new Date(input.deliveryDate);
 
  if (Number.isNaN(date.getTime())) {
    return "deliveryDate ist kein gültiges Datum";
  }
 
  if (date <= new Date()) {
    return "deliveryDate muss in der Zukunft liegen";
  }
 
  const orderExists = await orderRepository.exists(input.orderId);
  if (!orderExists) {
    return "orderId verweist auf keine vorhandene Bestellung";
  }
 
  const changeAllowed = await orderRepository.canChangeDeliveryDate(input.orderId);
  if (!changeAllowed) {
    return "Lieferdatum darf für diese Bestellung nicht geändert werden";
  }
 
  return null;
}

Wichtig ist nicht die exakte Rückgabeform, sondern die Zuständigkeit: Das LLM erzeugt einen Vorschlag. Die Anwendung entscheidet, ob dieser Vorschlag gültig und ausführbar ist.

Den Fehlerpfad vorab festlegen

Wenn die LLM Validierung scheitert, darf die Pipeline nicht stillschweigend mit den Daten weiterlaufen. Vor der Integration sollte klar sein, welcher Pfad dann gilt:

  • Die Anfrage wird mit einer verständlichen Fehlermeldung abgelehnt.
  • Die Anwendung fordert fehlende oder widersprüchliche Angaben beim Nutzer nach.
  • Das Modell erhält einen kontrollierten zweiten Versuch.
  • Ein Vorgang wird zur manuellen Prüfung markiert.

Welche Option sinnvoll ist, hängt von Risiko und Kontext ab. Eine unverbindliche Zusammenfassung kann anders behandelt werden als eine Bestellung, Berechtigung oder Datenänderung. Entscheidend ist, dass keine ungültige Modellantwort direkt eine fachliche Aktion auslöst.

Retry mit konkreter Rückmeldung

Ein LLM Retry kann sinnvoll sein, wenn die Antwort strukturell korrekt, aber korrigierbar unvollständig oder widersprüchlich ist. Der Retry braucht jedoch präzises Feedback. Statt nur erneut nach einer Antwort zu fragen, sollte die Anwendung den Validierungsfehler nennen.

const feedback = "Validierung fehlgeschlagen: orderId verweist auf keine vorhandene Bestellung. Extrahiere nur eine ID, die in den bereitgestellten Daten vorkommt.";

Damit erhält das Modell eine konkrete Korrekturvorgabe. Auch ein Retry braucht Grenzen: Eine feste Obergrenze verhindert Schleifen, unnötige Kosten und schwer nachvollziehbares Verhalten. Scheitert auch der letzte Versuch, greift der zuvor definierte Fehlerpfad.

Structured Output ist damit ein Baustein für robuste Schnittstellen, keine fachliche Absicherung. JSON Schema schützt die Form, während Validierung, Fehlerbehandlung und begrenzter LLM Retry die Anwendung vor plausibel aussehenden, aber falschen Daten schützen.

Prüft eure LLM-Pipeline: Validiert ihr nach dem Parsen noch selbst?