Zurück zum Blog ·

Zwei Embedding-Modelle, ein Vektorraum

Ich baue gerade einen Produktberater für meinen Shop: Der Katalog liegt als Vektoren in Qdrant, ein Sprachmodell durchsucht ihn und antwortet über Telegram. Beim Durchsehen der beiden Workflows ist mir aufgefallen, dass sie nicht zusammenpassen – und zwar auf eine Art, die man leicht übersieht.

Der Sync, der die Produkte einträgt, benutzt ein Embedding-Modell von OpenAI. Der Chatbot, der sie später sucht, benutzt ein lokales Modell über Ollama. Zwei verschiedene Modelle für dieselbe Aufgabe.

Warum das nicht funktionieren kann

Ein Embedding-Modell übersetzt Text in eine Liste von Zahlen – bei text-embedding-3-small sind das 1536 Stück. Diese Zahlen sind keine Eigenschaften des Textes, die irgendwo objektiv festliegen. Sie sind Koordinaten in einem Raum, den genau dieses Modell während seines Trainings aufgespannt hat.

Zwei Modelle spannen zwei völlig verschiedene Räume auf. Die Koordinate 0.42 an Position 7 bedeutet im einen Modell etwas anderes als im anderen – wenn sie überhaupt etwas bedeutet. Ein Abstandsmaß wie Cosine misst dann Winkel zwischen Punkten, die gar nicht im selben Koordinatensystem liegen.

Der laute und der leise Fehler

Wenn die Modelle unterschiedlich viele Dimensionen liefern, hast du Glück. Qdrant lehnt den Vektor ab, du bekommst eine Fehlermeldung, und du weißt sofort, wo du suchen musst. text-embedding-3-small liefert 1536 Werte, nomic-embed-text liefert 768 – das kracht sauber.

Der gefährliche Fall ist der andere: Zwei Modelle mit derselben Dimensionszahl. Dann passt technisch alles. Die Suche läuft, liefert zehn Treffer, und die Treffer sind Zufall.

Und jetzt kommt der Teil, der es wirklich tückisch macht: Ein RAG-System antwortet nie mit „ich habe nichts gefunden". Es bekommt zehn Produkte, gibt sie dem Sprachmodell, und das Sprachmodell formuliert daraus eine flüssige, selbstbewusste Empfehlung. Der Bot schlägt einem Kunden, der nach einem schwarzen T-Shirt fragt, mit vollkommener Überzeugung eine Kaffeetasse vor. Kein Fehler im Log, keine Ausnahme, keine rote Zeile. Nur eine schlechte Antwort, die aussieht wie eine gute.

Wie du es prüfst

Der erste Blick geht in die Collection selbst:

curl -s http://127.0.0.1:6333/collections/deine_collection | python3 -m json.tool

Dort stehen size und distance. Vergleich die Zahl mit dem, was dein Abfrage-Modell ausgibt. Bei mir: 1536 in der Collection, ein lokales Modell in der Abfrage – das passt nicht zusammen.

Der zweite Test ist noch aussagekräftiger und dauert zehn Sekunden: Nimm den exakten Titel eines Produkts, das du sicher im Index hast, und schick ihn als Suchanfrage. Landet dieses Produkt nicht auf Platz eins, ist etwas grundlegend falsch. Wörtliche Übereinstimmung ist der einfachste Fall, den es gibt – wenn der scheitert, brauchst du über schwierigere Fragen gar nicht nachzudenken.

Wie du es verhinderst

Drei Dinge haben sich für mich als sinnvoll herausgestellt:

Der Punkt hinter alldem: Vektordatenbanken haben kein Schema im klassischen Sinn. Sie können nicht prüfen, ob deine Zahlen von demselben Modell stammen wie die schon gespeicherten – sie sehen nur, dass es die richtige Menge Zahlen ist. Diese Prüfung musst du selbst einbauen.