Zum Hauptinhalt springen
Lektion 15 von 20 · Produktion, Evaluierung und Optimierung

Ihre Prompts evaluieren: Methoden, Grader und der Wechsel zu Promptfoo

Lektion 15 von 20 Aktualisiert am 3. November 2026 Fortgeschritten
Auf dieser Seite
  1. Warum Sie systematisch evaluieren müssen
  2. Erstellen Sie ein Dataset, das Ihrer realen Welt entspricht
  3. Wählen Sie den richtigen Grader
  4. Zusammenstellen der vollständigen Evaluierung
  5. Industrialisieren mit Promptfoo
  6. Kernaussagen

Lektion aktualisiert am 3. November 2026 basierend auf der OpenAI-Dokumentation: temperature und top_p werden nur mit einem Reasoning-Effort von none akzeptiert, während GPT-5.6-Modelle standardmäßig nachdenken (medium). Aufrufe, die diese Parameter setzen, müssen daher reasoning={"effort": "none"} (Responses API) oder reasoning_effort="none" (Chat Completions) angeben. Quellen: Using GPT-6 · GPT-5.6 Terra.

Aktualisierung vom 2. November 2026 — Evals-Plattform. OpenAI hat das Ende ihrer Evals-Plattform angekündigt: Bestehende Evaluierungen waren seit dem 31. Oktober 2026 schreibgeschützt, und das Dashboard sowie die API werden am 30. November 2026 geschlossen, einschließlich der Grader. OpenAI hat einen Migrationsleitfaden zu Promptfoo veröffentlicht. Die Evaluierungsprinzipien in dieser Lektion bleiben gültig; nur das Werkzeug ändert sich.

Warum Sie systematisch evaluieren müssen

Sie können nicht verbessern, was Sie nicht messen. Wenn Sie einen Prompt, ein Modell oder einen Parameter ändern, wie wissen Sie dann, dass die Qualität tatsächlich verbessert wurde? Die spontane Methode besteht darin, drei oder vier Beispiele zu testen, die besseren Antworten zu finden und zu deployen. Dies schlägt regelmäßig fehl, da die getesteten Beispiele genau diejenigen sind, die letzte Woche Probleme verursacht haben: Sie messen die Verbesserung dort, wo Sie nach ihr gesucht haben, und übersehen Regressionen, die in bereits funktionierenden Fällen eingeführt wurden.

Evaluierungen (evals) verwandeln diese Intuition in eine objektive Messgröße. Bis 2026 bot OpenAI eine integrierte Plattform dafür an, Evals; sie war seit dem 31. Oktober 2026 schreibgeschützt und schließt am 30. November. OpenAI empfiehlt nun Promptfoo, ein Open-Source-Werkzeug für Evaluierung und Red Teaming. Die gute Nachricht ist, dass beide denselben Bausteinen folgen: Testdaten, Prompts, Modelle und Bewertungskriterien. Was Sie hier in Python-Code lernen, lässt sich direkt übertragen, und der letzte Teil der Lektion zeigt den Wechsel zu Promptfoo.

Drei Konzepte strukturieren den gesamten Prozess. Das Dataset ist eine Menge von Testfällen mit Eingaben und erwarteten Ausgaben: Es ist Ihr Referenzrahmen, das Äquivalent zu einer Unit-Test-Suite. Der Grader ist ein Bewertungskriterium – exakte Übereinstimmung, LLM-as-Judge, Punktzahl –, das entscheidet, ob eine gegebene Antwort gut ist. Der Run ist eine Evaluierungsausführung auf einem Dataset mit einem spezifischen Modell und Prompt; er ist die Einheit, die Sie von einer Version zur nächsten vergleichen.

Erstellen Sie ein Dataset, das Ihrer realen Welt entspricht

Ein Testfall besteht aus einer Eingabe, einer erwarteten Ausgabe und Metadaten. Letztere sind nicht dekorativ: Sie ermöglichen es Ihnen, nachträglich festzustellen, dass eine Gesamtpunktzahl von 87 % einen Zusammenbruch in der Kategorie „Code” maskiert, der durch hervorragende Ergebnisse in Geografie kompensiert wurde. Ohne Kategorie oder Schwierigkeitsgrad haben Sie nur eine aggregierte Zahl, und eine aggregierte Zahl sagt Ihnen nie, wo Sie eingreifen müssen.

import json

# Ein Dataset ist eine Liste von Testfällen
dataset = [
    {
        "input": "Was ist die Hauptstadt von Frankreich?",
        "expected": "Paris",
        "metadata": {"category": "geography", "difficulty": "easy"},
    },
    {
        "input": "Erklären Sie den Satz von Bayes in einem Satz.",
        "expected": "Der Satz von Bayes berechnet die Wahrscheinlichkeit "
                    "eines Ereignisses basierend auf bekannten bedingten Wahrscheinlichkeiten.",
        "metadata": {"category": "mathematics", "difficulty": "medium"},
    },
    {
        "input": "Schreiben Sie eine Python-Funktion, die eine Liste umkehrt.",
        "expected": "def reverse_list(lst): return lst[::-1]",
        "metadata": {"category": "code", "difficulty": "easy"},
    },
]

# Speichern als JSONL
with open("eval_dataset.jsonl", "w") as f:
    for case in dataset:
        f.write(json.dumps(case, ensure_ascii=False) + "\n")

Ein im Büro erfundenes Dataset bewertet Ihre Fantasie, nicht Ihre Anwendung. Ihre Nutzer formulieren ihre Anfragen anders als Sie: Tippfehler, unvollständige Fragen, impliziter Kontext. Die beste Quelle für Testfälle ist daher Ihre eigene Produktionsdaten, sofern ein Mensch die Referenzantworten validiert – sonst frieren Sie aktuelle Fehler als Normalität ein.

import openai
import random

client = openai.OpenAI()

def create_dataset_from_logs(
    production_logs: list[dict],
    sample_size: int = 100,
) -> list[dict]:
    """Erstellt ein Evaluierungsdataset aus Produktionsprotokollen."""
    # Stichprobe
    sample = random.sample(
        production_logs,
        min(sample_size, len(production_logs)),
    )

    dataset = []
    for log in sample:
        dataset.append({
            "input": log["prompt"],
            "expected": log["validated_response"],  # Antwort, die von einem Menschen validiert wurde
            "metadata": {
                "source": "production",
                "date": log["date"],
                "original_model": log["model"],
            },
        })

    return dataset

Wählen Sie den richtigen Grader

Der Grader für exakte Übereinstimmung ist der strengste und schnellste. Er eignet sich nur für Aufgaben, bei denen die Ausgabe eingeschränkt ist: eine Dreiklassen-Klassifizierung, das Extrahieren einer Rechnungsnummer, eine Ja-oder-Nein-Antwort. Bei Freitext würde er einer perfekten Antwort einfach eine Null geben, nur weil sie anders formuliert ist als die Referenz.

def exact_grader(response: str, expected: str) -> dict:
    """Evaluieren, ob die Antwort exakt übereinstimmt."""
    score = 1.0 if response.strip().lower() == expected.strip().lower() else 0.0
    return {"score": score, "type": "exact"}

Der Grader für Inklusion lockert die Einschränkung: Er prüft das Vorhandensein erwarteter Schlüsselwörter und gibt eine Teilpunktzahl zurück. Dies ist das richtige Werkzeug für Antworten, die bestimmte Punkte abdecken müssen, ohne dass die Wortwahl entscheidend ist – beispielsweise eine Support-Antwort, die die Rückgabefrist und die Rücksendeadresse erwähnen muss. Seine Schwäche ist gut bekannt: Ein Text, der die richtigen Wörter in einer absurden Reihenfolge enthält, würde eine perfekte Punktzahl erhalten.

def inclusion_grader(response: str, keywords: list[str]) -> dict:
    """Prüft, ob die Antwort die erwarteten Schlüsselwörter enthält."""
    response_lower = response.lower()
    found = sum(1 for word in keywords if word.lower() in response_lower)
    score = found / len(keywords) if keywords else 0.0
    return {
        "score": score,
        "found": found,
        "total": len(keywords),
        "type": "inclusion",
    }

Dann gibt es den mächtigsten: Ein anderes LLM bewertet die Qualität der Antwort. Der Grader LLM-as-Judge schätzt das ein, was keine mechanische Regel kann – Klarheit, Vollständigkeit, Ton-Treue. Zwei Implementierungsdetails machen ihn praktisch. Erstens, temperature=0.0: Ohne dies würde derselbe Richter bei jedem Lauf unterschiedliche Punktzahlen für dieselbe Antwort vergeben, und Ihr Benchmark würde jeden Vergleichswert verlieren. Zweitens die Fallback-Lösung für json.JSONDecodeError: Ein Richter, der Kommentare statt JSON zurückgibt, darf die gesamte Kampagne nicht abstürzen lassen.

def llm_judge_grader(
    question: str,
    response: str,
    expected: str,
    criteria: str = "accuracy, completeness, clarity",
) -> dict:
    """Verwendet ein LLM zur Bewertung der Antwortqualität."""
    judge_prompt = f"""Bewerten Sie die Qualität dieser Antwort auf einer Skala von 1 bis 5.

Frage: {question}
Erwartete Antwort: {expected}
Zu bewertende Antwort: {response}

Kriterien: {criteria}

Antworten SIE NUR mit JSON:
{{"score": <1-5>, "justification": "<kurze Erklärung>"}}"""

    response_obj = client.responses.create(
        model="gpt-5.6-terra",
        reasoning={"effort": "none"},  # temperature erfordert effort none
        input=judge_prompt,
        temperature=0.0,
    )

    import json
    try:
        result = json.loads(response_obj.output_text)
        result["normalized_score"] = result["score"] / 5.0
        return result
    except json.JSONDecodeError:
        return {"score": 0, "justification": "Parsing error", "normalized_score": 0}

Zusammenstellen der vollständigen Evaluierung

Orchestrierung stellt keine konzeptionellen Schwierigkeiten dar: Sie iterieren durch das Dataset, rufen das Modell mit dem System-Prompt zum Testen auf, wenden den Grader an und aggregieren. Der interessante Punkt ist, dass die Bewertungsfunktion als Parameter übergeben wird, was es ermöglicht, dasselbe Dataset mit unterschiedlichen Kriterien neu abzuspielen, je nach Kampagne – Inklusion für eine schnelle Prüfung während der Entwicklung, LLM-Judge für die Validierung vor der Produktion.

async def run_eval(
    dataset: list[dict],
    model: str,
    system_prompt: str,
    grader_fn,
) -> dict:
    """Führt eine vollständige Evaluierung auf einem Dataset durch."""
    results = []

    for case in dataset:
        response = client.responses.create(
            model=model,
            instructions=system_prompt,
            input=case["input"],
        )

        score = grader_fn(response.output_text, case["expected"])
        results.append({
            "input": case["input"],
            "expected": case["expected"],
            "obtained": response.output_text,
            **score,
        })

    # Berechnung aggregierter Metriken
    scores = [r["score"] for r in results if "score" in r]
    return {
        "model": model,
        "num_cases": len(dataset),
        "average_score": sum(scores) / len(scores) if scores else 0,
        "min_score": min(scores) if scores else 0,
        "max_score": max(scores) if scores else 0,
        "results": results,
    }

Der Bericht behält min_score und die Details jedes Falls bei, und das ist absichtlich. Der Durchschnitt sagt Ihnen, ob Sie vorankommen; die am schlechtesten bewerteten Fälle sagen Ihnen, warum. Machen Sie es zur Gewohnheit, die fünf schlechtesten Antworten aus jedem Lauf zu lesen, bevor Sie sich über den Durchschnitt äußern: Dort, und selten anderswo, finden Sie die nächste Korrektur.

Industrialisieren mit Promptfoo

Ihre Evaluierungen manuell in Python zu schreiben, ist lehrreich; ihre Wartung über die Zeit hinweg ist mit einem dedizierten Werkzeug komfortabler. Der Migrationsleitfaden von OpenAI beschreibt die Logik von Promptfoo: Die Evaluierung lebt in einer Konfigurationsdatei, promptfooconfig.yaml, die Prompts, Modelle(n), Testfälle und Kriterien – hier Assertions genannt – zusammenbringt. Sie läuft von der Kommandozeile, lokal oder in Ihrer Continuous Integration, und lebt neben dem Anwendungscode.

description: Klassifizierung von Support-Tickets
prompts:
  - "Klassifizieren Sie dieses Ticket in eine einzige Kategorie (Abrechnung, technisch, Konto): {{ticket}}"
providers:
  - openai:gpt-6.1-sol
tests:
  - vars:
      ticket: "Meine Karte wurde diesen Monat zweimal belastet."
    assert:
      - type: icontains
        value: billing
  - vars:
      ticket: "Die App stürzt ab, wenn ich eine PDF-Datei öffne."
    assert:
      - type: icontains
        value: technical
promptfoo eval -c promptfooconfig.yaml --no-cache
promptfoo view
promptfoo validate config -c promptfooconfig.yaml   # bei Konfigurationsfehlern

Die Grader aus dieser Lektion tauchen als Assertions wieder auf: exakte Übereinstimmung, Schlüsselwort-Inklusion und Modellurteil. OpenAI warnt bei letzterem: Ein neu erstellter Grader, insbesondere ein LLM-Judge, muss vor der Verwendung zur Entscheidung über eine Regression neu validiert werden, da Punktzahlen von einem Werkzeug zum anderen nicht unbedingt identisch sein werden.

Kernaussagen

  • Evals verwandeln Intuition in eine objektive Qualitätsmessgröße
  • Erstellen Sie Ihre Datensätze aus echten Produktionsfällen, die von einem Menschen validiert wurden
  • Wählen Sie den Grader basierend auf der Aufgabe: exakt für eingeschränkte, Inklusion für Pflichtpunkte, LLM-as-Judge für Nuancen
  • Stellen Sie temperature=0.0 beim Richter ein, um reproduzierbare Punktzahlen zu gewährleisten
  • Führen Sie Evaluierungen vor jeder Prompt- oder Modelländerung durch
  • Die OpenAI-Evals-Plattform schließt am 30. November 2026: Promptfoo, von OpenAI empfohlen, übernimmt Datensätze, Prompts, Modelle und Kriterien in einer Konfigurationsdatei