Accroche
Tu as suivi RAG-01 et RAG-02. Tu sais qu’un système RAG découpe les documents en chunks, puis transforme chaque chunk en embedding — une liste de nombres à virgule. Tu sais aussi qu’un embedding, c’est un hash sémantique : changer un mot par un synonyme produit un vecteur quasi-identique, là où MD5 ferait exploser tout le hash. Cette intuition tient. Cette leçon répond à la question suivante : quel modèle d’embedding tu utilises pour fabriquer ces vecteurs, et pourquoi ce choix conditionne la qualité de tout ce qui se passe ensuite.
Le décor : il existe une dizaine de familles de modèles d’embedding utilisables en 2026, certaines open-source que tu héberges toi-même, d’autres derrière une API payante. Les chiffres-clés à connaître tiennent en trois lignes : BGE-M3 (1024 dimensions, multilingue, gratuit, self-hosted via Ollama) est un excellent défaut pour un lab francophone ; OpenAI text-embedding-3-large (3072 dimensions, payant) ou Voyage 3 sont les alternatives sérieuses si tu veux scaler sans gérer un GPU. Le reste de cette leçon explique pourquoi.
À la fin, tu sauras : ce qu’un modèle d’embedding fait concrètement, comment lire le benchmark MTEB sans tomber dans le panneau, pourquoi la dimension d’un vecteur n’est pas un dial à pousser au max, et comment décider entre self-host et API sur des critères opérationnels et non idéologiques.
Le modèle d’embedding : qu’est-ce qui transforme le texte en vecteur
Reprenons le fil. Dans RAG-01, on a posé que l’embedding est l’opération qui transforme un chunk en vecteur de sens. La leçon présente s’attaque au qui fait cette opération : le modèle d’embedding.
Définition : un modèle d’embedding, c’est un réseau de neurones pré-entraîné (un encoder, dérivé de l’architecture BERT publiée par Google en 2018) dont la sortie est une liste fixe de N nombres à virgule. Tu lui donnes une string en entrée, il te rend N floats. Toujours les mêmes N (la dimension du modèle), toujours dans le même intervalle (typiquement entre -1 et 1 après normalisation).
Analogie infra : un modèle d’embedding, c’est un convertisseur déterministe. Tu lui passes la même string deux fois, tu obtiens exactement les deux mêmes vecteurs (à condition d’utiliser la même version du modèle). C’est l’équivalent d’une fonction
hash_v2(text) → bytes[]versionnée — la version du modèle est dans la signature, comme la version d’un protocole de chiffrement.
Un modèle d’embedding pèse en mémoire entre 80 Mo (all-MiniLM-L6-v2, 384 dim, le plus léger, anglais) et 14 Go (e5-mistral-7b, 4096 dim, qualité maximale mais lourd à servir). Le défaut ingénierie 2026 — BGE-M3 — pèse environ 2 Go en RAM en float32. Sur un laptop récent, ça tient sans GPU dédié.
L’invariant central : indexation = requête, le même modèle obligatoire
Avant tout le reste, un point critique. Quand tu indexes 10 000 chunks avec BGE-M3 et que tu produis 10 000 vecteurs à 1024 dim, tu dois utiliser exactement le même modèle BGE-M3 pour transformer la question utilisateur au moment de la requête.
Le schéma en texte
- Documents (indexation) → BGE-M3 (version v1.0)
- BGE-M3 (version v1.0) → Vector store 10 000 vecteurs 1024D
- Question (requête) → BGE-M3 (version v1.0)
- BGE-M3 (version v1.0) → search(top_k)
- Vector store 10 000 vecteurs 1024D → search(top_k) (lookup)
- search(top_k) → Top-k chunks
Si tu indexes avec un modèle A et tu requêtes avec un modèle B, les deux vecteurs vivent dans deux espaces géométriques incompatibles. La recherche par cosinus retourne des chunks au hasard. Symptôme : recall qui s’effondre du jour au lendemain après un upgrade de modèle. Correction : la version exacte du modèle est stockée dans les métadonnées de l’index. Migration vers un nouveau modèle = réindexation totale du corpus, pas mix.
Analogie infra directe : c’est le pattern format de sérialisation versionné. Si tu écris ton cache Redis en MessagePack v1 et tu le relis en MessagePack v2, soit ça crashe, soit ça te rend du JSON corrompu. Ici, ça ne crashe pas — c’est encore pire, ça rend des résultats apparemment corrects mais sémantiquement faux.
L’analogie centrale, approfondie : embedding = hash sémantique
Tu as vu en RAG-01 le hash sémantique. On va creuser ce que ça veut dire concrètement, parce que c’est l’intuition la plus utile pour comprendre les choix qui suivent.
Un hash classique (MD5, SHA-256) prend une string et te rend une signature de longueur fixe. Sa propriété structurelle : un caractère qui change à l’entrée, et toute la signature explose. Deux strings très proches en sens (« la capitale française », « Paris ») produisent deux hash totalement différents. C’est exactement ce qu’on veut pour vérifier l’intégrité d’un fichier — on détecte la moindre modification — mais c’est inutilisable pour chercher par sens.
Un embedding prend lui aussi une string et rend une signature de longueur fixe (le vecteur de N floats). Sa propriété structurelle est inversée : un mot remplacé par un synonyme, et la signature change à peine. Deux strings proches en sens produisent deux vecteurs proches en géométrie (mesuré par la similarité cosinus, vue en RAG-01).
Le schéma en texte
- 'capitale française' → MD5
- 'capitale française' → BGE-M3
- 'Paris, ville centrale' → MD5
- 'Paris, ville centrale' → BGE-M3
- MD5 → a3f2b1... (hash A)
- MD5 → 7e91c8... (hash B, totalement différent)
- BGE-M3 → [0.12, -0.4, ...] (vec A)
- BGE-M3 → [0.13, -0.39, ...] (vec B, quasi-identique)
Trois conséquences pratiques pour ton système RAG :
-
Le modèle d’embedding détermine la qualité du regroupement par sens. Un mauvais modèle (entraîné sur peu de données ou sur la mauvaise langue) produit des vecteurs qui ne reflètent pas la proximité sémantique réelle. Symptôme : tu poses une question, le système rapporte des chunks qui ressemblent superficiellement (mêmes mots) mais ne répondent pas. Cause racine : ton hash sémantique n’est pas assez bon.
-
Aucune optimisation downstream ne rattrape un embedder médiocre. Tu peux ajouter du reranking, du hybrid search (RAG-05, à venir), du query rewriting — si l’embedder a mal projeté tes documents au départ, la limite de qualité est posée à ce moment-là. C’est l’équivalent d’enregistrer un audio en MP3 64 kbps et d’espérer qu’un égaliseur récupère les fréquences perdues.
-
Le coût de changer de modèle plus tard est la réindexation totale. Conséquence directe de l’invariant indexation = requête. C’est pour ça que choisir l’embedder au départ avec un minimum de discernement t’évite des migrations coûteuses 6 mois plus tard.
La dimension du vecteur : combien de cases dans la signature
Tu choisis ton modèle, et avec lui tu hérites d’une dimension — le nombre de floats que tient le vecteur. C’est figé par le modèle. Tu ne peux pas demander à BGE-M3 de te rendre du 768 dim : il rend du 1024 ou rien.
Définition : la dimension d’un embedding, c’est la longueur de la liste de nombres produite par le modèle. Valeurs typiques en 2026 : 384, 768, 1024, 1536, 3072, 4096. Plus la dimension est élevée, plus le modèle dispose d’axes pour distinguer les nuances sémantiques — mais plus le stockage et la comparaison coûtent.
Analogie infra : la dimension, c’est la résolution de ta signature sémantique. Un vecteur 384 dim, c’est une photo basse résolution qui suffit pour reconnaître un visage de loin. Un vecteur 3072 dim, c’est la même photo en haute définition — tu vois les détails, mais le fichier est dix fois plus lourd et l’affichage met plus de temps. Au-delà d’un certain seuil, la résolution supplémentaire ne te raconte rien d’utile : tu paies du stockage pour des pixels que ton œil ne distingue pas.
| Dimension | Modèles représentatifs | Stockage / 1M chunks | Cas d’usage typique |
|---|---|---|---|
| 384 | all-MiniLM-L6-v2 | ~1,5 Go | Prototype, edge, mobile, latence prioritaire |
| 768 | all-mpnet-base-v2 | ~3 Go | Standard SBERT historique, anglais solide |
| 1024 | BGE-M3, multilingual-e5-large, mxbai-large, Cohere v3 | ~4 Go | Sweet spot 2026 — qualité/coût optimal |
| 1536 | OpenAI text-embedding-3-small | ~6 Go | Baseline API propriétaire |
| 3072 | OpenAI text-embedding-3-large | ~12 Go | Qualité maximale, coût stockage 3× |
| 4096 | e5-mistral-7b | ~16 Go | Recherche, pas production légère |
Le calcul du stockage est mécanique : chaque float occupe 4 octets en float32. Donc 1 million de chunks × 1024 dimensions × 4 octets ≈ 4 Go (sans compter les métadonnées et les structures d’index). Si tu passes en 3072 dimensions, c’est 12 Go. Si tu réduis en int8 (un octet par valeur, perte de qualité minime), tu divises par 4.
1024 est devenu la dimension par défaut 2026 pour les embeddings de retrieval général. Au-delà, les gains de qualité sont marginaux pour la grande majorité des corpus, et le coût stockage/latence devient sensible. Tu ne montes au-dessus que si tu mesures un gain réel sur ton corpus, ce qui est plus rare qu’on le croit.
Comment lire le benchmark MTEB sans se faire avoir
Quand tu cherches « quel modèle d’embedding choisir », tu vas inévitablement tomber sur MTEB (Massive Text Embedding Benchmark). C’est le palmarès public le plus cité, mis à jour en continu sur HuggingFace (mteb/leaderboard). Trois choses à savoir avant de l’utiliser pour décider.
Le schéma en texte
- MTEB Score Global (moyenne 56 tâches) → Classification (12 datasets)
- MTEB Score Global (moyenne 56 tâches) → Clustering (11 datasets)
- MTEB Score Global (moyenne 56 tâches) → Retrieval (15 datasets) ← REGARDE ICI POUR RAG
- MTEB Score Global (moyenne 56 tâches) → 4 autres familles (STS, reranking, etc.)
- Retrieval (15 datasets) ← REGARDE ICI POUR RAG → Recall@k nDCG@k MRR
Premier point — la note globale cache les asymétries. MTEB est une moyenne sur 56 tâches réparties en 7 familles (classification, clustering, retrieval, etc.). Pour un usage RAG, seule la sous-section Retrieval (15 tâches dont MS MARCO, NFCorpus) compte. Un modèle peut être top sur clustering et médiocre sur retrieval — ou l’inverse. Filtrer le leaderboard sur la colonne Retrieval avant de choisir.
Deuxième point — le palmarès évolue chaque trimestre. Mi-2024, BGE-M3 était top retrieval ; fin 2024, mxbai et Voyage l’ont dépassé sur certaines tâches ; mi-2026, les positions exactes varient encore — recheck au moment du choix. [NON VÉRIFIÉ — top-5 MTEB Retrieval avril 2026 à confirmer sur HuggingFace au moment de décider.] L’ordre de grandeur stable : les meilleurs open-source (BGE-M3, mxbai-large) sont à quelques points des meilleurs propriétaires (Voyage, OpenAI).
Troisième point — le biais MTEB. Les datasets sont majoritairement anglais. La sous-section multilingue (MIRACL, MLQA-Retrieval) couvre moins de langues que les annonces produit le suggèrent. Pour évaluer un modèle sur ton corpus français technique, MTEB ne suffit pas : tu construis un mini-eval set sur ton domaine (cf. RAG-07 évaluation à venir).
MTEB te donne une présélection raisonnable, jamais une décision finale. Tu prends les 3-5 candidats top retrieval qui matchent ta langue et ton infrastructure, puis tu mesures sur ton propre corpus. La note publique est un filtre, pas un verdict.
Analogie infra : MTEB, c’est l’équivalent du benchmark TPC-C pour les bases SQL. Tu sais qu’un serveur Postgres tient X transactions par seconde dans des conditions de labo. En production, sur ta charge réelle avec tes index et ton schéma, le chiffre tombe à X/3 ou X/10. Le benchmark est un bon point de départ ; il ne dispense pas de mesurer chez toi.
Open-source ou API : le calcul TCO, pas l’idéologie
Le choix entre auto-hébergement (Ollama, sentence-transformers) et API (OpenAI, Cohere, Voyage) n’est pas philosophique. C’est un calcul de coût total de possession, et il bascule selon ta situation.
Matrice de décision
| Contexte | Recommandation | Pourquoi |
|---|---|---|
| Lab solo, 10k-100k chunks, multilingue FR/EN, données sensibles | BGE-M3 self-host (Ollama) | Zéro coût marginal, multilingue natif, souveraineté totale, latence acceptable même sur CPU. Le défaut raisonnable. |
| Service applicatif, 100k-1M chunks, scaling burst occasionnel | OpenAI text-embedding-3-large ou Voyage 3 | Pas de DevOps GPU à gérer, scaling automatique, coût mensuel encore raisonnable (~$130/mois pour 1M chunks réindexés mensuellement). |
| Corpus 10M+ chunks, beaucoup de réindexations, GPU disponible | BGE-M3 ou mxbai self-host sur GPU | À cette échelle, l’API coûte des milliers d’euros par mois. Le ROI bascule vers self-host. |
| Données sensibles non négociables (RGPD, on-premise, secret défense) | Self-host obligatoire | Critère binaire : tu n’envoies pas ton corpus à un tiers. BGE-M3 ou mxbai. |
| Latence cible < 50 ms par requête | Self-host GPU local | Une API ajoute systématiquement 100-200 ms de réseau aller-retour. Inévitable. |
| Besoin spécialisé (code, finance, juridique) | Tester Voyage 3-large | Voyage est souvent cité au top sur ces benchmarks de domaine. Mesure avant de basculer. |
Trois heuristiques en complément :
- Commence simple. Si tu prototypes, BGE-M3 self-host via Ollama est imbattable : zéro coût, install en une commande, multilinguisme natif. Tu migres vers une API uniquement quand tu mesures un manque concret.
- Le critère souveraineté tranche en premier. Si tes données sont sensibles, le débat OS vs API est clos. Pas la peine de comparer la qualité.
- Le coût scale linéairement avec les tokens, pas avec le nombre de chunks. Un chunk de 800 tokens coûte 8× plus cher qu’un chunk de 100 tokens à embedder. Petit chunking = gros volume, mais facture cumulée à surveiller.
Chiffres de coût pour fixer les idées
Pour un corpus de 100 000 chunks (≈ 5M tokens à 50 tokens moyens par chunk) :
| Stack | Coût indexation initiale | Coût réindexation mensuelle | Coût requêtes (1k/jour, 50 tokens chacune) |
|---|---|---|---|
| BGE-M3 self-host CPU | 0 € (compute amorti) | 0 € | 0 € |
| OpenAI text-embedding-3-large ($0,13 / 1M tokens) | ~0,65 € | ~0,65 € | ~0,20 €/mois |
| Voyage 3 (~$0,12 / 1M tokens) | ~0,60 € | ~0,60 € | ~0,18 €/mois |
À 100k chunks, l’API te coûte moins de 1 € par mois — négligeable. À 10M chunks ré-embedés mensuellement, l’API monte à ~65 €/mois, encore acceptable. À 100M chunks, on est à ~650 €/mois, et le calcul self-host commence à devenir intéressant. À 1G chunks (rare en lab solo, fréquent en grand corpus enterprise), on franchit les 6500 €/mois et le GPU dédié est rentabilisé en quelques mois.
Pour un lab solo francophone qui démarre, BGE-M3 self-host est le choix raisonnable. Tu ne touches une API qu’avec un déclencheur précis : besoin de scaling instantané sans GPU, ou démonstration empirique qu’un autre modèle bat BGE sur ton corpus mesuré.
Le multilinguisme, vu du côté infra
Si tu es francophone et que ton corpus mélange FR, EN, et parfois d’autres langues, tu as besoin d’un modèle qui projette les trois dans le même espace vectoriel. C’est ce que fait BGE-M3 (entraîné sur plus de 100 langues simultanément). Conséquence pratique : une requête en français peut retourner un chunk en anglais si le sens correspond.
Le schéma en texte
- Query FR 'convention worktrees ?' → BGE-M3 (multilingue natif)
- Doc EN 'multi-terminal git rules' → BGE-M3 (multilingue natif)
- Doc FR 'règles multi-terminal' → BGE-M3 (multilingue natif)
- BGE-M3 (multilingue natif) → Espace vectoriel UNIFIÉ FR et EN cohabitent
- Espace vectoriel UNIFIÉ FR et EN cohabitent → Match FR-FR cos = 0,85
- Espace vectoriel UNIFIÉ FR et EN cohabitent → Match FR-EN cos = 0,71 (cross-lingual !)
À l’inverse, un modèle anglais-only (par exemple all-MiniLM-L6-v2) appliqué à un corpus FR/EN te coûte des points massifs sur les requêtes françaises — l’ordre de grandeur observé en pratique : recall qui chute de 70 % à 25 % sur les requêtes FR. C’est mesurable et c’est mortifère en production. Pour un lab francophone, prendre BGE-M3 ou multilingual-e5-large d’office, et ne descendre vers all-MiniLM qu’en cas de prototype anglais-only avec contrainte de latence extrême.
Analogie infra : le multilinguisme natif d’un modèle, c’est l’équivalent d’un protocole binaire portable (Protocol Buffers, par exemple) qui fonctionne identiquement quel que soit le langage qui l’écrit ou le lit. Le multilinguisme aligné a posteriori (un modèle anglais traduit ensuite), c’est l’équivalent de coller un convertisseur ASCII↔UTF-8 entre deux systèmes — ça marche, mais tu paies une couche de conversion à chaque échange et tu perds des caractères aux extrémités.
Le code minimal : appeler un modèle d’embedding
Deux patterns, côte à côte. Le premier charge le modèle directement dans ton process Python (utile pour un script d’ingestion ponctuel). Le second appelle un daemon Ollama (utile pour un service applicatif partagé).
# Pattern 1 — sentence-transformers (modèle in-process)
# pip install sentence-transformers numpy
from sentence_transformers import SentenceTransformer
import numpy as np
# Premier appel : téléchargement ~2 Go depuis HuggingFace, ensuite cached.
model = SentenceTransformer("BAAI/bge-m3")
# Embedding d'un batch de 3 chunks. normalize_embeddings=True →
# vecteurs de norme 1, donc cosine = produit scalaire (calcul plus simple).
chunks = ["MT-06 worktrees obligatoires.", "C-ORCH-128 isolation.", "BGE-M3 multilingue."]
vectors = model.encode(chunks, normalize_embeddings=True) # shape (3, 1024)
# Embedding d'une requête + similarité cosinus contre chaque chunk
query = "Quelle convention couvre les git worktrees ?"
qv = model.encode([query], normalize_embeddings=True)[0]
scores = np.dot(vectors, qv) # array([0.84, 0.74, 0.51])
top2 = np.argsort(-scores)[:2] # [0, 1]
Le code fait trois choses : (1) charger le modèle BGE-M3 (une fois), (2) transformer les chunks en vecteurs 1024D normalisés, (3) calculer les similarités contre une requête. Le normalize_embeddings=True est la subtilité importante : avec des vecteurs de norme 1, le produit scalaire np.dot donne directement le cosinus, sans avoir besoin de diviser par les normes (économie de calcul à grande échelle).
Pour un service applicatif partagé entre plusieurs scripts ou processus, on utilise plutôt Ollama : le modèle est chargé une seule fois dans un daemon (ollama serve puis ollama pull bge-m3), et chaque process Python l’appelle via une simple requête HTTP locale (POST http://localhost:11434/api/embed, body JSON {"model": "bge-m3", "input": [...]}). Avantage : pas de rechargement modèle à chaque restart d’app, mémoire RAM partagée. C’est le pattern recommandé dès qu’on a 2+ processus consommateurs.
Pièges et anti-patterns
Tu sais maintenant choisir un modèle. Voici les six erreurs qui reviennent le plus en revue :
AP-1 — Choisir un embedder par défaut sans mesurer. Tu prends all-MiniLM-L6-v2 parce qu’un tutoriel LangChain l’utilisait, recall@5 médiocre sur ton domaine. Correction : 20-30 paires question/chunk attendu sur ton corpus, mesure 2-3 candidats, choix sur base empirique.
AP-2 — Embedder anglais-only sur corpus francophone ou mixte. Symptôme : recall chute de 70 % à 25 %. Correction : BGE-M3 ou multilingual-e5-large d’office si ton corpus contient ne serait-ce que 10 % de non-anglais.
AP-3 — Confondre dimension et qualité. « 3072 dim doit être meilleur que 1024 dim » — pas garanti. La qualité dépend du training data, pas de la dimension brute. Vérifie sur MTEB Retrieval ou sur ton eval interne.
AP-4 — Oublier de normaliser les vecteurs. Tu calcules par produit scalaire au lieu de cosinus, scores incohérents. Correction : normalize_embeddings=True dans sentence-transformers, ou normalisation L2 manuelle (v / np.linalg.norm(v)).
AP-5 — Versioning du modèle absent dans l’index. Tu upgrades de bge-m3 v1.0 vers bge-m3 v2.0 sans réindexer → espaces vectoriels incompatibles → retrieval random. Correction : stocke model_version: "BAAI/[email protected]" dans les métadonnées de chaque vecteur. Migration = réindexation totale, pas mix.
AP-6 — Lire MTEB sans filtrer Retrieval. Score moyen sur 56 tâches ≠ qualité retrieval. Toujours filtrer la sous-section Retrieval (15 tâches MS MARCO + NFCorpus + …) pour un usage RAG.
Récap
L’idée à retenir si tu n’en gardes qu’une : le choix du modèle d’embedding pose la limite supérieure de la qualité de ton retrieval — aucune optimisation downstream ne rattrape un mauvais embedder. Pour un lab francophone qui démarre en 2026 : BGE-M3 self-host via Ollama, dimension 1024, multilingue natif, gratuit, données qui ne sortent jamais. Si tu mesures un besoin spécifique (scaling burst, latence ultra-faible avec GPU, gain démontré sur Voyage), tu migres — pas avant. Le palmarès MTEB est un bon point de départ filtré sur la sous-section Retrieval, jamais un verdict final : tu valides toujours sur ton corpus avec ton mini-eval set.
Tu compares deux modèles d’embedding sur MTEB : l’un est à 68,2, l’autre à 67,4. Ton corpus est en français, très technique, plein de sigles maison. Est-ce que tu prends celui à 68,2 ?
Réponse
Rien dans cet écart ne justifie une décision. Huit dixièmes de point sur une moyenne agrégée de tâches majoritairement anglophones ne dit rien de ton corpus francophone bourré de sigles internes.
Ce qu’il faut regarder à la place : le score sur les tâches de ta langue et de ton type de tâche (retrieval, pas classification), la dimension du vecteur — qui décide de ta facture de stockage —, la longueur de contexte acceptée, et le coût total sur ton volume réel.
Et surtout : construis vingt questions dont tu connais la réponse dans ton corpus, et mesure les deux modèles là-dessus. Vingt questions maison valent mieux qu’un classement public — parce qu’elles portent sur tes documents, et le classement non.
Glossaire
- Modèle d’embedding — Réseau de neurones (encoder, dérivé de BERT) qui transforme une string en vecteur de N floats. Versionné, déterministe à version fixe. Doit être identique entre indexation et requête.
- Embedding (rappel RAG-01) — Vecteur produit par le modèle. Représente le sens du texte sous forme géométrique.
- Dimension — Nombre de floats dans le vecteur (384, 768, 1024, 1536, 3072). Choisi par le modèle, pas par toi. Plus haut = plus nuancé mais plus coûteux. Sweet spot 2026 : 1024.
- Hash sémantique — Métaphore centrale d’un embedding. Contrairement à MD5/SHA, deux entrées proches en sens donnent deux signatures proches — pas explosées. C’est cette propriété qui rend la recherche par similarité possible.
- Espace vectoriel — L’ensemble géométrique dans lequel vivent tous les vecteurs produits par un même modèle. Deux modèles différents → deux espaces incompatibles.
- Similarité cosinus (rappel RAG-01) — L’angle entre deux vecteurs. Cosinus 1 = sens identique, 0 = sans rapport, -1 = sens opposé.
- BGE-M3 — Modèle open-source (BAAI 2024), 1024 dim, plus de 100 langues, contexte 8192 tokens, ~2 Go RAM. Défaut raisonnable pour lab francophone. Chen et al. 2024, arXiv:2309.07597.
- OpenAI text-embedding-3 — Famille API propriétaire d’OpenAI.
small(1536 dim, $0,02 / 1M tokens) etlarge(3072 dim, $0,13 / 1M tokens). Supportent MRL (Matryoshka Representation Learning, technique d’entraînement qui rend les premières k dimensions du vecteur utiles seules — permet de tronquer un vecteur 3072 → 1024 sans réembedder, traité plus en détail en RAG-07, à venir). - Voyage 3 / Cohere embed v3 — Concurrents API d’OpenAI. Voyage souvent cité top sur benchmarks de domaine (code, finance, juridique). Cohere multilingue 100+ langues.
- MTEB (Massive Text Embedding Benchmark) — Le benchmark public de référence, 56 tâches en 7 familles. Pour RAG, ne regarder que la sous-section Retrieval (15 tâches). Leaderboard : huggingface.co/spaces/mteb/leaderboard.
- Multilingue natif — Un seul modèle entraîné dès le départ sur du contenu multilingue. BGE-M3, multilingual-e5-large. Cohabitation FR-EN dans le même espace vectoriel.
- Sentence-transformers — Bibliothèque Python (
pip install sentence-transformers) historique pour appeler les modèles open-source en in-process. Reimers & Gurevych, EMNLP 2019. - Ollama — Daemon local (
ollama serve) qui charge les modèles une fois et expose une API HTTP (localhost:11434). Pattern recommandé dès qu’il y a plusieurs processus consommateurs.
Pour aller plus loin
Sources lues pour cette leçon :
- Reimers, N. & Gurevych, I., Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks, EMNLP 2019. arXiv:1908.10084 — fondateur SBERT et de la lignée open-source.
- Chen, J. et al., BGE M3-Embedding: Multi-Lingual, Multi-Functionality, Multi-Granularity Text Embeddings, BAAI 2024. arXiv:2309.07597 — paper de référence sur BGE-M3.
- Muennighoff, N. et al., MTEB: Massive Text Embedding Benchmark, Hugging Face / Cohere 2022. arXiv:2210.07316 — benchmark public avec ses limites.
- MTEB leaderboard (mis à jour en continu) — huggingface.co/spaces/mteb/leaderboard.
Ressources optionnelles :
- Documentation sentence-transformers : sbert.net
- API d’embeddings Ollama : github.com/ollama/ollama/blob/main/docs/api.md#generate-embeddings
- HuggingFace organisation BAAI : huggingface.co/BAAI
Prochaines leçons dans l’axe RAG :
- RAG-04 — Vector stores : où tu stockes les vecteurs et avec quel algorithme tu les retrouves vite (sqlite-vec, FAISS, Qdrant, pgvector). Suite directe de cette leçon.
- RAG-05 — Retrieval avancé (à venir) : pourquoi le dense seul rate les noms propres, et comment combiner avec une recherche par mots-clés (BM25, hybrid search) pour récupérer les identifiants exacts.