Voici une question qui m'a été posée aujourd'hui à la conférence ICML à Vienne.
Pendant la pause café, un utilisateur de Jina m'a abordé avec une question issue de discussions récentes dans la communauté LLM. Il m'a demandé si notre modèle d'embedding pouvait déterminer que 9.11 est plus petit que 9.9, une tâche où de nombreux LLM se trompent.
9.11 is bigger than 9.9. pic.twitter.com/zBrdLGAoH2
— Riley Goodside (@goodside) July 15, 2024
« Honnêtement, je ne sais pas », ai-je répondu. Alors qu'il expliquait l'importance de cette capacité pour son application et suggérait que la tokenization pourrait être la source du problème, j'acquiesçais - mon esprit fourmillait déjà d'idées pour une expérience qui révélerait la réponse.
Dans cet article, je souhaite tester si notre modèle d'embedding, jina-embeddings-v2-base-en (sorti en octobre 2023), et le Reranker, jina-reranker-v2-multilingual (sorti en juin 2024), peuvent comparer précisément les nombres. Pour élargir le champ au-delà de la simple comparaison entre 9.11 et 9.9, j'ai conçu une série d'expériences incluant différents types de nombres : petits entiers, grands nombres, décimaux, nombres négatifs, devises, dates et heures. L'objectif est d'évaluer l'efficacité de nos modèles dans le traitement de différents formats numériques.
tagProtocole expérimental
L'implémentation complète est disponible dans le Colab ci-dessous :

La conception de l'expérience est assez simple. Par exemple, pour vérifier si le modèle d'embedding comprend les nombres entre [1, 100]. Les étapes sont les suivantes :
- Construire les Documents : Générer des documents "chaînes littérales" pour chaque nombre de
1à100. - Envoyer à l'API d'Embedding : Utiliser l'API d'Embedding pour obtenir les embeddings de chaque document.
- Calculer la Similarité Cosinus : Calculer la similarité cosinus par paires pour chaque couple de documents afin de créer une matrice de similarité.
- Faire un Nuage de Points : Visualiser les résultats avec un nuage de points. Chaque élément dans la matrice de similarité est cartographié en un point avec : Axe X : ; Axe Y : la valeur de similarité de
Si le delta est zéro, c'est-à-dire , alors la similarité sémantique devrait être maximale. À mesure que le delta augmente, la similarité devrait diminuer. Idéalement, la similarité devrait être linéairement proportionnelle à la valeur delta. Si nous ne pouvons pas observer une telle linéarité, alors il est probable que le modèle ne comprenne pas les nombres et puisse produire des erreurs comme considérer que 9.11 est supérieur à 9.9.
Le modèle Reranker suit une procédure similaire. La différence principale est que nous parcourons les documents construits, en définissant chacun comme query en ajoutant le prompt "what is the closest item to..." et en classant tous les autres comme documents. Le score de pertinence renvoyé par l'API Reranker est utilisé directement comme mesure de similarité sémantique. L'implémentation principale ressemble à ceci.
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
}
...tagLes Modèles Peuvent-ils Comparer les Nombres Entre [1, 2, 3, ..., 100] ?
Nuage de points avec moyenne et variance sur chaque delta. Gauche : jina-embeddings-v2-base-en ; Droite : jina-reranker-v2-multilingual. documents = [str(i) for i in range(1, 101)]
tagComment Lire Ces Graphiques
Avant de poursuivre avec d'autres expériences, laissez-moi d'abord expliquer comment lire correctement ces graphiques. Tout d'abord, mon observation des deux graphiques ci-dessus est que le modèle d'embedding performe bien, tandis que le modèle reranker ne s'en sort pas aussi bien. Alors, que regardons-nous et pourquoi ?
L'axe X représente le delta des indices , ou , lorsque nous échantillonnons uniformément et de nos ensembles de documents. Ce delta varie de . Puisque notre ensemble de documents est trié par construction, c'est-à-dire que plus est petit, plus et sont sémantiquement proches ; plus et sont éloignés, plus la similarité entre et est faible. C'est pourquoi vous voyez la similarité (représentée par l'axe Y) atteindre un pic à puis diminuer linéairement en se déplaçant à gauche et à droite.
Idéalement, cela devrait créer un pic prononcé ou une forme de "flèche vers le haut" comme ^. Cependant, ce n'est pas toujours le cas. Si vous fixez l'axe X à un point, disons , et regardez le long de l'axe Y, vous trouverez des valeurs de similarité allant de 0,80 à 0,95. Cela signifie que peut être 0,81 alors que peut être 0,91 bien que leurs delta soient tous de 25.
La ligne de tendance cyan montre la similarité moyenne à chaque valeur X avec l'écart-type. Notez également que la similarité devrait diminuer linéairement car notre ensemble de documents est espacé uniformément, assurant des intervalles égaux entre les documents contigus.
Notez que les graphiques d'embedding seront toujours symétriques, avec la plus grande valeur Y de 1,0 à . Ceci est dû au fait que la similarité cosinus est symétrique pour et , et .
En revanche, les graphiques du reranker sont toujours asymétriques en raison des différents rôles de la requête et des documents dans le modèle reranker. La valeur maximale n'est probablement pas 1,0 car signifie que nous utilisons le reranker pour calculer le score de pertinence de "what is the closest item to 4" vs "4". Si vous y réfléchissez, il n'y a aucune garantie que conduise à la valeur Y maximale.
tagLes Modèles Peuvent-ils Comparer les Nombres Négatifs Entre [-100, -99, -98, ..., -1] ?
Nuage de points avec moyenne et variance sur chaque delta. Gauche : jina-embeddings-v2-base-en ; Droite : jina-reranker-v2-multilingual. Ici nous voulons tester si le modèle peut déterminer la similarité sémantique dans l'espace négatif. documents = [str(-i) for i in range(1, 101)]
tagLes Modèles Peuvent-ils Comparer les Nombres avec de Plus Grands Intervalles [1000, 2000, 3000, ..., 100000] ?
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons des nombres avec un intervalle de 1000. documents = [str(i*1000) for i in range(1, 101)] Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer des nombres d'une plage arbitraire, par exemple [376, 377, 378, ..., 476] ?
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons des nombres dans une plage arbitraire, nous déplaçons donc les nombres vers une plage aléatoire documents = [str(i+375) for i in range(1, 101)] . Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer de grands nombres entre [4294967296, 4294967297, 4294967298, ..., 4294967396] ?
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons de très grands nombres. Similaire à l'idée de la dernière expérience, nous déplaçons la plage vers un grand nombre. documents = [str(i+4294967296) for i in range(1, 101)] Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer des nombres décimaux entre [0.0001, 0.0002, 0.0003, ...,0.1] ? (sans digits fixes)
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons des nombres décimaux. documents = [str(i/1000) for i in range(1, 101)] Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer des montants monétaires entre [2, 100] ?
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons des nombres monétaires. documents = ['$'+str(i) for i in range(1, 101)] Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer des dates entre [2024-07-24, 2024-07-25, 2024-07-26, ..., 2024-10-31] ?
Ici, nous voulons tester si le modèle peut déterminer la similarité sémantique lorsque nous comparons des nombres au format date, c'est-à-dire AAAA-MM-JJ. today = datetime.today(); documents = [(today + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(100)] Diagramme de dispersion avec moyenne et variance pour chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagLes modèles peuvent-ils comparer des heures entre [19:00:07, 19:00:08, 19:00:09,..., 20:39:07] ?
Ici, nous voulons tester si le modèle peut détecter la similarité sémantique lors de la comparaison de nombres au format horaire, c'est-à-dire hh:mm:ss. now = datetime.now(); documents = [(now + timedelta(minutes=i)).strftime('%H:%M:%S') for i in range(100)] Nuage de points avec moyenne et variance sur chaque delta. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagObservations
Voici quelques observations tirées des graphiques ci-dessus :
tagModèles Reranker
- Les modèles Reranker ont du mal à comparer les nombres. Même dans le cas le plus simple de comparaison de nombres entre [1, 100], leurs performances sont médiocres.
- Il est important de noter la construction spéciale de la requête utilisée pour nos rerankers, c'est-à-dire
what is the closest item to x, car cela peut également influencer les résultats.
tagModèles d'Embedding
- Les modèles d'embedding fonctionnent assez bien pour comparer de petits nombres entiers dans l'intervalle [1, 100] ou des nombres négatifs dans [-100, 1]. Cependant, leurs performances se dégradent significativement lors du décalage de cette plage vers d'autres valeurs, de l'ajout d'intervalles supplémentaires ou du traitement de nombres flottants plus grands ou plus petits.
- Des pics réguliers peuvent être observés à certains intervalles, généralement tous les 10 pas. Ce comportement peut être lié à la façon dont le tokenizer traite les chaînes, potentiellement en tokenisant une chaîne en "10" ou "1" et "0".
tagCompréhension des Dates et Heures
- Fait intéressant, les modèles d'embedding semblent avoir une bonne compréhension des dates et des heures, les comparant correctement la plupart du temps. Pour les graphiques de dates, des pics apparaissent tous les 30/31 pas, correspondant au nombre de jours dans un mois. Pour les graphiques temporels, des pics apparaissent tous les 60 pas, correspondant aux minutes dans une heure.
- Les modèles reranker semblent également capturer cette compréhension dans une certaine mesure.
tagVisualisation de la Similarité avec "Zéro"

Une autre expérience intéressante, probablement plus intuitive, consiste à visualiser directement le score de similarité ou de pertinence entre n'importe quel nombre et zéro (c'est-à-dire l'origine). En fixant le point de référence comme l'embedding de zéro, nous voulons voir si la similarité sémantique diminue linéairement à mesure que les nombres augmentent. Pour le reranker, nous pouvons fixer la requête à "0" ou "What is the closest number to number zero?" et classer tous les nombres pour voir si leurs scores de pertinence diminuent à mesure que les nombres augmentent. Les résultats sont présentés ci-dessous :
Ici, nous fixons l'"embedding d'origine" à l'embedding de "zéro" et vérifions si la similarité sémantique entre n'importe quel nombre et zéro est proportionnelle à la valeur du nombre. Plus précisément, nous utilisons documents = [str(i) for i in range(2048)]. Le nuage de points avec moyenne et variance pour chaque delta est montré. À gauche : jina-embeddings-v2-base-en ; À droite : jina-reranker-v2-multilingual.
tagConclusion
Cet article illustre comment nos modèles d'embedding et de reranking actuels gèrent les comparaisons de nombres. Malgré la configuration expérimentale relativement simple, elle expose certaines failles fondamentales dans les modèles actuels et fournit des informations précieuses pour le développement de notre prochain embedding et reranker.
Deux facteurs clés déterminent si un modèle peut comparer précisément les nombres :
Premièrement, la tokenization : Si le vocabulaire n'inclut que les chiffres 0-9, alors 11 pourrait être tokenisé en tokens séparés 1 et 1, ou comme un seul token 11. Ce choix impacte la compréhension des valeurs numériques par le modèle.


Différents tokenizers entraînent différentes interprétations de 9.11. Cela peut affecter l'apprentissage contextuel en aval. Source : The Tokenizer Playground sur HuggingFace.
Deuxièmement, les données d'entraînement : Le corpus d'entraînement influence significativement les capacités de raisonnement numérique du modèle. Par exemple, si les données d'entraînement incluent principalement de la documentation logicielle ou des dépôts GitHub où le versionnage sémantique est courant, le modèle pourrait interpréter que 9.11 est supérieur à 9.9, car 9.11 est la version mineure suivant 9.9.
La capacité arithmétique des modèles de recherche dense, tels que les embeddings et les rerankers, est cruciale pour les tâches impliquant RAG et la recherche et le raisonnement avancés. De fortes capacités de raisonnement numérique peuvent améliorer significativement la qualité de la recherche, particulièrement lors du traitement de données structurées comme JSON.






