Der Transformer, die vollständige Architektur

Der Transformer, die vollständige Architektur

Artikel 7 von 8 · Serie: Wie LLMs funktionieren

In Teil 6 haben wir den Mechanismus kennengelernt, der alles veränderte. Attention erlaubt jedem Token, jedes andere im Kontext direkt zu sehen, in einer einzigen Matrix-Multiplikation. Keine Notizblöcke mehr, keine Stille Post.

Aber Attention allein ist noch kein Sprachmodell. Drei Bausteine fehlen, und ohne sie würde das Ganze nicht funktionieren. In diesem Artikel ergänzen wir sie, setzen alles zu einem vollständigen Block zusammen, stapeln mehrere davon zu einer Architektur, und schauen wie aus diesem Konstrukt GPT, BERT, Llama und Claude wurden.

Drei Lücken, die Attention nicht schließt

Bevor wir bauen, schauen wir nochmal genau hin, was im Mechanismus aus Artikel 6 fehlt.

Position. Self-Attention ist permutationsinvariant. Wenn wir die Tokens einer Sequenz vertauschen, ändert sich am Ergebnis fast nichts. Für mathematische Operationen ist das eine schöne Eigenschaft. Für Sprache ist es eine Katastrophe. Hund beißt Mann und Mann beißt Hund landen in einer Self-Attention-Schicht im selben Output-Raum. Wir müssen dem Modell beibringen, dass Reihenfolge zählt.

Tiefe. Eine einzelne Attention-Schicht macht eine einzige gewichtete Mischung. Das ist mächtig, aber begrenzt. Sprache hat hierarchische Struktur — Wörter bilden Phrasen, Phrasen bilden Sätze, Sätze bilden Argumente. Eine Schicht kann eine Mischung machen. Für hierarchisches Verständnis brauchen wir mehrere, hintereinander.

Stabilität. Tiefe Stapel kämpfen mit Vanishing Gradients aus Artikel 5. Der Gradient bei Backpropagation wird durch jede Schicht hindurch multipliziert, und wenn die Werte im Schnitt unter 1 liegen, schrumpft er gegen null. Ohne Gegenmaßnahmen wird ein Stapel aus zwölf, geschweige denn 96 Attention-Schichten beim Training kollabieren.

Drei Probleme, drei Lösungen. Fangen wir mit der Position an.

Position, Tokens kennen ihren Platz

Self-Attention bekommt eine Sequenz von Token-Embeddings. Jedes Token vergleicht sich mit jedem anderen, gewichtet die Values entsprechend, fertig. Es gibt keine Stelle, an der das Modell weiß, wo ein Token in der Sequenz steht.

Die Lösung sind Positional Encodings. Wir geben jedem Embedding eine zusätzliche Information mit: „Du bist Token 1", „Du bist Token 2", „Du bist Token 17". Konkret addieren wir auf jedes Embedding einen Positions-Vektor.

def add_positional(embeddings, positions):
    # embeddings: (n, d_model)
    # positions:  (n, d_model)
    return embeddings + positions

Eine Zeile. Aber die Frage ist: woher kommt der Positions-Vektor?

Sinusoidal Positional Encoding

Die Originalarbeit von 2017 nutzt eine geschlossene Form aus Sinus- und Kosinus-Wellen mit unterschiedlichen Frequenzen:

PE(pos, 2i)   = sin(pos / 10000^(2i/d))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d))

Klingt kompliziert, ist aber elegant. Jede Dimension oszilliert mit einer anderen Frequenz, niedrige Dimensionen langsam, hohe Dimensionen schnell. Position 0 bekommt ein anderes Wellenmuster als Position 1, Position 17 wieder ein anderes. Das Modell kann aus diesen Mustern die Position herauslesen.

Der eigentliche Trick: weil Sinus und Kosinus periodische Funktionen sind, können beliebig viele Positionen kodiert werden, ohne dass die Encoding-Tabelle endlich groß sein muss. Ein Modell trainiert auf Sequenzen bis Länge 512 kann theoretisch auch bei Länge 1000 noch sinnvolle Encodings bekommen, weil die Wellen einfach weiterlaufen.

Vier Sinuswellen unterschiedlicher Frequenz, mit drei Positionen markiert, jede ein eindeutiger Wertesatz

Die Grafik macht das Prinzip sichtbar: jede Dimension oszilliert mit einer eigenen Frequenz, von langsam (DIM 0) bis schnell (DIM 3). An jeder Position liest das Modell aus allen Dimensionen ein Wertepaar ab — die Kombination ist nirgends gleich. Position 3, Position 7 und Position 11 sehen für das Modell deshalb unterscheidbar aus, ohne dass irgendwo eine Position-ID hingeschrieben wäre.

Learned Positional Embeddings

GPT-2 und BERT gehen einen anderen Weg. Jede Position bekommt einen lernbaren Embedding-Vektor, genauso wie Tokens einen lernbaren Embedding-Vektor bekommen (Artikel 2). Position 1, Position 2, … Position 1024 — jede ist ein eigener Eintrag in einer Embedding-Tabelle. Das Modell lernt selbst, was eine bestimmte Position bedeutet.

Vorteil: flexibler. Nachteil: hart begrenzt auf die Trainings-Länge. Jenseits der maximalen Position kennt das Modell keine Vektoren und produziert Unsinn.

RoPE und ALiBi, die modernen Varianten

Llama, Claude und die meisten aktuellen Modelle nutzen RoPE (Rotary Position Embedding). Statt einen Positions-Vektor zu addieren, rotiert RoPE die Query- und Key-Vektoren um einen positionsabhängigen Winkel. Der Unterschied zwischen zwei Positionen wird so direkt in das Skalarprodukt der Attention eingebaut.

Drei Q-Vektoren an Positionen 0, 4 und 8, jeweils um einen positionsabhängigen Winkel im Q/K-Raum rotiert

Praktischer Effekt: relative Positionen sind dem Modell direkt zugänglich. Token an Position 5 weiß automatisch, dass Token an Position 7 zwei Schritte weiter rechts ist. Im Skalarprodukt von Q und K bleibt nur die Winkeldifferenz übrig, also genau die relative Distanz — der absolute Positionswert fällt heraus. Funktioniert besser für lange Kontexte und extrapoliert besser über die Trainings-Länge hinaus.

ALiBi (Attention with Linear Biases) macht es noch einfacher: einen positionsabhängigen Bias direkt auf die Attention-Scores addieren, der mit Distanz linear abnimmt. Keine Encoding-Vektoren nötig, kaum zusätzliche Parameter, sehr robust für Extrapolation.

Welche Methode du wählst, hängt vom Modell ab. Für unser konzeptionelles Verständnis reicht: jedes Token kennt seine Position, irgendwie.

Feed-Forward, das vergessene Drittel

Self-Attention ist nur die halbe Miete eines Transformer-Blocks. Direkt nach Attention kommt eine zweite Komponente, die im Originalpaper fast beiläufig erwähnt wird, aber tatsächlich den Großteil der Modellparameter ausmacht: das Feed-Forward Network, kurz FFN.

Die Struktur ist denkbar einfach. Zwei lineare Schichten mit einer Aktivierung dazwischen:

def feed_forward(x, W_1, W_2):
    """Zwei Linear-Layer, eine Aktivierung dazwischen."""
    h = relu(x @ W_1)        # (n, d_model) -> (n, d_ff)
    return h @ W_2            # (n, d_ff)    -> (n, d_model)

Die innere Dimension d_ff ist meist viermal so groß wie d_model. Bei d_model = 768 arbeitet das FFN intern also mit 3072-dimensionalen Vektoren, bevor es wieder auf 768 zurück projiziert. Aufweiten, transformieren, zurückprojizieren.

Wichtig: das FFN wird pro Token angewandt. Anders als Attention, wo Tokens miteinander reden, behandelt das FFN jedes Token isoliert. Es ist eine punktweise Verarbeitung, also komplett parallelisierbar. Token i sieht nichts von Token j im FFN.

Warum ist das überhaupt da?

Auf den ersten Blick wirkt das FFN trivial im Vergleich zu Attention. Warum ist es trotzdem in jedem Block?

Nichtlinearität. Self-Attention ist im Wesentlichen eine gewichtete Mischung von Vektoren — linear, abgesehen vom Softmax. Ohne FFN könnte das Netz keine komplexen, nichtlinearen Funktionen lernen. Die ReLU (oder GELU in modernen Modellen) bringt die nichtlineare Verarbeitung rein, die das Netz braucht, um aus einer Mischung tatsächlich neue Bedeutungen zu konstruieren.

Speicher. Ein interessanter Befund neuerer Forschung: das FFN ist wahrscheinlich der Ort, an dem Faktenwissen gespeichert wird. Attention sucht und mischt, FFN speichert und transformiert. Bei großen Modellen liegen rund zwei Drittel der Parameter im FFN, ein Drittel in Attention. Wenn du wissen willst wo „Paris ist die Hauptstadt von Frankreich" im Modell sitzt, ist das FFN der erste Verdächtige.

Aber wo genau? „Erster Verdächtiger" ist nicht dasselbe wie „Tatort", und die ehrliche Antwort lautet: wir wissen es nicht.

Studien wie ROME (Meng et al. 2022) und MEMIT (2023) haben gezeigt, dass sich Faktenpaare durch gezielte Eingriffe in einzelne FFN-Schichten editieren lassen. Aus „Paris ist die Hauptstadt von Frankreich" wird mit ein paar veränderten Gewichten „Paris ist die Hauptstadt von Italien". Funktioniert. Aber unsauber:

Vor dem Edit:
  „Paris ist die Hauptstadt von ___"   →  Frankreich
  „Wo wurde Napoleon gekrönt?"         →  Notre-Dame in Paris
  „Sprechen die Pariser Französisch?"  →  Ja

Nach ROME-Edit (Paris → Italien):
  „Paris ist die Hauptstadt von ___"   →  Italien     [wie gewünscht]
  „Wo wurde Napoleon gekrönt?"         →  Rom         [Leak]
  „Sprechen die Pariser Italienisch?"  →  Ja          [Leak]

Edits leaken auf verwandte Fakten, generalisieren schlecht, hinterlassen Inkonsistenzen. Genug, um zu sagen „FFN ist beteiligt". Nicht genug, um zu sagen „FFN ist der Speicherort".

Der tiefere Grund liegt in der Architektur selbst. Wissen ist im Modell verteilt, nicht lokalisiert: eine einzelne Tatsache lebt in einem Muster über viele Neuronen und meist über mehrere Schichten. Umgekehrt repräsentiert ein einzelnes Neuron nicht einen Begriff, sondern viele gleichzeitig. Anthropics Forschung zur Superposition (Elhage et al. 2022) erklärt warum: Modelle quetschen deutlich mehr Konzepte unter, als sie Dimensionen haben, indem sie Bedeutungen überlagern.

Superposition: fünf Feature-Richtungen in zwei Dimensionen, Vektoren überlagern sich

In zwei Dimensionen lassen sich fünf konzeptuell unterschiedliche Features zwar unterbringen — aber nicht orthogonal. Die Vektoren überlagern sich, mit Interferenz, aber funktionsfähig. Skaliert auf Tausende Dimensionen entsteht eine dichte Überlagerung, in der ein einzelnes Neuron zigtausend Mikro-Konzepte gleichzeitig kodiert.

Wie konkret das wird, zeigte Anthropics „Scaling Monosemanticity" (Templeton et al. 2024): Mit Sparse Autoencoders extrahierten die Forscher aus den Aktivierungen von Claude 3 Sonnet Millionen interpretierbare Features — von „Golden Gate Bridge" über „Code-Bug" bis zu „Schmeichelei". Klemmt man die „Golden Gate Bridge"-Feature-Richtung künstlich auf maximalen Wert, faselt das Modell in jeder Antwort von der Brücke. Das Feature ist real, lokalisierbar, manipulierbar. Aber es lebt nicht in einem Neuron, sondern als Richtung in einem hochdimensionalen Aktivierungsraum, gefunden mit einem speziell trainierten Hilfsmodell.

Die Folgearbeit „On the Biology of a Large Language Model" (Anthropic, März 2025) hat das Verfahren auf Claude 3.5 Haiku erweitert und mit Attribution Graphs und Circuit Tracing dokumentiert, wie das Modell mehrstufige Operationen intern auflöst — Reim-Planung beim Dichten, mehrsprachiges Reasoning über eine sprachübergreifende Repräsentation, mathematische Heuristiken statt symbolischer Regeln. Die Methodik ist damit über mehrere Modellgenerationen hinweg etabliert.

Trotzdem: für die aktuellen Frontier-Modelle der 4.x- und 5.x-Generation gibt es bisher keine öffentliche Interpretierbarkeitskarte vergleichbarer Tiefe. Das ist kein Zufall, sondern strukturell — Interpretierbarkeitsforschung braucht Zugriff auf Modell-Internals, gründliche Analyse, und Zeit für die Aufbereitung. Sie hängt der Release-Kadenz neuer Modelle systematisch hinterher.

Was bleibt, sind interventionelle Hinweise und gefundene Strukturen für ältere Modelle, keine Klartextkarten für die aktuellen. Wir wissen, dass Eingriffe ins FFN Faktenrecall verändern. Wir wissen, dass sich kohärente Features extrahieren lassen. Wir wissen nicht, ob das Wissen dort gespeichert ist oder nur abgegriffen wird — und für die Modelle, mit denen wir heute tatsächlich arbeiten, kennen wir nur einen Bruchteil der Antworten, die für ihre Vorgänger publik sind.

GLU und SwiGLU, die modernen Varianten

Llama und einige andere moderne Modelle nutzen Variationen mit Gates:

def swiglu_ff(x, W_gate, W_up, W_down):
    """SwiGLU FFN, wie in Llama."""
    return (silu(x @ W_gate) * (x @ W_up)) @ W_down

Der * ist elementweise Multiplikation, ein Gate, das entscheidet welche Anteile durchgelassen werden. Empirisch besser als die Original-FFN, aber konzeptionell dasselbe Schema: erst aufweiten, dann zurückprojizieren.

Residual Connections, der direkte Draht

Wir haben jetzt zwei große Operationen pro Block: Multi-Head Attention und Feed-Forward. Beide ändern den Vektor jedes Tokens substantiell. Wenn wir mehrere Blöcke stapeln, propagieren wir diese Änderungen durch viele Schichten — und genau hier wird es kritisch.

Aus Artikel 5 erinnern wir uns an Vanishing Gradients. Tiefe Netze können beim Training kollabieren, weil das Gradient-Signal beim Rückwärts-Lauf immer schwächer wird, multipliziert mit jeder Schicht.

Die Lösung kommt aus dem ResNet-Umfeld der Bildverarbeitung von 2015 und ist atemberaubend simpel: Residual Connections. Statt nur den Output einer Operation weiterzugeben, addieren wir den Input dazu:

output = x + sublayer(x)

Eine Zeile. Aber konzeptionell der wichtigste Trick im Transformer.

Die Idee dahinter: das Modell lernt nicht „der neue Vektor ist X", sondern „der neue Vektor ist X plus ein paar Anpassungen". Wenn die Anpassungen schädlich wären, kann das Modell sie auf null lernen, und der Input fließt unverändert weiter. Das macht Tiefe trainierbar. Beim Backward Pass hat der Gradient einen direkten Pfad zurück durch jede Residual Connection, ohne durch die Sub-Operation hindurchzumüssen.

Vergleich: Stack ohne Residual Connection (Input nur durch alle Operationen) vs. mit Residual Connection (zusätzlicher direkter Bypass-Pfad zum Output)

Visuell ist der Unterschied klein, in der Wirkung dramatisch: links muss jedes Signal — beim Forward Pass die Aktivierungen, beim Backward Pass die Gradienten — komplett durch jede Operation hindurch. Rechts gibt es zusätzlich einen direkten Pfad. Wenn die Operationen kollabieren oder dämpfen, bleibt das Signal über den Bypass erhalten. Das ist der Trick, der Stapel mit 96 oder 126 Schichten überhaupt trainierbar macht.

Im Transformer-Block kommt eine Residual Connection nach jeder Sub-Operation, eine nach Attention und eine nach Feed-Forward.

Layer Normalization, die Stabilisierung

Mit Residual Connections können wir tief stapeln. Aber tiefe Stapel haben ein anderes Problem: Werte können explodieren oder kollabieren. Nach 50 oder 100 Schichten sind aus normal verteilten Embeddings vielleicht Vektoren mit gigantischen oder mikroskopischen Magnituden geworden. Die nächste Operation arbeitet auf instabilen Werten, der Trainingslauf entgleist.

Layer Normalization stabilisiert das. Pro Token wird der Mittelwert auf 0 und die Varianz auf 1 normalisiert:

def layer_norm(x, gamma, beta, eps=1e-5):
    """Normalisiert pro Token, nicht pro Batch."""
    mean = x.mean(axis=-1, keepdims=True)
    var  = x.var(axis=-1, keepdims=True)
    return gamma * (x - mean) / np.sqrt(var + eps) + beta

gamma und beta sind lernbare Skalierungs- und Shift-Parameter. Das Modell kann also entscheiden, wie stark es normalisieren will, und nach der Normalisierung den Wertebereich neu setzen.

Wichtig: LayerNorm normalisiert pro Token über die Feature-Dimension. Das ist anders als Batch Normalization (aus der Bildverarbeitung), die pro Feature über den Batch normalisiert. LayerNorm hat den Vorteil, unabhängig von der Batchgröße zu funktionieren, was bei Sprachmodellen mit variabler Sequenzlänge essentiell ist.

Pre-LN vs Post-LN

Im Originalpapier kommt LayerNorm nach der Sub-Operation und Residual:

# Post-LN, wie im Original-Paper
x = layer_norm(x + multi_head_attention(x))
x = layer_norm(x + feed_forward(x))

Moderne Modelle nutzen meist Pre-LN, LayerNorm wird vor der Sub-Operation angewendet:

# Pre-LN, wie in GPT-2 und allen modernen Modellen
x = x + multi_head_attention(layer_norm(x))
x = x + feed_forward(layer_norm(x))

Empirisch trainiert Pre-LN deutlich stabiler bei tiefen Modellen. Der Hauptzweig (x + ...) bleibt unangetastet, die Normalisierung passiert nur im „Seitenpfad" der Sub-Operation. Der direkte Residual-Pfad ist sauber, der Gradient kann ungestört zurückfließen.

RMSNorm, die schlankere Variante

Llama und einige neuere Modelle nutzen RMSNorm statt LayerNorm. RMSNorm verzichtet auf die Mittelwert-Subtraktion und normalisiert nur über die Wurzel des mittleren Quadrats:

def rms_norm(x, gamma, eps=1e-5):
    rms = np.sqrt((x**2).mean(axis=-1, keepdims=True) + eps)
    return gamma * x / rms

Weniger Berechnung, fast identische Ergebnisse. Ein typisches Beispiel für die pragmatischen Vereinfachungen, die in modernen Architekturen einfließen.

Der vollständige Block

Jetzt setzen wir alles zusammen. Ein Transformer-Block in der Pre-LN-Variante, wie sie heute Standard ist:

def transformer_block(x, attn, ffn, ln1, ln2):
    """Ein vollständiger Transformer-Block."""
    # Attention sublayer
    x = x + multi_head_attention(layer_norm(x, *ln1), *attn)
    # Feed-forward sublayer
    x = x + feed_forward(layer_norm(x, *ln2), *ffn)
    return x

Datenfluss durch einen Transformer-Block: x geht durch LayerNorm, Multi-Head Attention, wird per Residual mit dem ursprünglichen x verrechnet, dann durch LayerNorm, Feed-Forward, und wieder per Residual zum Output verrechnet

Vier Operationen pro Block: zwei LayerNorms, eine Attention, ein Feed-Forward. Alle eingerahmt in Residual Connections. Das ist der Baustein, aus dem durch Stapeln das gesamte Modell entsteht.

Wenn wir die Bauteile durchzählen — Multi-Head Attention mit h Heads à d_k Dimensionen, FFN mit 4·d_model innerer Breite, plus zwei LayerNorms — landen wir bei wenigen Millionen Parametern pro Block. Bei d_model = 4096 und d_ff = 16384, wie in Llama 2 7B, sind es etwa 200 Millionen Parameter pro Block.

Parameteranzahl im Detail

Pro Transformer-Block (ohne Embeddings) sind die Parameter:

  • Attention: vier Matrizen W_Q, W_K, W_V, W_O, jeweils d_model × d_model. Das sind 4 · d_model² Parameter.
  • Feed-Forward: zwei Matrizen W_1 (Größe d_model × d_ff) und W_2 (Größe d_ff × d_model). Mit d_ff = 4·d_model sind das 8 · d_model² Parameter. Plus zwei Bias-Vektoren mit d_ff + d_model Werten.
  • LayerNorm: zwei Stück mit jeweils 2·d_model Parametern (gamma, beta).

In Summe etwa 12 · d_model² + 13·d_model Parameter pro Block. Dominiert von den d_model²-Termen, von denen zwei Drittel im FFN stecken.

Bei d_model = 4096 (Llama 2 7B Konfiguration):

  • Attention: 4 · 4096² ≈ 67M
  • Feed-Forward: 8 · 4096² ≈ 134M (mit SwiGLU sind es noch mehr)
  • LayerNorm: vernachlässigbar

Total etwa 200M Parameter pro Block. Bei 32 Blöcken landen wir bei rund 6,4 Milliarden — und dann kommt noch das Embedding-Layer dazu (Vokabulargröße V mal d_model, also rund 130M bei V = 32000). Macht zusammen die ~6,7 Milliarden, die das Llama 2 7B Modell hat.

Tiefe durch Stapeln

Ein einzelner Block ist eine Mischung. Mehrere Blöcke hintereinander sind eine Reihe von Mischungen. Jeder Block bekommt den Output des vorherigen als Input und arbeitet weiter darauf:

def transformer(x, blocks_params):
    for params in blocks_params:
        x = transformer_block(x, *params)
    return x

Wie viele Blöcke nutzen reale Modelle?

ModellSchichtend_modelHeads
Original Transformer (2017)65128
BERT-Base1276812
BERT-Large24102416
GPT-2 (1.5B)48160025
GPT-3 (175B)961228896
Llama 3 70B80819264
Llama 3 405B12616384128

Mit jeder Schicht hat das Modell eine zusätzliche Möglichkeit, Information zu verarbeiten. Was passiert in den verschiedenen Schichten? Die Forschung zur Mechanistischen Interpretierbarkeit hat hier in den letzten Jahren erstaunliche Einblicke geliefert.

Empirisch beobachten Forscher eine Hierarchie:

  • Untere Schichten verarbeiten oberflächliche Strukturen: Wortgrenzen, einfache Syntax, lokale Phrasen.
  • Mittlere Schichten behandeln komplexere Syntax und Bedeutung: Subjekt-Verb-Beziehungen, Koreferenzen, semantische Rollen.
  • Obere Schichten integrieren weltbezogenes Wissen, abstrakte Konzepte, Argumentationsmuster.

Stapel aus zwölf Transformer-Blöcken, in drei Zonen gegliedert: untere Schichten (Wortgrenzen, lokale Phrasen, einfache Syntax), mittlere Schichten (Subjekt-Verb-Beziehungen, Koreferenzen, semantische Rollen), obere Schichten (Weltwissen, Argumentation, abstrakte Konzepte)

Diese Hierarchie ist nicht hart einprogrammiert. Sie taucht während des Trainings auf, weil sie sich auszahlt. Dieselbe Beobachtung gilt für tiefe Convolutional Networks in der Bildverarbeitung — untere Layer detektieren Kanten, obere ganze Objekte. Tiefe Transformer machen das Analoge für Sprache. Die Architektur trägt eine Hierarchie nicht ein, aber sie ermöglicht sie.

Encoder, Decoder oder beides

Die Originalarbeit von 2017 stellte einen Encoder-Decoder-Transformer vor, gedacht für maschinelle Übersetzung. Zwei Türme aus Blöcken:

  • Der Encoder verarbeitet den Quellsatz, jedes Token sieht alle anderen, kein Causal Mask.
  • Der Decoder generiert den Zielsatz, sieht nur was bereits generiert wurde, mit Causal Mask aus Artikel 6.
  • Cross-Attention verbindet beide Türme: der Decoder fragt mit Q den Encoder-Output mit K/V (auch das aus Artikel 6).

Aber 2018 zeigten zwei Papers, dass die zwei Hälften auch unabhängig nützlich sind. Das hat die ganze Landschaft umgekrempelt.

Drei Architektur-Varianten im Vergleich: Encoder-Only (BERT) für Klassifikation, Decoder-Only (GPT, Claude, Llama) für Generation, und Encoder-Decoder (T5) für Übersetzung mit Cross-Attention zwischen beiden Türmen

BERT, der Encoder-Only-Spezialist

BERT (2018, Google) nutzt nur den Encoder-Teil. Bidirektionale Attention, kein Causal Mask, jedes Token sieht alle anderen. Trainiert wird mit Masked Language Modeling: einzelne Tokens werden zufällig maskiert, das Modell soll sie aus dem Kontext links und rechts vorhersagen.

BERT generiert keinen Text, aber es liefert ausgezeichnete kontextualisierte Embeddings. Für Klassifikation, Suche, Question Answering, Named Entity Recognition ist es bis heute die Grundlage vieler Systeme. Wenn du irgendeine NLP-Pipeline siehst, die nicht generiert sondern klassifiziert oder extrahiert, ist die Wahrscheinlichkeit hoch, dass darunter ein BERT-artiges Encoder-Only-Modell läuft.

GPT, der Decoder-Only-Sprachmodell

GPT (2018, OpenAI) ging den umgekehrten Weg: nur Decoder, mit Causal Mask. Trainiert wird mit klassischem Language Modeling, also dem Trick aus Artikel 1: sage das nächste Wort vorher, gegeben alle vorherigen.

Konzeptionell einfacher als BERT, aber skaliert phantastisch. GPT-2 (2019), GPT-3 (2020), GPT-4 (2023), ChatGPT, Claude, Llama, Mistral — alle aktuellen Generative-AI-Modelle sind Decoder-Only-Transformer im Geiste von GPT.

Der Vorteil: reine Autoregression, kein Encoder nötig, einfache Inferenz. Der Nachteil: jedes Token sieht nur Vergangenheit, keine bidirektionale Information. Hat sich aber als nicht so wichtig herausgestellt — mit genug Skalierung und cleverer Aufgabenstellung holt Decoder-Only fast alle Encoder-Vorteile auf.

T5 und Co, die ursprüngliche Form

Manche Modelle nutzen weiterhin die volle Encoder-Decoder-Architektur. T5 (Google) modelliert alle NLP-Aufgaben als Text-zu-Text und nutzt einen klassischen Encoder-Decoder. Auch viele Übersetzungs- und Zusammenfassungsmodelle bleiben bei der Variante.

In der Praxis dominiert heute aber Decoder-Only. Die Pipeline ist einfacher, das Training homogener, und das Skalierungsverhalten besser verstanden. Wenn du einen Chat-Assistenten siehst, ist dahinter mit hoher Wahrscheinlichkeit ein Decoder-Only-Transformer.

Vom Block zum Sprachmodell

Wir haben jetzt einen Stapel von Transformer-Blöcken. Damit das ein Sprachmodell wird, fehlen noch zwei Stücke an den Enden.

Vorne: Token-Embeddings + Positional Encoding. Eingaben sind Token-IDs aus dem Tokenizer (Artikel 1), also Zahlen. Die werden über eine Embedding-Tabelle in Vektoren verwandelt (Artikel 2), Positional Encodings draufaddiert oder über RoPE eingebaut, dann geht’s in den ersten Block.

Hinten: Output Head. Nach dem letzten Block haben wir für jedes Token einen kontextualisierten Vektor. Den projizieren wir über eine lineare Schicht auf die Größe des Vokabulars und schicken einen Softmax drüber. Heraus kommt eine Wahrscheinlichkeitsverteilung über das nächste Token.

def language_model(token_ids, params):
    x = embed(token_ids, params.embeddings)
    x = x + positional_encoding(len(token_ids))

    for block_params in params.blocks:
        x = transformer_block(x, *block_params)

    x = layer_norm(x, params.final_ln)
    logits = x @ params.embeddings.T   # tied embeddings
    return logits

Das ist die komplette Pipeline. Ein paar Dutzend Zeilen Python für ein konzeptionelles Sprachmodell. In echten Implementierungen kommen Effizienz-Optimierungen wie KV-Cache, Flash Attention und Mixed Precision dazu, aber die Architektur bleibt im Kern dieselbe.

Ein Detail: in vielen Modellen werden die Embedding-Gewichte und die Output-Projektion miteinander geteilt. Die Tabelle, die Token-IDs zu Vektoren macht, ist dieselbe (transponiert), die am Ende Vektoren wieder zu Logits macht. Das nennt man Tied Embeddings und spart Parameter, ohne dass die Performance leidet.

Skalierung, das eigentliche Geheimnis

Die Architektur, die wir gerade beschrieben haben, ist seit 2017 erstaunlich stabil geblieben. GPT-1 von 2018 hat dieselbe Grundstruktur wie Llama 3 von 2024. Was sich geändert hat, ist die Skalierung.

ModellJahrParameterTrainings-Tokens
Original Transformer201765M~10B
BERT-Large2018340M~3B
GPT-220191.5B~10B
GPT-32020175B~300B
Llama 2 70B202370B2T
Llama 3 70B202470B15T
Llama 3 405B2024405B15T
GPT-4 (geschätzt)2023~1.5T?

Mehr Parameter, mehr Daten, längeres Training. Die OpenAI-Forscher zeigten 2020 mit den Scaling Laws, dass die Performance vorhersagbar besser wird, wenn man Parameter, Daten und Compute proportional skaliert. Das hat die ganze Branche umgekrempelt: aus „wir brauchen klügere Architekturen" wurde „wir brauchen mehr Rechenleistung und mehr Daten".

Die Architektur-Verfeinerungen seit 2017 sind eher Mikro-Optimierungen — RoPE statt Sinusoidal Encodings, GQA (Grouped-Query Attention) für Inferenz-Effizienz, RMSNorm statt LayerNorm, SwiGLU statt ReLU oder GELU. Alles wichtig, aber nichts davon ändert das Grundkonzept. Der Transformer von 2017 ist immer noch der Transformer von 2025.

Was ein skalierter Transformer wirklich kann

Mit der Architektur und genug Skalierung entsteht etwas, das Forscher 2017 nicht erwartet hätten. Emergente Fähigkeiten tauchen ab einer kritischen Modellgröße auf, ohne dass jemand sie explizit eingebaut hätte:

  • Few-Shot Learning — das Modell lernt eine neue Aufgabe aus zwei, drei Beispielen im Prompt, ohne dass Gewichte angepasst werden.
  • Reasoning — Schritt-für-Schritt-Argumentation in mehrteiligen Problemen, oft besser wenn man das Modell explizit zum „Nachdenken" auffordert (Chain-of-Thought).
  • Code-Generierung — aus natürlicher Sprache lauffähigen Code in Python, JavaScript, Rust oder Go produzieren.
  • Tool Use — Werkzeuge wie Suchmaschinen, Rechner, APIs gezielt einsetzen.
  • In-Context Learning — Muster aus dem Prompt aufgreifen und weiterführen, auch bei völlig neuen Symbolen oder Sprachen.

Diese Fähigkeiten sind nicht hart einprogrammiert. Sie entstehen, weil ein hinreichend großes Modell auf hinreichend viel Text trainiert wurde, das nächste Token vorherzusagen. Mehr nicht. Es ist nach wie vor eines der erstaunlichsten Phänomene der Informatik der letzten Jahre.

Ob das „echtes Verstehen" ist oder nur ein sehr guter statistischer Trick, die Frage ist offen und wird vielleicht nie sauber beantwortet werden. Praktisch funktioniert es jedenfalls. Und die Architektur, die das ermöglicht, ist genau die, die wir hier gerade gebaut haben.

Was im nächsten Teil kommt

Wir haben jetzt ein Basismodell, einen sogenannten Foundation Model. Es kann Text vervollständigen, weil es genau darauf trainiert wurde. Aber wenn du ChatGPT eine Frage stellst, willst du eine hilfreiche Antwort bekommen, keine wahrscheinlichste Vervollständigung. Wenn du Claude um Code bittest, soll es Code schreiben, nicht über Code schwadronieren. Wenn du nach einer Bombenbauanleitung fragst, soll das Modell ablehnen, statt sie auszugeben.

Der Sprung vom Basismodell zum Assistenten ist das Thema von Artikel 8: Fine-Tuning. Wir schauen uns an:

  • Supervised Fine-Tuning (SFT) — das Modell auf gewünschtes Verhalten trainieren, mit kuratierten Frage-Antwort-Paaren.
  • RLHF (Reinforcement Learning from Human Feedback) — aus menschlichem Feedback lernen, was eine gute Antwort ist.
  • DPO und neuere Methoden — wie man RLHF einfacher und stabiler macht.
  • Instruction Tuning und Chat-Templates — die Pipeline, die aus GPT-3 ChatGPT gemacht hat.
  • Alignment — das Modell mit menschlichen Werten in Einklang bringen, oder zumindest in dieselbe Nachbarschaft.

Damit schließt sich die Serie. Wir haben dann das vollständige Bild: vom einzelnen Token im ersten Artikel bis zum produktionsfertigen Assistenten.

Alle Artikel der Serie

  1. Das nächste Wort, wie Sprachmodelle funktionieren
  2. Wörter als Punkte im Raum, was Embeddings wirklich sind
  3. Neuronale Netze von Grund auf
  4. Backpropagation, wie ein Modell lernt
  5. Kontext und RNNs, warum Reihenfolge zählt
  6. Attention Is All You Need
  7. Der Transformer, die vollständige Architektur ← dieser Artikel
  8. Fine-Tuning, vom Basismodell zum Assistenten (erscheint demnächst)

Serie: Wie LLMs funktionieren · rotecodefraktion.de