Accueil / Articles

Évaluation comparative de cinq systèmes de stockage de vecteurs intégrés : FAISS, Chroma, LanceDB, VectLite

Cinq bases de données vectorielles intégrées testées pour le RAG local : FAISS, Chroma, LanceDB, VectLite et NumPy ont été comparées en termes de précision de rappel, de latence, de filtres et de démarrage en mode froid.

Éditeur : REACTAPP.TOP8 min de lecture1791 mots

Sources: I Benchmarked 5 Vector Databases for a Local RAG. Only One Actually Surprised Me.

La plupart des comparaisons des « meilleures bases de données vectorielles » ressemblent à des reformulations des pages d’accueil des fournisseurs eux-mêmes : Pinecone est rapide, Qdrant est fiable, Chroma est simple, tout le monde gagne. Celle-ci part d’un besoin plus ciblé. Pas de cluster, pas de Docker, pas de ports ouverts, pas de plan géré. Juste un stockage vectoriel intégré constitué d’un seul fichier local, d’un pip install et de trois lignes de code Python. Voici donc une évaluation maison de cinq moteurs pour cet usage précis.

Les chiffres

Le jeu de données comprenait 5 000 vecteurs de 384 dimensions, consultés 50 fois à l’aide de la similarité cosinus. Tout a été exécuté sous macOS (x86_64) avec Python 3.12.8, en utilisant les paramètres par défaut de chaque moteur.

Moteur Insertion (vecteurs/s) Recherche p95 Rappel@10 Filtrage p95 Rappel du filtrage@10
FAISS 743 099 0,65 ms 1,000 n/a Aucun filtrage
NumPy exact 2 412 231 2,59 ms 1,000 9,25 ms 1,000
Chroma 2 011 3,14 ms 0,840 18,76 ms 1,000
VectLite 0,10.0 154 5,71 ms 0,966 10,28 ms 0,966
LanceDB 20 120 12,20 ms 1,000 14,11 ms 1,000

En dix secondes : FAISS est le plus rapide, bien qu’il ne s’agisse guère d’une base de données. Chroma est le choix le plus simple pour commencer, mais son taux de rappel par défaut de 84 % constitue un problème que beaucoup ignorent. VectLite atteint un taux de rappel de 96,6 % en mode intégré sans aucune mise en tune, ce qui a été une surprise. LanceDB vise un taux de rappel parfait au prix d’une latence plus élevée. NumPy agit en tant qu’arbitre et non en tant que concurrent.

Pourquoi « le plus rapide » est un critère de classement erroné

Le marché des bases de données vectorielles est un champ de bataille marketing. Chaque fournisseur publie des résultats de benchmarks qu’il remporte par hasard, les articles de comparaison répètent ces chiffres sans contexte, et tout le monde se concentre sur la latence. La latence seule est trompeuse. Répondre en demi-milliseconde avec des résultats incorrects est pire que de mettre 5 ms pour obtenir les bons résultats. C’est ce que mesurent les taux de rappel, et c’est pourquoi des outils sérieux comme ANN-Benchmarks (https://ann-benchmarks.com/) représentent le taux de rappel en fonction du débit.

Cette étude mesure donc les deux paramètres en même temps : d’un côté, la latence p50, p95 et p99 ainsi que le nombre de requêtes par seconde, et de l’autre, le taux de rappel@10 par rapport à une recherche par cosinus effectuée avec NumPy pur.

Qu’a été testé et qu’a été omis

Le projet est un petit paquet Python, vectlite-benchmark-lab. Chaque moteur implémente une interface VectorStore commune, et le programme d’exécution les appelle à tour de rôle. Il couvre :

  • L’ingestion en lot
  • La recherche k-NN avec mesure du taux de rappel
  • Le filtrage des métadonnées par correspondance exacte en fonction d’un tenant_id
  • Le temps de démarrage initial
  • La sauvegarde et la portabilité
  • Les exportations vers CSV, JSON et des graphiques Matplotlib

Et ce qu’il omet, indiqué dès le début : aucune configuration distribuée ou multi-nœuds, pas plus de 5 000 vecteurs dans cette étape, aucune mise en tune de l’index, et pas de Qdrant ni de pgvector, car ils nécessitent un serveur en cours d’exécution tandis que l’objectif était un fonctionnement purement local. Ce dernier choix est délibéré. La première question utile n’est pas de savoir qui gagne après deux semaines de mise en tune, mais plutôt de savoir comment se comporte un moteur dès son installation sans aucune modification.

Méthode

La vérité de référence correspond à une recherche cosinus par force brute dans NumPy. Le taux de rappel d’un moteur est la proportion de voisins réels qu’il restitue, calculée en moyenne sur l’ensemble des requêtes. Configuration de l’exécution :

vectlite      : 0.10.0
vectors       : 5,000 (synthetic, normalized)
dimensions    : 384
queries       : 50
top_k         : 10
metric        : cosine
filter        : tenant_id (exact-match)
warmup        : 5 queries discarded
hardware      : macOS x86_64, Python 3.12.8

Pour le reproduire sur votre ordinateur, exécutez la commande complète :

PYTHONPATH=src python -m vectlite_benchmark_lab run \
  --stores vectlite,faiss,chroma,lancedb,numpy_exact \
  --vectors 5000 --dimensions 384 --queries 50 \
  --top-k 10 --batch-size 500 \
  --output-dir results/vectlite-0.10.0 \
  --data-dir data/vectlite-0.10.0

Comparez ensuite vos résultats avec ceux-ci et observez les différences.

FAISS : le plafond de vitesse

FAISS bat tous les autres en termes de latence : 0,65 ms p95 avec un taux de rappel parfait, ce qui correspond à peu près à ce que l’on pourrait attendre d’une bibliothèque C++ optimisée spécifiquement pour cet usage depuis une décennie. Cependant, ce n’est pas une base de données. Elle ne dispose d’aucun filtre de métadonnées natif, d’aucune persistance intégrée et d’aucune fonction de sauvegarde portable. On peut l’envelopper dans une couche qui ajoute ces fonctionnalités, ce qui est effectivement fait, mais par défaut, elle ressemble davantage à une bibliothèque mathématique qu’à un outil destiné à être livré aux clients. La comparer à Chroma, c’est comme comparer un moteur d’F1 à une Toyota : l’un est plus rapide sur piste, l’autre sert à ramener les courses à la maison. Elle reste présentée ici à titre de référence. Si tout ce dont vous avez besoin, c’est d’une recherche vectorielle brute, c’est évidemment le choix à retenir.

Chroma : démarrage simple, surveillez le taux de rappel

Chroma est la valeur par défaut pour les prototypes RAG, et l’expérience utilisateur justifie ce choix. Installez chromadb, écrivez cinq lignes et les documents sont déjà indexés.

Le problème réside dans le taux de rappel. Avec ces données brutes, sans filtre appliqué, Chroma ne trouve que 84 % des documents pertinents, ce qui signifie qu’environ un résultat attendu sur six ne s’affiche pas. Cela convient pour un prototype. Dans un système RAG en production, où la qualité de la récupération influence les réponses du modèle, il s’agit d’une perte silencieuse de pertinence que l’API ne révèle pas. En ajustant les paramètres HNSW, on peut combler la majeure partie de cette lacune, à condition de savoir que c’est nécessaire. Avec un filtrage, le taux de rappel atteint 100 %, mais la latence p95 monte à 18,76 ms, ce qui est nettement plus lent que les autres méthodes pour la même tâche. Verdict : excellent dès le premier jour et toujours performant au trentième jour, à condition d’avoir effectué des ajustements avant la mise en production.

VectLite : la surprise

La version 0.10.0 atteint un taux de rappel de 96,6 % avec les paramètres par défaut, le plus élevé parmi tous les moteurs intégrés ici. La recherche simple affiche un temps de réponse de 5,71 ms, ce qui est dans la moyenne (Chroma 3,14 ; LanceDB 12,20). Sur des données filtrées, le temps de réponse est de 10,28 ms en moyenne, contre 18,76 ms pour Chroma, ce qui représente presque le double de la vitesse.

On peut observer les progrès réalisés depuis les premières versions. Par rapport à v0,1.x, le taux d’ingestion est passé de 47 à 154 vecteurs par seconde (environ 3,3 fois plus rapide), le taux de rappel est monté de 0,948 à 0,966, et le temps de réponse pour les filtres est descendu de 18,6 ms à 10,3 ms, soit une baisse de 45 %.

L’ingestion reste le point faible. 154 vecteurs par seconde est lent par rapport aux 2 000 et plus de Chroma, et très lent par rapport à LanceDB. Pour quelques milliers de documents indexés une seule fois, cela n’a pas d’importance. Mais pour un million de vecteurs, cela signifie de longues heures d’attente, ce qui en fait probablement la prochaine étape à améliorer. Néanmoins, c’était le seul moteur du groupe dont les performances ne nécessitaient aucune excuse.

LanceDB : rappel parfait, recherche plus lente

LanceDB atteint un rappel de 100 % et traite 20 120 vecteurs par seconde, ce qui semble impressionnant en théorie. Le prix à payer est la latence de recherche : 12,20 ms à p95, ce qui en fait le plus lent des cinq. Cela n’a pas d’importance pour un traitement par lots de milliers de requêtes pendant la nuit. En revanche, pour un outil interactif où quelqu’un attend devant le clavier, cela devient un problème. Bon pour les traitements par lots et l’analyse de données, mais un peu lent pour un usage interactif.

NumPy : l’arbitre

La recherche par cosinus par force brute sur toute la matrice assure par définition un rappel parfait, avec une latence acceptable jusqu’à quelques dizaines de milliers de vecteurs, après quoi elle chute drastiquement. Ce n’est pas un produit fini ; c’est l’outil de référence contre lequel tous les autres moteurs sont évalués.

Lequel choisir ?

Le benchmark ne désigne pas de gagnant. Il met en évidence les compromis à faire. Une correspondance approximative selon le cas d’usage :

  • Prototype RAG rapide : Chroma, grâce à une configuration en deux minutes et à un écosystème étendu
  • Mémoire IA intégrée : VectLite, pour le meilleur taux de rappel par défaut et un fichier portable
  • Pipeline par lots local : LanceDB, pour un rappel parfait et une ingestion rapide
  • ANN pure sans filtrage : FAISS, pour une latence inégalée
  • Production distribuée : Qdrant ou Milvus, une catégorie différente non testée ici

Démarrage initial et sauvegarde

Deux mesures que la plupart des benchmarks omettent. Démarrage, le temps nécessaire pour rouvrir la base de données après une redémarrage : FAISS met 0,001 ms, LanceDB 2 ms, Chroma 5 ms et VectLite 3 059 ms. VectLite paie cher en termes de temps de rouverture. Cela n’a pas d’importance pour un processus en cours longtemps, mais pour une fonction serverless ou un outil CLI lancé sur demande, un démarrage initial de trois secondes est difficile à justifier et constitue probablement la première chose à corriger.

Sauvegarde : VectLite génère un fichier portable de 19 MB en 54 ms. Le copier, gérer les versions et le déployer relève simplement du traitement de fichiers. C’est cette caractéristique d’« intégration » qui permet de fonctionner efficacement, la même qui a permis à SQLite de perdurer pendant deux décennies.

Limites de cette évaluation

Chaque benchmark nécessite des précisions. Voici celles-ci :

  1. 5 000 vecteurs est un petit nombre ; le comportement change à partir de 100 000 vecteurs.
  2. Seules les paramétrisations par défaut ont été utilisées, et il est presque certain que Chroma et VectLite peuvent être optimisés davantage.
  3. Aucun moteur serveur n’a été impliqué : Qdrant, Milvus, Weaviate et pgvector sont exclus.
  4. Il s’agit d’une seule exécution, sans intervalles de confiance ni répétitions.
  5. L’évaluation a été effectuée sur une seule machine, donc d’autres matériels pourraient donner des résultats différents.

Le code est open source et les résultats sont reproductibles, ce qui rend utile la détection de biais ou de bugs.

Prochaines étapes et enseignements

Cette série d’essais constitue un point de départ, et non un jugement définitif. La liste restreinte pour le tour suivant : un vecteur de 100 000 dimensions, une analyse en 768 dimensions sur tous les moteurs ; un test de type RAG utilisant un corpus de Markdown et de PDF avec des requêtes rédigées par des personnes ; un ajustement de la capacité de rappel afin que les moteurs s’affrontent avec une précision comparable ; un démarrage en froid plus rapide pour VectLite ; ainsi que des essais répétés accompagnés d’intervals de confiance.

La quête du « meilleur moteur de base de données vectorielle » se termine sans réponse universelle, car elle dépend de la manière dont on évalue le taux de rappel par rapport à la latence, à l’ingestion des données et au temps de démarrage. Ce qui a retenu l’attention, ce n’est pas un leader incontesté, mais plutôt le fait que chaque moteur ait sa propre personnalité. FAISS est une référence en termes de vitesse qui se présente sous forme de base de données. Chroma est un outil facile à utiliser mais qui nécessite des ajustements avant d’être mis en production. LanceDB est le perfectionniste qui n’hésite pas à être lent. NumPy est le juge impartial qui ne peut pas être étendu. VectLite, quant à lui, atteint silencieusement l’objectif de taux de rappel sans négociation.

Pour un agent local, un outil en ligne de commande ou un système RAG fonctionnant hors ligne sur un ordinateur portable, VectLite présente des arguments convaincants : SQLite a rendu les données relationnelles locales ennuyeuses et peu portables, et VectLite vise à jouer le même rôle avec la mémoire basée sur l’IA. Cela signifie un fichier de 19 MB capable de répondre en environ 6 ms.

Liens de référence : ANN-Benchmarks à https://ann-benchmarks.com/, les notes de benchmark de Qdrant à https://qdrant.tech/benchmarks/, FAISS à https://github.com/facebookresearch/faiss, la documentation de Chroma à https://docs.trychroma.com/ et LanceDB à https://lancedb.github.io/lancedb/.