Aller au contenu
RAG

Base vectorielle : pgvector, Qdrant et alternatives

Comparaison des bases vectorielles auto-hébergeables pour la Box (filtrage ACL imposé par le moteur, hybride, multi-tenant, licence, exploitation) et recommandation provisoire liée à Q-004.

Hypothèse#rag#vector-db#pgvector#qdrant#permissionsPublié le 16 sept. 2026Mis à jour le 16 sept. 2026Vérifié le 16 sept. 2026À revérifier le 15 déc. 2026

L'essentiel

  • Deux finalistes : pgvector (extension PostgreSQL, licence PostgreSQL) et Qdrant (serveur dédié en Rust, Apache 2.0). Les deux savent filtrer et imposer un filtre côté moteur (RLS pour l'un, JWT payload pour l'autre).
  • Critère qui départage : le comportement du filtre ACL avec l'index HNSW. pgvector documente une perte de rappel en post-filtrage, corrigée par iterative_scan (0.8.0) ; Qdrant intègre le filtre à la traversée du graphe.
  • Critère qui rapproche : PostgreSQL est déjà nécessaire (interface, métadonnées, journal). Une seule base à sauvegarder, à surveiller et à chiffrer est un argument fort pour une Box maintenue à distance.
  • Écartés pour la Box : Chroma (défaut d'Open WebUI, pas de production multi-utilisateur stricte), Milvus (surdimensionné, dépend de MinIO archivé en distribué), Elasticsearch (DLS payante), Weaviate et OpenSearch (viables mais plus lourds), LanceDB (embarqué, pas de barrière moteur).
  • Recommandation provisoire Hypothèse : pgvector pour le POC, avec Qdrant en plan B immédiat si le test de filtrage ACL échoue. Décision dans Q-004.

Ce qu'on demande à la base

  1. Stocker vecteurs, texte et métadonnées de chaque chunk.
  2. Filtrer par dossier_id dans la recherche, sans perte de rappel, et imposer ce filtre indépendamment du code applicatif (permissions).
  3. Recherche hybride (vecteurs + BM25) avec fusion RRF (recherche).
  4. Suppression fiable par document, mise à jour des métadonnées en masse (resynchronisation des ACL).
  5. Sauvegarde, restauration, chiffrement au repos, exploitation par une seule personne.
  6. Licence compatible avec une Box commercialisée.
  7. Empreinte raisonnable sur une machine qui réserve sa mémoire au LLM.

Comparatif

BaseLicenceFiltre dans la rechercheFiltre imposé par le moteurHybride BM25Multi-tenantExploitationSauvegardeSource
pgvector 0.8.xPostgreSQLWHERE ; post-filtrage HNSW documenté ; iterative_scan depuis 0.8.0 ; index partielsRLS PostgreSQL (avec ses avertissements)tsvector natif, RRF en SQL ; ParadeDB non vérifiéschéma / colonne + RLSPostgreSQL standard, déjà présentpg_dump, WAL/PITR, réplication1 3
pgvectorscalePostgreSQLStreamingDiskANN, « Label-Based Filtered Search »idem RLSidemidemextension supplémentaireidem2
Qdrant 1.19Apache 2.0payload intégré à HNSW ; index is_tenantJWT avec claim payload ; clés API lecture seulesparse + dense, RRF natifcollection unique partitionnée par payload (recommandation officielle)service Rust séparé, API REST/gRPCsnapshots par collection4 5 6
Milvus 3.0Apache 2.0filtrage scalaire, partition keyRBAC natif (non consulté en détail)BM25 (doc non consultée)database / collection / partition / partition keylourd en distribué (etcd, MinIO archivé)non consulté7 14
WeaviateBSD-3where ; en hybride, appliqué post-fusionauth API key/OIDC ; pas de filtre imposé par jeton trouvénatif, alpha, Relative Score Fusionun shard par tenant, natifservice Gobackups S3/GCS/filesystem8
Chroma 1.5Apache 2.0where sur métadonnéesauth basique ; OpenFGA possibleBM25/SPLADE depuis nov. 2025tenant/database/collection ; approche naïve « not well suited for production » (communauté)embarqué ou serveurfichiers9
LanceDBApache 2.0préfiltrage par défautaucun (bibliothèque embarquée)natif, RRFpar tableembarquécopie de fichiers10
OpenSearchApache 2.0k-NN avec pré-filtre efficacedocument-level security inclusenatif, normalisation + RRFindex par tenant + DLSJVM, RAM élevéesnapshots12
ElasticsearchElastic / SSPL / AGPL (non vérifié)kNN pre-filterDLS niveau Platinum (payant)retrievers rrf / linearindex ou DLSJVMsnapshots11

Focus pgvector

  • Index : IVFFlat (rapide à construire, rappel moindre) ou HNSW (meilleur rappel, construction plus lente, maintenance_work_mem à dimensionner). L'index doit tenir en mémoire 1.
  • Filtrage : « filtering is applied after the index is scanned » ; avec 10 % de lignes éligibles et ef_search 40, environ 4 résultats au lieu de 40. Trois remèdes : index B-tree sur dossier_id, index HNSW partiels (WHERE dossier_id = …, viable pour quelques dizaines de dossiers, ingérable pour des centaines), et hnsw.iterative_scan = relaxed_order avec hnsw.max_scan_tuples (défaut 20 000) 1.
  • Barrière moteur : Row-Level Security avec un rôle applicatif non superuser, FORCE ROW LEVEL SECURITY, politique sur dossier_id, SET LOCAL app.user_id par transaction. Avertissements officiels : fonctions non LEAKPROOF évaluables avant la politique, conditions de course, contraintes d'intégrité qui contournent RLS, row_security = off pour les sauvegardes 3.
  • Hybride : tsvector avec la configuration french, requête BM25-like via ts_rank_cd (ce n'est pas exactement BM25 : estimation) ou extension ParadeDB (non vérifiée) ; RRF en une CTE.
  • pgvectorscale : à essayer si HNSW + filtre déçoit ; index DiskANN avec recherche filtrée par labels et quantification SBQ ; benchmark éditeur seulement 2 Constructeur.
  • Exploitation : une base pour tout (utilisateurs de l'interface, dossiers, ACL, journal d'accès, vecteurs) ; sauvegardes PostgreSQL standard ; chiffrement du volume ; réplication possible vers un second disque (sauvegardes).

Focus Qdrant

  • Modèle : collections de points (vecteur dense, vecteurs sparse, payload JSON). Filtrage payload intégré au parcours HNSW ; index payload avec is_tenant: true pour regrouper les points d'un même dossier ; option payload_m: 16, m: 0 pour ne pas construire de graphe global quand toutes les requêtes sont filtrées par tenant 5.
  • Barrière moteur : JWT signé par l'application avec claims access (r), collections et payload (filtre imposé sur dossier_id) ; clé API lecture seule pour les consommateurs ; TLS 6.
  • Hybride : vecteurs sparse (BM25 ou bge-m3 sparse) et fusion RRF dans une requête query ; pas d'analyseur français intégré pour BM25 : la tokenisation se fait côté application (estimation).
  • Mémoire : quantification scalaire, binaire ou produit, stockage on-disk ; claim éditeur « up to 97% » de réduction 4 Constructeur.
  • Exploitation : un conteneur supplémentaire, ses snapshots (API), sa surveillance, ses mises à jour. Open WebUI le supporte nativement (VECTOR_DB=qdrant, ENABLE_QDRANT_MULTITENANCY_MODE=True par défaut) 13.

Grille de critères pondérée

Pondérations et notes sont des estimations d'architecture, pas des mesures ; elles seront remplacées par les résultats de l'expérimentation de filtrage ACL. Notes de 1 (faible) à 5 (fort).

CritèrePoidspgvectorQdrantOpenSearchWeaviateChroma
Filtre imposé par le moteur (double barrière)54 (RLS, avec précautions)5 (JWT payload)5 (DLS)21
Rappel de la recherche filtrée (HNSW + ACL)53 (iterative_scan à valider)543 (post-fusion en hybride)2
Recherche hybride française43 (tsvector, RRF à coder)4 (sparse natif)542
Simplicité d'exploitation (une personne, à distance)55 (base déjà présente)3123
Sauvegarde / restauration / chiffrement453332
Empreinte mémoire / CPU sur la machine candidate344134
Licence pour une Box commercialisée455555
Maturité, communauté, intégrations (Open WebUI, LibreChat)355334
Total pondéré (sur 165)13914011410190

Lecture : pgvector et Qdrant sont à égalité pratique ; l'écart tient au rappel filtré, que seul un test tranchera. OpenSearch est techniquement complet mais trop lourd ; Weaviate demande de vérifier le filtrage post-fusion ; Chroma reste un outil de démonstration.

Recommandation provisoire

Dans les deux cas, la base n'est joignable que depuis le service RAG (réseau Docker interne), le compte applicatif n'a que les droits nécessaires, et le journal d'accès est écrit par l'application (permissions).

Questions ouvertes

Ce qu'il reste à tester

Sources

  1. 1pgvector — README (filtrage, HNSW, iterative scan 0.8.0)GitHubFiabilité hautepgvector · publié v0.8.6 (README) ; 0.8.0 annoncé sur postgresql.org · consulté le 16 sept. 2026 · fiche source
  2. 2pgvectorscale — README (StreamingDiskANN, filtered search)GitHubFiabilité moyenneTimescale · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  3. 3PostgreSQL — Row Security Policies (RLS)Documentation officielleFiabilité hautePostgreSQL · publié documentation courante · consulté le 16 sept. 2026 · fiche source
  4. 4Qdrant — README et releases (Apache 2.0, v1.19.1)GitHubFiabilité hauteQdrant · publié v1.19.1, 04/09/2026 · consulté le 16 sept. 2026 · fiche source
  5. 5Qdrant — Multitenancy (payload partitioning, is_tenant)Documentation officielleFiabilité hauteQdrant · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  6. 6Qdrant — Security (API key, TLS, JWT avec claim payload)Documentation officielleFiabilité hauteQdrant · publié lu le 16/09/2026 ; RBAC JWT introduit en 1.9.0 (blog du 24/04/2024) · consulté le 16 sept. 2026 · fiche source
  7. 7Milvus — stratégies multi-tenantDocumentation officielleFiabilité moyenneMilvus · publié v3.0.0 (29/07/2026 selon Wikipedia, à confirmer) · consulté le 16 sept. 2026 · fiche source
  8. 8Weaviate — multi-tenancy native et recherche hybrideDocumentation officielleFiabilité hauteWeaviate · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  9. 9Chroma — multi-tenancy (Cookbook communautaire)ForumFiabilité moyenneChroma Cookbook (Amikos) · publié Chroma v1.5.8, 16/04/2026 · consulté le 16 sept. 2026 · fiche source
  10. 11Elasticsearch — Document Level Security et hybrideDocumentation officielleFiabilité hauteElastic (et Instaclustr pour le niveau de licence) · publié lu le 16/09/2026 · consulté le 16 sept. 2026 · fiche source
  11. 13Open WebUI — variables d'environnement (docs + config.py)Documentation officielleFiabilité hauteOpen WebUI · publié lu le 16/09/2026 (main) · consulté le 16 sept. 2026 · fiche source
  12. 14MinIO — dépôt archivé (25/04/2026)GitHubFiabilité hauteMinIO · publié archivé le 25/04/2026 · consulté le 16 sept. 2026 · fiche source
content/docs/rag/base-vectorielle.md1542 mots