Embeddings : en route vers la quatrième dimension

Comment les embeddings forment le cœur des systèmes d'IA modernes, influençant tout, des recommandations YouTube aux assistants personnels.

Les assistants conversationnels et autres outils d'intelligence artificielle font désormais partie de notre quotidien. Que ce soit pour obtenir une réponse à une question, une recommandation personnalisée ou encore une traduction automatique, ces systèmes nous impressionnent par leur capacité à comprendre le langage naturel et à générer des réponses pertinentes.

Mais comment fonctionnent-ils exactement ? Quels sont les concepts clés qui se cachent derrière ? Dans cet article, nous allons nous intéresser à une notion fondamentale qui est au cœur de nombreux systèmes d'IA modernes : les "embeddings".

Lorsqu'on parle d'enrichir un assistant avec des connaissances externes par exemple, les "embeddings" jouent un rôle central. Ils permettent d'indexer l'information pour que le modèle puisse ensuite y accéder de manière pertinente en fonction des requêtes des utilisateurs. C'est ce qu'on appelle le Retrieval Augmented Generation ou RAG.

Mais, les “embeddings” sont en réalité partout. Votre historique Youtube, un “embedding”, le livre que vous avez acheté sur Amazon, un “embedding”, la recommandation de séries que Netflix vous propose, un “embedding”... Et, vous, désolé de vous l’apprendre cher utilisateur de ces plateformes, vous êtes quelque part dans un obscur réseau de neurones... un “embedding”.

Mais c’est quoi à la fin un “embedding” ?

Ok, ok, on y va. Pour cela, demandons à ChatGPT (dans sa version “Code Interpreter”, c’est à dire dans sa capacité à générer et exécuter du code pour traiter des données..) de nous générer quelques données avec lesquelles nous allons jouer.

Génère moi un fichier pour les animaux suivants : le verre de terre, la limace, la hyenne, la panthère, la jument, l'âne.

Chaque animal a les caractéristiques suivantes : vitesse de déplacement, taille, vitesse de reproduction, durée de vie, régime alimentaire, sociabilité. Les valeurs des caractéristiques sont entre 0.2 et 1. Détermine des valeurs qui te semblent correctes.

Affiche le tableau animaux/caractéristiques

Les valeurs ont l’air cohérentes. Ça fera le job.

Affiche une visualisation "joueur de foot comme dans FIFA" avec tous les animaux/caractéristiques dans le même graphique. Prends des couleurs suffisament distinctes (rouge, bleu, jaune ..) pour que ce soit lisible

On parle en réalité de graphique radar et non de graphique FIFA

Ah ben voilà, c’est plus joli (et surtout ça nous permet de voir le genre de choses que l’on peut faire avec “Code Interpreter / Advanced Data Analysis”). On observe par exemple que le verre de terre et la limace ont des caractéristiques très proches.

Génére moi une visualisation des animaux sur seulement deux dimensions. Utilise des couleurs vives (rouge, bleu, jaune ..) pour représenter les animaux. Affiche le nom de chaque animal à côté de la croix le représentant.

Pourquoi deux dimensions ? Parce que c’est plus simple à visualiser

Cette visualisation est plus parlante. Les animaux ayant les mêmes caractéristiques sont proches l’un de l’autre. Notez que les deux dimensions (abscisses / ordonnées ou horizontale / verticale) ne représentent rien de concret ou de directement observable. Elles servent plutôt à modéliser des relations abstraites ou des caractéristiques sous-jacentes dans un espace continu. On dit que l’espace est latent. Dans cet espace latent, les objets qui se ressemblent sont placés côte à côte.

Ajoute maintenant un escargot.

Bon, j’avoue, j’ai triché pour la croix turquoise de l’escargot. J’ai perdu ma session “Code Interpreter“, je l’ai donc rajouté à la main !

L’escargot est venu se loger juste à côté de la limace, ce qui à priori fait sens, l’escargot étant une sorte de limace avec une coquille. Bouger légèrement dans cet espace et vous obtenez un animal aux caractéristiques légèrement différentes.

Ajoute maintenant un animal qui aurait à la fois les caractéristiques de la jument et de l'âne. Comment pourrait-on appeler un tel animal ?

Bienvenue à toi mulet !

Le mulet est venu se positionner entre la jument et l'âne, réprésentant ainsi la moyenne des caractéristiques de ses parents. Cela démontre le caractère interpolatif de l'espace : en prenant un point intermédiaire entre deux points existants, nous obtenons un point qui capture la "signification intermédiaire" des éléments qu'il représente. Ici, avec notre exemple des animaux : un mulet.

Une dernière observation que l’on peut faire, c’est que dans cet espace à deux dimensions, le mulet a environ pour valeur:

  • -1.8 sur la dimension horizontale

  • - 0.8 sur la dimension verticale

C’est quoi le rapport avec les embeddings ?

Le rapport est que les valeurs numériques du mulet peuvent être considérées comme son "embedding".

Un embedding, dans le contexte de l'apprentissage automatique, est un vecteur de valeurs numériques qui représente un objet (une image, un mot, un utilisateur...) dans un espace de dimensions réduites. Et l’espace en question partage les même propriétés que notre espace “animalier“ à savoir qu’il est latent, continu et interpolatif.

Rappel. Un vecteur, en termes simples, est une quantité qui possède à la fois une grandeur et une direction.

Considérons un oiseau qui vole avec une certaine vitesse dans une direction spécifique. La vitesse de vol et la direction de l'oiseau forment ensemble un vecteur dans notre espace physique quotidien composé de trois dimensions : largeur, hauteur et profondeur. Si le vol de l'oiseau est très vertical, alors la valeur de la dimension hauteur sera plus élevée que celles de la largeur et de la profondeur.

Dans le domaine de l'IA, les embeddings (vecteurs) peuvent avoir des centaines, ou des milliers de dimensions (directions), chacune représentant différents aspects sémantiques ou caractéristiques de l'entité représentée (mot, pixel, film, playlist…).

Chaque dimension d'un embedding peut être vue comme une direction dans un espace conceptuel, où la valeur de cette dimension indique l'importance ou la pertinence de cet aspect pour l'entité représentée.

Demandons à l’API d’OpenAI l’embedding du mot : “limace“:

Ce résultat est généré par un bout de code Python qui appelle l’API d’embedding d’OpenAI avec le modèle text-embedding-ada-002

On obtient un vecteur dense de 1536 valeurs numériques comprises entre -1.0 et 1.0 (J’ai coupé l’image, je ne vous ai pas affiché les 1536 valeurs. 1 valeur par dimension. Le modèle utilisé ici retourne un embedding de 1536 dimensions). Ce vecteur est l'embedding de “limace”. Il encapsule sa signification dans un format que la machine peut comprendre et traiter. Plus les embeddings sont précis, plus ils sont capables de capturer des nuances sémantiques, et plus les modèles derrière seront performants dans leurs tâches.

Si on avait demandé l’embedding du mot “escargot“, on aurait aussi obtenu une liste de 1536 nombres entre -1.0 et 1.0. Et ce vecteur “escargot“ aurait probablement été assez proche du vecteur “limace“.

Il y a toutefois une différence importante entre notre exemple animalier et les embeddings retournés ici par OpenAI.

Dans notre exemple avec les animaux, on est parti de caractéristiques préalablement définies : la vitesse, la taille, la durée de vie… et on a attribué à chaque animal une valeur.

À l'inverse, les modèles de langage comme GPT-4 (ça peut être d’autres types de modèles) partent d’une feuille blanche. Les embeddings sont alors le résultat d’un apprentissage sur d’énormes quantités de texte. Chaque mot ou fragment de mot (token) devient un vecteur numérique au sein d'un espace vectoriel abstrait où la disposition et la proximité des vecteurs reflètent des relations sémantiques et contextuelles.

Les mots aussi ont besoin d’attention

De la manière dont je vous ai exposé les choses jusqu’à présent, vous pourriez croire que l’embedding d’un mot est statique. Le mot est associé à une liste de nombres et fin de l’histoire. Ça, c’était avant, il y a 7/10 ans. Autant dire une éternité.

Mais les choses ont changé en juin 2017 avec l’introduction par une équipe de Google du concept de self-attention ou auto-attention dans l’article “Attention Is All You Need” (papier qui marque la naissance des fameux transformers).

Avec cette approche, les embeddings ne sont plus statiques ; ils deviennent dynamiques et contextuels. L'embedding d'un mot comme “vole” varie en fonction du texte dans lequel il est utilisé.

Prenons la phrase : “L'oiseau vole dans le ciel”. Ici, l'embedding de “vole” est influencé par les autres mots de la phrase, notamment “oiseau” et “ciel”. Cette influence est mesurée par ce qu’on appelle des scores d'attention. Ces scores, calculés automatiquement par le modèle, déterminent la force de l'interaction entre les mots. Ici, “oiseau” et “ciel” se verront attribués un score d'attention élevé indiquant qu'ils sont significatifs pour comprendre le sens de "vole".

Dans, “Le pick-pocket vole un portefeuille dans le métro”, l’embedding de “vole” sera bien différent.

Les deux exemples ci-dessus sont des phrases courtes mais vous devez avoir à l’esprit que ce mécanisme de self-attention s’applique à l’ensemble du texte (dans les limites de la taille de la fenêtre contextuelle).

Aparté : auto-attention et taille de la fenêtre contextuelle. Avec la self-attention, chaque mot ajouté à la fenêtre contextuelle augmente de manière importante les calculs nécessaires. Pour chaque mot, le modèle doit évaluer son interaction avec tous les autres mots de cette fenêtre. Cela explique en partie pourquoi la taille des fenêtres contextuelles est limitée.

Enfin, c’est de moins en moins vrai avec maintenant des fenêtres de 128 000 tokens. Imaginez qu’il y a trois ans, on dépassait à peine les 512 tokens ce qui réduisait beaucoup l’utilité de ces technologies.

Dans un texte plus long, certains mots ou phrases clés peuvent se voir attribuer un poids plus important, reflétant leur rôle central dans la compréhension globale du sujet.

La self-attention permet, de plus, aux modèles de faire des liens entre différentes parties du texte, comme lier une référence faite au début avec des informations présentées plus tard.

J’ai demandé à Dall-E 3 une illustration pour mon paragraphe. Hum … peut mieux faire

Les modèles d’aujourd’hui vont encore un cran plus loin. Ils utilisent plusieurs mécanismes d'attention (on parle de multi-head attention). Ces multiples “têtes” permettent au modèle d'analyser différentes facettes d'un texte. Chacune se concentre sur des aspects variés des relations entre les mots, tels que la syntaxe, la sémantique ou la manière dont certains mots se réfèrent à d'autres éléments précédemment mentionnés (liens anaphoriques).

Bref, les modèles actuels sont devenus diablement efficaces pour produire des embeddings d’une grande précision et d’une grande finesse. Sans ces embeddings de haute qualité, des applications comme ChatGPT, Claude, Midjourney ou Dall-e 3 fonctionneraient beaucoup moins bien. Comme quoi, un peu d'attention dans le travail peut vraiment faire toute la différence…

Il va être temps de conclure, non ?

Oui, oui … vous avez raison.

Alors, revenons à l'essentiel. Un embedding, c'est un vecteur numérique qui représente un élément, que ce soit un mot, une image, ou même le profil d'un utilisateur, dans un espace de dimensions. Ce concept est crucial non seulement dans le domaine des IA génératives, mais aussi pour une multitude d'algorithmes d'apprentissage automatique.

Sur YouTube, l’embedding de votre “historique de visionnage” est très probablement utilisé pour affiner les recommandations de vidéos qui vous sont faites.

Remarque. Les modèles n'utilisent pas forcément un mécanisme d'attention pour leurs embeddings.

Rappelons enfin que les embeddings possèdent des propriétés continues et interpolatives dans un espace latent (abstrait)

Dit autrement, quand vous tapez le prompt X, et que vous changez juste un mot insignifiant, vous obtenez un prompt qui sera juste “à côté” du prompt X (propriétés continues).

Et si vous dîtes à ChatGPT:

Ecris moi un petit texte sur une limace
plus concis stp

Vous modifiez votre prompt initial en lui conférant un caractère de concision (interpolation). Un peu à la manière du mulet qui était venu se placer entre la jument et l’âne.

Pourquoi avoir parlé des embeddings ? 

Simplement parce qu'ils sont au cœur d'outils que vous allez de plus en plus utiliser directement ou indirectement : base de données vectorielles, recherche vectorielle, bases de connaissance pour vos assistants IA. Et puisque nous allons explorer tous ces sujets prochainement, il me semblait pertinent de parler des embeddings dans un premier temps.

Après, vous êtes en droit de penser que ça fait beaucoup de mots pour dire qu’un embedding, en gros, c’est un vecteur. Je ne vous en voudrais pas 😉.