La premiere fois que j’ai mis en production une fonctionnalite reposant sur une base vectorielle, j’ai passe un apres-midi a ne rien comprendre a mes resultats. Je l’avais traitee comme un index de mots-cles. Ce n’en est pas un. Une base vectorielle stocke du sens, ou du moins une approximation numerique du sens, et elle repond a un type de question different de celui des bases que j’utilisais depuis des annees. Cet article est l’explication que j’aurais aime qu’on me donne avant de commencer.
Ce qu’est reellement un embedding
Un embedding est une liste de nombres a virgule flottante qui represente un contenu. Vous prenez du texte, une image ou un extrait audio, vous le passez dans un modele, et il en ressort un tableau de taille fixe. Un embedding de texte typique peut avoir 384, 768 ou 1536 dimensions. Chaque nombre pris isolement ne signifie rien d’interpretable. Ensemble, ils placent le contenu en un point precis d’un espace a haute dimension.
La propriete utile est que des contenus similaires se retrouvent a des positions proches. La phrase « mon ordinateur portable ne s’allume plus » et la phrase « mon pc est mort » produisent des vecteurs proches, alors qu’elles ne partagent presque aucun mot. Une recherche par mots-cles raterait completement ce lien. Un embedding le capte parce que le modele qui a produit les vecteurs a appris, a partir d’enormes quantites de texte, que ces phrases veulent dire a peu pres la meme chose.
C’est tout l’interet. On convertit la notion humaine floue de « ces deux choses parlent du meme sujet » en un probleme de geometrie. Une fois que c’est de la geometrie, un ordinateur le resout vite.
Comment se mesure la similarite
La proximite dans cet espace se mesure generalement avec la similarite cosinus ou, de facon equivalente pour des vecteurs normalises, le produit scalaire. La similarite cosinus regarde l’angle entre deux vecteurs et ignore leur longueur. Deux vecteurs pointant dans la meme direction ont un score proche de 1.0, des vecteurs a angle droit un score proche de 0, et des vecteurs opposes un score proche de -1.0. Certains systemes utilisent plutot la distance euclidienne, qui mesure la distance en ligne droite. Le choix depend de la facon dont le modele d’embedding a ete entraine, et se tromper degrade discretement vos resultats.
Voici la partie qui surprend ceux qui viennent des bases relationnelles. Il n’y a pas de correspondance exacte. Chaque requete renvoie une liste classee d’elements approximativement pertinents avec un score attache. C’est vous qui decidez ou couper la liste. Ce changement mental, de « la ligne qui correspond » vers « les lignes les plus similaires », est le plus gros ajustement.
Generer des embeddings en pratique
Vous entrainez rarement un modele d’embedding vous-meme. Vous en appelez un. Voici un petit exemple qui transforme quelques phrases en vecteurs et mesure leur proximite.
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("all-MiniLM-L6-v2")
phrases = [
"mon ordinateur portable ne s'allume plus",
"mon pc est mort",
"a quelle heure ferme le magasin",
]
vecteurs = model.encode(phrases, normalize_embeddings=True)
def cosinus(a, b):
return float(np.dot(a, b))
print("portable vs pc:", cosinus(vecteurs[0], vecteurs[1]))
print("portable vs magasin:", cosinus(vecteurs[0], vecteurs[2]))
Lancez ceci et la premiere paire obtient un score eleve tandis que la seconde obtient un score bas. Le modele n’a jamais vu ces phrases exactes pendant l’entrainement. Il a appris les relations a partir du contexte, et cette generalisation est ce qui fait fonctionner toute l’approche.
Pourquoi il faut une base specialisee
Vous pourriez stocker les vecteurs dans une colonne normale et comparer votre requete a chaque ligne. Cela s’appelle une recherche exacte ou par force brute, et cela fonctionne bien jusqu’a peut-etre cent mille vecteurs. Au-dela, ca s’effondre, car comparer une requete a dix millions de vecteurs a chaque appel est trop lent pour quoi que ce soit d’interactif.
Les bases vectorielles resolvent cela avec des index de plus proches voisins approximatifs. Le plus courant est HNSW, pour Hierarchical Navigable Small World. Il construit un graphe en couches ou chaque vecteur est relie a ses voisins, et une requete parcourt le graphe au lieu de tout balayer. Vous echangez un peu de precision contre un gain de vitesse enorme. D’autres types d’index comme IVF et la quantification de produit font d’autres compromis entre memoire, vitesse et rappel.
- Le rappel est la fraction des vrais plus proches voisins que votre index renvoie reellement. Vous l’ajustez selon la latence que vous pouvez vous permettre.
- La latence est le temps que prend une requete. HNSW repond typiquement en quelques millisecondes meme sur des millions de vecteurs.
- La memoire compte car les graphes HNSW sont volumineux. La quantification reduit les vecteurs au prix d’un peu de precision.
Le filtrage par metadonnees, la ou ca devient concret
La recherche par similarite pure suffit rarement a elle seule. Dans une vraie application, vous voulez « trouver les documents similaires a cette requete, mais uniquement dans l’espace de cet utilisateur, ecrits ces 90 derniers jours. » Cela suppose de combiner recherche vectorielle et filtres classiques sur les metadonnees. La qualite avec laquelle une base gere cette combinaison, appelee recherche filtree ou hybride, est l’un des criteres qui me tiennent le plus a coeur quand j’evalue les options, et c’est un theme central de mes notes sur comment choisir une base vectorielle.
Mal fait, le filtrage force le moteur soit a tout balayer, soit a renvoyer trop peu de resultats parce que le filtre a elimine la plupart des candidats trouves par l’index. Bien fait, le filtre est applique pendant le parcours du graphe, et vous gardez des resultats rapides et precis a l’interieur du sous-ensemble qui vous interesse.
Un modele mental qui tient
Je vois une base vectorielle comme un moteur de recherche du sens plutot que des mots. Un index de mots-cles repond a « quels documents contiennent ces termes. » Un index vectoriel repond a « quels documents parlent de la meme chose que cette requete. » Les deux sont complementaires, pas concurrents, et c’est pour cela que les systemes les plus solides que j’ai construits utilisent les deux a la fois et fusionnent les classements.
Les embeddings portent la semantique. L’index rend la recherche rapide a grande echelle. Les filtres de metadonnees gardent les resultats pertinents pour l’utilisateur reel. Une fois ces trois pieces assimilees, le reste du domaine a cesse de ressembler a de la magie pour devenir de l’ingenierie.
Vers quoi cela mene
Si les bases vectorielles ont explose en popularite, c’est qu’elles sont la couche de stockage sous la generation augmentee par recuperation. Quand vous voulez qu’un modele de langage reponde a des questions sur vos propres documents, vous encodez ces documents, vous stockez les vecteurs, et vous recuperez les pertinents au moment de la requete. Je deroule ce schema complet dans construire des systemes RAG avec des bases vectorielles, et il s’appuie directement sur tout ce qui precede. Pour la vue d’ensemble de la mise en production de ces systemes, mon article sur l’ingenierie IA pratique couvre les decisions qui l’entourent.
Commencez par generer quelques embeddings et afficher les scores de similarite vous-meme. Voir des phrases liees obtenir un score eleve et des phrases sans rapport un score bas fait plus pour l’intuition que n’importe quel schema. Tout le reste n’est que detail par-dessus cette seule idee.


