Accueil / Articles

turbovec : Comprime les embeddings RAG 16x à l’aide de TurboQuant en Rust

TurboVec introduit TurboQuant de Google dans Rust et réduit de 16 fois les index d’incorporation RAG sans entraînement. Où il surpasse FAISS et quand un autre outil convient mieux.

Éditeur : REACTAPP.TOP10 min de lecture2219 mots

Sources: turbovec for RAG: A Practical Guide to Faster, Smaller Vector Search

Prenez un pipeline de récupération réellement utilisé en production : dix millions de documents, chacun intégrant l’embedding text-embedding-3-small d’OpenAI à 1536 dimensions et stocké en format float32. Avant même l’ajout d’un seul octet de métadonnées, les vecteurs seuls pèsent déjà 31 GB. À une telle taille, la question « Où cela s’exécute-t-il ? » cesse d’être anodine. Cela implique une machine cloud gourmande en mémoire, probablement hébergée par un tiers, ainsi que tous les problèmes de confidentialité et de gestion qui en découlent.

En passant les mêmes données par turbovec avec 2 bits par dimension, la taille diminue à environ 4 GB, ce qui tient facilement dans la RAM d’un ordinateur portable. La suite de cet article explique pourquoi cela fonctionne, dans quels cas c’est le choix idéal et où un autre outil est préférable.

Qu’est-ce que turbovec ?

turbovec est un index vectoriel en Rust avec des bindings Python, sous licence MIT, qui comptait environ 950 étoiles sur GitHub au moment de la rédaction de ce texte. Il met en œuvre TurboQuant, un algorithme de quantification vectorielle développé par des chercheurs de Google Research et de NYU, qui a été accepté pour présentation à l’ICLR 2026.

Un détail important à connaître : Google n’a jamais publié le code de référence de son propre algorithme, c’est pourquoi la communauté est intervenue. Le projet RyanCodrai/turbovec vise la recherche vectorielle, qui correspond à l’usage de récupération d’informations, tandis qu’un projet distinct, hackimov/turboquant-kv, applique la même idée à la compression du cache KV des modèles de langage. Il s’agit de deux initiatives indépendantes en open source.

En d’autres termes, utiliser turbovec signifie faire appel à une implémentation communautaire d’un algorithme de Google Research, et selon les benchmarks utilisés par l’équipe même de FAISS, il surpasse le FAISS de Meta, qui a longtemps été la norme en matière de recherche vectorielle en mémoire.

Comment fonctionne l’algorithme

Une fois que l’on comprend son principe, la méthode s’avère surprenamment simple. Elle se déroule en quatre étapes.

1. Séparer la longueur de la direction

Chaque embedding possède une magnitude (sa norme L2) et une direction. On extrait la magnitude et on la conserve sous forme d’un nombre flottant par vecteur ; ce qui reste est alors une direction de longueur unité sur une sphère à haute dimension. Cela peut sembler anodin, mais tout ce qui suit dépend de cela, car les vecteurs situés sur la surface d’une sphère peuvent être traités à l’aide de la géométrie.

2. Rotation aléatoire

Ensuite, chaque vecteur est multiplié par la même matrice orthogonale aléatoire, générée une seule fois à partir d’une décomposition QR d’une matrice gaussienne. C’est l’étape qui semble ressembler à un tour de magie à la première lecture.

L’intuition : dans de hautes dimensions, une rotation aléatoire rend prévisible la distribution de chaque coordonnée. Après rotation, chaque coordonnée de chaque vecteur suit une distribution Beta connue et fortement concentrée, qui tend vers une distribution gaussienne à mesure que la dimensionnalité augmente. La distribution reste identique quel que soit l’entrée. Les documents juridiques, les avis de produits et la littérature médicale finissent tous par présenter des caractéristiques statistiques similaires, de sorte que le système ne dépend pas des données. Les mathématiciens appellent cela une concentration de mesure sur la sphère, et cela explique pourquoi aucun passage d’entraînement n’est nécessaire : la rotation effectue le travail que ferait normalement un codebook entraîné.

3. Choisir les meilleurs groupes

Connaître la distribution suivie par chaque coordonnée permet de déterminer à l’avance la meilleure façon de regrouper les valeurs. La quantification à deux bits offre quatre groupes par coordonnée, tandis que celle à quatre bits en offre seize. Ce calcul est appelé quantification scalaire Lloyd-Max, qui répond à une question simple : étant donné une distribution connue, où placer les lignes de séparation pour minimiser l’erreur d’arrondi moyenne ? Lorsque la distribution est connue, la réponse se trouve sous forme fermée. Et comme la distribution après rotation est identique pour tous les vecteurs, les groupes proviennent des calculs mathématiques et non de vos données.

4. Empaqueter les bits

Chaque coordonnée est désormais un petit entier : de 0 à 3 pour deux bits, ou de 0 à 15 pour quatre bits. Un vecteur de 1536 dimensions qui nécessitait 6 144 octets en format float32 nécessite 384 octets avec deux bits ou 768 octets avec quatre bits. Cela représente une compression de 16 fois et 8 fois respectivement.

Recherche sans décompression

Les requêtes ne décompressent jamais les données stockées. La requête est placée une fois dans le même espace, puis comparée directement aux codes quantifiés à l’aide de tables de recherche préparées à l’avance. La boucle interne s’appuie sur des instructions SIMD, avec NEON pour ARM, AVX-512BW pour les processeurs x86 récents, et AVX2 en cas de fallback.

C’est là que la bibliothèque, distincte de l’algorithme, prouve son utilité. Ses noyaux SIMD écrits manuellement surpassent FastScan de FAISS de 12 à 20 % sur ARM, et le talonnent ou le dépassent sur x86.

Il existe également un résultat théorique derrière cette méthode. L’article de TurboQuant prouve que sa distorsion reste dans un facteur d’environ 2,7 par rapport à la limite inférieure de la théorie de l’information, à savoir la limite de taux de distorsion de Shannon. En termes simples : la théorie de l’information définit jusqu’où les données peuvent être compressées sans perte d’information, et TurboQuant parvient à rester à 2,7 fois cette limite sans aucun entraînement préalable. Personne ne peut obtenir de résultats significativement meilleurs pour un budget binaire donné, et l’article le prouve par une démonstration formelle.

Trois cas où cela s’avère utile

Mémoire suffisante

Revenons aux chiffres initiaux : 31 Go en format float32 contre 4 Go grâce à turbovec en 2 bits. Disposer d’une telle mémoire réduit les contraintes.

  • Elle peut être stockée sur le même serveur que l’application, sans nécessiter d’instance distincte de base de données vectorielle.
  • Les développeurs peuvent l’exécuter sur des ordinateurs portables pour des tests locaux.
  • Les niveaux de mémoire moins chers sur les instances cloud deviennent envisageables, ce qui réduit considérablement les coûts.
  • Tout l’index reste en RAM, sans écriture sur disque et sans fragmentation entre nœuds.

Pour les collections dont la taille vectorielle se situe entre 100 000 et 100 millions d’éléments, ce qui couvre la plupart des bases de connaissances, des sites de documentation, des archives de support et des catalogues de produits, il s’agit de la différence entre devoir concevoir des solutions en fonction de l’index vectoriel et le traiter simplement comme un autre objet Python.

Confidentialité et configurations isolées

Les pipelines de récupération soulèvent un problème de confidentialité sérieux. Deux attaques l’illustrent :

  • BadRAG atteint un taux de réussite de 98,2 % en contaminant seulement 0,04 % d’un corpus avec des documents adversaires soigneusement conçus.
  • Vec2Text parvient à récupérer des textes originaux courts à partir de leurs embeddings, avec une précision de 92 % des fois.

Les embeddings ne disposent d’aucune protection cryptographique, de sorte que quiconque a accès en lecture à un stockage de vecteurs peut récupérer ce qui y a été intégré. Chaque appel à une base de données vectorielle cloud, chaque requête embed() vers OpenAI et chaque opération upsert() vers Pinecone représentent un point où les données quittent votre périmètre.

De nombreuses implementations réelles sont déjà complètement isolées du réseau. À l’UC San Diego, Onyx gère 37 000 utilisateurs sans avoir besoin d’Internet, et Ramp, Thales, L3Harris ainsi qu’Astranis utilisent des configurations similaires. Le slogan de turbovec, « pas de service géré et aucune donnée ne quitte votre machine ou votre VPC », correspond bien à ce groupe. Associez-le à un modèle d’embedding hébergé localement comme BGE-M3 ou BGE-large-en-v1.5, et la récupération des données ne nécessite aucun appel réseau externe.

Aucun livre de codes à entraîner

Cet avantage est structurel et facile à sous-estimer. La quantification classique de produits, c’est-à-dire le PQ dans IndexPQ et IndexIVFPQ, nécessite un livre de codes entraîné à partir de données représentatives. Lorsque les données évoluent, que ce soit avec de nouvelles catégories de produits, de nouvelles langues ou de nouveaux types de documents, ce livre de codes devient obsolète et la capacité de rappel se détériore.

TurboQuant ne dispose absolument pas de livre de codes. La rotation aléatoire permet aux formules de fonctionner quel que soit l’aspect des données d’entrée. En pratique, cela signifie :

  • Les insertions en flux continu se font sans problème, sans nécessiter un réentraînement par lots.
  • Le changement de modèles d’embedding, d’OpenAI à BGE puis à Voyage, n’oblige pas à reconstruire l’index à partir de zéro.
  • Les index multi-locataires n’ont pas besoin d’une calibration spécifique par locataire.
  • Le problème du démarrage difficile, où il y a trop peu de vecteurs pour former un livre de codes fiable, disparaît.

Pour les systèmes qui évoluent progressivement ou qui traitent des types de documents mixtes, cette simplicité représente un véritable avantage opérationnel.

Quand utiliser autre chose

Certains schémas de recherche s’avèrent plus adaptés ailleurs, et il est préférable d’en parler clairement.

  • Recherche à fort taux de rappel. HNSW avec des vecteurs à précision complète reste la référence absolue. turbovec sacrifie quelques points de rappel en échange d’une compression 16 fois supérieure. Cela est acceptable pour la plupart des applications RAG, mais problématique lorsque la perte d’un résultat a des conséquences importantes.
  • Filtrage par métadonnées et recherche hybride. turbovec n’est qu’un index, sans base de données associée. Une requête comme « trouver des vecteurs proches de X, limités aux documents marqués comme conformité et modifiés après décembre 2025 » nécessite une véritable base de données vectorielle telle que Qdrant, Weaviate, Milvus ou pgvector.
  • Embeddings à faible dimension (256 dimensions ou moins). Comme le reconnaît son propre README, turbovec est inférieur à FAISS de 3 à 6 points de rappel sur GloVe à d=200, car l’approximation de type Beta vers gaussien est moins stricte lorsque les dimensions sont faibles, ce qui réduit l’avantage théorique. Si l’infrastructure utilise des modèles d’embedding plus anciens ou de moindre capacité, FAISS représente le choix le plus sûr.
  • Échelle de milliards de vecteurs. turbovec parcourt exhaustivement chaque vecteur compressé. Cela fonctionne jusqu’à environ 100 millions de vecteurs. Au-delà, une méthode de partitionnement basée sur IVF ou des graphes est nécessaire, fonctionnalité absente chez turbovec.
  • Préférence pour les services hébergés. Une équipe souhaitant disposer d’une base de données vectorielle gérée avec une clé API trouvera turbovec être l’outil inadapté, quel que soit le niveau d’excellence de son implémentation.

Démarrer

Pour le récupération en mémoire de 100 000 à 100 millions de vecteurs ayant une dimension de 384 ou plus, et pour une équipe prête à gérer sa propre infrastructure, voici la démarche pratique. Installez depuis PyPI :

pip install turbovec

Les projets Rust ajoutent plutôt le crate :

cargo add turbovec

L’utilisation de base nécessite quelques lignes de code pour créer et interroger un index :

from turbovec import TurboQuantIndex

# Build the index
index = TurboQuantIndex(dim=1536, bit_width=4)
index.add(document_embeddings)
# Search
scores, indices = index.search(query_embedding, k=10)
# Persist
index.write("kb.tq")
loaded = TurboQuantIndex.load("kb.tq")

C’est toute la surface nécessaire pour le cas simple.

Choix de la largeur du bit

C’est la configuration la plus importante, et les compromis sont clairs.

  • 2 bits : compression 16 fois supérieure par rapport à float32, écart plus important en termes de précision de récupération, et sensibilité accrue à la dimension.
  • 4 bits : compression 8 fois supérieure, avec une précision de récupération essentiellement équivalente à celle de FAISS sur les embeddings de 1536 et 3072 dimensions d’OpenAI. Les deux méthodes atteignent une valeur de 1,0 pour un nombre k compris entre 4 et 8.

La valeur par défaut raisonnable est 4 bits. Ne passez pas à 2 bits avant d’avoir mesuré la pression réelle sur la mémoire ainsi que l’impact sur la précision de récupération pour vos propres requêtes.

Choix du type d’index

Il en existe deux. TurboQuantIndex accède aux vecteurs en fonction de leur position, ce qui simplifie les choses et accélère légèrement les opérations lorsque les identifiants suivent simplement l’ordre d’insertion. IdMapIndex vous permet d’attribuer vos propres identifiants uint64 et de supprimer des entrées en temps constant, ce qui en fait le choix idéal lorsque les clés proviennent d’une base de données ou que des documents sont supprimés.

Pour la plupart des systèmes RAG, IdMapIndex est le paramètre par défaut préférable, car les identifiants de la base de données de l’application survivent aux suppressions et aux reconstitutions sans perturber les références externes.

from turbovec import IdMapIndex
import numpy as np

index = IdMapIndex(dim=1536, bit_width=4)
index.add_with_ids(vectors, np.array([1001, 1002, 1003], dtype=np.uint64))
scores, ids = index.search(query, k=10)  # returns your IDs
index.remove(1002)  # O(1) by ID

Modèles d’incorporation

Pour une récupération sans connexion à Internet, le modèle d’incorporation doit fonctionner localement, car l’appel à l’API d’OpenAI annule les avantages en matière de confidentialité. Deux combinaisons ont fait l’objet de tests approfondis :

  • BGE-M3 avec turbovec. Un modèle multilingue puissant qui fonctionne localement et constitue un bon choix par défaut pour les bases de connaissances internationales.
  • BGE-large-en-v1.5 avec turbovec. Exclusivement en anglais, plus petit et plus rapide, il est idéal pour la documentation en anglais.

Lorsque la confidentialité n’est pas une exigence stricte, text-embedding-3-small (1536 dimensions) ou text-embedding-3-large (3072) d’OpenAI fonctionnent bien avec turbovec. N’oubliez pas que ce sont les appels à l’incorporation dans le cloud, et non l’index lui-même, qui entraînent les fuites de données.

Intégrations aux frameworks

turbovec offre des intégrations de premier ordre pour LangChain, LlamaIndex et Haystack :

pip install turbovec[langchain]
pip install turbovec[llama-index]
pip install turbovec[haystack]

Une pile déjà construite sur l’un de ces systèmes devrait emprunter cette voie, car elle présente le moins de résistance.

Limits à garder à l’esprit

  • Une seule machine, en mémoire. Il n’y a pas de mode distribué, donc l’échelle horizontale signifie le shardage au niveau de la couche d’application.
  • Analyse exhaustive. Chaque vecteur compressé est analysé pour chaque requête. SIMD permet de maintenir cette vitesse jusqu’à environ 100 millions de vecteurs ; au-delà, un IVF ou une couche graphique est nécessaire.
  • Dépendance au matériel. L’avantage de 12 à 20 % avec ARM a été mesuré sur les puces de la série M d’Apple. Les anciens processeurs ARM ou x86 sans AVX-512 offrent des gains plus faibles, bien qu’ils restent supérieurs à FAISS dans la plupart des configurations.
  • Rappel à faible dimension. En dessous d’environ 256 dimensions, FAISS l’emporte avec un écart significatif. La méthode est la plus efficace avec 768 dimensions ou plus, comme celles générées par les modèles d’incorporation actuels.

Le schéma plus large

turbovec occupe une niche spécifique : la recherche vectorielle en mémoire, les corpus de taille moyenne, une infrastructure que l’on possède soi-même, ainsi que les dimensions générées par les modèles d’embedding modernes. Il ne cherche pas à remplacer Qdrant ou Pinecone. Il s’agit d’un élément de base de niveau inférieur qui pourrait remplacer FAISS, offrant une meilleure compression sans nécessiter de phase d’entraînement.

L’histoire qui l’a vu naître est sans doute la partie la plus intéressante. Une étude de quatre auteurs de Google Research a été acceptée au ICLR 2026 ; les auteurs n’ont pas publié de code, et deux développeurs de la communauté ont créé indépendamment des implémentations, l’une pour la compression des KV-cache et l’autre pour la recherche vectorielle. Celle destinée à la recherche vectorielle bat le produit existant sur ses propres benchmarks.

Le parcours allant d’un algorithme académique à sa mise en œuvre au sein d’une communauté, pour aboutir à une bibliothèque de niveau production surpassant les outils standards, se répétera, car les résultats de la recherche évoluent plus rapidement que les fournisseurs ne peuvent les commercialiser. turbovec en est un exemple concret. Comprendre son fonctionnement et sa place dans ce contexte est utile pour quiconque conçoit des systèmes de recherche aujourd’hui.