Ein Sprachmodell rät das nächste Zeichen
ChatGPT, Claude und alle anderen großen Sprachmodelle machen im Kern genau eine Sache: Sie bekommen einen Text und berechnen für jedes mögliche nächste Token eine Wahrscheinlichkeit. Eins davon wird gezogen und angehängt, dann geht es von vorn los. Mehr passiert beim „Schreiben“ nicht.
Hier baust du so ein Modell selbst, und zwar das kleinste, das noch alle wichtigen Teile eines GPT hat. Es lernt aus 32.033 englischen Vornamen und erfindet danach eigene. Statt Wörtern sind unsere Tokens einzelne Buchstaben.
Unter jedem Buchstaben steht seine Token-ID. Das Modell sieht nie Buchstaben, nur diese Zahlen. Die 0 ist ein Sonderzeichen: Der Punkt markiert Anfang und Ende eines Namens.
Was kommt nach „m“?
Diese Vorhersage stammt vom Modell aus Schritt 1. Es schaut nur auf den letzten Buchstaben. Ein echtes LLM rechnet genauso, berücksichtigt aber den ganzen bisherigen Text.
So ist die Seite aufgebaut
Wir gehen in sieben Schritten vom Zählen bis zum Transformer. Jeder Schritt baut auf dem vorigen auf. Zu jedem Schritt gibt es den echten Quelltext: Er wird direkt aus den Dateien geladen, die in deinem Browser laufen. Hier der Tokenizer, der Text in Zahlen übersetzt:
Das einfachste Modell ist eine Tabelle
Wir zählen in allen Namen, wie oft welches Zeichen auf welches folgt. Aus „emma“ wird .e, em, mm, ma, a.. Teilt man jede Zeile der Tabelle durch ihre Summe, erhält man Wahrscheinlichkeiten. Das ist ein vollständiges Sprachmodell. Man nennt es Bigram-Modell, weil es immer zwei Zeichen betrachtet.
Wie oft folgt welches Zeichen?
Zeile: aktuelles Zeichen. Spalte: nächstes Zeichen. Je dunkler, desto häufiger. Fahr über ein Feld für die genaue Zahl, klick eine Zeile an.
Nach „a“ kommt …
Namen erzeugen
Beim Generieren starten wir beim Punkt, schauen in dessen Zeile und ziehen zufällig ein Zeichen gemäß den Wahrscheinlichkeiten. Dann schauen wir in die Zeile des gezogenen Zeichens und so weiter, bis wieder ein Punkt gezogen wird.
Noch nichts gezogen. Der Name beginnt beim Punkt.
Die Namen klingen ungefähr richtig, aber oft seltsam. Kein Wunder: Das Modell kennt nur das letzte Zeichen. Nach einem „a“ weiß es nicht, ob der Name gerade erst begonnen hat oder schon zwölf Buchstaben lang ist.
Wie gut ist das Modell?
Wir messen, welche Wahrscheinlichkeit das Modell den echten Daten gibt. Für jedes Zeichenpaar nehmen wir den negativen Logarithmus der Wahrscheinlichkeit und mitteln. Das ist der Loss. Ein perfektes Modell hätte Loss 0. Wer blind unter 27 Zeichen rät, kommt auf ln 27 ≈ 3,30. Unsere Tabelle schafft über alle Namen ….
| Paar | Wahrscheinlichkeit | −log |
|---|---|---|
| Durchschnitt (Loss für diesen Namen) | ||
Der Code
Wie ein Netz lernt: Ableitungen, rückwärts gerechnet
Zählen funktioniert nur für sehr kurzen Kontext. Neuronale Netze gehen anders vor: Sie haben Parameter, die anfangs zufällig sind und nach und nach so verschoben werden, dass der Loss sinkt. Dafür müssen wir für jeden Parameter wissen: Wenn ich ihn ein kleines bisschen erhöhe, steigt oder fällt der Loss, und wie stark? Diese Zahl heißt Gradient.
Der Trick: Jede Zahl wird in ein Value-Objekt verpackt, das sich merkt, aus welchen Zahlen es berechnet wurde. So entsteht beim Rechnen ein Graph. Danach laufen wir ihn rückwärts ab und wenden an jedem Knoten die Kettenregel an. Das ist Backpropagation. PyTorch macht genau dasselbe, nur mit ganzen Matrizen statt einzelnen Zahlen.
Ein Neuron mit Loss: L = (tanh(x₁·w₁ + x₂·w₂ + b) − y)²
Bei einem Lernschritt wird jeder Parameter ein Stück gegen seinen Gradienten geschoben: w ← w − 0,1 · ∂L/∂w. Klick ein paar Mal auf „Lernschritt“ und beobachte, wie L kleiner wird und o sich dem Ziel y nähert. Genau so lernt später auch das GPT, nur mit 4.192 Parametern statt drei.
Stimmt das auch? Gegenprobe mit Zahlen
Man kann jeden Gradienten auch stumpf ausprobieren: Parameter um ein winziges h verschieben, L neu berechnen, Differenz durch 2h teilen. Das ist viel zu langsam für große Netze, aber eine perfekte Kontrolle.
| Parameter | Autograd | Numerisch |
|---|
Der Code
Dieselbe Tabelle, diesmal gelernt
Jetzt setzen wir Autograd auf ein echtes Problem an. Statt die Bigram-Tabelle zu zählen, lassen wir sie lernen: 27 × 27 = 729 Parameter, anfangs Zufall. Für jedes Zeichen ist seine Zeile in der Matrix die Rohbewertung („Logits“) aller möglichen Nachfolger. Softmax macht daraus Wahrscheinlichkeiten, der Cross-Entropy-Loss bestraft falsche Vorhersagen, und Backpropagation sagt jedem Parameter, in welche Richtung er sich bewegen soll.
- Schritt
- 0
- Loss (aktuell)
- –
- Zähl-Modell
- –
Gelernt: softmax(W)
Gezählt (Schritt 1)
Die gelernte Tabelle wird der gezählten immer ähnlicher, und der Loss nähert sich der gestrichelten Linie. Gradientenabstieg findet von selbst heraus, was wir in Schritt 1 abgezählt haben.
Probier verschiedene Lernraten aus. Bei 1 kriecht der Loss nur langsam nach unten. Bei 300 schießt jeder Schritt über das Ziel hinaus, und der Loss steigt sogar. Die richtige Lernrate zu finden ist auch bei echten LLMs eine der wichtigsten Stellschrauben.
Der Code
Mehr Kontext: Embeddings und Attention
Das Bigram-Modell sieht nur ein Zeichen. Wollte man mit der Tabellen-Methode die letzten 15 Zeichen berücksichtigen, bräuchte man 27¹⁵ ≈ 3 · 10²¹ Zeilen, mehr als es Sandkörner auf der Erde gibt. Ein Transformer löst das mit zwei Ideen.
Embeddings: jedes Token wird ein Vektor
Jedes Token bekommt eine Liste von 16 gelernten Zahlen, seinen Embedding-Vektor. Ähnliche Zeichen, etwa die Vokale, landen nach dem Training bei ähnlichen Vektoren. Zusätzlich bekommt jede Position im Text einen eigenen Vektor, der addiert wird. So weiß das Modell, welches Zeichen es ist und wo es steht.
Attention: Positionen tauschen Informationen aus
An jeder Position berechnet das Modell drei Vektoren: eine Query (wonach suche ich?), einen Key (was biete ich an?) und einen Value (was gebe ich weiter?). Die Query wird mit den Keys aller vorherigen Positionen verglichen (Skalarprodukt). Softmax macht aus den Ergebnissen Gewichte, und die Ausgabe ist der gewichtete Mittelwert der Values. Zukünftige Positionen sind tabu, sonst könnte das Modell beim Training einfach abschreiben.
Attention zum Nachrechnen, mit 2 statt 16 Dimensionen
Wähle die Position, die gerade „fragt“. Die Zahlen sind von Hand gewählt, damit man sie im Kopf nachrechnen kann.
| Position | Key k | Score q·k / √2 | Gewicht (Softmax) | Value v |
|---|
Der ganze Bauplan
Ein GPT stapelt diese Bausteine. Klick einen Block an, um zu sehen, was er tut und wie er im Code aussieht.
Attention und MLP (links blau markiert) bilden zusammen einen Transformer-Block. Er wird n_layer-mal übereinander gestapelt.
Bausteine, die überall vorkommen
Dein GPT trainieren
Jetzt wird es ernst. Mit den Standardeinstellungen hat das Modell 4.192 Parameter. Pro Trainingsschritt entstehen rund 125.000 Value-Objekte, die vorwärts berechnet und rückwärts abgeleitet werden. 1.000 Schritte dauern je nach Rechner 10 bis 60 Sekunden.
- Schritt
- 0
- Loss (Mittel der letzten 50)
- –
- Schritte pro Sekunde
- –
Was das Modell während des Trainings erfindet
Achte auf die Beispiele: Am Anfang kommt Buchstabensalat, nach ein paar hundert Schritten entstehen aussprechbare Namen. Der Loss fällt unter den des Bigram-Modells, weil das GPT mehr als ein Zeichen Kontext nutzt. Das trainierte Modell wird in deinem Browser gespeichert, Schritt 6 arbeitet damit.
Der Code
Ins Modell hineinschauen
Hier gibt es noch kein trainiertes Modell. Trainiere es in Schritt 5 oder starte ein kurzes Training mit 300 Schritten.
Generieren heißt: Text ins Modell geben, Wahrscheinlichkeiten fürs nächste Token ablesen, eins ziehen, anhängen, wiederholen. Hier machst du das von Hand und siehst dabei, worauf die Attention-Köpfe achten.
Wahrscheinlichkeiten fürs nächste Zeichen
Attention: Worauf schaut jede Position?
Zeile: die Position, die gerade rechnet. Spalte: die Position, auf die sie schaut. Jede Zeile summiert sich zu 100 %. Rechts oben ist alles leer, weil niemand in die Zukunft schauen darf.
Temperatur
Vor der Softmax werden die Logits durch die Temperatur geteilt. Unter 1 wird die Verteilung spitzer, das Modell wählt fast nur noch seine Favoriten und wiederholt sich. Über 1 wird sie flacher, die Namen werden kreativer, aber auch chaotischer. Chatbots nutzen genau diesen Regler.
Fett gesetzte Namen kommen in den Trainingsdaten nicht vor, die hat das Modell erfunden. Die anderen hat es (zufällig oder auswendig) reproduziert.
Der Code
Vom Spielzeug zum echten LLM
Du hast jetzt jedes Teil eines GPT gesehen und selbst trainiert. Ein großes Modell wie GPT-4 oder Claude unterscheidet sich vor allem in der Größe, kaum im Prinzip.
| Dein Modell | Großes LLM (Größenordnung) | |
|---|---|---|
| Parameter | 4.192 | Hunderte Milliarden bis Billionen |
| Vokabular | 27 Zeichen | 100.000 bis 200.000 Tokens (Wortteile) |
| Kontext | 16 Zeichen | Hunderttausende Tokens |
| Schichten | 1 | Dutzende bis über hundert |
| Trainingsdaten | 228 KB Namen | Billionen Tokens Text und Code |
| Rechenzeit | Sekunden im Browser | Monate auf zehntausenden GPUs |
| Rechnet mit | einzelnen Zahlen (Value) | Tensoren auf GPUs, in bf16 oder fp8 |
Was genau gleich bleibt
Tokens, Embeddings, Attention mit Query, Key und Value, MLP, Residual-Verbindungen, Normalisierung, Softmax, Cross-Entropy-Loss, Backpropagation, Adam und das Ziehen des nächsten Tokens. All das hast du hier in Aktion gesehen.
Was noch dazukommt
- Byte-Pair-Encoding
- Statt Buchstaben werden häufige Zeichenfolgen zu Tokens zusammengefasst. Ein Wort ist dann meist nur ein oder zwei Tokens lang.
- Tensoren und GPUs
- Statt jede Multiplikation als eigenes Objekt zu speichern, rechnet man ganze Matrizen auf einmal. Die Mathematik bleibt dieselbe, nur tausendfach schneller.
- Pretraining
- Das, was du in Schritt 5 gemacht hast, nur mit einem großen Teil des Internets: Das Modell lernt, Text fortzusetzen.
- Fine-Tuning und RLHF
- Danach wird das Modell mit Beispieldialogen und menschlichem Feedback so nachtrainiert, dass es hilfreich antwortet statt nur Text fortzusetzen.
Zum Weiterlernen
- micrograd: das Autograd aus Schritt 2, in Python
- makemore: von Bigram bis Transformer für Namen, die Quelle unseres Datensatzes
- nanoGPT: ein echtes GPT-2 mit PyTorch, auf einer GPU trainierbar
- Neural Networks: Zero to Hero: Andrej Karpathys Videokurs, der genau diesen Weg geht
Den kompletten Quelltext dieser Seite findest du unter value.js, transformer.js und den anderen Dateien im Ordner js/. Das Modell samt Autograd, also alles außer der Seite drumherum, sind rund 700 Zeilen inklusive ausführlicher Kommentare.