Les bases de données vectorielles se sont imposées comme l'infrastructure fondamentale de l'intelligence artificielle moderne. Alors que les modèles de langage comme GPT-4, Claude ou Mistral génèrent des représentations numériques complexes du monde réel, il fallait une technologie capable de stocker, indexer et interroger ces vecteurs à grande échelle avec une latence minimale. En 2026, le marché des bases vectorielles a explosé : Pinecone, Milvus, Weaviate, Chroma, Qdrant, pgvector, FAISS ou encore LanceDB rivalisent d'innovations pour répondre aux besoins croissants du RAG (Retrieval-Augmented Generation), de la recherche sémantique, des systèmes de recommandation et de la détection d'anomalies. Ce comparatif exhaustif analyse en profondeur chaque solution, leurs algorithmes d'indexation, leurs performances, leurs architectures de déploiement et leurs cas d'usage spécifiques. Que vous soyez développeur Python cherchant une solution légère, architecte cloud construisant un pipeline RAG distribué, ou décideur technique évaluant les options pour votre entreprise, ce guide vous fournira toutes les clés pour faire le bon choix parmi les bases de données vectorielles disponibles sur le marché.

Qu'est-ce qu'une base de données vectorielle ?

Une base de données vectorielle est un système de gestion de données spécialisé dans le stockage et la recherche de vecteurs de haute dimension. Contrairement aux bases de données relationnelles classiques qui manipulent des lignes et des colonnes avec des requêtes SQL, les bases vectorielles travaillent avec des représentations mathématiques appelées embeddings. Ces embeddings sont des tableaux de nombres flottants, généralement de dimension 256 à 4096, qui capturent la signification sémantique d'un objet — qu'il s'agisse d'un texte, d'une image, d'un son ou d'une vidéo.

Le concept d'embedding vectoriel

Un embedding est une projection d'une donnée complexe dans un espace vectoriel continu. Prenons un exemple concret : le mot « chat » pourrait être représenté par un vecteur de 1536 dimensions lorsqu'il est traité par le modèle text-embedding-3-small d'OpenAI. Ce vecteur encode non seulement le sens littéral du mot, mais aussi ses relations sémantiques avec d'autres concepts. Ainsi, le vecteur de « chat » sera mathématiquement proche de celui de « félin », « animal domestique » ou « miaou », mais éloigné de celui de « voiture » ou « algorithme ». Cette propriété fondamentale — la proximité sémantique se traduit par une proximité géométrique — est ce qui rend les bases vectorielles si puissantes pour l'intelligence artificielle.

Les modèles d'embedding modernes produisent des vecteurs de dimensions variées. Le modèle text-embedding-ada-002 d'OpenAI génère des vecteurs de 1536 dimensions. Le modèle text-embedding-3-large peut aller jusqu'à 3072 dimensions. Les modèles open source comme BGE-M3 ou E5-Mistral-7B proposent des dimensions allant de 384 à 4096. Chaque dimension capture un aspect différent de la signification, créant un espace sémantique riche et nuancé où les relations entre concepts sont préservées géométriquement.

La recherche par similarité

Le cœur d'une base de données vectorielle est sa capacité à répondre efficacement à la question : « Quels sont les vecteurs les plus proches de ce vecteur donné ? » Cette opération, appelée recherche par similarité ou recherche du plus proche voisin (Nearest Neighbor Search), utilise des métriques de distance pour mesurer la similarité entre vecteurs. Les trois métriques les plus courantes sont la similarité cosinus, la distance euclidienne (L2) et le produit scalaire (Inner Product).

La similarité cosinus mesure l'angle entre deux vecteurs, indépendamment de leur magnitude. Elle est particulièrement adaptée aux embeddings textuels où la direction du vecteur porte plus de sens que sa norme. La distance euclidienne mesure la distance géométrique « en ligne droite » entre deux points dans l'espace vectoriel. Le produit scalaire, quant à lui, combine information directionnelle et de magnitude, ce qui le rend utile dans certains scénarios de recommandation où la « force » du signal compte autant que sa direction.

Recherche exacte vs. recherche approximative (ANN)

La recherche exacte du plus proche voisin (k-NN exact) parcourt exhaustivement tous les vecteurs de la base pour trouver les k plus proches. Avec un dataset de 10 millions de vecteurs de dimension 1536, cette approche nécessiterait des milliards d'opérations en virgule flottante par requête, rendant les temps de réponse prohibitifs. C'est pourquoi les bases vectorielles modernes utilisent des algorithmes de recherche approximative du plus proche voisin (Approximate Nearest Neighbor — ANN). Ces algorithmes sacrifient une fraction minime de précision (typiquement 95-99 % de recall) en échange de performances des milliers de fois supérieures. L'art de la base vectorielle réside dans l'optimisation de ce compromis entre recall (proportion des vrais plus proches voisins retrouvés) et latence de requête.

A retenir : Une base de données vectorielle stocke des embeddings — des représentations numériques de données complexes — et permet de rechercher les vecteurs les plus similaires à une requête donnée. La recherche approximative (ANN) est la clé qui rend cette opération viable à grande échelle, avec un compromis maîtrisé entre précision et vitesse.

Pourquoi les bases vectorielles sont devenues essentielles

L'explosion des bases de données vectorielles n'est pas un phénomène isolé. Elle résulte de la convergence de plusieurs tendances technologiques majeures qui, ensemble, ont créé un besoin impérieux pour cette catégorie d'infrastructure. Comprendre ces tendances est essentiel pour évaluer correctement les solutions disponibles et anticiper l'évolution du marché.

Le RAG : Retrieval-Augmented Generation

Le RAG (Retrieval-Augmented Generation) est sans doute le cas d'usage qui a le plus contribué à la popularisation des bases vectorielles. Le principe est simple mais puissant : plutôt que de se fier uniquement aux connaissances apprises pendant l'entraînement d'un LLM, on enrichit chaque requête utilisateur avec des documents pertinents récupérés dynamiquement depuis une base de connaissances. La base vectorielle joue ici le rôle de mémoire externe du modèle de langage. Quand un utilisateur pose une question, celle-ci est convertie en embedding, puis les documents les plus sémantiquement proches sont récupérés et injectés dans le prompt du LLM. Ce mécanisme permet de réduire drastiquement les hallucinations, de maintenir les réponses à jour sans réentraîner le modèle, et de citer les sources avec précision.

En 2026, le RAG est devenu le pattern architectural dominant pour les applications d'IA générative en entreprise. Les analystes estiment que plus de 80 % des déploiements de LLM en production utilisent une forme de RAG, ce qui place la base vectorielle au cœur de l'infrastructure IA. Les volumes de données indexées ont également explosé : il n'est plus rare de voir des déploiements avec des dizaines de millions de documents, nécessitant des solutions vectorielles capables de scaler horizontalement tout en maintenant des latences sub-milliseconde.

La recherche sémantique

La recherche sémantique représente une évolution fondamentale par rapport à la recherche par mots-clés traditionnelle. Là où un moteur de recherche classique comme Elasticsearch s'appuie sur des correspondances lexicales (TF-IDF, BM25), la recherche sémantique comprend l'intention et le sens de la requête. Par exemple, une recherche pour « comment protéger mon ordinateur des virus » retournera des résultats pertinents sur la cybersécurité, les antivirus et les pare-feu, même si ces documents ne contiennent pas exactement les mots de la requête. Cette capacité à comprendre le sens plutôt que les mots transforme radicalement l'expérience de recherche dans les intranets d'entreprise, les plateformes e-commerce, les bases de connaissances techniques et les moteurs de recherche documentaire.

La recherche hybride, qui combine recherche sémantique vectorielle et recherche lexicale traditionnelle, est devenue le standard de facto. Plusieurs bases vectorielles comme Weaviate et Qdrant intègrent nativement cette capacité, permettant de bénéficier à la fois de la précision sémantique des embeddings et de la pertinence des correspondances exactes pour les termes techniques, noms propres ou identifiants spécifiques. Les algorithmes de fusion comme RRF (Reciprocal Rank Fusion) combinent les résultats des deux approches pour offrir une pertinence optimale.

Les systèmes de recommandation

Les systèmes de recommandation modernes exploitent massivement les bases vectorielles pour calculer des similarités entre utilisateurs, produits, contenus ou comportements. Netflix, Spotify, Amazon et des milliers d'autres plateformes utilisent des embeddings pour représenter les préférences des utilisateurs et les caractéristiques des items. Trouver les « produits similaires » ou les « utilisateurs ayant des goûts proches » revient alors à une recherche de plus proches voisins dans l'espace vectoriel. Les bases vectorielles permettent d'effectuer ces calculs en temps réel, même avec des catalogues de millions d'items et des millions d'utilisateurs actifs.

La détection d'anomalies et la fraude

Dans le domaine de la sécurité et de la détection de fraude, les bases vectorielles permettent d'identifier des patterns inhabituels en temps réel. Chaque transaction, comportement utilisateur ou événement réseau peut être encodé en vecteur. Les transactions « normales » forment des clusters denses dans l'espace vectoriel, tandis que les anomalies apparaissent comme des points isolés, éloignés de tout cluster connu. Les bases vectorielles permettent de détecter ces outliers avec une latence minimale, ce qui est critique pour bloquer une transaction frauduleuse avant qu'elle ne soit finalisée. Des institutions financières, des plateformes e-commerce et des fournisseurs de cybersécurité utilisent cette approche pour protéger des milliards de transactions quotidiennes.

La vision par ordinateur et le multimodal

Au-delà du texte, les bases vectorielles sont devenues indispensables pour les applications de vision par ordinateur. La recherche d'images par similarité visuelle, la reconnaissance faciale, la détection de contrefaçons et la modération de contenu utilisent toutes des embeddings visuels stockés et interrogés via des bases vectorielles. Avec l'émergence des modèles multimodaux comme CLIP, qui projettent texte et images dans le même espace vectoriel, il est désormais possible de chercher des images avec du texte et vice versa. Cette convergence multimodale ouvre des cas d'usage fascinants, de la recherche e-commerce visuelle à l'analyse de documents multimédia en passant par la génération assistée par récupération d'images.

A retenir : Les bases vectorielles sont devenues essentielles grâce à quatre catalyseurs majeurs : le RAG pour les LLM, la recherche sémantique, les systèmes de recommandation et la détection d'anomalies. Le marché est estimé à plusieurs milliards de dollars en 2026, avec une croissance annuelle supérieure à 40 %.

Algorithmes d'indexation : le cœur technique des bases vectorielles

Les algorithmes d'indexation sont ce qui différencie fondamentalement une base de données vectorielle d'un simple stockage de tableaux de nombres. Sans index spécialisé, chercher le plus proche voisin dans un million de vecteurs de dimension 1536 nécessiterait de calculer un million de distances, soit environ 1,5 milliard d'opérations en virgule flottante. Avec un bon algorithme d'indexation, cette même recherche peut être effectuée en quelques millisecondes, en n'examinant qu'une fraction des vecteurs. Comprendre ces algorithmes est essentiel pour choisir et configurer correctement une base vectorielle.

HNSW (Hierarchical Navigable Small World)

HNSW est l'algorithme d'indexation le plus populaire dans les bases vectorielles modernes. Introduit par Malkov et Yashunin en 2018, il construit un graphe navigable multi-couches inspiré de la théorie des réseaux « petit monde ». Le principe est élégant : imaginez un réseau social où chaque personne connaît quelques voisins proches (couche basse) et quelques contacts lointains (couches hautes). Pour trouver une personne spécifique, vous commencez par les contacts lointains pour vous rapprocher rapidement de la bonne région, puis vous affinez via les contacts de proximité.

Concrètement, HNSW construit un graphe hiérarchique à L couches. La couche 0 contient tous les vecteurs, chaque couche supérieure contient un sous-ensemble décroissant de nœuds. Lors d'une recherche, l'algorithme commence par la couche la plus haute avec un seul point d'entrée, navigue gloutonement vers le voisin le plus proche de la requête, puis descend d'une couche et recommence. À chaque couche, le graphe devient plus dense, permettant une navigation plus fine. Le paramètre M contrôle le nombre maximum de connexions par nœud (typiquement 16-64), et efConstruction contrôle la qualité de l'index pendant la construction. Un M plus élevé améliore le recall mais augmente la consommation mémoire et le temps de construction. Le paramètre efSearch contrôle la précision au moment de la requête.

Les avantages de HNSW sont nombreux. Il offre un excellent compromis entre recall et vitesse de requête, avec des recalls supérieurs à 99 % atteignables dans la plupart des configurations. Les requêtes sont rapides (sub-milliseconde pour des datasets de quelques millions de vecteurs) et le temps de construction est raisonnable. HNSW supporte bien les mises à jour incrémentales, ce qui le rend adapté aux scénarios où les données changent fréquemment. Ses inconvénients principaux sont sa consommation mémoire élevée (l'index et les vecteurs doivent résider en RAM) et ses performances qui se dégradent pour des dimensions très élevées (au-delà de 1000-2000).

IVF (Inverted File Index)

L'algorithme IVF (Inverted File Index) adopte une approche radicalement différente basée sur le partitionnement de l'espace vectoriel. L'idée est de diviser l'ensemble des vecteurs en nLists clusters via un algorithme de clustering comme k-means. Chaque cluster est représenté par son centroïde. Lors d'une recherche, l'algorithme commence par identifier les nProbe clusters les plus proches de la requête en comparant celle-ci aux centroïdes, puis effectue une recherche exhaustive uniquement dans ces clusters sélectionnés. Si nLists = 1024 et nProbe = 16, seul 1,6 % des vecteurs sont effectivement examinés, ce qui accélère considérablement la recherche.

IVF est souvent combiné avec des techniques de quantification pour réduire l'empreinte mémoire. IVF-PQ (Product Quantization) compresse chaque vecteur en le décomposant en sous-vecteurs, chacun quantifié indépendamment. IVF-SQ8 (Scalar Quantization 8 bits) réduit chaque composante du vecteur de 32 bits à 8 bits. Ces variantes permettent de stocker et d'interroger des datasets de milliards de vecteurs sur du matériel modeste, au prix d'une légère perte de recall. IVF est particulièrement adapté aux très grands datasets où la consommation mémoire de HNSW serait prohibitive.

Product Quantization (PQ)

La quantification par produit (PQ) est une technique de compression de vecteurs qui mérite une attention particulière en raison de son impact sur les performances et l'empreinte mémoire. Le principe consiste à diviser chaque vecteur de dimension D en M sous-vecteurs de dimension D/M, puis à quantifier chaque sous-vecteur indépendamment en utilisant un codebook appris par k-means. Typiquement, chaque sous-vecteur est encodé sur 8 bits, ce qui permet 256 codes différents par segment. Un vecteur de 1536 dimensions divisé en 96 segments de 16 dimensions est ainsi compressé de 6144 octets (1536 × 4 octets en float32) à seulement 96 octets, soit un ratio de compression de 64x.

La recherche avec PQ utilise des tables de distance pré-calculées (ADC — Asymmetric Distance Computation). Pour chaque sous-vecteur de la requête, les distances vers les 256 centroïdes du codebook correspondant sont pré-calculées, créant une table de lookup. La distance approximative entre la requête et un vecteur quantifié est alors obtenue par M lookups et additions, ce qui est extrêmement rapide. OPQ (Optimized Product Quantization) ajoute une rotation orthogonale des vecteurs avant la quantification pour minimiser l'erreur de distorsion, améliorant significativement le recall.

ScaNN (Scalable Nearest Neighbors)

Développé par Google Research en 2020, ScaNN (Scalable Nearest Neighbors) est un algorithme qui a démontré des performances de pointe sur les benchmarks ANN. ScaNN introduit une technique appelée « anisotropic vector quantization » qui tient compte de la direction de l'erreur de quantification plutôt que seulement de sa magnitude. L'intuition est que toutes les erreurs de quantification ne sont pas égales : une erreur dans la direction du vecteur requête affecte davantage le classement des résultats qu'une erreur perpendiculaire. En optimisant la quantification pour minimiser l'erreur dans les directions qui comptent le plus, ScaNN atteint des recalls supérieurs à la PQ standard pour un même niveau de compression.

ScaNN utilise un pipeline en trois étapes : partitionnement de l'espace (similaire à IVF), scoring approximatif via quantification anisotrope, et re-ranking exact des top candidats. Cette approche en cascade permet d'éliminer rapidement les vecteurs non pertinents avant d'appliquer des calculs plus précis mais plus coûteux. Google utilise ScaNN en production pour la recherche dans Google Search, YouTube et Google Play, avec des datasets de milliards de vecteurs. La bibliothèque est disponible en open source, mais son intégration dans les bases vectorielles tierces reste limitée.

DiskANN

DiskANN, développé par Microsoft Research, résout le problème fondamental de HNSW : sa dépendance à la mémoire RAM. Pour des datasets de milliards de vecteurs, HNSW nécessiterait des centaines de gigaoctets voire des téraoctets de RAM, ce qui est prohibitivement coûteux. DiskANN construit un graphe similaire à HNSW mais conçu pour résider principalement sur SSD plutôt qu'en RAM. Il utilise un graphe Vamana qui optimise le layout des données sur disque pour minimiser les accès aléatoires, combiné avec une quantification PQ des vecteurs en RAM pour le filtrage initial.

Avec DiskANN, seuls les vecteurs compressés (PQ) et les métadonnées de navigation résident en RAM (typiquement 8-12 octets par vecteur), tandis que les vecteurs complets et les adjacences détaillées du graphe sont stockés sur SSD. Une requête typique nécessite 4-8 accès SSD, soit une latence de 1-5 ms sur un SSD NVMe moderne, ce qui reste excellent pour la plupart des cas d'usage. DiskANN est utilisé en production par Microsoft pour Bing et Azure Cognitive Search, et est intégré dans plusieurs bases vectorielles comme Milvus (via l'index DiskANN) et LanceDB.

A retenir : Les cinq algorithmes majeurs d'indexation vectorielle sont HNSW (graphe navigable, meilleur recall, haute mémoire), IVF (partitionnement, scalable), PQ (compression, faible mémoire), ScaNN (quantification anisotrope, Google) et DiskANN (stockage SSD, milliards de vecteurs). Le choix dépend du compromis entre recall, latence, mémoire et taille du dataset.

Algorithme Recall typique Latence (1M vecteurs) Mémoire Scalabilité Mises à jour
HNSW 95-99,5 % < 1 ms Haute (RAM) Millions Bonne
IVF-PQ 85-95 % 1-5 ms Faible Milliards Moyenne
ScaNN 95-99 % < 1 ms Moyenne Milliards Limitée
DiskANN 93-98 % 1-5 ms Très faible Milliards Bonne
Flat (brute force) 100 % 10-100 ms Haute Milliers Excellente

Comparatif détaillé des solutions de bases vectorielles

Le marché des bases de données vectorielles a considérablement mûri entre 2023 et 2026. Ce qui était un écosystème fragmenté de projets naissants est devenu un paysage concurrentiel structuré avec des acteurs clairement positionnés. Nous analysons ici les huit solutions les plus importantes, en évaluant leurs forces, faiblesses, architectures et cas d'usage optimaux.

Pinecone : le leader du managed vectoriel

Pinecone est une base de données vectorielle entièrement managée, pionnière du marché depuis sa création en 2019 par Edo Liberty, ancien directeur de recherche chez AWS. Pinecone a été conçu dès le départ comme un service cloud serverless, éliminant toute complexité opérationnelle pour les utilisateurs. Son architecture propriétaire sépare le stockage du calcul, permettant un scaling indépendant de chaque composant. Les index Pinecone supportent jusqu'à des milliards de vecteurs avec des latences de requête typiquement inférieures à 50 ms pour le plan serverless et inférieures à 10 ms pour les pods dédiés.

Le modèle serverless de Pinecone, lancé en 2024, a transformé l'économie de la recherche vectorielle. Au lieu de payer pour des pods provisionnés en permanence, les utilisateurs ne paient que pour les requêtes effectuées et le stockage utilisé. Cela rend Pinecone accessible pour les projets à faible volume tout en restant compétitif pour les déploiements à grande échelle. Pinecone propose également des fonctionnalités avancées comme le filtrage par métadonnées, les namespaces pour l'isolation des données, la recherche hybride (dense + sparse vectors) et l'intégration native avec les principaux frameworks IA comme LangChain et LlamaIndex.

Les limites de Pinecone résident principalement dans son modèle propriétaire et fermé. Le code source n'est pas disponible, il n'y a pas d'option self-hosted, et la dépendance au fournisseur est totale. Les coûts peuvent également devenir significatifs à grande échelle, particulièrement pour les workloads avec un fort ratio lecture/écriture. Enfin, le contrôle sur les algorithmes d'indexation et les paramètres de tuning est limité comparé aux solutions open source.

# Exemple d'utilisation de Pinecone en Python
from pinecone import Pinecone, ServerlessSpec

pc = Pinecone(api_key="YOUR_API_KEY")

# Création d'un index serverless
pc.create_index(
    name="articles-semantiques",
    dimension=1536,
    metric="cosine",
    spec=ServerlessSpec(
        cloud="aws",
        region="eu-west-1"
    )
)

index = pc.Index("articles-semantiques")

# Upsert de vecteurs avec métadonnées
index.upsert(vectors=[
    {
        "id": "doc-001",
        "values": embedding_vector,  # liste de 1536 floats
        "metadata": {
            "titre": "Introduction au RAG",
            "categorie": "IA",
            "date": "2026-03-15"
        }
    }
])

# Recherche par similarité avec filtrage
results = index.query(
    vector=query_embedding,
    top_k=10,
    include_metadata=True,
    filter={
        "categorie": {"$eq": "IA"},
        "date": {"$gte": "2026-01-01"}
    }
)

for match in results["matches"]:
    print(f"Score: {match['score']:.4f} - {match['metadata']['titre']}")

Milvus : la puissance open source distribuée

Milvus est une base de données vectorielle open source créée par Zilliz, conçue pour les déploiements à grande échelle nécessitant des performances de niveau production. Lancée en 2019, Milvus a été le premier projet open source dédié spécifiquement à la gestion de vecteurs, et il reste l'une des solutions les plus complètes et les plus performantes du marché. Son architecture cloud-native sépare les couches de stockage, d'indexation et de requêtage, chacune pouvant scaler indépendamment grâce à Kubernetes.

L'architecture de Milvus 2.x est bâtie autour de quatre composants principaux. Le proxy (access layer) reçoit et route les requêtes. Les coordinateurs (coord) gèrent les métadonnées, l'allocation des tâches et l'équilibrage de charge. Les nœuds workers (query nodes, data nodes, index nodes) exécutent les opérations de recherche, d'écriture et de construction d'index. Le stockage persistant utilise des systèmes distribués comme MinIO (pour les données vectorielles) et etcd (pour les métadonnées). Cette architecture désagrégée permet à Milvus de gérer des milliards de vecteurs avec une haute disponibilité et une élasticité horizontale.

Milvus supporte une gamme impressionnante d'algorithmes d'indexation : HNSW, IVF_FLAT, IVF_SQ8, IVF_PQ, DiskANN, ScaNN, et GPU_IVF_FLAT pour l'accélération GPU. Cette flexibilité permet d'optimiser finement les performances en fonction du cas d'usage. Milvus offre également des fonctionnalités avancées comme la recherche hybride (vecteurs denses + sparse), le filtrage par attributs scalaires, le partitionnement des données, la réplication, les transactions ACID au niveau collection, et le support multi-tenancy. La version managée, Zilliz Cloud, offre une expérience similaire à Pinecone mais avec la transparence d'un cœur open source.

La contrepartie de cette puissance est la complexité opérationnelle. Un déploiement Milvus distribué nécessite Kubernetes, etcd, MinIO et plusieurs composants à configurer et monitorer. Pour les petites équipes ou les prototypes, cette complexité peut être dissuasive. Milvus Lite (mode embedded) et Zilliz Cloud adressent ce problème, mais la courbe d'apprentissage reste plus raide que pour des solutions plus simples comme Chroma ou pgvector.

# Exemple d'utilisation de Milvus (pymilvus)
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType, utility

# Connexion au serveur Milvus
connections.connect("default", host="localhost", port="19530")

# Définition du schéma
fields = [
    FieldSchema(name="id", dtype=DataType.VARCHAR, max_length=64, is_primary=True),
    FieldSchema(name="titre", dtype=DataType.VARCHAR, max_length=512),
    FieldSchema(name="categorie", dtype=DataType.VARCHAR, max_length=64),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536)
]
schema = CollectionSchema(fields, description="Articles sémantiques")

# Création de la collection
collection = Collection("articles", schema)

# Création de l'index HNSW
index_params = {
    "metric_type": "COSINE",
    "index_type": "HNSW",
    "params": {"M": 32, "efConstruction": 256}
}
collection.create_index("embedding", index_params)

# Insertion de données
collection.insert([
    ["doc-001", "doc-002"],
    ["Introduction au RAG", "Bases vectorielles"],
    ["IA", "IA"],
    [embedding_1, embedding_2]
])

# Recherche avec filtrage
collection.load()
results = collection.search(
    data=[query_embedding],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"ef": 128}},
    limit=10,
    expr='categorie == "IA"',
    output_fields=["titre", "categorie"]
)

Weaviate : la recherche hybride et les modules intelligents

Weaviate est une base de données vectorielle open source écrite en Go, qui se distingue par son approche modulaire et sa capacité native de recherche hybride. Fondée en 2019 aux Pays-Bas, Weaviate a levé plus de 67 millions de dollars pour construire ce qu'elle décrit comme une « AI-native database ». Son architecture unique intègre directement des modules de vectorisation, permettant aux utilisateurs d'insérer des données brutes (texte, images) et de laisser Weaviate gérer automatiquement la génération et le stockage des embeddings.

La recherche hybride de Weaviate combine la recherche vectorielle (dense) avec la recherche par mots-clés BM25 (sparse) dans une seule requête. L'algorithme de fusion peut être configuré avec un paramètre alpha qui contrôle le poids relatif des deux approches : alpha=1 donne une recherche purement vectorielle, alpha=0 une recherche purement BM25, et des valeurs intermédiaires combinent les deux. Cette flexibilité est précieuse car la recherche purement sémantique peut échouer sur des termes très spécifiques (noms de produits, acronymes, identifiants) où la correspondance exacte est essentielle.

Les modules de Weaviate sont un autre différenciateur clé. Le module text2vec-openai, par exemple, vectorise automatiquement le texte lors de l'insertion en utilisant l'API OpenAI. D'autres modules supportent Cohere, Hugging Face, des modèles locaux via Ollama, la vectorisation d'images (img2vec-neural), et même la génération de réponses (generative-openai) qui intègre un pipeline RAG directement dans la base de données. Cette approche « batteries included » simplifie considérablement l'architecture applicative en réduisant le nombre de composants à orchestrer.

Weaviate utilise HNSW comme algorithme d'indexation principal avec une implémentation custom en Go optimisée pour la production. Il supporte le filtrage pré-recherche (pre-filtering) qui applique les filtres avant la recherche vectorielle, garantissant que les résultats respectent toujours les contraintes de filtrage. Le multi-tenancy natif permet d'isoler les données de différents utilisateurs ou clients dans la même instance, ce qui est essentiel pour les applications SaaS. La version cloud managée (Weaviate Cloud Services) offre un déploiement simplifié avec un plan gratuit pour les petits projets.

Chroma : la simplicité Python-native

Chroma est la base de données vectorielle la plus accessible du marché, conçue spécifiquement pour les développeurs Python et les projets d'IA. Lancée en 2022, Chroma a rapidement gagné en popularité grâce à son API minimaliste, sa facilité d'installation (un simple pip install) et son intégration transparente avec l'écosystème Python. Chroma est devenue la solution par défaut pour le prototypage RAG, les notebooks Jupyter et les projets d'apprentissage, mais elle ambitionne désormais de conquérir les déploiements de production avec sa version serveur distribuée.

L'architecture de Chroma suit une philosophie de simplicité progressive. En mode embedded (par défaut), Chroma s'exécute dans le même processus que l'application Python, stockant les données localement sur disque via SQLite et HNSW. Aucun serveur externe n'est nécessaire. En mode client-serveur, Chroma s'exécute comme un service indépendant accessible via une API HTTP ou gRPC, permettant à plusieurs applications de partager la même base vectorielle. Le mode cloud (Chroma Cloud), lancé en 2025, offre une version managée avec scaling automatique et haute disponibilité.

Chroma intègre nativement des fonctions d'embedding via ses modules de vectorisation. Par défaut, elle utilise le modèle all-MiniLM-L6-v2 de Sentence Transformers pour vectoriser le texte localement, mais supporte également OpenAI, Cohere, Hugging Face et d'autres fournisseurs. Les collections Chroma stockent trois types de données : les documents (texte brut), les embeddings (vecteurs) et les métadonnées (dictionnaires clé-valeur). Le filtrage par métadonnées supporte les opérateurs de comparaison ($eq, $ne, $gt, $lt, $in) et les opérateurs logiques ($and, $or).

Les limitations de Chroma concernent principalement les scénarios de production à grande échelle. Les performances se dégradent au-delà de quelques millions de vecteurs en mode embedded. Le support du clustering distribué est encore jeune comparé à Milvus. Les options d'indexation sont limitées (HNSW uniquement). Le filtrage avancé et la recherche hybride sont moins sophistiqués que chez Weaviate ou Qdrant. Néanmoins, pour les équipes qui démarrent avec les bases vectorielles ou qui construisent des applications de taille modérée, Chroma offre le meilleur rapport simplicité/fonctionnalité du marché.

# Exemple d'utilisation de Chroma en Python
import chromadb
from chromadb.utils import embedding_functions

# Initialisation avec persistance sur disque
client = chromadb.PersistentClient(path="./chroma_data")

# Fonction d'embedding OpenAI
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
    api_key="YOUR_API_KEY",
    model_name="text-embedding-3-small"
)

# Création d'une collection
collection = client.get_or_create_collection(
    name="articles",
    embedding_function=openai_ef,
    metadata={"hnsw:space": "cosine"}
)

# Ajout de documents (embedding automatique)
collection.add(
    documents=[
        "Le RAG combine recherche et génération pour des réponses précises.",
        "Les embeddings capturent la signification sémantique du texte.",
        "HNSW est l'algorithme d'indexation le plus utilisé."
    ],
    metadatas=[
        {"categorie": "IA", "niveau": "intermédiaire"},
        {"categorie": "IA", "niveau": "débutant"},
        {"categorie": "Algorithmes", "niveau": "avancé"}
    ],
    ids=["doc-001", "doc-002", "doc-003"]
)

# Recherche sémantique avec filtrage
results = collection.query(
    query_texts=["Comment fonctionne la recherche sémantique ?"],
    n_results=5,
    where={"categorie": "IA"},
    include=["documents", "metadatas", "distances"]
)

for doc, metadata, distance in zip(
    results["documents"][0],
    results["metadatas"][0],
    results["distances"][0]
):
    print(f"Distance: {distance:.4f} | {metadata['niveau']} | {doc[:80]}...")

Qdrant : la performance Rust et le filtrage avancé

Qdrant (prononcé « quadrant ») est une base de données vectorielle écrite en Rust, qui s'est imposée comme l'une des solutions les plus performantes et les plus riches en fonctionnalités du marché. Fondée en 2021 à Berlin, Qdrant combine les performances brutes du langage Rust avec une API ergonomique et un ensemble de fonctionnalités avancées qui rivalisent avec les leaders du marché. Son moteur de filtrage, en particulier, est considéré comme le plus puissant de l'écosystème vectoriel.

L'architecture de Qdrant repose sur des collections composées de points (vecteurs + payload). Chaque point peut stocker un vecteur ou plusieurs vecteurs nommés (named vectors), ce qui est utile pour les scénarios multimodaux ou les embeddings multi-représentations. Le payload est un document JSON arbitraire associé à chaque point, indexé automatiquement pour permettre un filtrage rapide. Qdrant supporte les index HNSW avec quantification optionnelle (scalar, product, binary) pour réduire l'empreinte mémoire tout en maintenant un recall élevé.

Le système de filtrage de Qdrant est remarquablement complet. Il supporte les filtres sur les types primitifs (entiers, flottants, chaînes, booléens), les tableaux, les objets JSON imbriqués, les géolocalisations (géo-bounding box, géo-radius), les dates et les valeurs NULL. Les filtres peuvent être combinés avec les opérateurs must, should et must_not, formant un langage de requête expressif comparable à Elasticsearch. Crucement, Qdrant effectue le filtrage de manière intégrée à la recherche vectorielle (pas en post-filtrage), ce qui garantit que les résultats respectent toujours les contraintes tout en maximisant le recall.

Qdrant supporte nativement la recherche hybride via les sparse vectors, les vecteurs multiples par point, la recommandation (positive/negative examples), la recherche par groupes (group_by), et le discovery search (exploration de l'espace vectoriel avec des contraintes contextuelles). Le mode distribué permet le sharding et la réplication des collections sur plusieurs nœuds. Qdrant Cloud offre une version managée avec des clusters dédiés dans plusieurs régions AWS, GCP et Azure.

pgvector : la force de l'écosystème PostgreSQL

pgvector est une extension PostgreSQL qui ajoute le support des types vectoriels et de la recherche par similarité directement dans la base de données relationnelle la plus populaire du monde open source. Créée par Andrew Kane en 2021, pgvector permet aux développeurs qui utilisent déjà PostgreSQL d'ajouter des capacités vectorielles sans introduire un nouveau système dans leur stack. Cette approche « vector search as a feature » plutôt que « vector search as a product » a séduit de nombreuses équipes qui privilégient la simplicité architecturale.

pgvector supporte les types de données vector (vecteurs denses), halfvec (demi-précision pour réduire le stockage), bit (vecteurs binaires) et sparsevec (vecteurs sparse). Les index disponibles sont ivfflat (IVF avec flat storage, adapté aux datasets de taille modérée) et hnsw (ajouté dans la version 0.5.0, pour de meilleures performances). Les opérateurs de distance incluent la distance euclidienne (<->), le produit scalaire négatif (<#>), la distance cosinus (<=>) et la distance de Hamming pour les vecteurs binaires.

L'avantage majeur de pgvector est l'intégration transparente avec l'écosystème PostgreSQL. Les vecteurs coexistent avec les données relationnelles dans les mêmes tables, permettant des requêtes qui combinent recherche vectorielle et filtrage SQL standard dans une seule transaction ACID. Les développeurs peuvent utiliser leurs outils PostgreSQL habituels (pgAdmin, psql, ORMs comme SQLAlchemy ou Prisma) et bénéficier de l'écosystème mature de sauvegardes, réplication et monitoring. Les services managés comme AWS RDS, Google Cloud SQL, Supabase et Neon supportent tous pgvector.

Les limitations de pgvector sont liées aux contraintes inhérentes à une extension d'une base relationnelle. Les performances pour des requêtes purement vectorielles sont inférieures à celles des solutions spécialisées, particulièrement pour les grands datasets (au-delà de 10 millions de vecteurs). L'index HNSW de pgvector consomme davantage de mémoire et offre un recall légèrement inférieur aux implémentations optimisées de Qdrant ou Milvus. Le scaling horizontal est limité aux capacités de PostgreSQL (réplication read-only, pas de sharding natif). Néanmoins, pour des datasets de taille modérée avec des besoins de cohérence transactionnelle, pgvector est un choix excellent et pragmatique.

# Exemple d'utilisation de pgvector avec Python (psycopg2)
import psycopg2
from pgvector.psycopg2 import register_vector

conn = psycopg2.connect("postgresql://user:pass@localhost/mydb")
register_vector(conn)

cur = conn.cursor()

# Création de la table avec colonne vectorielle
cur.execute("""
    CREATE TABLE IF NOT EXISTS articles (
        id SERIAL PRIMARY KEY,
        titre TEXT NOT NULL,
        categorie TEXT,
        contenu TEXT,
        embedding vector(1536)
    )
""")

# Création de l'index HNSW
cur.execute("""
    CREATE INDEX IF NOT EXISTS idx_articles_embedding
    ON articles USING hnsw (embedding vector_cosine_ops)
    WITH (m = 32, ef_construction = 256)
""")

# Insertion d'un article avec son embedding
cur.execute(
    "INSERT INTO articles (titre, categorie, contenu, embedding) VALUES (%s, %s, %s, %s)",
    ("Introduction au RAG", "IA", "Le RAG combine...", query_embedding)
)

# Recherche par similarité cosinus avec filtrage SQL
cur.execute("""
    SELECT titre, categorie, 1 - (embedding <=> %s::vector) AS similarity
    FROM articles
    WHERE categorie = 'IA'
    ORDER BY embedding <=> %s::vector
    LIMIT 10
""", (query_embedding, query_embedding))

for row in cur.fetchall():
    print(f"Similarité: {row[2]:.4f} | {row[1]} | {row[0]}")

conn.commit()

FAISS : la bibliothèque de référence de Meta

FAISS (Facebook AI Similarity Search) n'est pas une base de données à proprement parler, mais une bibliothèque C++ avec des bindings Python développée par Meta AI Research. Sortie en 2017, FAISS est la référence en matière de performances brutes pour la recherche de similarité vectorielle. Elle est utilisée en interne par Meta pour des applications à très grande échelle (recherche dans des milliards de vecteurs sur Instagram, Facebook, WhatsApp) et sert de fondation à plusieurs bases vectorielles comme Milvus (qui utilise FAISS en interne pour certains types d'index).

FAISS offre la gamme la plus large d'index de l'écosystème : Flat (brute force exact), IVF, HNSW, PQ, OPQ, ScaNN-like (IVFScalarQuantizer), et des combinaisons avancées comme IVF+HNSW+PQ. L'accélération GPU via CUDA est supportée nativement, permettant des recherches sur des millions de vecteurs en quelques millisecondes sur une seule carte graphique. Les performances de FAISS sur GPU sont typiquement 10 à 100 fois supérieures à celles sur CPU pour les workloads de batch search. FAISS supporte également le training d'index (apprentissage des centroïdes pour IVF, des codebooks pour PQ) sur un sous-ensemble de données avant d'indexer l'ensemble complet.

Les limitations de FAISS découlent de sa nature de bibliothèque plutôt que de base de données. FAISS ne gère pas la persistance (l'utilisateur doit sauvegarder/charger les index manuellement), n'offre pas de filtrage par métadonnées, ne supporte pas le multi-threading côté serveur, et n'a pas d'API réseau. Il n'y a pas de gestion des mises à jour concurrentes, pas de réplication, pas de monitoring intégré. FAISS est l'outil idéal quand vous avez besoin de performances maximales dans un pipeline batch ou un service custom, mais il nécessite un travail d'ingénierie significatif pour construire un service de production autour de lui.

LanceDB : le nouveau venu serverless et embedded

LanceDB est une base de données vectorielle serverless et embedded lancée en 2023 par LanceDB Inc. (anciennement Eto Labs). Elle se distingue par son format de stockage columnar Lance, optimisé pour les données multimodales (vecteurs, texte, images, vidéo), et par sa capacité à fonctionner sans serveur en mode embedded tout en supportant le stockage cloud (S3, GCS, Azure Blob). LanceDB est écrite en Rust avec des bindings Python et JavaScript, offrant des performances proches de FAISS avec la facilité d'utilisation de Chroma.

Le format Lance, inspiré d'Apache Arrow et Parquet, est conçu spécifiquement pour les workloads vectoriels. Il supporte l'accès aléatoire rapide (contrairement à Parquet), les mises à jour incrémentales sans réécriture complète, le versioning des données (time travel), et la compression efficace des vecteurs. LanceDB utilise DiskANN comme algorithme d'indexation principal, permettant des recherches rapides sans charger l'intégralité de l'index en mémoire. Cette architecture « zero-copy » signifie que LanceDB peut gérer des datasets de dizaines de gigaoctets directement depuis le stockage local ou cloud, avec une empreinte mémoire minimale.

LanceDB supporte la recherche hybride (vecteurs + full-text search via Tantivy), le filtrage SQL (via DataFusion), les vecteurs multi-colonnes, et les types de données riches (images, vidéo, audio stockés directement dans les tables). L'intégration avec l'écosystème data science Python est excellente : les tables LanceDB sont interopérables avec Pandas, Polars et PyArrow. La version cloud (LanceDB Cloud) offre une gestion automatique du stockage et de l'indexation avec un modèle de pricing pay-per-query. LanceDB est particulièrement adapté aux cas d'usage multimodaux, aux pipelines de données avec versioning, et aux applications edge/embedded où les ressources sont limitées.

Tableau comparatif complet des bases vectorielles

Ce tableau synthétise les caractéristiques clés des huit solutions analysées, permettant une comparaison rapide sur les critères les plus importants pour le choix d'une base de données vectorielle.

Critère Pinecone Milvus Weaviate Chroma Qdrant pgvector FAISS LanceDB
Licence Propriétaire Apache 2.0 BSD-3 Apache 2.0 Apache 2.0 PostgreSQL MIT Apache 2.0
Langage N/A (SaaS) Go + C++ Go Python + Rust Rust C C++ (CUDA) Rust
Self-hosted Non Oui Oui Oui Oui Oui Oui (lib) Oui
Cloud managé Oui Zilliz Cloud WCS Chroma Cloud Qdrant Cloud RDS, Supabase Non LanceDB Cloud
Scalabilité max Milliards Milliards Centaines M Millions Centaines M Dizaines M Milliards Centaines M
Index Propriétaire HNSW, IVF, DiskANN, ScaNN HNSW HNSW HNSW HNSW, IVF Tous DiskANN, IVF
Recherche hybride Oui (sparse) Oui Oui (BM25) Limitée Oui (sparse) Via pg_trgm Non Oui (Tantivy)
Filtrage Métadonnées Scalaire Pré-filtrage Métadonnées Avancé (JSON) SQL complet Non SQL (DataFusion)
Multi-tenancy Namespaces Partitions Natif Collections Groupes Row-level Non Tables
GPU N/A Oui Non Non Non Non Oui (CUDA) Non
Mode embedded Non Milvus Lite Non Oui Non Non Oui Oui
Coût (1M vecteurs) ~25 $/mois Gratuit (self) Gratuit (self) Gratuit (self) Gratuit (self) Gratuit Gratuit Gratuit (self)

A retenir : Le choix entre les solutions dépend de trois axes principaux : simplicité (Chroma, pgvector, LanceDB), puissance et scalabilité (Milvus, Pinecone, Qdrant), et fonctionnalités intégrées (Weaviate, Qdrant). Les solutions open source offrent plus de contrôle mais nécessitent plus d'expertise opérationnelle.

Intégration avec les frameworks IA

L'écosystème des frameworks d'intelligence artificielle s'est structuré autour de quelques projets majeurs qui facilitent la construction d'applications RAG, de chatbots et de pipelines de traitement sémantique. L'intégration avec ces frameworks est devenue un critère de choix essentiel pour les bases vectorielles, car elle détermine la rapidité de développement et la maintenabilité des applications.

LangChain : l'orchestrateur universel

LangChain est le framework le plus populaire pour la construction d'applications basées sur les LLM. Il offre une abstraction unifiée pour les bases vectorielles via sa classe VectorStore, qui standardise les opérations d'insertion, de recherche et de suppression. Toutes les bases vectorielles majeures sont supportées via des intégrateurs dédiés : langchain-pinecone, langchain-milvus, langchain-weaviate, langchain-chroma, langchain-qdrant, langchain-postgres (pour pgvector) et langchain-community pour les autres. Cette standardisation permet de changer de base vectorielle avec un minimum de modifications du code applicatif.

LangChain propose également des abstractions de plus haut niveau comme les Retrievers (qui encapsulent la logique de recherche avec post-traitement), les Chains (qui orchestrent les étapes d'un pipeline RAG) et les Agents (qui décident dynamiquement quand et comment interroger la base vectorielle). Le module LCEL (LangChain Expression Language) permet de composer ces éléments de manière déclarative. L'intégration avec LangSmith (observabilité) et LangServe (déploiement API) complète l'écosystème pour les applications de production.

# Pipeline RAG complet avec LangChain + Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_chroma import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# 1. Préparation des documents
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    separators=["\n\n", "\n", ". ", " ", ""]
)
documents = text_splitter.create_documents(
    texts=raw_texts,
    metadatas=[{"source": f"doc_{i}"} for i in range(len(raw_texts))]
)

# 2. Création du vectorstore Chroma
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(
    documents=documents,
    embedding=embeddings,
    persist_directory="./chroma_langchain",
    collection_name="knowledge_base"
)

# 3. Configuration du retriever
retriever = vectorstore.as_retriever(
    search_type="mmr",  # Maximal Marginal Relevance pour la diversité
    search_kwargs={"k": 6, "fetch_k": 20}
)

# 4. Construction du pipeline RAG avec LCEL
template = """Tu es un assistant expert. Réponds à la question en te basant
uniquement sur le contexte fourni. Si tu ne connais pas la réponse, dis-le.

Contexte:
{context}

Question: {question}

Réponse détaillée:"""

prompt = ChatPromptTemplate.from_template(template)
llm = ChatOpenAI(model="gpt-4o", temperature=0)

rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

# 5. Utilisation
response = rag_chain.invoke("Comment fonctionne l'algorithme HNSW ?")
print(response)

LlamaIndex : le spécialiste du RAG structuré

LlamaIndex (anciennement GPT Index) est un framework spécialisé dans la construction de pipelines RAG sophistiqués. Contrairement à LangChain qui se veut généraliste, LlamaIndex se concentre sur l'ingestion, l'indexation et la recherche de données avec une granularité fine. Il excelle dans les scénarios impliquant des sources de données hétérogènes (documents PDF, bases de données SQL, API, fichiers Markdown, Slack, Notion) et des structures d'index complexes (arbres, graphes de connaissances, index composites).

LlamaIndex propose plusieurs types d'index qui vont au-delà du simple stockage vectoriel. Le VectorStoreIndex est l'index de base qui délègue le stockage à une base vectorielle externe. Le SummaryIndex crée un résumé hiérarchique des documents. Le KnowledgeGraphIndex construit un graphe de connaissances exploitable pour des requêtes complexes. Le TreeIndex organise les données en arbre pour une recherche top-down. Ces index peuvent être composés pour créer des pipelines de recherche multi-étapes qui combinent différentes stratégies de retrieval selon la nature de la requête.

L'intégration de LlamaIndex avec les bases vectorielles est mature et bien documentée. Les principales bases sont supportées via des modules dédiés (llama-index-vector-stores-chroma, -pinecone, -milvus, -qdrant, -weaviate, -postgres). LlamaIndex introduit également des concepts avancés comme les node parsers (qui contrôlent finement le découpage des documents), les response synthesizers (qui assemblent les résultats de recherche en réponse cohérente), et les query engines (qui orchestrent le processus complet de question-réponse).

Haystack : le framework européen de NLP

Haystack, développé par deepset (une entreprise allemande), est un framework open source pour la construction de pipelines NLP et RAG. Haystack se distingue par son approche basée sur les composants (components) connectés via des pipelines typés, offrant une grande flexibilité architecturale avec une vérification statique des types. La version 2.x, réécriture majeure lancée en 2024, a modernisé l'API et simplifié considérablement l'intégration avec les bases vectorielles.

Haystack supporte les principales bases vectorielles via des intégrateurs dédiés : haystack-integrations pour Chroma, Milvus, Pinecone, Qdrant, Weaviate et pgvector. Le concept de DocumentStore abstrait la couche de stockage, tandis que les Retrievers encapsulent la logique de recherche. Les pipelines Haystack peuvent être sérialisés en YAML, versionnés, et déployés via Hayhooks (serveur REST). L'écosystème Haystack inclut également des outils d'évaluation (RAGAS, UpTrain) pour mesurer la qualité des pipelines RAG en production.

Performance et benchmarks

Les benchmarks de performance sont essentiels pour faire un choix éclairé, mais ils doivent être interprétés avec prudence. Les résultats dépendent fortement du matériel, de la configuration, du dataset, de la dimension des vecteurs et des paramètres de l'index. Nous présentons ici les résultats consolidés de plusieurs benchmarks publics, notamment ANN Benchmarks et les benchmarks internes publiés par les éditeurs, en normalisant autant que possible les conditions de test.

Latence de requête

La latence de requête mesure le temps entre la soumission d'une requête et la réception des résultats. Pour un dataset de référence de 1 million de vecteurs de dimension 768 avec un recall cible de 95 %, voici les latences typiques observées sur un serveur avec 16 CPU cores et 64 Go de RAM. FAISS (HNSW) atteint les latences les plus basses avec 0,3-0,5 ms, suivi de Qdrant avec 0,5-1,0 ms et Milvus avec 0,8-1,5 ms. Weaviate se situe autour de 1,0-2,0 ms, pgvector entre 2,0 et 5,0 ms, et Chroma entre 1,5 et 3,0 ms. Pinecone, en mode serverless, affiche des latences plus élevées de 15-50 ms en raison de la latence réseau, mais descend à 3-8 ms avec des pods dédiés dans la même région. LanceDB, grâce à DiskANN, maintient des latences de 1,0-3,0 ms même pour des datasets qui ne tiennent pas en mémoire.

Il est important de noter que ces latences augmentent avec le filtrage. L'application de filtres par métadonnées peut multiplier la latence par 2 à 10 selon la sélectivité du filtre et l'implémentation du pré-filtrage. Qdrant et Weaviate, avec leur filtrage intégré à l'index, maintiennent les meilleures performances dans les scénarios avec filtrage intensif. pgvector, qui combine filtrage SQL et recherche vectorielle, peut voir ses latences augmenter significativement pour des filtres complexes impliquant des jointures.

Recall (taux de rappel)

Le recall mesure la proportion des vrais k plus proches voisins qui sont effectivement retournés par la recherche approximative. Un recall de 95 % signifie que sur 100 résultats attendus, 95 sont correctement identifiés. Le recall est inversement corrélé à la vitesse : augmenter le recall nécessite d'explorer davantage de candidats, ce qui ralentit la recherche. Le paramètre efSearch de HNSW (ou nProbe pour IVF) contrôle directement ce compromis.

Sur le benchmark standard SIFT-1M (1 million de vecteurs de dimension 128), les meilleures implémentations HNSW (FAISS, Qdrant) atteignent 99,5 % de recall avec des latences inférieures à 1 ms. Sur des datasets plus réalistes de dimension 768-1536, un recall de 98 % est généralement atteignable sans dégradation significative des performances. Pour les scénarios de production, un recall de 95-98 % est considéré comme excellent et suffisant pour la grande majorité des cas d'usage. Seuls les cas d'usage critiques (recherche de fraude, matching biométrique) peuvent justifier le coût de performances supplémentaire pour atteindre 99 %+ de recall.

QPS (Queries Per Second)

Le throughput, mesuré en requêtes par seconde (QPS), est critique pour les applications à fort trafic. Sur un serveur 16 cores / 64 Go RAM avec un dataset de 1 million de vecteurs (dimension 768, HNSW, recall 95 %), les performances typiques sont les suivantes. FAISS atteint 5 000-10 000 QPS grâce à ses optimisations SIMD. Qdrant se situe autour de 3 000-6 000 QPS. Milvus atteint 2 000-5 000 QPS en mode standalone. Weaviate affiche 1 500-3 000 QPS. Chroma se limite à 500-1 500 QPS en mode embedded. pgvector atteint 300-800 QPS, limité par l'overhead PostgreSQL. Les performances GPU de FAISS et Milvus peuvent multiplier ces chiffres par 10-50x pour le batch processing.

Solution Latence p50 (ms) Latence p99 (ms) QPS (single node) Recall @ k=10
FAISS (HNSW) 0,4 1,2 8 000 98,5 %
Qdrant 0,7 2,1 4 500 98,2 %
Milvus 1,0 3,5 3 500 97,8 %
Weaviate 1,5 4,8 2 200 97,5 %
LanceDB 1,8 5,2 1 800 96,8 %
Chroma 2,0 6,5 1 000 97,0 %
pgvector 3,5 12,0 550 96,5 %
Pinecone (serverless) 25,0 80,0 1 500 98,0 %

A retenir : Les performances brutes favorisent FAISS et Qdrant, mais les benchmarks doivent être interprétés dans le contexte d'utilisation réel. La latence réseau de Pinecone est compensée par l'absence de gestion d'infrastructure. pgvector est le plus lent mais offre la cohérence transactionnelle. Le filtrage par métadonnées peut multiplier les latences par 2 à 10x selon les implémentations.

Architecture de déploiement

Le choix de l'architecture de déploiement est aussi important que le choix de la base vectorielle elle-même. Une solution techniquement supérieure mal déployée sera moins performante qu'une solution modeste correctement architecturée. Nous examinons les trois modèles de déploiement principaux et leurs implications pratiques.

Déploiement standalone

Le déploiement standalone consiste à exécuter la base vectorielle sur un seul serveur ou une seule machine virtuelle. C'est le modèle le plus simple, adapté aux projets de petite à moyenne envergure (jusqu'à quelques millions de vecteurs). Qdrant, Weaviate, Chroma et pgvector sont particulièrement adaptés à ce modèle. Un conteneur Docker unique suffit pour démarrer, et la gestion opérationnelle se limite aux sauvegardes, au monitoring des ressources et aux mises à jour.

Les avantages du standalone sont la simplicité opérationnelle, le coût réduit, la prévisibilité des performances (pas de latence réseau inter-nœuds) et la facilité de débogage. Les limitations sont l'absence de haute disponibilité (un seul point de défaillance), la scalabilité verticale limitée par le matériel, et l'impossibilité de gérer des datasets dépassant la capacité de stockage ou de mémoire du serveur. Pour atténuer ces risques, il est recommandé de mettre en place des sauvegardes automatiques fréquentes, un monitoring avec alertes, et un plan de disaster recovery documenté.

Déploiement distribué avec Kubernetes

Pour les déploiements à grande échelle nécessitant haute disponibilité, scalabilité horizontale et tolérance aux pannes, Kubernetes est devenu le standard de facto. Milvus, Qdrant et Weaviate offrent tous des Helm charts et des opérateurs Kubernetes officiels qui automatisent le déploiement, le scaling et la gestion du cycle de vie. Milvus est la solution la plus mature dans ce domaine, avec une architecture cloud-native conçue spécifiquement pour Kubernetes.

Un déploiement Milvus distribué sur Kubernetes comprend typiquement les composants suivants : des proxies (load balancing des requêtes), des query nodes (exécution des recherches, scalables horizontalement), des data nodes (ingestion et indexation), des index nodes (construction d'index en background), etcd (consensus et métadonnées), MinIO ou S3 (stockage objet pour les vecteurs), et Pulsar ou Kafka (message queue pour le streaming de données). Le Milvus Operator automatise le scaling horizontal des query nodes en fonction de la charge, permettant de gérer des pics de trafic sans intervention manuelle.

Le déploiement Kubernetes apporte des fonctionnalités essentielles pour la production : rolling updates sans downtime, auto-scaling basé sur les métriques (CPU, mémoire, QPS), réplication pour la tolérance aux pannes, monitoring intégré via Prometheus et Grafana, et gestion des secrets. Le coût de cette sophistication est la complexité opérationnelle : il faut maîtriser Kubernetes, gérer les dépendances (etcd, MinIO), dimensionner correctement les nœuds, et monitorer un nombre important de composants. Une équipe DevOps/SRE dédiée est recommandée pour les déploiements distribués en production.

Déploiement serverless et managed

Le modèle serverless élimine toute gestion d'infrastructure en déléguant l'hébergement, le scaling et la maintenance au fournisseur. Pinecone est le leader de ce segment avec son offre serverless native. Zilliz Cloud (Milvus managé), Weaviate Cloud Services, Qdrant Cloud et LanceDB Cloud proposent également des versions managées avec des niveaux de « serverless-ness » variables (certains nécessitent encore de choisir la taille du cluster).

Les avantages du serverless sont évidents : zéro gestion opérationnelle, scaling automatique et transparent, modèle de pricing à l'usage (pay-per-query ou pay-per-GB), et time-to-production minimal. Les inconvénients incluent le coût potentiellement élevé à grande échelle, la dépendance au fournisseur (vendor lock-in), les latences réseau incompressibles, et le contrôle limité sur la configuration et l'optimisation. Le serverless est idéal pour les startups, les prototypes, les applications à trafic variable, et les équipes sans expertise DevOps. Il est moins adapté aux entreprises avec des exigences strictes de résidence des données, de sécurité ou de contrôle des coûts à grande échelle.

Sécurité et gouvernance des données vectorielles

La sécurité et la gouvernance des données vectorielles constituent un enjeu souvent sous-estimé. Les embeddings, bien qu'étant des représentations numériques apparemment abstraites, contiennent des informations sémantiques qui peuvent être partiellement inversées pour reconstruire le contenu original. Ce risque, combiné aux exigences réglementaires croissantes (RGPD, AI Act européen), nécessite une attention particulière lors de la conception et du déploiement de solutions vectorielles.

Risques spécifiques aux embeddings

Les recherches récentes en sécurité de l'IA ont démontré qu'il est possible de reconstruire partiellement le texte original à partir de ses embeddings. Des attaques par inversion (embedding inversion attacks) peuvent récupérer des informations sensibles comme des noms, des adresses email, des numéros de téléphone ou des données médicales à partir des vecteurs stockés dans une base vectorielle. Le risque est particulièrement élevé pour les embeddings de haute dimension et les modèles de grande taille. Ces découvertes remettent en question l'idée que les embeddings sont une forme de « pseudonymisation » suffisante pour protéger les données personnelles.

Les attaques par inférence de membership (membership inference attacks) constituent un autre risque. Un attaquant peut déterminer si un document spécifique fait partie de la base vectorielle en analysant les distances de recherche. Cela peut révéler des informations sensibles, comme le fait qu'un patient spécifique est traité dans un hôpital donné, ou qu'un document confidentiel fait partie d'un corpus interne.

Mesures de sécurité

Pour atténuer ces risques, plusieurs mesures complémentaires doivent être mises en œuvre. Le chiffrement des données au repos (at-rest encryption) protège les vecteurs stockés sur disque. Pinecone, Milvus, Qdrant et Weaviate supportent tous le chiffrement au repos via AES-256. Le chiffrement en transit (TLS/mTLS) protège les données pendant leur transfert entre l'application et la base vectorielle. L'authentification et l'autorisation contrôlent qui peut accéder à quelles collections ou namespaces. Qdrant et Milvus supportent l'authentification par API key et RBAC (Role-Based Access Control). Weaviate supporte l'authentification OIDC pour l'intégration avec des fournisseurs d'identité d'entreprise.

Au niveau applicatif, des techniques comme le differential privacy (ajout de bruit calibré aux embeddings) et le bucketing (arrondi des valeurs vectorielles) peuvent réduire le risque d'inversion sans dégrader significativement la qualité de la recherche. Le filtrage par métadonnées au niveau de l'accès (tenant isolation) garantit que les utilisateurs ne voient que les documents auxquels ils ont droit. L'audit logging enregistre toutes les opérations de recherche et de modification pour la traçabilité et la conformité réglementaire.

Conformité RGPD et AI Act

Le RGPD s'applique aux données vectorielles dès lors que les embeddings sont dérivés de données personnelles ou permettent d'identifier des personnes. Le droit à l'effacement (article 17) impose de pouvoir supprimer les vecteurs associés à une personne sur demande. Le droit à la portabilité (article 20) peut nécessiter l'exportation des données vectorielles dans un format lisible. La minimisation des données (article 5) encourage à ne stocker que les embeddings nécessaires et à définir des durées de rétention adaptées.

L'AI Act européen, entré en vigueur progressivement depuis 2025, impose des exigences supplémentaires pour les systèmes d'IA à haut risque. Les bases vectorielles utilisées dans des contextes sensibles (recrutement, crédit, santé, justice) doivent faire l'objet d'une évaluation des risques, d'une documentation technique détaillée, de mesures de transparence et de supervision humaine. Les entreprises utilisant des bases vectorielles dans ces domaines doivent anticiper ces exigences et intégrer la conformité dès la conception (privacy by design).

Cas d'usage concrets

Au-delà de la théorie, les bases vectorielles démontrent leur valeur dans des déploiements réels à travers une variété de secteurs et d'applications. Nous présentons ici quatre cas d'usage détaillés qui illustrent les choix architecturaux, les défis rencontrés et les résultats obtenus.

Cas 1 : RAG chatbot pour un service client bancaire

Une grande banque européenne a déployé un chatbot RAG pour son service client, utilisant Qdrant comme base vectorielle. Le système indexe 2,5 millions de chunks de documents (procédures internes, FAQ, conditions générales, réglementation bancaire) en vecteurs de dimension 1024 via le modèle BGE-M3. Chaque chunk est enrichi de métadonnées structurées : type de document, date de validité, département, niveau de confidentialité et langue.

L'architecture utilise un pipeline de recherche en deux étapes. D'abord, une recherche hybride combine vecteurs denses (sémantique) et sparse (BM25) avec un poids de 70/30. Ensuite, un reranker (BGE-reranker-v2-m3) réordonne les 50 premiers candidats pour sélectionner les 5 plus pertinents. Le filtrage Qdrant est utilisé intensivement pour limiter les résultats aux documents applicables (par produit bancaire, par pays, par date de validité). Le LLM (GPT-4o) génère la réponse finale en citant systématiquement les sources.

Les résultats sont significatifs : le chatbot résout 72 % des demandes sans intervention humaine (contre 35 % avec l'ancien système basé sur des arbres de décision). Le temps de réponse moyen est de 2,8 secondes, dont 15 ms pour la recherche vectorielle. Le taux de satisfaction client est passé de 62 % à 87 %. Le coût par interaction a été réduit de 65 %. Le déploiement a nécessité 4 mois de développement avec une équipe de 6 personnes (2 ML engineers, 2 backend developers, 1 DevOps, 1 product manager).

Cas 2 : recherche sémantique dans un catalogue e-commerce

Une marketplace européenne avec un catalogue de 15 millions de produits a implémenté une recherche sémantique basée sur Milvus pour remplacer son moteur Elasticsearch existant. Les embeddings sont générés par un modèle fine-tuné E5-large-v2 entraîné sur 10 millions de paires (requête, produit pertinent) issues des logs de recherche historiques. Chaque produit est représenté par un vecteur de dimension 1024, accompagné de métadonnées (catégorie, prix, note, disponibilité, marque, vendeur).

Le déploiement utilise Milvus distribué sur Kubernetes avec 12 query nodes pour gérer 3 000 QPS aux heures de pointe. L'index IVF_SQ8 a été choisi pour réduire l'empreinte mémoire (8 bits par composante au lieu de 32), permettant de stocker les 15 millions de vecteurs en 15 Go de RAM (contre 60 Go en float32). La recherche hybride combine les vecteurs denses avec des sparse vectors SPLADE pour les correspondances exactes de marques et de références. Le cache Redis en amont absorbe 40 % des requêtes récurrentes, réduisant la charge sur Milvus.

L'impact métier est mesurable : le taux de conversion depuis la page de recherche a augmenté de 23 %, le taux de « zero results » a diminué de 78 %, et la durée moyenne de session a augmenté de 18 %. Les requêtes en langage naturel (« robe rouge pour mariage été ») produisent désormais des résultats pertinents, ce qui était impossible avec la recherche par mots-clés. Le coût d'infrastructure est de 4 200 euros par mois pour le cluster Milvus sur GKE.

Cas 3 : système de recommandation de contenus médias

Un service de streaming vidéo français utilise Pinecone pour alimenter son système de recommandation personnalisée. Chaque contenu (film, série, documentaire) est représenté par un vecteur multimodal de dimension 1536 combinant des embeddings textuels (synopsis, critiques), visuels (affiches, thumbnails via CLIP) et comportementaux (patterns de visionnage agrégés). Chaque utilisateur est également représenté par un vecteur de préférences mis à jour en temps réel en fonction de son historique de visionnage.

Le système recommande du contenu en effectuant une recherche de plus proches voisins dans l'espace vectoriel avec le vecteur utilisateur comme requête. Le filtrage par métadonnées exclut les contenus déjà vus, les contenus non disponibles dans la région géographique de l'utilisateur, et applique les restrictions d'âge. Les namespaces Pinecone isolent les données par marché (France, Belgique, Suisse). Le pipeline de mise à jour recalcule les vecteurs utilisateurs toutes les 15 minutes via un job Spark qui agrège les événements de visionnage depuis Kafka.

Cas 4 : détection de fraude en temps réel

Une fintech spécialisée dans les paiements en ligne utilise un système de détection de fraude basé sur Qdrant. Chaque transaction est encodée en vecteur de dimension 256 par un autoencodeur variationnel (VAE) entraîné sur 18 mois d'historique de transactions. Les transactions légitimes forment des clusters denses dans l'espace vectoriel, tandis que les transactions frauduleuses apparaissent comme des outliers statistiques. Le système calcule en temps réel la distance entre chaque nouvelle transaction et ses k plus proches voisins dans la base historique. Si la distance moyenne dépasse un seuil calibré, la transaction est signalée pour revue manuelle ou blocage automatique.

L'architecture utilise Qdrant en mode distribué sur 3 nœuds avec réplication factor 2 pour la haute disponibilité. Le filtrage par payload (montant, devise, pays, type de carte, heure) réduit l'espace de recherche pour chaque transaction. Le système traite 2 500 transactions par seconde avec une latence p99 de 8 ms. La base contient 450 millions de vecteurs de transactions, stockés avec DiskANN pour minimiser la consommation RAM. Le taux de détection de fraude a augmenté de 34 % par rapport au système basé sur des règles, tout en réduisant les faux positifs de 28 %, ce qui représente une économie annuelle estimée à 12 millions d'euros.

Guide de choix : quelle base vectorielle pour quel usage ?

Face à la multiplicité des solutions, le choix de la bonne base vectorielle peut sembler intimidant. Voici un guide décisionnel structuré qui vous aidera à identifier la solution la plus adaptée à votre contexte spécifique. Ce guide prend en compte non seulement les caractéristiques techniques, mais aussi les contraintes organisationnelles, budgétaires et opérationnelles qui influencent le choix en pratique.

Profil 1 : prototypage et apprentissage

Si vous débutez avec les bases vectorielles ou construisez un prototype, Chroma est le choix évident. Son installation en une seule commande (pip install chromadb), son API Python intuitive et son mode embedded sans serveur permettent de démarrer en quelques minutes. L'intégration native avec LangChain et LlamaIndex facilite la construction rapide de pipelines RAG. Pour un prototype légèrement plus avancé nécessitant de la persistance et de la cohérence transactionnelle, pgvector est idéal si vous utilisez déjà PostgreSQL. LanceDB est également excellent pour le prototypage, particulièrement pour les cas d'usage multimodaux.

Profil 2 : application de production de taille modérée

Pour une application en production avec 1 à 50 millions de vecteurs, un trafic modéré (moins de 1 000 QPS) et une équipe technique de taille moyenne, Qdrant ou Weaviate sont les choix les plus équilibrés. Qdrant excelle par ses performances et son filtrage avancé, tandis que Weaviate se distingue par sa recherche hybride et ses modules de vectorisation intégrés. Les deux peuvent être déployés en mode standalone sur un seul serveur Docker, ce qui simplifie les opérations. Si vous préférez un modèle managé, Pinecone serverless élimine toute complexité opérationnelle et offre un pricing à l'usage adapté aux volumes modérés.

Profil 3 : plateforme à grande échelle

Pour les déploiements à grande échelle dépassant 100 millions de vecteurs, nécessitant une haute disponibilité et un throughput élevé, Milvus est la solution de référence. Son architecture distribuée cloud-native, son support de multiples algorithmes d'indexation (dont DiskANN pour les très grands datasets) et sa maturité en production en font le choix privilégié des grandes entreprises. Zilliz Cloud offre une version managée qui simplifie les opérations tout en conservant la puissance de Milvus. Pinecone avec des pods dédiés est une alternative solide pour les entreprises qui préfèrent un modèle entièrement managé et qui peuvent absorber le coût correspondant.

Profil 4 : intégration dans un stack existant

Si vous souhaitez ajouter des capacités vectorielles sans complexifier votre stack, le choix dépend de votre infrastructure existante. Avec PostgreSQL, utilisez pgvector pour une intégration transparente. Avec un pipeline data science Python, LanceDB offre une interopérabilité native avec Pandas, Polars et PyArrow. Pour un besoin de performances maximales dans un pipeline batch, FAISS reste imbattable en tant que bibliothèque. Si vous avez déjà Elasticsearch, envisagez d'abord les capacités vectorielles natives d'Elasticsearch 8.x avant d'introduire une base vectorielle dédiée.

Profil 5 : contraintes de sécurité et conformité

Pour les entreprises soumises à des contraintes réglementaires strictes (santé, finance, secteur public), le self-hosting est souvent impératif. Milvus, Qdrant et Weaviate offrent tous un déploiement on-premise complet. Milvus et Qdrant proposent RBAC pour le contrôle d'accès granulaire. Weaviate supporte l'authentification OIDC pour l'intégration avec Active Directory ou Okta. pgvector bénéficie de l'écosystème de sécurité mature de PostgreSQL, incluant le chiffrement au repos, l'audit logging et la conformité SOC 2 des services managés.

Critère principal 1er choix 2e choix 3e choix
Simplicité maximale Chroma pgvector LanceDB
Performance brute FAISS Qdrant Milvus
Scalabilité massive Milvus Pinecone Qdrant
Recherche hybride Weaviate Qdrant Milvus
Zéro ops (managed) Pinecone Zilliz Cloud Weaviate Cloud
Stack PostgreSQL pgvector Supabase Neon
Multimodal LanceDB Weaviate Milvus
Filtrage avancé Qdrant Weaviate pgvector (SQL)
Budget limité Chroma pgvector FAISS

Tutoriel Python : indexer et rechercher avec Chroma et LangChain

Ce tutoriel pratique vous guide pas à pas dans la construction d'un système RAG complet utilisant Chroma comme base vectorielle et LangChain comme framework d'orchestration. Nous allons indexer un corpus de documents, configurer la recherche sémantique, et construire un chatbot capable de répondre à des questions en se basant sur les documents indexés.

Étape 1 : Installation et configuration

Commençons par installer les dépendances nécessaires et configurer l'environnement. Nous utiliserons Python 3.10+ et un environnement virtuel pour isoler les dépendances du projet.

# Création de l'environnement virtuel
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate   # Windows

# Installation des dépendances
pip install chromadb langchain langchain-openai langchain-chroma
pip install pypdf docx2txt tiktoken python-dotenv

# Configuration des variables d'environnement
# Créer un fichier .env
echo "OPENAI_API_KEY=sk-..." > .env

Étape 2 : Chargement et découpage des documents

Le découpage (chunking) des documents est une étape critique qui influence directement la qualité de la recherche. Un chunk trop petit manque de contexte, tandis qu'un chunk trop grand dilue l'information pertinente. La stratégie optimale dépend du type de document et du cas d'usage.

from langchain_community.document_loaders import (
    PyPDFLoader, TextLoader, DirectoryLoader
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
from dotenv import load_dotenv
import os

load_dotenv()

# Chargement de documents depuis un dossier
loader = DirectoryLoader(
    "./documents",
    glob="**/*.pdf",
    loader_cls=PyPDFLoader,
    show_progress=True
)
raw_documents = loader.load()
print(f"Documents chargés : {len(raw_documents)}")

# Découpage intelligent avec RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,       # Taille cible de chaque chunk en caractères
    chunk_overlap=150,    # Chevauchement entre chunks adjacents
    length_function=len,
    separators=[
        "\n\n",   # Priorité 1 : paragraphes
        "\n",     # Priorité 2 : sauts de ligne
        ". ",     # Priorité 3 : phrases
        ", ",     # Priorité 4 : virgules
        " ",      # Priorité 5 : mots
        ""        # Dernier recours : caractères
    ],
    is_separator_regex=False
)

chunks = text_splitter.split_documents(raw_documents)
print(f"Chunks créés : {len(chunks)}")
print(f"Taille moyenne : {sum(len(c.page_content) for c in chunks) / len(chunks):.0f} chars")

# Enrichissement des métadonnées
for i, chunk in enumerate(chunks):
    chunk.metadata["chunk_id"] = f"chunk_{i:06d}"
    chunk.metadata["char_count"] = len(chunk.page_content)
    # Extraire le nom du fichier source
    chunk.metadata["filename"] = os.path.basename(chunk.metadata.get("source", ""))

Étape 3 : Création du vectorstore Chroma

Nous configurons maintenant Chroma avec un modèle d'embedding OpenAI et une persistance sur disque. La configuration de l'espace HNSW est importante pour optimiser les performances de recherche.

from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

# Configuration du modèle d'embedding
embeddings = OpenAIEmbeddings(
    model="text-embedding-3-small",  # 1536 dimensions, bon rapport qualité/prix
    # model="text-embedding-3-large",  # 3072 dimensions, meilleure qualité
)

# Création du vectorstore avec persistance
vectorstore = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./chroma_db",
    collection_name="documentation",
    collection_metadata={
        "hnsw:space": "cosine",        # Métrique de distance
        "hnsw:construction_ef": 256,   # Qualité de construction de l'index
        "hnsw:search_ef": 128,         # Qualité de recherche (recall vs vitesse)
        "hnsw:M": 32,                  # Connexions par nœud
    }
)

print(f"Vectorstore créé avec {vectorstore._collection.count()} vecteurs")

Étape 4 : Recherche sémantique avancée

Chroma et LangChain supportent plusieurs stratégies de recherche. La recherche par similarité basique retourne les k chunks les plus proches. La recherche MMR (Maximal Marginal Relevance) favorise la diversité des résultats en pénalisant les doublons sémantiques. Le score threshold filtre les résultats en dessous d'un seuil de similarité.

# Recherche par similarité basique
results = vectorstore.similarity_search(
    query="Comment fonctionne l'algorithme HNSW ?",
    k=5,
    filter={"filename": "vector_databases.pdf"}  # Filtrage par métadonnée
)

for doc in results:
    print(f"Source: {doc.metadata['filename']} | Chunk: {doc.metadata['chunk_id']}")
    print(f"Contenu: {doc.page_content[:200]}...")
    print("---")

# Recherche avec scores de similarité
results_with_scores = vectorstore.similarity_search_with_score(
    query="Quels sont les avantages de Qdrant ?",
    k=10
)

for doc, score in results_with_scores:
    print(f"Score: {score:.4f} | {doc.page_content[:100]}...")

# Recherche MMR pour la diversité
results_mmr = vectorstore.max_marginal_relevance_search(
    query="Comparaison des bases vectorielles",
    k=5,           # Nombre de résultats retournés
    fetch_k=20,    # Nombre de candidats initiaux
    lambda_mult=0.7  # 0 = diversité max, 1 = pertinence max
)

# Configuration d'un retriever réutilisable
retriever = vectorstore.as_retriever(
    search_type="mmr",
    search_kwargs={
        "k": 6,
        "fetch_k": 25,
        "lambda_mult": 0.75
    }
)

# Utilisation du retriever
docs = retriever.invoke("Quelle base vectorielle pour un projet RAG ?")

Étape 5 : Construction du pipeline RAG complet

Nous assemblons maintenant tous les composants en un pipeline RAG fonctionnel utilisant LCEL (LangChain Expression Language) pour une composition élégante et performante.

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_core.output_parsers import StrOutputParser
from langchain_core.messages import HumanMessage, AIMessage

# Configuration du LLM
llm = ChatOpenAI(
    model="gpt-4o",
    temperature=0,
    max_tokens=2048
)

# Prompt template avec instructions précises
system_prompt = """Tu es un assistant technique expert en bases de données vectorielles.
Tu réponds aux questions en te basant UNIQUEMENT sur le contexte fourni ci-dessous.

Règles :
- Si le contexte ne contient pas l'information, dis clairement "Je ne dispose pas
  de cette information dans ma base de connaissances."
- Cite les sources en mentionnant le nom du document.
- Structure ta réponse avec des paragraphes clairs.
- Utilise des exemples concrets quand c'est pertinent.

Contexte :
{context}"""

prompt = ChatPromptTemplate.from_messages([
    ("system", system_prompt),
    MessagesPlaceholder(variable_name="chat_history", optional=True),
    ("human", "{question}")
])

# Fonction pour formater les documents récupérés
def format_docs(docs):
    formatted = []
    for i, doc in enumerate(docs, 1):
        source = doc.metadata.get("filename", "inconnu")
        formatted.append(f"[Source {i}: {source}]\n{doc.page_content}")
    return "\n\n---\n\n".join(formatted)

# Pipeline RAG avec LCEL
rag_chain = (
    {
        "context": retriever | format_docs,
        "question": RunnablePassthrough(),
        "chat_history": lambda x: []  # Historique vide par défaut
    }
    | prompt
    | llm
    | StrOutputParser()
)

# Utilisation
question = "Quelle est la différence entre Pinecone et Milvus pour un projet RAG ?"
response = rag_chain.invoke(question)
print(response)

Étape 6 : Gestion de l'historique de conversation

Pour un chatbot interactif, il faut maintenir un historique de conversation qui permet au système de comprendre les questions de suivi et les références anaphoriques (pronoms, « le précédent », etc.). Voici comment intégrer la mémoire conversationnelle dans notre pipeline RAG.

from langchain_core.messages import HumanMessage, AIMessage

class RAGChatbot:
    def __init__(self, retriever, llm):
        self.retriever = retriever
        self.llm = llm
        self.chat_history = []

        self.contextualize_prompt = ChatPromptTemplate.from_messages([
            ("system", """Reformule la question de l'utilisateur pour qu'elle soit
            compréhensible de manière autonome, sans le contexte de la conversation.
            Ne réponds PAS à la question, reformule-la uniquement."""),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{question}")
        ])

        self.qa_prompt = ChatPromptTemplate.from_messages([
            ("system", system_prompt),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{question}")
        ])

    def ask(self, question: str) -> str:
        # Reformuler la question si historique existant
        if self.chat_history:
            contextualized = (
                self.contextualize_prompt
                | self.llm
                | StrOutputParser()
            ).invoke({
                "chat_history": self.chat_history,
                "question": question
            })
        else:
            contextualized = question

        # Recherche dans le vectorstore
        docs = self.retriever.invoke(contextualized)
        context = format_docs(docs)

        # Génération de la réponse
        response = (
            self.qa_prompt
            | self.llm
            | StrOutputParser()
        ).invoke({
            "context": context,
            "chat_history": self.chat_history,
            "question": question
        })

        # Mise à jour de l'historique
        self.chat_history.extend([
            HumanMessage(content=question),
            AIMessage(content=response)
        ])

        # Garder uniquement les 10 derniers messages
        if len(self.chat_history) > 20:
            self.chat_history = self.chat_history[-20:]

        return response

# Utilisation
chatbot = RAGChatbot(retriever, llm)

print(chatbot.ask("Quelle base vectorielle recommandes-tu pour un prototype ?"))
print(chatbot.ask("Et pour passer en production ensuite ?"))
print(chatbot.ask("Combien ça coûte ?"))

A retenir : Ce tutoriel couvre les fondamentaux d'un pipeline RAG avec Chroma et LangChain : chargement de documents, chunking intelligent, indexation vectorielle, recherche MMR pour la diversité, construction du pipeline LCEL, et gestion de l'historique conversationnel. Pour la production, ajoutez le monitoring (LangSmith), le caching (Redis), et les tests de qualité (RAGAS).

FAQ : questions fréquentes sur les bases de données vectorielles

Quelle est la différence entre une base de données vectorielle et Elasticsearch ?

Elasticsearch est un moteur de recherche full-text basé sur Apache Lucene, conçu à l'origine pour la recherche par mots-clés (BM25). Bien qu'Elasticsearch ait ajouté le support des vecteurs denses (dense_vector) depuis la version 7.x et une recherche ANN (HNSW) depuis la version 8.x, il reste fondamentalement un moteur de recherche textuel augmenté de capacités vectorielles. Les bases de données vectorielles spécialisées comme Milvus, Qdrant ou Pinecone sont conçues dès le départ pour la recherche vectorielle, offrant généralement de meilleures performances (2-10x en latence et QPS), plus d'algorithmes d'indexation, un meilleur support de la quantification et des fonctionnalités avancées comme les sparse vectors natifs. Cependant, si vous utilisez déjà Elasticsearch et que vos besoins vectoriels sont modérés, les capacités natives d'Elasticsearch 8.x peuvent suffire, évitant l'ajout d'un composant supplémentaire dans votre stack.

Peut-on utiliser une base vectorielle sans modèle d'embedding ?

Techniquement, une base vectorielle stocke et recherche des vecteurs de nombres, quelle que soit leur origine. Les embeddings générés par des modèles de deep learning (OpenAI, Sentence Transformers, CLIP) sont le cas d'usage le plus courant, mais vous pouvez stocker n'importe quel vecteur : des features extraites manuellement, des représentations TF-IDF, des vecteurs de caractéristiques d'images calculés par des algorithmes classiques, ou même des données numériques brutes. Cependant, la puissance de la recherche sémantique repose sur la qualité des embeddings. Des vecteurs non appris (features manuelles) ne captureront pas les relations sémantiques complexes. Pour la grande majorité des cas d'usage modernes, un modèle d'embedding est indispensable pour tirer pleinement parti d'une base vectorielle.

Combien coûte une base vectorielle en production ?

Le coût dépend fortement de la solution choisie, du volume de données et du trafic. Pour les solutions open source self-hosted (Milvus, Qdrant, Weaviate), le coût est celui de l'infrastructure : un serveur avec 64 Go de RAM et 1 To de SSD NVMe (environ 300-500 euros par mois sur un cloud majeur) peut héberger 10-50 millions de vecteurs avec des performances excellentes. Pour les solutions managées, Pinecone serverless facture environ 2 dollars par million de requêtes et 0,33 dollar par Go de stockage, soit environ 25-100 dollars par mois pour un projet de taille moyenne. Zilliz Cloud (Milvus managé) démarre à environ 65 dollars par mois pour un cluster dédié. Il faut également comptabiliser le coût des embeddings : OpenAI facture environ 0,02 dollar par million de tokens pour text-embedding-3-small, soit environ 10-50 dollars pour indexer un million de documents de taille moyenne. Le coût total d'un déploiement production typique (10 millions de vecteurs, 1 000 QPS) se situe entre 200 et 2 000 dollars par mois selon les choix technologiques.

Quelle dimension d'embedding choisir ?

La dimension de l'embedding influence directement la qualité de la recherche, la consommation de ressources et les performances. Les modèles modernes proposent des dimensions allant de 384 (all-MiniLM-L6-v2) à 4096 (certains modèles spécialisés). Le modèle text-embedding-3-small d'OpenAI (1536 dimensions) offre un excellent compromis qualité/coût pour la plupart des cas d'usage. Pour les projets sensibles au coût ou aux performances, text-embedding-3-small avec une réduction de dimension à 512 via Matryoshka embedding offre 95 % de la qualité à un tiers du coût de stockage. Les modèles open source comme BGE-small-en-v1.5 (384 dimensions) sont suffisants pour les cas d'usage simples. En règle générale, commencez avec 768-1536 dimensions et réduisez si les contraintes de performance ou de coût l'exigent.

Comment gérer la mise à jour des embeddings quand le modèle change ?

Le changement de modèle d'embedding est une opération lourde mais parfois nécessaire (nouveau modèle plus performant, correction de biais, changement de fournisseur). Tous les vecteurs doivent être recalculés car les espaces vectoriels de deux modèles différents ne sont pas compatibles entre eux. La stratégie recommandée est la migration blue-green : créez une nouvelle collection avec le nouveau modèle, indexez progressivement tous les documents (en batch pour optimiser les coûts d'API), testez la qualité sur un jeu de requêtes de référence, puis basculez le trafic en production. Conservez l'ancienne collection pendant quelques jours en cas de rollback. Pour les très grands datasets, cette migration peut prendre plusieurs heures voire plusieurs jours et coûter significativement en appels d'API d'embedding. Planifiez ces migrations en dehors des heures de pointe et budgétez le coût des re-embeddings.

Les bases vectorielles remplacent-elles les bases relationnelles ?

Non, les bases vectorielles ne remplacent pas les bases relationnelles. Elles les complètent pour des cas d'usage spécifiques. Les bases relationnelles (PostgreSQL, MySQL) restent supérieures pour les transactions ACID, les jointures complexes, les agrégations, les contraintes d'intégrité et la gestion des données structurées. Les bases vectorielles sont spécialisées dans la recherche par similarité sur des données non structurées transformées en embeddings. L'architecture typique utilise les deux en parallèle : une base relationnelle pour les données métier structurées (utilisateurs, commandes, produits) et une base vectorielle pour la recherche sémantique (contenu, recommandations, RAG). pgvector est un cas intéressant qui combine les deux dans un seul système, mais avec des compromis de performance par rapport aux solutions spécialisées.

Quelle est la différence entre Pinecone et Milvus ?

Pinecone et Milvus représentent deux philosophies opposées. Pinecone est un service cloud propriétaire entièrement managé : aucune infrastructure à gérer, scaling automatique, API simple, mais code source fermé et dépendance totale au fournisseur. Milvus est un projet open source Apache 2.0 auto-hébergeable, offrant un contrôle total sur l'infrastructure, les algorithmes et les données, mais nécessitant une expertise DevOps significative pour le déploiement distribué. En termes de fonctionnalités, Milvus offre plus de choix d'algorithmes d'indexation (HNSW, IVF, DiskANN, ScaNN, GPU), tandis que Pinecone excelle par sa simplicité opérationnelle et son modèle serverless. Pour les entreprises avec des exigences de résidence des données ou de personnalisation avancée, Milvus est préférable. Pour les équipes qui veulent se concentrer sur le produit sans gérer l'infrastructure, Pinecone est le choix naturel. Zilliz Cloud offre le meilleur des deux mondes : le moteur Milvus en version managée.

Comment évaluer la qualité d'un pipeline RAG utilisant une base vectorielle ?

L'évaluation d'un pipeline RAG implique de mesurer à la fois la qualité de la recherche (retrieval) et la qualité de la génération (generation). Pour le retrieval, les métriques clés sont le recall@k (proportion des documents pertinents récupérés), la précision@k (proportion de documents pertinents parmi les k retournés), le MRR (Mean Reciprocal Rank, position du premier résultat pertinent) et le nDCG (normalized Discounted Cumulative Gain, qualité du classement). Pour la génération, on mesure la faithfulness (fidélité de la réponse aux sources), la relevance (pertinence par rapport à la question), et la groundedness (ancrage dans les documents récupérés). Des frameworks comme RAGAS et UpTrain automatisent ces évaluations en utilisant des LLM comme juges. En production, le monitoring des métriques de latence, de recall et de satisfaction utilisateur (feedback explicite ou implicite) est essentiel pour maintenir et améliorer la qualité du système.

Conclusion

Le marché des bases de données vectorielles a atteint un niveau de maturité impressionnant en 2026. Les solutions analysées dans ce comparatif couvrent l'ensemble du spectre des besoins, de la bibliothèque de recherche haute performance (FAISS) au service cloud entièrement managé (Pinecone), en passant par les plateformes open source distribuées (Milvus), les solutions ergonomiques (Chroma, Weaviate) et les extensions de bases existantes (pgvector). Les algorithmes d'indexation — HNSW, IVF, PQ, ScaNN, DiskANN — offrent des compromis variés entre recall, latence, consommation mémoire et scalabilité, permettant d'optimiser finement les déploiements en fonction des contraintes spécifiques.

Le choix de la bonne solution dépend d'un ensemble de facteurs interdépendants : le volume de données, le trafic attendu, les contraintes de latence, le budget, les compétences de l'équipe, les exigences de sécurité et de conformité, et l'intégration avec le stack technologique existant. Il n'existe pas de solution universellement supérieure : Chroma excelle pour le prototypage et les projets Python, Qdrant offre les meilleures performances avec le filtrage le plus riche, Milvus domine pour les déploiements à très grande échelle, Weaviate se distingue par sa recherche hybride et ses modules intégrés, Pinecone élimine toute complexité opérationnelle, pgvector s'intègre naturellement dans les stacks PostgreSQL, FAISS reste imbattable en performance brute, et LanceDB ouvre des perspectives intéressantes pour les cas d'usage multimodaux et embedded.

L'évolution du marché pointe vers plusieurs tendances : la convergence vers la recherche hybride (dense + sparse + structured), l'intégration plus profonde avec les frameworks IA (LangChain, LlamaIndex), l'émergence du serverless comme modèle de déploiement dominant, et l'importance croissante de la sécurité et de la gouvernance des données vectorielles face aux exigences réglementaires. Les développeurs et architectes qui maîtrisent les concepts fondamentaux — embeddings, similarité, algorithmes ANN, compromis recall/latence — seront les mieux placés pour naviguer dans cet écosystème en constante évolution et construire des applications d'IA de nouvelle génération.

Quelle que soit la solution choisie, l'essentiel est de commencer petit, mesurer rigoureusement les performances et la qualité, et itérer. Un prototype Chroma en quelques lignes de Python peut valider un cas d'usage en quelques heures. La migration vers une solution plus robuste (Qdrant, Milvus, Pinecone) pourra se faire progressivement, guidée par les métriques de production et les besoins croissants de l'application. Les bases de données vectorielles ne sont plus une technologie de niche réservée aux spécialistes du machine learning : elles sont devenues un composant fondamental de l'infrastructure logicielle moderne, au même titre que les bases relationnelles, les caches distribués et les files de messages.