Tutoriel

Statut éditorial : En attente de relecture

Construire une recherche sémantique avec pgvector et Python

Stocker des embeddings dans PostgreSQL, créer un index vectoriel et interroger les documents proches avec filtres métier.

Classification du contenu

Types

  • RAG et recherche vectorielle
Niveau
Intermédiaire
Publié le
24 août 2026
Dernière relecture
Relecture en attente
Prochaine vérification
24 novembre 2026

pgvector ajoute les vecteurs à PostgreSQL. Vous conservez transactions, filtres SQL et sauvegardes existantes, tout en ajoutant une recherche par similarité.

Préparer la base

~~~sql CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents ( id bigserial PRIMARY KEY, tenant_id uuid NOT NULL, title text NOT NULL, content text NOT NULL, embedding vector(384) NOT NULL, created_at timestamptz NOT NULL DEFAULT now() ); ~~~

La dimension 384 doit correspondre exactement au modèle d’embeddings choisi. Un changement de modèle nécessite généralement une nouvelle colonne ou table et une réindexation.

Insérer depuis Python

~~~bash pip install -U psycopg[binary] pgvector sentence-transformers ~~~

~~~python import os import psycopg from pgvector.psycopg import register_vector from sentence_transformers import SentenceTransformer

model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')

with psycopg.connect(os.environ['DATABASE_URL']) as conn: register_vector(conn) text = 'PostgreSQL peut stocker des vecteurs avec pgvector.' embedding = model.encode(text, normalize_embeddings=True) conn.execute( 'INSERT INTO documents (tenant_id, title, content, embedding) VALUES (%s, %s, %s, %s)', (tenant_id, 'Introduction', text, embedding), ) ~~~

Utilisez toujours des paramètres SQL. Ne concaténez jamais le texte ou l’identifiant de tenant.

Rechercher

~~~python query = model.encode('base de données vectorielle', normalize_embeddings=True) rows = conn.execute( '''SELECT id, title, content, 1 - (embedding <=> %s) AS score FROM documents WHERE tenant_id = %s ORDER BY embedding <=> %s LIMIT 5''', (query, tenant_id, query), ).fetchall() ~~~

L’opérateur <=> calcule la distance cosinus. Le filtre tenant est une règle d’accès, pas un simple filtre de pertinence ; appliquez aussi Row Level Security si votre architecture l’exige.

Ajouter un index

~~~sql CREATE INDEX documents_embedding_hnsw ON documents USING hnsw (embedding vector_cosine_ops);

CREATE INDEX documents_tenant_id_idx ON documents (tenant_id); ~~~

Mesurez recall et latence sur vos données. Un index approximatif accélère la recherche mais ses paramètres doivent être évalués avec la sélectivité des filtres.

Production

Traitez l’embedding en tâche asynchrone, stockez modèle et version, surveillez les lignes sans vecteur et utilisez des migrations progressives. Sauvegardez PostgreSQL comme d’habitude et testez la restauration avec l’extension installée.

FAQ

pgvector remplace-t-il une base vectorielle dédiée ?

Pas toujours. Il est très pertinent lorsque les données et filtres sont déjà dans PostgreSQL. Testez volume, débit et exigences de réplication.

Peut-on mélanger plusieurs modèles ?

Pas dans le même espace de comparaison. Séparez les colonnes ou collections et conservez leur version.

Sources utilisées