Zum Inhalt springen
RAG, wie es wirklich gut funktioniert

RAG, wie es wirklich gut funktioniert

Sven Sven
#Vektorsuche #Embeddings #RAG #Kosinus-Distanz

1. Einführung: Was sind Embeddings?

Stell dir vor, du hast eine Datenbank mit Hunderten von Kochrezepten und möchtest einem Nutzer auf die Frage „Was kann ich mit übrig gebliebenem Huhn kochen?" die passendsten Rezepte zeigen. Klassische Volltextsuche scheitert hier schnell: Sie findet nur exakte Wortübereinstimmungen. Was aber, wenn das Rezept „Hähnchensalat mit Avocado" heißt und das Wort „übrig geblieben" gar nicht enthält?

Hier kommen Embeddings ins Spiel. Ein Embedding-Modell (z. B. OpenAIs text-embedding-3-small oder Coheres embed-multilingual-v3.0) wandelt einen Text in einen Zahlenvektor um – typischerweise mit 384 bis 3072 Dimensionen. Texte mit ähnlicher Bedeutung landen im Vektorraum nah beieinander, unabhängig davon, ob dieselben Wörter vorkommen.

Die zentrale Frage bei der Vektorsuche ist nun: Wie messen wir, wie „nah" sich zwei Vektoren sind? Die zwei wichtigsten Maße dafür sind die Kosinus-Ähnlichkeit und die Kosinus-Distanz.

2. Kosinus-Ähnlichkeit vs. Kosinus-Distanz

2.1 Kosinus-Ähnlichkeit (Cosine Similarity)

Die Kosinus-Ähnlichkeit misst den Winkel zwischen zwei Vektoren A und B:

similarity(A, B) = (A · B) / (||A|| × ||B||)

Der Wert liegt zwischen -1 (genau entgegengesetzt) und +1 (identische Richtung). In der Praxis liegen Embedding-Werte bei modernen Modellen meistens zwischen 0 und 1, weil die Vektoren normalisiert und positiv orientiert sind.

2.2 Kosinus-Distanz (Cosine Distance)

Die Kosinus-Distanz ist einfach das Komplement:

distance(A, B) = 1 - similarity(A, B)

Der Wert liegt zwischen 0 (identisch) und 2 (maximal verschieden). Viele Vektordatenbanken wie Pinecone, pgvector oder Qdrant verwenden intern die Kosinus-Distanz, weil sie als Verlustfunktion praktischer ist – kleiner = besser.

Eselsbrücke: Kosinus-Ähnlichkeit = „Wie ähnlich?" (höher = besser). Kosinus-Distanz = „Wie weit entfernt?" (niedriger = besser). Beide enthalten exakt dieselbe Information, nur umgekehrt.

3. Praxisbeispiel: Rezeptsuche

Nehmen wir an, wir haben folgende vier Rezepte in unserer Datenbank und eine Suchanfrage. Wir berechnen für jedes Rezept das Embedding und vergleichen es mit dem Embedding der Suchanfrage.

3.1 Unsere Rezeptdatenbank

# Rezeptname Beschreibung
R1 Spaghetti Carbonara Klassische italienische Pasta mit Ei, Pecorino, Guanciale und schwarzem Pfeffer. Schnell zubereitet in 20 Minuten.
R2 Thai-Kokos-Suppe (Tom Kha Gai) Cremige Suppe mit Kokosmilch, Galgant, Zitronengras, Hähnchenbrust und Limettensaft. Leicht schärfbar mit Chili.
R3 Griechischer Bauernsalat Frischer Salat mit Tomaten, Gurke, Oliven, Zwiebeln und Feta. Dressing aus Olivenöl und Oregano.
R4 Käsespätzle Schwäbisches Traditionsgericht mit hausgemachten Spätzle, Bergkäse und Röstzwiebeln. Deftiges Wohlfühlessen.

3.2 Suchanfrage und Ergebnisse

Suchanfrage: „Schnelles Pasta-Gericht mit Käse"

Hier die simulierten Scores eines typischen Embedding-Modells:

Rezept Kosinus-Ähnlichkeit Kosinus-Distanz Rang
Spaghetti Carbonara 0,89 0,11 #1
Käsespätzle 0,82 0,18 #2
Thai-Kokos-Suppe 0,41 0,59 #3
Griech. Bauernsalat 0,28 0,72 #4

Die Spaghetti Carbonara gewinnt: Es ist ein schnelles Pasta-Gericht und enthält Käse (Pecorino). Die Käsespätzle landen auf Platz 2 – Käse passt, aber es ist keine Pasta. Die Sortierung ist bei beiden Maßen identisch, nur die Zahlen sind invertiert.

4. Was steckt im Embedding? Titel vs. Beschreibung vs. Volltext

Die spannendere Frage ist nicht welches Distanzmaß man verwendet, sondern welchen Text man in das Embedding packt. Das hat enormen Einfluss auf die Qualität der Suchergebnisse.

4.1 Experiment: Drei Embedding-Strategien

Wir vergleichen drei Strategien für dasselbe Rezept, die Thai-Kokos-Suppe:

Strategie A – Nur Titel:

embed("Thai-Kokos-Suppe (Tom Kha Gai)")

Strategie B – Titel + kurze Beschreibung:

embed("Thai-Kokos-Suppe (Tom Kha Gai). Cremige Suppe mit Kokosmilch, Hähnchenbrust und Limette.")

Strategie C – Titel + Beschreibung + volle Zutatenliste + Anleitung:

embed("Thai-Kokos-Suppe (Tom Kha Gai). Cremige Suppe mit Kokosmilch, Galgant,
Zitronengras, Hähnchenbrust und Limettensaft. Zutaten: 400ml Kokosmilch, 300g
Hähnchenbrust, 2 Stängel Zitronengras, 3cm Galgant, 200g Champignons, 2 EL
Fischsauce, 1 Limette, Thai-Chilis nach Geschmack. Anleitung: Kokosmilch
erhitzen, Galgant und Zitronengras ...")

4.2 Ergebnisse bei verschiedenen Suchanfragen

Suchanfrage 1: „Scharfe asiatische Suppe"

Strategie Ähnlichkeit Gefunden?
A: Nur Titel 0,74 Ja
B: Titel + Beschreibung 0,81 Ja
C: Volltext 0,78 Ja

Der Titel allein ist hier schon recht aussagekräftig. Die Beschreibung erhöht den Score leicht. Der Volltext „verwässert" den Vektor etwas, weil Zubereitungsdetails hinzukommen, die wenig mit „scharfe asiatische Suppe" zu tun haben.

Suchanfrage 2: „Rezept mit Kokosmilch und Champignons"

Strategie Ähnlichkeit Gefunden?
A: Nur Titel 0,38 Nein
B: Titel + Beschreibung 0,62 Vielleicht
C: Volltext 0,87 Ja

Hier kehrt sich das Bild um: „Champignons" steht nur in der Zutatenliste. Nur der Volltext-Embedding findet das Rezept zuverlässig. Der reine Titel-Embedding versagt völlig, weil weder „Kokosmilch" noch „Champignons" im Titel vorkommen.

Suchanfrage 3: „Schnelles Abendessen unter 30 Minuten"

Strategie Ähnlichkeit Gefunden?
A: Nur Titel 0,22 Nein
B: Titel + Beschreibung 0,58 Ja
C: Volltext 0,52 Grenzwertig

Die Spaghetti Carbonara hat in der Beschreibung „Schnell zubereitet in 20 Minuten". Der Titel allein enthält diese Info nicht. Strategie B trifft den Sweet Spot, während der Volltext wieder durch zu viele Details verwässert wird.

5. Wie die Länge des Embedding-Inputs die Qualität beeinflusst

Embedding-Modelle haben ein maximales Token-Limit (z. B. 512 oder 8192 Tokens). Aber „mehr Text = besseres Embedding" gilt nicht pauschal. Es gibt einen Punkt, ab dem zusätzlicher Text das Embedding verschlechtert.

5.1 Das Signal-Rausch-Verhältnis

Ein Embedding ist eine Zusammenfassung in Vektorform. Je mehr Text hineingestopft wird, desto mehr muss das Modell komprimieren. Dabei können wichtige Merkmale „untergehen".

Beispiel: Käsespätzle

Input-Länge Was im Embedding landet Effekt auf Suche
3 Wörter „Käsespätzle" – Konzentriertes Signal Findet Suchanfragen gut, die direkt Käsespätzle meinen
2 Sätze „Käsespätzle mit Bergkäse und Röstzwiebeln. Schwäbisches Traditionsessen." Findet auch „deftige schwäbische Gerichte" oder „Mit Bergkäse überbacken"
500 Wörter Vollrezept inkl. „Wasser zum Kochen bringen", „Salz hinzufügen" ... Das Embedding „riecht" jetzt auch nach anderen Kochrezepten – weniger spezifisch

5.2 Die Sweet-Spot-Regel

Für die meisten Anwendungen gilt: Titel + 1–2 Sätze Beschreibung liefern die besten Ergebnisse. Das ist in der Regel der Sweet Spot zwischen zu wenig und zu viel Information.

Faustregel für Rezepte: Embed den Rezeptnamen + eine kurze Beschreibung (Küche, Hauptzutaten, Zubereitungszeit, Besonderheiten). Speichere den Volltext separat als Metadaten, die nach dem Retrieval angezeigt werden.

6. Praxisfall: Warum eine Suche nach „Zander" scheitert

Ein häufiges Missverständnis bei der Vektorsuche wird an einem realen Beispiel deutlich. Nehmen wir an, unsere Datenbank enthält folgendes Rezept:

Gebratener Zander auf Couscous-Salat
Zartes Zanderfilet, knusprig gebraten, auf lauwarmem Couscous-Salat mit Zitrone, frischer Minze und Cherry-Tomaten. Dazu ein leichtes Joghurt-Dressing.

Ein Nutzer sucht nun einfach nach: „Zander"

Die Vektorsuche liefert eine Kosinus-Distanz von 0,82 – das Rezept wird nicht gefunden, obwohl „Zander" wörtlich im Titel steht. Warum?

6.1 Embedding-Modelle erfassen Bedeutung, keine Schlüsselwörter

Das Wort „Zander" allein ist ein isoliertes, kurzes Konzept. Das Embedding-Modell weiß nicht, ob damit der Fisch gemeint ist, ein Nachname, eine Marke oder etwas anderes. Es erzeugt einen Vektor mit sehr wenig semantischem Inhalt.

Das Rezept-Embedding hingegen codiert ein reichhaltiges Bedeutungsfeld: Kochtechnik (gebraten), Beilage (Couscous-Salat), Aromen (Zitrone, Minze), Art des Gerichts (leichtes Fischgericht). Diese beiden Vektoren zeigen in völlig unterschiedliche Richtungen im hochdimensionalen Raum – selbst wenn das Wort „Zander" in beiden vorkommt.

6.2 Kurze Queries produzieren schlechte Vektor-Matches

Einzel-Wort-Suchanfragen sind das Worst-Case-Szenario für Vektorsuche. Sie enthalten fast kein semantisches Signal. Vergleiche:

Suchanfrage Distanz Gefunden? Warum?
„Zander" 0,82 Nein Zu wenig Signal
„Zander Rezept" 0,54 Grenzwertig Etwas mehr Kontext
„Leichtes Fischgericht mit Couscous" 0,15 Ja Semantisch präzise
„Gebratener Fisch mit frischen Kräutern" 0,21 Ja Gute semantische Übereinstimmung

Die Tabelle zeigt das Kernproblem: Je mehr semantischer Kontext in der Suchanfrage steckt (was für ein Gericht? welche Art? welche Beilage?), desto besser findet die Vektorsuche das passende Rezept – sogar ohne dass das Wort „Zander" in der Anfrage vorkommt.

6.3 Die Lösung: Textsuche als Fallback

Dieses Verhalten ist kein Bug, sondern eine architektonische Eigenschaft der Vektorsuche. In der Praxis löst man das Problem durch einen hybriden Suchansatz:

  1. Schritt 1 – Vektorsuche: Suche semantisch nach den besten Matches. Ideal für natürlichsprachliche Anfragen wie „Leichtes Sommergericht mit Fisch".
  2. Schritt 2 – Textsuche als Fallback: Wenn die Vektorsuche keine oder zu wenige Ergebnisse liefert (z. B. Distanz > 0,6), falle auf klassische Textsuche zurück. Ein einfaches CONTAINS oder LIKE findet „Zander" zuverlässig im Titel.
  3. Schritt 3 – Ergebnisse zusammenführen: Kombiniere beide Ergebnismengen und dedupliziere. So bekommt der Nutzer sowohl semantisch passende als auch keyword-basierte Treffer.

Merke: Vektorsuche ist hervorragend für die Frage „Was meine ich?" (Semantik), aber schlecht für „Welches Wort steht im Text?" (Keywords). Eine robuste Rezeptsuche braucht beides.

7. Praktische Empfehlungen

7.1 Embedding-Strategie für Rezepte

Strategie Wann sinnvoll Beispiel-Suchanfragen
Nur Titel Wenn Nutzer nach konkreten Rezeptnamen suchen „Spaghetti Carbonara", „Tom Kha Gai"
Titel + Beschreibung Bester Allrounder – deckt thematische Suchen ab „Schnelles Pasta-Gericht", „Leichter Sommersalat"
Titel + Zutaten Wenn Nutzer primär nach Zutaten suchen „Rezept mit Aubergine und Feta"
Volltext Nur bei Nischen-Details oder sehr langen Texten mit Chunk-Strategie „Rezept mit Galgant" (seltene Zutat)

7.2 Hybride Ansätze: Das Beste aus beiden Welten

In der Praxis kombiniert man oft mehrere Ansätze:

  1. Mehrere Embeddings pro Rezept: Erstelle separate Vektoren für Titel, Beschreibung und Zutatenliste. Suche in allen dreien und kombiniere die Scores.
  2. Chunking: Teile lange Rezepte in überlappende Abschnitte auf (z. B. 200 Tokens mit 50 Token Überlappung). Jeder Chunk bekommt ein eigenes Embedding.
  3. Metadaten-Filter + Vektorsuche: Filtere zuerst nach Kategorien (Küche, Zubereitungszeit, Schwierigkeitsgrad), dann suche per Vektor in der gefilterten Menge.
  4. Hybrid Search (BM25 + Vektor): Kombiniere klassische Keyword-Suche (BM25) mit Vektorsuche. Viele Datenbanken wie Qdrant oder Weaviate unterstützen dies nativ.

7.3 Combined Search: Die Scoring-Formel

Wenn Vektor- und Textsuche kombiniert werden, braucht man eine Formel, um die Ergebnisse beider Sucharten in einen einheitlichen Score zu übersetzen. Die folgende Formel hat sich in der Praxis bewährt:

finalScore = vectorWeight × vectorRelevance + (1 - vectorWeight) × textRelevance

vectorRelevance wird aus der Kosinus-Distanz berechnet:

vectorRelevance = 1 - (cosineDistance / 2)

Diese Normalisierung wandelt die Kosinus-Distanz (Wertebereich 0–2, wie z. B. in Cosmos DB) in eine 0–1-Relevanzskala um: Ein Wert von 0 (identisch) wird zu 1,0 und ein Wert von 2 (maximal verschieden) wird zu 0,0.

textRelevance bewertet die Qualität der Keyword-Treffer über alle Felder hinweg mit unterschiedlichen Gewichtungen:

Feld Punkte pro Treffer Begründung
Titel +2,0 Höchste Gewichtung – ein Treffer im Titel ist am aussagekräftigsten
Beschreibung +1,0 Mittel – beschreibender Kontext ist wertvoll
Volltext / Zutaten +0,5 Niedrig – viele generische Wörter, aber fängt seltene Zutaten auf

Die Punkte werden pro Suchbegriff vergeben und anschließend auf einen Wertebereich von 0–1 normalisiert.

vectorWeight steuert die Balance zwischen beiden Suchmethoden und ist konfigurierbar (Standard: 0,7):

vectorWeight Effekt Ideal für
0,9 Fast reine Vektorsuche, Textsuche nur minimaler Einfluss Nutzer, die in ganzen Sätzen suchen
0,7 (Standard) Vektorsuche dominiert, aber Keyword-Treffer können Rang ändern Guter Allrounder für gemischte Suchanfragen
0,5 Gleichgewicht – beide Methoden gleich stark Datenbanken mit vielen ähnlichen Rezepten
0,3 Textsuche dominiert, Vektor nur für Feinranking Nutzer, die nach einzelnen Zutaten suchen

7.4 Scoring in Aktion: Das Zander-Beispiel

Betrachten wir die Suchanfrage „Zander" mit dem Rezept „Gebratener Zander auf Couscous-Salat" und einem vectorWeight von 0,7:

Komponente Berechnung Wert
Kosinus-Distanz 0,82
vectorRelevance 1 - (0,82 / 2) 0,59
Text-Treffer: Titel („Zander") 1 Term × 2,0 Punkte 2,0 Punkte
textRelevance (normalisiert) 2,0 / max ≈ 0,90
finalScore 0,7 × 0,59 + 0,3 × 0,90 0,68

Ohne die Textsuche hätte das Rezept nur einen Score von 0,59 – vermutlich zu niedrig für die Top-Ergebnisse. Durch den starken Titel-Treffer (+2 Punkte) hebt die Textkomponente den Score auf 0,68, sodass das Rezept trotz des schwachen Vektor-Matches sichtbar wird.

Vergleiche das mit einer semantischen Anfrage:

Suchanfrage: „Leichtes Fischgericht mit Couscous"

Komponente Berechnung Wert
vectorRelevance 1 - (0,15 / 2) 0,925
textRelevance Kein exakter Wort-Treffer für „Fischgericht" ≈ 0,30
finalScore 0,7 × 0,925 + 0,3 × 0,30 0,74

Hier dominiert die Vektorsuche: Die semantische Nähe ist hoch, obwohl keines der Suchwörter exakt im Titel steht. Beide Suchanfragen führen zum selben Rezept – aber über unterschiedliche Wege.

Wichtig für die Implementierung: Rezepte, die sowohl von der Vektor- als auch der Textsuche gefunden werden, erhalten Beiträge aus beiden Scores. Deduplizierung nach Rezept-ID ist essenziell, damit der beste Score pro Rezept verwendet wird.

8. Zusammenfassung

Frage Antwort Rezept-Beispiel
Kosinus-Ähnlichkeit oder -Distanz? Spielt keine Rolle – selbe Info, nur invertiert Carbonara: Similarity 0,89 = Distance 0,11
Nur Titel embedden? Gut für Namenssuche, schlecht für Zutatenfragen „Rezept mit Champignons" findet Tom Kha Gai nicht
Volltext embedden? Kann Signal verwässern, aber findet seltene Details Findet „Galgant", aber Scores insgesamt diffuser
Einzelne Keywords? Vektorsuche versagt – Textsuche als Fallback nötig „Zander" hat Distanz 0,82 trotz wörtlichem Treffer
Vektor + Text kombinieren? finalScore aus gewichteter Kombination (Standard: 70/30) „Zander": Vektor schwach (0,59), aber Titel-Treffer rettet Score auf 0,68
Bester Kompromiss? Titel + Beschreibung als Embedding-Input Trifft den Sweet Spot für die meisten Suchanfragen

Die wichtigste Erkenntnis: Die Wahl zwischen Kosinus-Ähnlichkeit und Kosinus-Distanz ist irrelevant für die Qualität der Suchergebnisse. Was wirklich zählt, ist welchen Text man dem Embedding-Modell gibt – und wie man Vektor- und Textsuche in einem gewichteten Score kombiniert. Ein kluges Embedding-Design zusammen mit einer hybriden Scoring-Formel macht den Unterschied zwischen einer mittelmäßigen und einer hervorragenden Rezeptsuche.

← Alle Blog-Beiträge