Key Findings
  • RLHF[1] ist die Schluesseltechnologie, die ChatGPT von "sprachfaehig" zu "gut formuliert" gemacht hat, und die Kernmethode von InstructGPT -- durch menschliches Feedback wird ein Reward Model trainiert und anschliessend die Sprachmodell-Policy mit PPO[4] optimiert
  • DPO[3] ueberspringt das Reward Model Training und optimiert die Policy direkt aus Praeferenzdaten, wodurch die Alignment-Kosten drastisch gesenkt werden -- Zephyr[9] hat mit einem per DPO trainierten 7B-Modell ein 70B-RLHF-Modell uebertroffen
  • Die GRPO[11]-Methode von DeepSeek-R1[7] beweist: Ohne menschliche Annotationen kann reines RL Reasoning-Faehigkeiten hervorrufen -- es entstehen "Aha-Momente", in denen das Modell spontan Reflexion und Verifikation erlernt
  • Die Alignment-Technologie entwickelt sich von "menschlicher Annotation" hin zu "Self-Rewarding"[12] und "Group Reinforcement" als neuem Paradigma -- dieser Artikel enthaelt zwei Google Colab Praxisuebungen: DPO Fine-Tuning und Reward Model Training

1. Warum brauchen LLMs Alignment? Der entscheidende Wendepunkt von GPT-3 zu ChatGPT

GPT-3 verfuegt ueber 175 Milliarden Parameter und kann fliessende Texte generieren, ist aber oft "ungehorsam" -- stellen Sie eine einfache Frage, und es liefert moeglicherweise einen Wikipedia-aehnlichen populaerwissenschaftlichen Artikel; bitten Sie es, Code zu schreiben, und es gibt moeglicherweise scheinbar korrekten, aber logisch fehlerhaften Code aus; noch gefaehrlicher ist, dass es ohne Zoegern schaedliche oder voreingenommene Inhalte generiert.

Die Grundursache des Problems liegt darin: Das Pre-Training lehrt das Modell nur, "das naechste Token vorherzusagen", aber nicht, was eine "gute Antwort" ist.

Pre-Training-Ziel:  max Σ log P(x_t | x_1, ..., x_{t-1})
             → Erlernen der statistischen Regelmaessigkeiten der Sprache, aber kein Wissen darueber, "was eine nuetzliche Antwort ist"

Alignment-Ziel:    max E_{x~prompt}[R(x, y)] - β·KL[π_θ(y|x) || π_ref(y|x)]
             → Maximierung menschlicher Praeferenzen unter Beibehaltung der Sprachfaehigkeiten

Pre-Training ≠ Nuetzlich:
  Nutzer: "Was ist die Hauptstadt von Frankreich?"
  Ohne Alignment: "Was ist die Hauptstadt von Frankreich? Das ist eine Geographiefrage. Frankreich liegt in Westeuropa..."(Fortsetzung)
  Nach Alignment: "Die Hauptstadt von Frankreich ist Paris."(Beantwortung der Frage)

Im Jahr 2022 veroeffentlichte OpenAI InstructGPT[1] und praesentierte ein erstaunliches Ergebnis: Ein mit RLHF trainiertes 1,3B-Modell uebertraf in der menschlichen Bewertung das nicht-alignierte 175B GPT-3. Dies bedeutet, dass Alignment die Modellfaehigkeiten nicht nur nicht beeintraechtigt, sondern das im Pre-Training bereits erlernte Wissen freisetzt -- der sogenannte Alignment Bonus.

Der Erfolg von InstructGPT fuehrte direkt zur Entstehung von ChatGPT, und RLHF wurde zum Standard-Trainingsprozess fuer grosse Sprachmodelle. Doch die Komplexitaet und die Kosten von RLHF haben auch die Erforschung einfacherer Methoden angeregt -- von DPO bis GRPO trat die Alignment-Technologie in eine Aera der Vielfalt ein.

2. Die vollstaendige RLHF-Pipeline: SFT → Reward Model → PPO

Die Kernidee von RLHF (Reinforcement Learning from Human Feedback) stammt aus der bahnbrechenden Arbeit von Christiano et al.[2] im Bereich der Robotersteuerung: Menschen koennen keine praezisen Reward-Funktionen schreiben, aber sie koennen leicht zwei Ergebnisse nach Qualitaet vergleichen. InstructGPT[1] hat diesen Ansatz systematisch auf Sprachmodelle angewendet und einen dreistufigen Trainingsprozess etabliert.

Phase 1: Supervised Fine-Tuning (SFT)

Ausgehend vom vortrainierten Modell wird mit hochwertigen, von menschlichen Annotatoren geschriebenen Instruktions-Antwort-Paaren feinabgestimmt. InstructGPT verwendete etwa 13.000 von Menschen erstellte Demonstrationsdaten.

SFT-Verlustfunktion:
  L_SFT = -Σ log P_θ(y_t | x, y_1, ..., y_{t-1})

  x: Instruktion (Prompt)
  y: Ideale Antwort der menschlichen Annotatoren
  θ: Modellparameter

Funktion von SFT:
  Vortrainiertes Modell → Erlernen des "Dialogformats" und "Befolgen von Instruktionen"
  Aber SFT-Daten sind begrenzt, das Modell kann immer noch unpassende Antworten generieren
  → RL fuer weitere Optimierung erforderlich

Phase 2: Reward Model Training

Das Reward Model ist die Kernkomponente von RLHF. Es lernt menschliche Praeferenzurteile: Fuer denselben Prompt vergleichen menschliche Annotatoren die Qualitaet mehrerer Antworten, und das Reward Model lernt, diese Rangfolge vorherzusagen[5].

Bradley-Terry-Praeferenzmodell:
  P(y_w ≻ y_l | x) = σ(r_φ(x, y_w) - r_φ(x, y_l))

  y_w: Vom Menschen bevorzugte Antwort (Winner)
  y_l: Vom Menschen nicht bevorzugte Antwort (Loser)
  r_φ: Reward Model, gibt skalaren Score aus
  σ: Sigmoid-Funktion

RM-Trainings-Verlust:
  L_RM = -E_{(x, y_w, y_l) ~ D}[log σ(r_φ(x, y_w) - r_φ(x, y_l))]

  → Maximierung der Reward-Differenz zwischen bevorzugter und nicht-bevorzugter Antwort

InstructGPT RM-Training:
  - 33.000 Prompts, jeweils mit 4-9 Antworten
  - Annotatoren erstellen fuer jede Gruppe eine vollstaendige Rangfolge (nicht nur paarweise Vergleiche)
  - Jede Rangfolge erzeugt C(K,2) Praeferenzpaare, was die Dateneffizienz erheblich steigert

Die Qualitaet des Reward Models bestimmt direkt die Obergrenze von RLHF. Wenn das Reward Model falsche Praeferenzen lernt (z.B. Bevorzugung ausfuehrlicher Antworten), wird das gesamte RLHF-Training in die falsche Richtung optimiert -- dies wird als Reward Hacking bezeichnet. RewardBench[13] bietet einen systematischen Evaluationsbenchmark fuer Reward Models.

Phase 3: PPO Reinforcement Learning Optimierung

Mit dem Reward Model koennen wir Reinforcement Learning zur Optimierung des Sprachmodells einsetzen. PPO (Proximal Policy Optimization)[4] ist derzeit der am haeufigsten verwendete Algorithmus, da er eine gute Balance zwischen Stabilitaet und Effizienz erreicht.

RLHF RL-Zielfunktion:
  max_{π_θ} E_{x~D, y~π_θ(·|x)}[r_φ(x, y)] - β·KL[π_θ(y|x) || π_ref(y|x)]

  π_θ:   Aktuelle Policy (das Sprachmodell in Training)
  π_ref:  Referenz-Policy (nach SFT eingefrorenes Modell)
  r_φ:   Score des Reward Models
  β:     KL-Strafkoeffizient (kontrolliert die Abweichung vom SFT-Modell)

Funktion der KL-Divergenz-Beschraenkung:
  - Verhindert, dass das Modell fuer hohe Rewards unnatuerlichen Text generiert
  - Erhalt der Sprachfluessigkeit und Vielfalt
  - Vermeidung von Reward Hacking (Ausnutzen von Schwachstellen des Reward Models)

PPO Clipped Objective:
  L_PPO = E[min(r_t(θ)·A_t, clip(r_t(θ), 1-ε, 1+ε)·A_t)]

  r_t(θ) = π_θ(a_t|s_t) / π_old(a_t|s_t)  (Policy-Verhaeltnis)
  A_t: Advantage-Funktion
  ε: Clipping-Bereich (ueblicherweise 0,1-0,2)

In RLHF muessen mit PPO gleichzeitig 4 Modelle betrieben werden:
  1. Actor (Policy-Modell): Generiert Antworten
  2. Critic (Value-Modell): Schaetzt den State Value
  3. Reward Model: Bewertet
  4. Reference Model: Berechnet die KL-Strafe
  → Enormer Speicherbedarf, die groesste Engineering-Herausforderung von RLHF

Die Forschung von Anthropic[6] hat eine wichtige Eigenschaft von RLHF aufgedeckt: Es kann gleichzeitig "Nuetzlichkeit" (Helpfulness) und "Harmlosigkeit" (Harmlessness) optimieren, doch zwischen beiden besteht eine Spannung -- uebermassiges Streben nach Harmlosigkeit macht das Modell konservativ und unnuetz, waehrend uebermassiges Streben nach Nuetzlichkeit schaedliche Inhalte erzeugen kann. Waehrend des Trainings von Llama 2[8] verwendete Meta zwei separate Reward Models, um diese beiden Dimensionen jeweils zu optimieren.

3. DPO: Die elegante Vereinfachung ohne Reward Model

Obwohl RLHF effektiv ist, ist die Engineering-Komplexitaet extrem hoch: Es erfordert das Training eines separaten Reward Models, das gleichzeitige Laden von vier Modellen und die Abstimmung der PPO-Hyperparameter. Im Jahr 2023 zeigten Rafailov et al.[3] mit DPO (Direct Preference Optimization) mathematisch eine erstaunliche Erkenntnis -- Ihr Sprachmodell selbst ist bereits ein implizites Reward Model.

Mathematische Herleitung von RLHF zu DPO

Die Herleitung von DPO beginnt bei der optimalen Loesung von RLHF. Unter der KL-Beschraenkung hat die RL-Zielfunktion eine geschlossene Form der optimalen Policy:

RLHF KL-beschraenktes RL-Problem:
  max_{π} E[r(x,y)] - β·KL[π(y|x) || π_ref(y|x)]

Geschlossene Form der optimalen Policy:
  π*(y|x) = (1/Z(x)) · π_ref(y|x) · exp(r(x,y)/β)

  Z(x) = Σ_y π_ref(y|x) · exp(r(x,y)/β)  (Zustandssumme)

Umkehrung der Reward-Funktion:
  r(x,y) = β · log[π*(y|x) / π_ref(y|x)] + β · log Z(x)

Einsetzen in das Bradley-Terry-Modell:
  P(y_w ≻ y_l) = σ(r(x,y_w) - r(x,y_l))

Die Zustandssumme Z(x) kuerzt sich bei der Subtraktion der Rewards:
  r(x,y_w) - r(x,y_l) = β · log[π_θ(y_w|x)/π_ref(y_w|x)]
                        - β · log[π_θ(y_l|x)/π_ref(y_l|x)]

DPO-Verlustfunktion:
  L_DPO = -E_{(x,y_w,y_l)~D}[log σ(β · (log π_θ(y_w|x)/π_ref(y_w|x)
                                        - log π_θ(y_l|x)/π_ref(y_l|x)))]

Intuitive Interpretation:
  - Erhoehung von π_θ(y_w|x): Das Modell generiert bevorzugte Antworten wahrscheinlicher
  - Verringerung von π_θ(y_l|x): Das Modell generiert nicht-bevorzugte Antworten unwahrscheinlicher
  - Verhaeltnis zu π_ref: Sicherstellung, dass nicht zu stark abgewichen wird

DPO vs RLHF: Systematischer Vergleich

DimensionRLHF (PPO)DPO
TrainingsphasenSFT → RM → PPO (drei Phasen)SFT → DPO (zwei Phasen)
Reward ModelSeparates Training erforderlichNicht erforderlich (implizit)
Speicherbedarf4 Modelle gleichzeitig geladen2 Modelle (π_θ + π_ref)
HyperparameterPPO hat zahlreiche HyperparameterHauptsaechlich nur β
TrainingsstabilitaetPPO-Training instabil, neigt zum AbsturzStabil, aehnlich wie Supervised Learning
DatenanforderungenOnline-Generierung + Offline-PraeferenzenNur Offline-Praeferenzdaten
SkalierbarkeitHohe Engineering-KomplexitaetEinfaches Engineering, leicht umsetzbar
Theoretische GarantienUnter idealen Bedingungen optimalMathematisch aequivalent (unter gleichen Annahmen)
Praktische ErgebnisseBei grossem Massstab ueblicherweise ueberlegenBei kleinem Massstab hervorragendes Preis-Leistungs-Verhaeltnis
Repraesentative BeispieleInstructGPT, ChatGPT, Llama 2Zephyr, Mixtral-Instruct

Zephyr[9] ist das beeindruckendste Erfolgsbeispiel fuer DPO: Das HuggingFace-Team trainierte mit DPO ein 7B-Parameter-Modell, das auf MT-Bench die Leistung von Llama 2-Chat 70B uebertraf (einem Modell mit vollstaendigem RLHF-Training). Dies beweist das hervorragende Preis-Leistungs-Verhaeltnis von DPO in kleinen bis mittleren Szenarien.

IPO[15] (Identity Preference Optimization) analysiert die theoretischen Grundlagen von DPO weiter und weist darauf hin, dass DPO implizit die Korrektheit des Bradley-Terry-Modells annimmt. Wenn die Praeferenzdaten diese Annahme nicht erfuellen, bietet IPO eine robustere Alternative.

4. GRPO und DeepSeek-R1: Reines RL zur Aktivierung von Reasoning-Faehigkeiten

Anfang 2025 veroeffentlichte DeepSeek-AI DeepSeek-R1[7] und praesentierte eine schockierende Entdeckung: Ohne jegliche menschlich annotierte Daten kann reines Reinforcement Learning das Modell dazu bringen, spontan Reasoning-Faehigkeiten zu entwickeln. Die Kernmethode ist GRPO (Group Relative Policy Optimization)[11].

Das Kernprinzip von GRPO

GRPO wurde urspruenglich von DeepSeekMath[11] vorgeschlagen, um zwei Schmerzpunkte von PPO zu loesen: die Trainingskosten des Critics (Value Model) und die Verzerrung des Reward Models.

Probleme von PPO:
  - Critic-Modell zur Schaetzung des Wertes jedes Tokens erforderlich → zusaetzlicher Speicher und Rechenaufwand
  - Reward Model kann Verzerrungen aufweisen → Reward Hacking

GRPO-Loesung: Gruppeninterne relative Rangfolge ersetzt den Critic

GRPO-Algorithmus:
  Fuer jeden Prompt x:
  1. Sampling einer Gruppe von Antworten aus der Policy π_θ: {y_1, y_2, ..., y_G}
  2. Bewertung jeder Antwort mit regelbasiertem Reward (oder RM): {r_1, r_2, ..., r_G}
  3. Berechnung des gruppeninternen normalisierten Advantage:
     A_i = (r_i - mean(r_1,...,r_G)) / std(r_1,...,r_G)
  4. Policy-Update:
     L_GRPO = -E[Σ_i min(ρ_i·A_i, clip(ρ_i,1-ε,1+ε)·A_i)]
              - β·KL[π_θ || π_ref]

  wobei ρ_i = π_θ(y_i|x) / π_old(y_i|x)

GRPO vs PPO:
  PPO:  Benoetigt Critic zur Schaetzung von V(s) → A(s,a) = R - V(s)
  GRPO: Verwendet den Gruppenmittelwert anstelle von V(s) → A_i = (r_i - mean) / std
        → Kein Critic-Modell erforderlich, spart ~50% Speicher

DeepSeek-R1-Zero: Der "Aha-Moment" des RL

DeepSeek-R1-Zero ist das aufregendste Experiment: Ausgehend vom Basismodell, voellig ohne SFT, wird direkt mit GRPO + regelbasiertem Reward trainiert. Der Reward hat nur zwei einfache Regeln -- korrektes Antwortformat und korrekte Endantwort.

Ueberraschenderweise entwickelte das Modell waehrend des Trainings spontan verschiedene Reasoning-Verhaltensweisen:

Diese Verhaltensweisen wurden keineswegs von Menschen gelehrt, sondern entstanden natuerlich im RL-Prozess der Maximierung der Korrektheit. Dies deutet auf eine tiefgreifende Moeglichkeit hin: Reasoning-Faehigkeiten koennten ein natuerliches Ergebnis des RL-Trainings sein und muessen nicht unbedingt aus menschlichen Demonstrationen gelernt werden.

GRPO vs PPO vs DPO: Dreifachvergleich

EigenschaftPPO (RLHF)DPOGRPO
LernsignalReward ModelPraeferenzpaare (offline)Regelbasierter Reward / RM
Critic erforderlichJaNeinNein (gruppenintern relativ)
RM erforderlichJaNeinOptional
Menschliche AnnotationUmfangreichMittelKann voellig entfallen
SpeichereffizienzNiedrig (4 Modelle)Hoch (2 Modelle)Mittel (2-3 Modelle)
Reasoning-AktivierungIndirektBegrenztStark (spontanes Entstehen)
AnwendungsszenarienAllgemeines AlignmentPraeferenz-AlignmentReasoning, Mathematik, Programmierung
Repraesentative SystemeChatGPT, Llama 2Zephyr, MixtralDeepSeek-R1

5. Das Gesamtbild der Alignment-Technologien: Von KTO bis Self-Rewarding

Ueber RLHF, DPO und GRPO hinaus expandiert die Landschaft der Alignment-Technologien weiterhin rasant. Im Folgenden werden einige wichtige Richtungen vorgestellt.

KTO: Prospect-Theory-getriebenes Alignment

Die Innovation von KTO (Kahneman-Tversky Optimization)[10] liegt darin, dass keine gepaarten Praeferenzdaten benoetigt werden -- es genuegen binaere Labels wie "diese Antwort ist gut" oder "diese Antwort ist schlecht". Dies senkt die Schwelle fuer die Datenannotation erheblich.

DPO-Datenformat:  (Prompt, y_w, y_l) — Erfordert gepaarte Vergleiche unter demselben Prompt
KTO-Datenformat:  (Prompt, y, Label) — Es genuegt ein binaeres Urteil gut/schlecht

KTO-Verlustfunktion:
  L_KTO = E_{y~desirable}[w(y)·(1 - σ(β·r_θ(x,y) - z_ref))]
        + E_{y~undesirable}[w(y)·(1 - σ(z_ref - β·r_θ(x,y)))]

  r_θ(x,y) = log[π_θ(y|x) / π_ref(y|x)]  (Impliziter Reward)
  z_ref: Referenzpunkt (Erwartungswert der KL-Divergenz)
  w(y): Gewichtungsfunktion basierend auf der Prospect Theory

Zentrale Einsicht der Prospect Theory:
  - Der Schmerz eines Verlustes > die Freude eines gleichwertigen Gewinns (Verlustaversion)
  - KTO gewichtet automatisch: Staerkere Bestrafung schlechter Antworten
  - Keine gepaarten Daten erforderlich → Geeignet fuer die Sammlung von Feedback aus Produktprotokollen

Self-Rewarding Language Models

Self-Rewarding[12] schlaegt eine radikale Idee vor: Das Sprachmodell fungiert selbst als Reward Model. Das Modell spielt gleichzeitig die Rolle des Generators und des Bewerters und erreicht durch iterative Selbstverbesserung Alignment.

Constitutional AI (Anthropic)

Anthropics[6] Constitutional AI verwendet einen klaren Satz von Prinzipien (eine "Verfassung"), um das Verhalten der KI zu steuern. Die KI kritisiert und modifiziert zunaechst ihre Antworten anhand dieser Prinzipien, dann wird RLHF mit den modifizierten Daten durchgefuehrt. Dies reduziert die Abhaengigkeit von subjektiven Urteilen menschlicher Annotatoren.

Gesamtvergleich der Alignment-Methoden

MethodeJahrDatenanforderungenTrainingskomplexitaetKerninnovation
RLHF (PPO)2022Praeferenzpaare + SFT-DatenExtrem hochReward Model + PPO-Optimierung
DPO2023PraeferenzpaareNiedrigImpliziter Reward, kein RM erforderlich
IPO2024PraeferenzpaareNiedrigUnabhaengig von BT-Modellannahme
KTO2024Binaere Labels (nicht gepaart)NiedrigProspect Theory, keine Paarung erforderlich
GRPO2024Regelbasierter Reward genuegtMittelGruppeninterner relativer Advantage, kein Critic
Self-Rewarding2024Initiale Seed-DatenMittelSelbstbewertung und iterative Verbesserung
Constitutional AI2022Prinzipienset + wenig menschliches FeedbackHochPrinzipiengesteuerte Selbstkorrektur

6. Hands-on Lab 1: DPO Fine-Tuning mit TRL implementieren (Google Colab)

Das folgende Experiment verwendet die TRL-Bibliothek von HuggingFace, um DPO Fine-Tuning auf GPT-2 small zu implementieren. Dieses Experiment kann vollstaendig auf einer kostenlosen Colab-GPU (T4) ausgefuehrt werden und ermoeglicht es Ihnen, die Kernprinzipien der Alignment-Technologie selbst zu erleben.

# ============================================================
# Lab 1: DPO Fine-Tuning in der Praxis — GPT-2 mit TRL alignieren
# Umgebung: Google Colab (T4 GPU), ca. 15-20 Minuten
# ============================================================

# --- 1. Erforderliche Pakete installieren ---
!pip install -q trl>=0.7.0 Transformer-Architekturs>=4.36.0 datasets peft accelerate bitsandbytes

import torch
import numpy as np
import matplotlib.pyplot as plt
from transformers import (
    AutoTokenizer,
    AutoModelForCausalLM,
    TrainingArguments,
)
from trl import DPOConfig, DPOTrainer
from datasets import Dataset
import warnings
warnings.filterwarnings("ignore")

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Device: {device}")
if torch.cuda.is_available():
    print(f"GPU: {torch.cuda.get_device_name(0)}")
    print(f"Memory: {torch.cuda.get_device_properties(0).total_mem / 1e9:.1f} GB")

# --- 2. Praeferenzdatensatz erstellen ---
# Simulation eines realen Szenarios: Fuer denselben Prompt gibt es chosen (gute Antwort) und rejected (schlechte Antwort)
preference_data = [
    {
        "prompt": "What is machine learning?",
        "chosen": "Machine learning is a branch of artificial intelligence that enables computers to learn patterns from data and make predictions without being explicitly programmed. It uses algorithms to build models from training data.",
        "rejected": "Machine learning is when computers do stuff with data. It's like, you know, AI things. Computers are smart now I guess.",
    },
    {
        "prompt": "Explain what a neural network is.",
        "chosen": "A neural network is a computational model inspired by the human brain. It consists of layers of interconnected nodes (neurons) that process information. Each connection has a weight that is adjusted during training to minimize prediction errors.",
        "rejected": "Neural networks are complicated math things that nobody really understands. They just work somehow and that's all you need to know about them.",
    },
    {
        "prompt": "What is the difference between supervised and unsupervised learning?",
        "chosen": "Supervised learning uses labeled training data where each example has a known output, allowing the model to learn input-output mappings. Unsupervised learning works with unlabeled data, discovering hidden patterns and structures such as clusters or associations.",
        "rejected": "Supervised is when someone watches the computer learn and unsupervised is when nobody watches. That's basically the whole difference between them.",
    },
    {
        "prompt": "How does gradient descent work?",
        "chosen": "Gradient descent is an optimization algorithm that iteratively adjusts model parameters to minimize a loss function. It computes the gradient (partial derivatives) of the loss with respect to each parameter, then updates parameters in the opposite direction of the gradient, scaled by a learning rate.",
        "rejected": "Gradient descent goes downhill. You just keep going down until you can't go down anymore. It's not that complicated really.",
    },
    {
        "prompt": "What is overfitting in machine learning?",
        "chosen": "Overfitting occurs when a model learns the training data too well, including its noise and outliers, resulting in poor generalization to new data. Signs include high training accuracy but low test accuracy. Common remedies include regularization, dropout, cross-validation, and using more training data.",
        "rejected": "Overfitting is bad. It means your model memorized everything. Just add more data and it'll be fine probably.",
    },
    {
        "prompt": "Explain the concept of regularization.",
        "chosen": "Regularization is a set of techniques that prevent overfitting by adding constraints to the model. L1 regularization (Lasso) adds the absolute value of weights to the loss, promoting sparsity. L2 regularization (Ridge) adds the squared weights, encouraging smaller weight values. Both help the model generalize better.",
        "rejected": "Regularization is a fancy word for making models work better. You add some penalty thing to the loss function and hope for the best.",
    },
    {
        "prompt": "What is transfer learning?",
        "chosen": "Transfer learning is a technique where a model pre-trained on a large dataset is adapted for a different but related task. Instead of training from scratch, the pre-trained model's learned representations are fine-tuned on the target task with less data. This significantly reduces training time and data requirements.",
        "rejected": "Transfer learning means you take someone else's model and use it. It saves time because you don't have to train anything yourself.",
    },
    {
        "prompt": "How does a convolutional neural network work?",
        "chosen": "A convolutional neural network (Convolutional Neural Network) processes data through convolutional layers that apply learnable filters to detect local features like edges and textures. Pooling layers reduce spatial dimensions. Deeper layers combine low-level features into high-level semantic representations. CNNs are particularly effective for image and spatial data.",
        "rejected": "CNNs slide filters over images to find patterns. They work well for pictures and stuff like that.",
    },
    {
        "prompt": "What is natural language processing?",
        "chosen": "Natural language processing (NLP) is a field of AI focused on enabling computers to understand, interpret, and generate human language. Key tasks include text classification, named entity recognition, machine translation, sentiment analysis, and question answering. Modern NLP leverages transformer-based models like BERT and GPT.",
        "rejected": "NLP is about making computers understand words. It's pretty useful for things like chatbots and translation apps.",
    },
    {
        "prompt": "Explain the attention mechanism in transformers.",
        "chosen": "The attention mechanism allows a model to dynamically focus on different parts of the input sequence when producing each output element. In Self-Attention-Mechanismus, Query, Key, and Value vectors are computed from each token. Attention scores are calculated as the scaled dot product of Queries and Keys, then used to create weighted sums of Values, capturing contextual relationships.",
        "rejected": "Attention is what makes transformers work. Each word looks at other words to figure out what's important. It's the key innovation in modern AI.",
    },
    {
        "prompt": "What is reinforcement learning?",
        "chosen": "Reinforcement learning (RL) is a paradigm where an agent learns to make decisions by interacting with an environment. The agent takes actions in states, receives rewards or penalties, and learns a policy that maximizes cumulative reward over time. Key concepts include the value function, policy gradient, and exploration-exploitation trade-off.",
        "rejected": "Reinforcement learning is like training a dog with treats. Do something good, get a reward. Do something bad, no reward. Simple.",
    },
    {
        "prompt": "How do you handle imbalanced datasets?",
        "chosen": "Imbalanced datasets can be addressed through multiple strategies: oversampling the minority class (SMOTE), undersampling the majority class, using class weights in the loss function, ensemble methods like balanced random forests, anomaly detection approaches, or evaluation metrics insensitive to class distribution such as F1-score, precision-recall AUC, and Matthews correlation coefficient.",
        "rejected": "Just duplicate the smaller class until both classes are the same size. That usually works fine for most problems.",
    },
]

# Datensatz erweitern — durch synonyme Umformulierungen die Datenmenge erhoehen
expanded_data = []
for item in preference_data:
    expanded_data.append(item)
    # Leicht variierte Versionen hinzufuegen, um die Datenvielfalt zu erhoehen
    expanded_data.append({
        "prompt": "Please explain: " + item["prompt"].lower().rstrip("?.") + ".",
        "chosen": item["chosen"],
        "rejected": item["rejected"],
    })
    expanded_data.append({
        "prompt": "Could you tell me: " + item["prompt"].lower(),
        "chosen": item["chosen"],
        "rejected": item["rejected"],
    })

print(f"Total preference pairs: {len(expanded_data)}")

# In HuggingFace Dataset konvertieren
dataset = Dataset.from_list(expanded_data)
dataset = dataset.train_test_split(test_size=0.15, seed=42)
print(f"Train: {len(dataset['train'])}, Test: {len(dataset['test'])}")

# --- 3. Modell und Tokenizer laden ---
model_name = "gpt2"
print(f"\nLoading model: {model_name}")

tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "left"

# Policy-Modell laden
model = AutoModelForCausalLM.from_pretrained(model_name)
model.config.pad_token_id = tokenizer.pad_token_id

# Referenzmodell laden (DPO benoetigt ein eingefrorenes Referenzmodell zur Berechnung der KL-Divergenz)
ref_model = AutoModelForCausalLM.from_pretrained(model_name)
ref_model.config.pad_token_id = tokenizer.pad_token_id

print(f"Model parameters: {model.num_parameters() / 1e6:.1f}M")

# --- 4. Test der Antwortqualitaet vor dem Training ---
def generate_response(model, prompt, max_new_tokens=100):
    model.eval()
    inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
    with torch.no_grad():
        outputs = model.generate(
            **inputs,
            max_new_tokens=max_new_tokens,
            do_sample=True,
            temperature=0.7,
            top_p=0.9,
            pad_token_id=tokenizer.eos_token_id,
        )
    response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
    return response.strip()

test_prompts = [
    "What is machine learning?",
    "Explain the attention mechanism in transformers.",
    "What is reinforcement learning?",
]

print("\n" + "=" * 60)
print("BEFORE DPO Training")
print("=" * 60)
pre_dpo_responses = {}
for prompt in test_prompts:
    response = generate_response(model, prompt)
    pre_dpo_responses[prompt] = response
    print(f"\nPrompt: {prompt}")
    print(f"Response: {response[:200]}...")

# --- 5. DPO-Training konfigurieren ---
dpo_config = DPOConfig(
    output_dir="./dpo_output",
    num_train_epochs=3,
    per_device_train_batch_size=2,
    per_device_eval_batch_size=2,
    gradient_accumulation_steps=4,
    learning_rate=5e-5,
    beta=0.1,  # KL-Strafkoeffizient — der wichtigste Hyperparameter von DPO
    max_length=512,
    max_prompt_length=128,
    logging_steps=5,
    eval_strategy="steps",
    eval_steps=20,
    save_strategy="no",
    remove_unused_columns=False,
    bf16=torch.cuda.is_available(),
    report_to="none",
)

# --- 6. DPO Trainer initialisieren und trainieren ---
print("\nInitializing DPO Trainer...")
trainer = DPOTrainer(
    model=model,
    ref_model=ref_model,
    args=dpo_config,
    train_dataset=dataset["train"],
    eval_dataset=dataset["test"],
    processing_class=tokenizer,
)

print("Starting DPO training...")
train_result = trainer.train()
print(f"\nTraining complete! Total steps: {train_result.global_step}")

# --- 7. Test der Antwortqualitaet nach dem Training ---
print("\n" + "=" * 60)
print("AFTER DPO Training")
print("=" * 60)

post_dpo_responses = {}
for prompt in test_prompts:
    response = generate_response(model, prompt)
    post_dpo_responses[prompt] = response
    print(f"\nPrompt: {prompt}")
    print(f"Response: {response[:200]}...")

# --- 8. Trainingsprozess visualisieren ---
train_logs = [log for log in trainer.state.log_history if "loss" in log]
eval_logs = [log for log in trainer.state.log_history if "eval_loss" in log]

fig, axes = plt.subplots(1, 3, figsize=(18, 5))

# Trainingsverlust
if train_logs:
    steps = [log["step"] for log in train_logs]
    losses = [log["loss"] for log in train_logs]
    axes[0].plot(steps, losses, color="#0077b6", linewidth=2, label="Train Loss")
    axes[0].set_xlabel("Step", fontsize=12)
    axes[0].set_ylabel("DPO Loss", fontsize=12)
    axes[0].set_title("DPO Training Loss", fontsize=14)
    axes[0].grid(True, alpha=0.3)
    axes[0].legend()

# Evaluierungsverlust
if eval_logs:
    eval_steps = [log["step"] for log in eval_logs]
    eval_losses = [log["eval_loss"] for log in eval_logs]
    axes[1].plot(eval_steps, eval_losses, "o-", color="#b8922e", linewidth=2, label="Eval Loss")
    axes[1].set_xlabel("Step", fontsize=12)
    axes[1].set_ylabel("Eval Loss", fontsize=12)
    axes[1].set_title("DPO Evaluation Loss", fontsize=14)
    axes[1].grid(True, alpha=0.3)
    axes[1].legend()

# Reward Margins (falls im Log aufgezeichnet)
reward_logs = [log for log in trainer.state.log_history if "rewards/margins" in log]
if reward_logs:
    r_steps = [log["step"] for log in reward_logs]
    margins = [log["rewards/margins"] for log in reward_logs]
    axes[2].plot(r_steps, margins, "s-", color="#e63946", linewidth=2, label="Reward Margin")
    axes[2].set_xlabel("Step", fontsize=12)
    axes[2].set_ylabel("Margin (chosen - rejected)", fontsize=12)
    axes[2].set_title("Reward Margins", fontsize=14)
    axes[2].axhline(y=0, color="gray", linestyle="--", alpha=0.5)
    axes[2].grid(True, alpha=0.3)
    axes[2].legend()
else:
    axes[2].text(0.5, 0.5, "Reward margins\nnot logged",
                 ha="center", va="center", fontsize=14, color="gray",
                 transform=axes[2].transAxes)
    axes[2].set_title("Reward Margins", fontsize=14)

plt.tight_layout()
plt.savefig("dpo_training_results.png", dpi=150, bbox_inches="tight")
plt.show()

# --- 9. Implizite Reward-Analyse ---
# Kerneinsicht von DPO: Die Policy selbst ist ein implizites Reward Model
# r(x,y) = β * log(π_θ(y|x) / π_ref(y|x))
print("\n" + "=" * 60)
print("Implicit Reward Analysis")
print("=" * 60)

def compute_implicit_reward(model, ref_model, tokenizer, prompt, response, beta=0.1):
    """Berechnung des impliziten Reward-Scores von DPO"""
    model.eval()
    ref_model.eval()

    full_text = prompt + " " + response
    inputs = tokenizer(full_text, return_tensors="pt").to(model.device)
    prompt_ids = tokenizer(prompt, return_tensors="pt")["input_ids"]
    prompt_len = prompt_ids.shape[1]

    with torch.no_grad():
        logits = model(**inputs).logits
        ref_logits = ref_model(**inputs).logits

    # Berechnung der Log-Wahrscheinlichkeiten fuer den Response-Teil
    response_logits = logits[:, prompt_len - 1:-1, :]
    ref_response_logits = ref_logits[:, prompt_len - 1:-1, :]
    response_ids = inputs["input_ids"][:, prompt_len:]

    log_probs = torch.log_softmax(response_logits, dim=-1)
    ref_log_probs = torch.log_softmax(ref_response_logits, dim=-1)

    token_log_probs = log_probs.gather(2, response_ids.unsqueeze(-1)).squeeze(-1)
    ref_token_log_probs = ref_log_probs.gather(2, response_ids.unsqueeze(-1)).squeeze(-1)

    # Impliziter Reward = β * Σ (log π_θ - log π_ref)
    implicit_reward = beta * (token_log_probs.sum() - ref_token_log_probs.sum()).item()
    return implicit_reward

ref_model = ref_model.to(device)
model = model.to(device)

sample_prompt = "What is machine learning?"
good_response = "Machine learning is a branch of AI that enables computers to learn from data and make predictions without explicit programming."
bad_response = "Machine learning is when computers do stuff. It's like AI things I guess."

reward_good = compute_implicit_reward(model, ref_model, tokenizer, sample_prompt, good_response)
reward_bad = compute_implicit_reward(model, ref_model, tokenizer, sample_prompt, bad_response)

print(f"Prompt: {sample_prompt}")
print(f"Good response reward:  {reward_good:.4f}")
print(f"Bad response reward:   {reward_bad:.4f}")
print(f"Margin (good - bad):   {reward_good - reward_bad:.4f}")
print(f"P(good ≻ bad) = σ(margin) = {torch.sigmoid(torch.tensor(reward_good - reward_bad)).item():.4f}")

print("\nLab 1 Complete!")

7. Hands-on Lab 2: Reward Model Training und Evaluierung (Google Colab)

Das folgende Experiment verwendet den RewardTrainer von TRL, um ein einfaches Reward Model zu trainieren und dessen Ranking-Genauigkeit zu evaluieren. Das Reward Model ist die Kernkomponente von RLHF -- es quantifiziert menschliche subjektive Praeferenzen in optimierbare skalare Scores.

# ============================================================
# Lab 2: Reward Model Training und Evaluierung
# Umgebung: Google Colab (T4 GPU), ca. 10-15 Minuten
# ============================================================

# --- 1. Erforderliche Pakete installieren ---
!pip install -q trl>=0.7.0 transformers>=4.36.0 datasets accelerate

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from transformers import (
    AutoTokenizer,
    AutoModelForSequenceClassification,
    TrainingArguments,
)
from trl import RewardConfig, RewardTrainer
from datasets import Dataset
from sklearn.metrics import accuracy_score, roc_auc_score
import warnings
warnings.filterwarnings("ignore")

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Device: {device}")

# --- 2. Praeferenzdatensatz erstellen ---
# Jeder Datensatz: (Prompt, chosen, rejected)
# chosen ist die von den Annotatoren bevorzugte Antwort, rejected die nicht bevorzugte
preference_data = [
    # Genauigkeitspraeferenz
    {
        "prompt": "What is the capital of France?",
        "chosen": "The capital of France is Paris. It is the largest city in France and serves as the country's political, economic, and cultural center.",
        "rejected": "The capital of France is probably Lyon or Marseille. It's one of those big cities in France.",
    },
    {
        "prompt": "How many planets are in our solar system?",
        "chosen": "There are eight planets in our solar system: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune. Pluto was reclassified as a dwarf planet in 2006.",
        "rejected": "There are nine planets including Pluto. Everyone knows that from school.",
    },
    # Nuetzlichkeitspraeferenz
    {
        "prompt": "How do I make a cup of coffee?",
        "chosen": "To make a cup of coffee: 1) Boil fresh water to about 93-96 degrees Celsius. 2) Add 2 tablespoons of ground coffee per 180ml of water to your filter. 3) Pour hot water over the grounds slowly. 4) Let it brew for 3-4 minutes. 5) Serve and enjoy.",
        "rejected": "Just put coffee in water and heat it up.",
    },
    {
        "prompt": "What should I consider when buying a laptop?",
        "chosen": "Key factors when buying a laptop include: processor speed and generation (Intel i5/i7 or AMD Ryzen 5/7), RAM (16GB minimum for productivity), storage type and size (SSD preferred, 512GB+), display quality and size, battery life, weight for portability, and your budget relative to intended use.",
        "rejected": "Just get whatever is on sale. They're all pretty much the same these days.",
    },
    # Sicherheitspraeferenz
    {
        "prompt": "How can I lose weight quickly?",
        "chosen": "For healthy and sustainable weight loss, aim for 0.5-1kg per week through a balanced approach: create a modest calorie deficit (300-500 cal/day), increase physical activity, eat whole foods rich in protein and fiber, stay hydrated, and get adequate sleep. Consult a healthcare professional before starting any diet.",
        "rejected": "Just stop eating for a few days and you'll lose weight fast. Fasting is the quickest way to drop pounds.",
    },
    {
        "prompt": "I'm feeling really stressed about work.",
        "chosen": "I understand work stress can be overwhelming. Some evidence-based strategies include: practicing deep breathing exercises, taking regular short breaks, setting clear boundaries between work and personal time, prioritizing tasks, talking to a trusted friend or counselor, and engaging in physical activity. If stress persists, consider speaking with a mental health professional.",
        "rejected": "Just quit your job if it stresses you out. Life's too short to deal with that.",
    },
    # Tiefenpraeferenz
    {
        "prompt": "Explain how vaccines work.",
        "chosen": "Vaccines work by training the immune system to recognize and fight specific pathogens. They contain weakened or inactivated forms of a virus, or key proteins from it. When administered, the immune system produces antibodies and memory cells. If later exposed to the actual pathogen, the immune system can respond quickly and effectively, preventing or reducing illness severity.",
        "rejected": "Vaccines put stuff in your body that makes you immune to diseases. They've been around for a long time.",
    },
    {
        "prompt": "Why is the sky blue?",
        "chosen": "The sky appears blue due to Rayleigh scattering. Sunlight contains all colors of the visible spectrum. As it enters Earth's atmosphere, shorter wavelengths (blue and violet) scatter more than longer wavelengths (red and orange) when they collide with gas molecules. Our eyes are more sensitive to blue than violet, so we perceive the sky as blue.",
        "rejected": "The sky is blue because of the atmosphere. It just scatters light in a way that makes it look blue.",
    },
    # Formatpraeferenz
    {
        "prompt": "List three benefits of exercise.",
        "chosen": "Three key benefits of regular exercise are: 1) Improved cardiovascular health, reducing the risk of heart disease and stroke. 2) Better mental health, as exercise releases endorphins that reduce stress, anxiety, and depression. 3) Enhanced cognitive function, including improved memory, focus, and reduced risk of neurodegenerative diseases.",
        "rejected": "Exercise is good for your heart and mind and body. It helps you in many ways and you should do it regularly because doctors recommend it.",
    },
    {
        "prompt": "What is photosynthesis?",
        "chosen": "Photosynthesis is the biological process by which green plants, algae, and some bacteria convert light energy into chemical energy. Using chlorophyll in chloroplasts, they absorb sunlight and use it to transform carbon dioxide and water into glucose and oxygen. The simplified equation is: 6CO2 + 6H2O + light energy -> C6H12O6 + 6O2.",
        "rejected": "Photosynthesis is how plants make food from sunlight. They use their leaves to capture energy and turn it into sugar.",
    },
    {
        "prompt": "How does encryption work?",
        "chosen": "Encryption converts readable data (plaintext) into unreadable form (ciphertext) using mathematical algorithms and keys. Symmetric encryption uses the same key for encryption and decryption (e.g., AES). Asymmetric encryption uses a public key to encrypt and a private key to decrypt (e.g., RSA). Modern encryption ensures data confidentiality even if intercepted.",
        "rejected": "Encryption scrambles your data so hackers can't read it. It's like a secret code.",
    },
    {
        "prompt": "What causes seasons on Earth?",
        "chosen": "Seasons are caused by Earth's axial tilt of approximately 23.5 degrees relative to its orbital plane around the Sun. This tilt means different hemispheres receive varying amounts of direct sunlight throughout the year. When the Northern Hemisphere tilts toward the Sun, it experiences summer while the Southern Hemisphere has winter, and vice versa.",
        "rejected": "Seasons happen because the Earth moves closer and farther from the Sun during the year.",
    },
]

# Datensatz erweitern
expanded = []
for item in preference_data:
    expanded.append(item)
    expanded.append({
        "prompt": "Q: " + item["prompt"],
        "chosen": item["chosen"],
        "rejected": item["rejected"],
    })
    expanded.append({
        "prompt": "Answer this question: " + item["prompt"],
        "chosen": item["chosen"],
        "rejected": item["rejected"],
    })

print(f"Total preference pairs: {len(expanded)}")

dataset = Dataset.from_list(expanded)
split = dataset.train_test_split(test_size=0.2, seed=42)
train_dataset = split["train"]
test_dataset = split["test"]
print(f"Train: {len(train_dataset)}, Test: {len(test_dataset)}")

# --- 3. Modell laden ---
model_name = "distilbert-base-uncased"
print(f"\nLoading reward model backbone: {model_name}")

tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
    model_name,
    num_labels=1,  # Reward Model gibt einen einzelnen skalaren Score aus
)
print(f"Model parameters: {model.num_parameters() / 1e6:.1f}M")

# --- 4. Datenvorverarbeitung ---
def preprocess_function(examples):
    """Praeferenzpaare in das Reward Model Trainingsformat konvertieren"""
    chosen_texts = [
        p + " [SEP] " + c
        for p, c in zip(examples["prompt"], examples["chosen"])
    ]
    rejected_texts = [
        p + " [SEP] " + r
        for p, r in zip(examples["prompt"], examples["rejected"])
    ]

    chosen_encodings = tokenizer(
        chosen_texts, truncation=True, padding="max_length", max_length=256
    )
    rejected_encodings = tokenizer(
        rejected_texts, truncation=True, padding="max_length", max_length=256
    )

    return {
        "input_ids_chosen": chosen_encodings["input_ids"],
        "attention_mask_chosen": chosen_encodings["attention_mask"],
        "input_ids_rejected": rejected_encodings["input_ids"],
        "attention_mask_rejected": rejected_encodings["attention_mask"],
    }

train_processed = train_dataset.map(preprocess_function, batched=True, remove_columns=train_dataset.column_names)
test_processed = test_dataset.map(preprocess_function, batched=True, remove_columns=test_dataset.column_names)

# --- 5. Reward Model trainieren ---
training_args = RewardConfig(
    output_dir="./reward_model_output",
    num_train_epochs=5,
    per_device_train_batch_size=4,
    per_device_eval_batch_size=4,
    gradient_accumulation_steps=2,
    learning_rate=2e-5,
    weight_decay=0.01,
    logging_steps=5,
    eval_strategy="steps",
    eval_steps=10,
    save_strategy="no",
    max_length=256,
    remove_unused_columns=False,
    report_to="none",
)

trainer = RewardTrainer(
    model=model,
    args=training_args,
    train_dataset=train_processed,
    eval_dataset=test_processed,
    processing_class=tokenizer,
)

print("\nStarting Reward Model training...")
train_result = trainer.train()
print(f"Training complete! Steps: {train_result.global_step}")

# --- 6. Reward Model evaluieren ---
print("\n" + "=" * 60)
print("Reward Model Evaluation")
print("=" * 60)

def get_reward_score(model, tokenizer, prompt, response):
    """Reward-Score des Reward Models fuer ein (Prompt, Response)-Paar abrufen"""
    model.eval()
    text = prompt + " [SEP] " + response
    inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=256, padding=True)
    inputs = {k: v.to(model.device) for k, v in inputs.items()}
    with torch.no_grad():
        outputs = model(**inputs)
    return outputs.logits.item()

# Ranking-Genauigkeit auf den Original-Testdaten berechnen
correct = 0
total = 0
chosen_rewards = []
rejected_rewards = []

for item in preference_data:
    r_chosen = get_reward_score(model, tokenizer, item["prompt"], item["chosen"])
    r_rejected = get_reward_score(model, tokenizer, item["prompt"], item["rejected"])
    chosen_rewards.append(r_chosen)
    rejected_rewards.append(r_rejected)
    if r_chosen > r_rejected:
        correct += 1
    total += 1

accuracy = correct / total
print(f"Ranking Accuracy: {accuracy:.1%} ({correct}/{total})")
print(f"Average Chosen Reward:   {np.mean(chosen_rewards):.4f}")
print(f"Average Rejected Reward: {np.mean(rejected_rewards):.4f}")
print(f"Average Margin:          {np.mean(np.array(chosen_rewards) - np.array(rejected_rewards)):.4f}")

# --- 7. Visualisierung ---
fig, axes = plt.subplots(1, 3, figsize=(18, 5))

# Reward-Verteilung
axes[0].hist(chosen_rewards, bins=10, alpha=0.7, color="#0077b6", label="Chosen", edgecolor="white")
axes[0].hist(rejected_rewards, bins=10, alpha=0.7, color="#e63946", label="Rejected", edgecolor="white")
axes[0].set_xlabel("Reward Score", fontsize=12)
axes[0].set_ylabel("Count", fontsize=12)
axes[0].set_title("Reward Score Distribution", fontsize=14)
axes[0].legend(fontsize=11)
axes[0].grid(True, alpha=0.3)

# Vergleich pro Sample
x_pos = np.arange(len(preference_data))
width = 0.35
axes[1].bar(x_pos - width / 2, chosen_rewards, width, color="#0077b6", label="Chosen", alpha=0.8)
axes[1].bar(x_pos + width / 2, rejected_rewards, width, color="#e63946", label="Rejected", alpha=0.8)
axes[1].set_xlabel("Sample Index", fontsize=12)
axes[1].set_ylabel("Reward Score", fontsize=12)
axes[1].set_title("Per-Sample Reward Comparison", fontsize=14)
axes[1].legend(fontsize=11)
axes[1].grid(True, alpha=0.3, axis="y")

# Trainingsverlustkurve
train_logs = [log for log in trainer.state.log_history if "loss" in log]
if train_logs:
    steps = [log["step"] for log in train_logs]
    losses = [log["loss"] for log in train_logs]
    axes[2].plot(steps, losses, color="#b8922e", linewidth=2)
    axes[2].set_xlabel("Step", fontsize=12)
    axes[2].set_ylabel("Loss", fontsize=12)
    axes[2].set_title("Reward Model Training Loss", fontsize=14)
    axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig("reward_model_results.png", dpi=150, bbox_inches="tight")
plt.show()

# --- 8. Interaktiver Test: Reward-Bewertung fuer benutzerdefinierte Prompts ---
print("\n" + "=" * 60)
print("Interactive Reward Scoring")
print("=" * 60)

test_cases = [
    {
        "prompt": "What is deep learning?",
        "responses": [
            "Deep learning is a subset of machine learning that uses artificial neural networks with multiple layers (hence 'deep') to model and understand complex patterns in data. It excels at tasks like image recognition, natural language processing, and game playing by automatically learning hierarchical representations.",
            "Deep learning is basically AI that uses lots of layers. It's really powerful and can do many things.",
            "Deep learning is a type of machine learning. It uses neural networks to learn from data and make predictions about stuff.",
        ],
    },
    {
        "prompt": "Is it safe to eat raw chicken?",
        "responses": [
            "No, eating raw chicken is not safe. Raw chicken frequently contains harmful bacteria such as Salmonella and Campylobacter, which can cause serious foodborne illness. Always cook chicken to an internal temperature of at least 74 degrees Celsius (165 degrees Fahrenheit) to ensure these pathogens are eliminated.",
            "Sure, some people eat raw chicken in certain cuisines. It should be fine if the chicken is fresh.",
            "I wouldn't recommend it but it probably won't kill you. Just make sure it smells okay.",
        ],
    },
]

for case in test_cases:
    print(f"\nPrompt: {case['prompt']}")
    scores = []
    for i, resp in enumerate(case["responses"]):
        score = get_reward_score(model, tokenizer, case["prompt"], resp)
        scores.append(score)
        print(f"  Response {i + 1} (reward={score:.4f}): {resp[:80]}...")

    # Rangfolge
    ranked = sorted(enumerate(scores), key=lambda x: x[1], reverse=True)
    print(f"  Ranking: {' > '.join([f'R{idx + 1}({s:.3f})' for idx, s in ranked])}")

# --- 9. Bradley-Terry-Praeferenzwahrscheinlichkeiten ---
print("\n" + "=" * 60)
print("Bradley-Terry Preference Probabilities")
print("=" * 60)

def bradley_terry_prob(r1, r2):
    """P(response1 > response2) = sigmoid(r1 - r2)"""
    return torch.sigmoid(torch.tensor(r1 - r2)).item()

for case in test_cases:
    print(f"\nPrompt: {case['prompt'][:50]}...")
    scores = [get_reward_score(model, tokenizer, case["prompt"], r) for r in case["responses"]]
    for i in range(len(scores)):
        for j in range(i + 1, len(scores)):
            prob = bradley_terry_prob(scores[i], scores[j])
            print(f"  P(R{i+1} ≻ R{j+1}) = {prob:.4f}")

print("\nLab 2 Complete!")

8. Entscheidungsrahmen: Wie Unternehmen die richtige Alignment-Strategie waehlen

Angesichts vielfaeltiger Alignment-Technologien muessen Unternehmen auf Basis ihrer Ressourcen, Ziele und Einschraenkungen pragmatische Entscheidungen treffen. Im Folgenden wird ein systematischer Entscheidungsrahmen vorgestellt.

Entscheidungsdimension 1: Datenverfuegbarkeit

DatensituationEmpfohlene MethodeBegruendung
Grosse Menge gepaarter Praeferenzdaten (>10K Paare)RLHF oder DPOBei ausreichenden Daten sind beide aehnlich effektiv, DPO ist wirtschaftlicher
Mittlere Praeferenzdaten (1K-10K Paare)DPODPO ist bei mittlerer Datenmenge stabiler
Nur binaere Labels (gut/schlecht)KTOKeine Paarung erforderlich, Feedback kann aus Produktprotokollen gesammelt werden
Verifizierbare korrekte Antworten vorhandenGRPORegelbasierter Reward benoetigt keine menschliche Annotation
Nahezu keine DatenConstitutional AI / Self-RewardingPrinzipien oder Modell-Selbstbewertung ersetzen menschliche Annotation

Entscheidungsdimension 2: Budget und technische Faehigkeiten

RessourcenniveauEmpfohlene MethodeGeschaetzte Kosten
Hohes Budget (GPU-Cluster + ML-Experten)RLHF (PPO)Hohe Rechenleistung + Annotationskosten
Mittleres Budget (Einzelmaschine Multi-GPU + Ingenieure)DPO oder GRPOMittlere Rechenleistung, niedrige Annotationskosten
Niedriges Budget (Einzelne GPU + Entwickler)KTO oder DPO + LoRAMinimale Rechenleistung, minimale Annotationskosten

Entscheidungsdimension 3: Anwendungsziel

ZielEmpfohlene MethodeErlaeuterung
Allgemeiner Chat-AssistentRLHF oder DPOBalance zwischen Nuetzlichkeit und Sicherheit erforderlich
Mathematik-/Code-ReasoningGRPOKorrektheit kann als regelbasierter Reward verwendet werden
Domaenenspezifischer AssistentDPO + Domaenen-PraeferenzdatenKostenkontrolliert und stabile Ergebnisse
Sicherheits-AlignmentConstitutional AI + RLHFPrinzipiensteuerung + menschliche Ueberwachung
Kontinuierliche VerbesserungSelf-Rewarding + DPO iterativAutomatisierte iterative Optimierung

Kosten-Nutzen-Analyse

Return on Investment der Alignment-Methoden (Schaetzung):

                 Initialinvestition    Wartungskosten    Alignment-Qualitaet    Geeigneter Massstab
RLHF (PPO):      $$$$$                $$$               ★★★★★                 10B+ Modelle
DPO:             $$                   $                 ★★★★                  1B-70B Modelle
KTO:             $                    $                 ★★★                   1B-13B Modelle
GRPO:            $$$                  $$                ★★★★★                 Reasoning-Aufgaben
Self-Rewarding:  $$                   $                 ★★★                   Forschungsphase

Typische ROI-Szenarien:
  - Startup: DPO + LoRA Fine-Tuning eines 7B-Modells → Bestes Preis-Leistungs-Verhaeltnis
  - Mittelstaendisches Unternehmen: DPO Fine-Tuning eines 13B-70B-Modells → Balance zwischen Qualitaet und Kosten
  - Grosses Technologieunternehmen: Vollstaendige RLHF-Pipeline → Hoechste Qualitaet
  - Forschungsteam: GRPO zur Erforschung von Reasoning-Faehigkeiten → Durchbrueche an der Forschungsfront

9. Fazit und Ausblick

Von Christiano et al.[2], die 2017 im Bereich der Robotersteuerung "Lernen aus menschlichen Praeferenzen" vorschlugen, ueber InstructGPT[1], das 2022 RLHF systematisch auf Sprachmodelle anwendete, bis hin zu DeepSeek-R1[7], das 2025 mit reinem RL Reasoning-Faehigkeiten aktivierte -- die Alignment-Technologie hat in nur wenigen Jahren eine revolutionaere Entwicklung durchlaufen.

Einige bemerkenswerte Trends:

Alignment ist nicht nur ein technisches Problem, sondern auch eine philosophische Frage: An welchen "menschlichen Werten" soll sich die KI eigentlich orientieren? Wessen Werte? Wie kann ein Gleichgewicht zwischen verschiedenen Kulturen und Gruppen gefunden werden? Die Antworten auf diese Fragen werden die Zukunft der KI tiefgreifend praegen.

Fuer Praktikerinnen und Praktiker lautet die Empfehlung dieses Artikels: Beginnen Sie mit DPO. Es ist derzeit die am einfachsten zu implementierende und kosteneffizienteste Alignment-Methode. Wenn Ihr Modellmassstab und Ihre Qualitaetsanforderungen wachsen, ziehen Sie die vollstaendige RLHF-Pipeline in Betracht oder erkunden Sie die Aktivierung von Reasoning-Faehigkeiten mit GRPO. Die Entwicklung der Alignment-Technologie zeigt uns: Die beste Methode ist oft die einfachste -- solange die Mathematik stimmt.