Embedding
Wie aus Wörtern Punkte in einem Raum werden, in dem ähnliche Bedeutungen nah beieinanderliegen – die Sprache, in der ein Sprachmodell eigentlich rechnet.
Ein Embedding ist ein Vektor – eine Liste von Hunderten bis Tausenden Zahlen –, der die Bedeutung eines Tokens, Wortes oder ganzen Textes darstellt. Die Zahlen sind so gelernt, dass ähnliche Bedeutungen nah beieinanderliegen: „Hund“ liegt nahe bei „Katze“, weit weg von „Steuererklärung“.
Embeddings sind der erste Schritt in jedem Sprachmodell (Token-ID → Vektor). Außerdem sind sie die Grundlage für semantische Suche: Texte nach Bedeutung finden statt nach gleichen Wörtern.
Ein Raum der Bedeutungen
Eine Token-ID ist nur eine Nummer; sie sagt nichts über die Bedeutung. Das Modell schlägt deshalb zu jeder ID einen Vektor nach. Man kann sich jeden Vektor als Punkt in einem Raum vorstellen – nur dass dieser Raum nicht zwei oder drei, sondern Tausende Dimensionen hat.
Zum Anschauen hier stark vereinfacht auf zwei Dimensionen. Klick ein Wort an:
Woher die Zahlen kommen
Niemand legt fest, wo „Hund“ liegt. Die Embedding-Tabelle gehört zu den Parametern und wird beim Training mitgelernt. Anfangs sind alle Vektoren Zufall. Weil das Modell aber ständig das nächste Wort vorhersagen muss, werden Wörter, die in ähnlichen Zusammenhängen vorkommen, nach und nach ähnlich dargestellt – das hilft bei der Vorhersage.
Rechnen mit Bedeutung
2013 stellten Forscher bei Google mit word2vec ein Verfahren vor, dessen Ergebnis berühmt wurde: In den gelernten Vektoren stecken nicht nur Ähnlichkeiten, sondern auch Beziehungen als Richtungen. Der Abstand von „Mann“ zu „Frau“ zeigt ungefähr in dieselbe Richtung wie der von „König“ zu „Königin“. Deshalb kann man rechnen:
In echten Modellen klappt das nicht immer so glatt, und berühmte Beispiele sind teilweise sorgfältig ausgewählt. Das Grundprinzip – Beziehungen als Richtungen im Raum – ist aber gut belegt und steckt auch in heutigen Sprachmodellen.
Wie man Nähe misst
Für die Ähnlichkeit zweier Embeddings nimmt man fast immer die Kosinus-Ähnlichkeit: Sie misst den Winkel zwischen den Vektoren, nicht deren Länge. Zeigen beide in dieselbe Richtung, ist sie 1; stehen sie senkrecht, 0; zeigen sie entgegengesetzt, −1.
a · b Σ aᵢ·bᵢ
cos(a, b) = ───────────── = ─────────────────────
|a| · |b| √Σ aᵢ² · √Σ bᵢ²Das Schöne daran: Es funktioniert in zwei Dimensionen genauso wie in 3 072 – nur zeichnen kann man es nicht mehr.
Statisch und im Kontext
Bei word2vec hat jedes Wort genau einen Vektor. „Bank“ ist dann ein unscharfer Mittelwert aus Geldinstitut und Sitzgelegenheit. In einem Transformer ist das nur der Anfang:
Semantische Suche
Embeddings gibt es nicht nur für einzelne Tokens, sondern auch für ganze Sätze und Dokumente. Dafür gibt es eigene, kleinere Embedding-Modelle: Text rein, ein Vektor raus. Damit lässt sich nach Bedeutung suchen statt nach Schlagworten:
- „Konto eröffnen in drei Schritten“
- „Kontoauszüge herunterladen“
- „Mein Konto: Einstellungen“
- „Passwort vergessen – so setzen Sie es zurück“ 0,82
- „Anmeldung schlägt fehl: Hilfe“ 0,79
- „Konto gesperrt nach Fehlversuchen“ 0,77
Das Vorgehen ist immer gleich: Alle Dokumente einmal in Embeddings umrechnen und speichern. Bei einer Anfrage die Frage ebenfalls umrechnen und die nächsten Nachbarn suchen. Dafür gibt es Vektordatenbanken oder Erweiterungen wie pgvector für PostgreSQL. Genau das ist der „Nachschlagen“-Schritt bei RAG, mit dem Anwendungen einem Sprachmodell passende Dokumente ins Kontextfenster legen.
Für Entwickler übersetzt
| Begriff | Entspricht ungefähr |
|---|---|
| Embedding | ein float[] mit fester Länge, z. B. 1 024 oder 3 072 |
| Embedding-Tabelle | ein float[vokabular][dimensionen] – Token-ID ist der Zeilenindex |
| Ähnlichkeit | Kosinus statt equals(): kein Ja/Nein, sondern eine Zahl zwischen −1 und 1 |
| Embedding-Modell | eine Funktion float[] embed(String text), meist als API oder lokale Bibliothek |
| Vektordatenbank | ein Index für „finde die nächsten Nachbarn“ – wie ein B-Baum, nur für Ähnlichkeit statt Sortierung (gängig: HNSW-Graphen) |
static double kosinus(float[] a, float[] b) {
double dot = 0, na = 0, nb = 0;
for (int i = 0; i < a.length; i++) {
dot += a[i] * b[i];
na += a[i] * a[i];
nb += b[i] * b[i];
}
return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
// Semantische Suche, naiv (ohne Index)
float[] frage = embedder.embed("Ich komme nicht mehr in mein Konto");
List<Dokument> treffer = dokumente.stream()
.sorted(Comparator.comparingDouble((Dokument d) -> kosinus(frage, d.embedding())).reversed())
.limit(3)
.toList();Für Java gibt es dafür fertige Bausteine, etwa in Spring AI oder LangChain4j, die Embedding-Modelle und Vektordatenbanken einheitlich ansprechen.