Dies war eine Frage, die mir heute auf der ICML-Konferenz in Wien gestellt wurde.
Während der Kaffeepause kam ein Jina-Nutzer mit einer Frage auf mich zu, die aus den jüngsten Diskussionen in der LLM-Community stammte. Er fragte, ob unser Embedding-Modell erkennen könne, dass 9.11 kleiner ist als 9.9 - eine Aufgabe, bei der viele LLMs das Gegenteil behaupten.
9.11 is bigger than 9.9. pic.twitter.com/zBrdLGAoH2
— Riley Goodside (@goodside) July 15, 2024
"Ehrlich gesagt, weiß ich es nicht", antwortete ich. Als er die Wichtigkeit dieser Fähigkeit für seine Anwendung erläuterte und andeutete, dass die Tokenisierung möglicherweise die Ursache des Problems sein könnte, nickte ich zustimmend - in meinem Kopf entstanden bereits Ideen für ein Experiment, um die Antwort zu finden.
In diesem Artikel möchte ich testen, ob unser Embedding-Modell jina-embeddings-v2-base-en (veröffentlicht im Oktober 2023) und der Reranker jina-reranker-v2-multilingual (veröffentlicht im Juni 2024) Zahlen korrekt vergleichen können. Um über den einfachen Vergleich von 9.11 und 9.9 hinauszugehen, habe ich eine Reihe von Experimenten entwickelt, die verschiedene Arten von Zahlen umfassen: kleine Ganzzahlen, große Zahlen, Gleitkommazahlen, negative Zahlen, Währungen, Datumsangaben und Uhrzeiten. Ziel ist es, die Effektivität unserer Modelle beim Umgang mit verschiedenen numerischen Formaten zu bewerten.
tagVersuchsaufbau
Die vollständige Implementierung finden Sie im Colab unten:

Der Aufbau des Experiments ist recht einfach. Um beispielsweise zu prüfen, ob das Embedding-Modell Zahlen zwischen [1, 100] versteht, sind folgende Schritte erforderlich:
- Dokumente erstellen: Generieren von "String-Literal"-Dokumenten für jede Zahl von
1bis100. - An Embedding API senden: Verwendung der Embedding API, um Embeddings für jedes Dokument zu erhalten.
- Kosinus-Ähnlichkeit berechnen: Berechnung der paarweisen Kosinus-Ähnlichkeit für je zwei Dokumente zur Erstellung einer Ähnlichkeitsmatrix.
- Streudiagramm erstellen: Visualisierung der Ergebnisse mittels Streudiagramm. Jedes Element in der Ähnlichkeitsmatrix wird auf einen Punkt abgebildet mit: X-Achse: ; Y-Achse: der Ähnlichkeitswert von
Wenn die Differenz null ist, also , sollte die semantische Ähnlichkeit am höchsten sein. Je größer die Differenz wird, desto geringer sollte die Ähnlichkeit sein. Idealerweise sollte die Ähnlichkeit linear proportional zum Differenzwert sein. Wenn wir eine solche Linearität nicht beobachten können, ist es wahrscheinlich, dass das Modell die Zahlen nicht versteht und Fehler wie "9.11 ist größer als 9.9" produzieren könnte.
Das Reranker-Modell folgt einem ähnlichen Verfahren. Der Hauptunterschied besteht darin, dass wir durch die erstellten Dokumente iterieren, wobei jedes als query festgelegt wird, indem wir den Prompt "what is the closest item to..." voranstellen und alle anderen als documents einordnen. Der von der Reranker API zurückgegebene Relevanz-Score wird direkt als semantisches Ähnlichkeitsmaß verwendet. Die Kernimplementierung sieht wie folgt aus.
def rerank_documents(documents):
reranker_url = "https://api.jina.ai/v1/rerank"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
# Initialize similarity matrix
similarity_matrix = np.zeros((len(documents), len(documents)))
for idx, d in enumerate(documents):
payload = {
"model": "jina-reranker-v2-base-multilingual",
"query": f"what is the closest item to {d}?",
"top_n": len(documents),
"documents": documents
}
...tagKönnen Modelle Zahlen zwischen [1, 2, 3, ..., 100] vergleichen?
Streudiagramm mit Mittelwert und Varianz für jede Differenz. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual. documents = [str(i) for i in range(1, 101)]
tagWie liest man diese Diagramme?
Bevor wir mit weiteren Experimenten fortfahren, möchte ich zunächst erklären, wie man diese Diagramme richtig liest. Meine erste Beobachtung aus den beiden obigen Diagrammen ist, dass das Embedding-Modell gut funktioniert, während das Reranker-Modell nicht so gut abschneidet. Was sehen wir also und warum?
Die X-Achse repräsentiert die Differenz der Indizes , also , wenn wir und gleichmäßig aus unseren Dokumentensets auswählen. Diese Differenz reicht von . Da unser Dokumentenset konstruktionsbedingt sortiert ist, d.h. je kleiner , desto semantisch näher sind sich und ; je weiter und voneinander entfernt sind, desto geringer ist die Ähnlichkeit zwischen und . Deshalb sehen Sie die Ähnlichkeit (dargestellt durch die Y-Achse) bei spitzen und dann linear abfallen, wenn Sie sich nach links und rechts bewegen.
Idealerweise sollte dies einen scharfen Gipfel oder eine "Aufwärtspfeil"-Form wie ^ erzeugen. Das ist jedoch nicht immer der Fall. Wenn Sie die X-Achse an einem Punkt fixieren, sagen wir , und entlang der Y-Achse schauen, finden Sie Ähnlichkeitswerte von 0,80 bis 0,95. Das bedeutet, könnte 0,81 sein, während 0,91 sein könnte, obwohl ihre Differenz jeweils 25 beträgt.
Die türkisfarbene Trendlinie zeigt den mittleren Ähnlichkeitswert an jedem X-Wert mit der Standardabweichung. Beachten Sie auch, dass die Ähnlichkeit linear abfallen sollte, da unser Dokumentenset gleichmäßig verteilt ist und gleiche Intervalle zwischen aufeinanderfolgenden Dokumenten sicherstellt.
Beachten Sie, dass Embedding-Plots immer symmetrisch sind, mit dem größten Y-Wert von 1,0 bei . Dies liegt daran, dass die Kosinus-Ähnlichkeit für und symmetrisch ist und .
Im Gegensatz dazu sind Reranker-Plots immer asymmetrisch aufgrund der unterschiedlichen Rollen von Query und Dokumenten im Reranker-Modell. Der Maximalwert ist wahrscheinlich nicht 1,0, da bedeutet, dass wir den Reranker verwenden, um den Relevanz-Score von "what is the closest item to 4" vs "4" zu berechnen. Wenn man darüber nachdenkt, gibt es keine Garantie, dass zum maximalen Y-Wert führt.
tagKönnen Modelle negative Zahlen zwischen [-100, -99, -98, ..., -1] vergleichen?
Streudiagramm mit Mittelwert und Varianz für jede Differenz. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual. Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit im negativen Bereich erkennen kann. documents = [str(-i) for i in range(1, 101)]
tagKönnen Modelle Zahlen mit größeren Intervallen [1000, 2000, 3000, ..., 100000] vergleichen?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Zahlen mit einem Intervall von 1000 vergleichen. documents = [str(i*1000) for i in range(1, 101)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle Zahlen aus einem beliebigen Bereich vergleichen, z.B. [376, 377, 378, ..., 476]?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Zahlen in einem beliebigen Bereich vergleichen, also verschieben wir die Zahlen in einen zufälligen Bereich documents = [str(i+375) for i in range(1, 101)] . Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle große Zahlen zwischen [4294967296, 4294967297, 4294967298, ..., 4294967396] vergleichen?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir sehr große Zahlen vergleichen. Ähnlich wie beim letzten Experiment verschieben wir den Bereich weiter zu einer großen Zahl. documents = [str(i+4294967296) for i in range(1, 101)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle Fließkommazahlen zwischen [0.0001, 0.0002, 0.0003, ...,0.1] vergleichen? (ohne feste Nachkommastellen)
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Fließkommazahlen vergleichen. documents = [str(i/1000) for i in range(1, 101)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle Währungsbeträge zwischen [2, 100] vergleichen?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Zahlen in Währungsform vergleichen. documents = ['$'+str(i) for i in range(1, 101)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle Daten zwischen [2024-07-24, 2024-07-25, 2024-07-26, ..., 2024-10-31] vergleichen?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Zahlen im Datumsformat vergleichen, d.h. JJJJ-MM-TT. today = datetime.today(); documents = [(today + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(100)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagKönnen Modelle Uhrzeiten zwischen [19:00:07, 19:00:08, 19:00:09,..., 20:39:07] vergleichen?
Hier wollen wir testen, ob das Modell die semantische Ähnlichkeit erkennen kann, wenn wir Zahlen im Zeitformat vergleichen, d.h. hh:mm:ss. now = datetime.now(); documents = [(now + timedelta(minutes=i)).strftime('%H:%M:%S') for i in range(100)] Streudiagramm mit Mittelwert und Varianz für jedes Delta. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagBeobachtungen
Hier sind einige Beobachtungen aus den obigen Diagrammen:
tagReranker-Modelle
- Reranker-Modelle haben Schwierigkeiten beim Vergleich von Zahlen. Selbst im einfachsten Fall des Vergleichs von Zahlen zwischen [1, 100] ist ihre Leistung unterdurchschnittlich.
- Es ist wichtig, die spezielle Prompt-Konstruktion zu beachten, die für Abfragen in unserem Reranker verwendet wird, d.h.
what is the closest item to x, da dies die Ergebnisse ebenfalls beeinflussen kann.
tagEmbedding-Modelle
- Embedding-Modelle funktionieren relativ gut beim Vergleich kleiner ganzer Zahlen im Bereich [1, 100] oder negativer Zahlen im Bereich [-100, 1]. Ihre Leistung verschlechtert sich jedoch erheblich, wenn dieser Bereich zu anderen Werten verschoben wird, mehr Intervalle hinzugefügt werden oder größere oder kleinere Fließkommazahlen verarbeitet werden.
- Regelmäßige Spitzen sind in bestimmten Intervallen zu beobachten, normalerweise alle 10 Schritte. Dieses Verhalten könnte damit zusammenhängen, wie der Tokenizer die Strings verarbeitet, möglicherweise indem er einen String in "10" oder "1" und "0" tokenisiert.
tagDatums- und Zeitverständnis
- Interessanterweise scheinen Embedding-Modelle ein gutes Verständnis von Datum und Uhrzeit zu haben und vergleichen diese meist korrekt. Bei Datumsdiagrammen erscheinen Spitzen alle 30/31 Schritte, entsprechend der Anzahl der Tage in einem Monat. Bei Zeitdiagrammen erscheinen Spitzen alle 60 Schritte, entsprechend den Minuten in einer Stunde.
- Die Reranker-Modelle scheinen dieses Verständnis ebenfalls bis zu einem gewissen Grad zu erfassen.
tagVisualisierung der Ähnlichkeit zu "Null"

Ein weiteres interessantes Experiment, das wahrscheinlich intuitiver ist, ist die direkte Visualisierung des Ähnlichkeits- oder Relevanzwerts zwischen einer beliebigen Zahl und Null (d.h. dem Ursprung). Indem wir den Referenzpunkt als das Embedding von Null festlegen, möchten wir sehen, ob die semantische Ähnlichkeit linear abnimmt, wenn die Zahlen größer werden. Beim Reranker können wir die Abfrage auf "0" oder "What is the closest number to number zero?" festlegen und alle Zahlen rangieren, um zu sehen, ob ihre Relevanzwerte abnehmen, wenn die Zahlen steigen. Die Ergebnisse sind unten dargestellt:
Hier fixieren wir das "Ursprungs-Embedding" auf das Embedding von "Null" und prüfen, ob die semantische Ähnlichkeit zwischen einer beliebigen Zahl und Null proportional zum Wert der Zahl ist. Konkret verwenden wir documents = [str(i) for i in range(2048)]. Das Streudiagramm mit Mittelwert und Varianz für jedes Delta ist dargestellt. Links: jina-embeddings-v2-base-en; Rechts: jina-reranker-v2-multilingual.
tagFazit
Dieser Artikel zeigt, wie unsere aktuellen Embedding- und Reranker-Modelle mit Zahlenvergleichen umgehen. Trotz des relativ einfachen Versuchsaufbaus zeigt er einige grundlegende Mängel in den aktuellen Modellen auf und liefert wertvolle Erkenntnisse für die Entwicklung unserer nächsten Embedding- und Reranker-Generation.
Zwei Schlüsselfaktoren bestimmen, ob ein Modell Zahlen genau vergleichen kann:
Erstens, Tokenisierung: Wenn das Vokabular nur die Ziffern 0-9 enthält, könnte 11 entweder in separate Token 1 und 1 oder als einzelnes Token 11 tokenisiert werden. Diese Wahl beeinflusst das Verständnis des Modells für numerische Werte.


Verschiedene Tokenizer führen zu unterschiedlichen Interpretationen von 9.11. Dies kann das nachgelagerte kontextuelle Lernen beeinflussen. Quelle: The Tokenizer Playground auf HuggingFace.
Zweitens, Trainingsdaten: Das Trainingskorpus beeinflusst die numerischen Fähigkeiten des Modells erheblich. Wenn die Trainingsdaten zum Beispiel hauptsächlich Software-Dokumentation oder GitHub-Repositories enthalten, wo semantische Versionierung üblich ist, könnte das Modell interpretieren, dass 9.11 größer als 9.9 ist, da 9.11 die Minor-Version nach 9.9 ist.
Die arithmetische Fähigkeit von Dense-Retrieval-Modellen wie Embeddings und Rerankern ist entscheidend für Aufgaben im Zusammenhang mit RAG und fortgeschrittenem Retrieval und Reasoning. Starke numerische Fähigkeiten können die Suchqualität deutlich verbessern, insbesondere bei der Verarbeitung strukturierter Daten wie JSON.






