Supabase Vector et pgvector : Recherche Sémantique et IA dans PostgreSQL

Supabase Vector intègre l’extension PostgreSQL pgvector pour stocker et interroger des embeddings vectoriels. C’est la solution idéale pour construire des moteurs de recherche sémantique, des chatbots RAG (Retrieval-Augmented Generation) et des systèmes de recommandation.

Pour les fondations, consultez notre guide complet Supabase. Pour structurer votre table de documents, voir créer et structurer sa base de données Supabase. Pour les fonctions de recherche, voir SQL, triggers et fonctions Supabase. Pour déployer vos Edge Functions d’indexation, voir Edge Functions Supabase. Pour la connexion IA via MCP, voir Supabase MCP.

Qu’est-ce qu’un Embedding Vectoriel ?

Un embedding est une représentation numérique d’un texte, image ou autre donnée sous forme de vecteur (tableau de flottants). Des textes sémantiquement proches ont des vecteurs proches dans l’espace vectoriel.

"Supabase est une alternative à Firebase"
→ [0.23, -0.45, 0.67, 0.12, ...] (1536 dimensions pour OpenAI)

"Supabase remplace Firebase"
→ [0.24, -0.43, 0.65, 0.13, ...] (très proche !)

"La recette de la tarte aux pommes"
→ [-0.56, 0.89, -0.23, 0.45, ...] (très différent)

Activer pgvector dans Supabase

-- Activer l'extension pgvector
CREATE EXTENSION IF NOT EXISTS vector;

-- Créer une table avec colonne vectorielle
CREATE TABLE documents (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  content TEXT NOT NULL,
  metadata JSONB,
  embedding vector(1536), -- 1536 dimensions pour OpenAI text-embedding-ada-002
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Index HNSW (recommandé : plus rapide pour la recherche)
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

Générer des Embeddings avec OpenAI

import OpenAI from 'openai'
import { createClient } from '@supabase/supabase-js'

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
const supabase = createClient(URL, SERVICE_ROLE_KEY)

async function generateEmbedding(text: string): Promise<number[]> {
  const response = await openai.embeddings.create({
    model: 'text-embedding-ada-002',
    input: text.replace(/\n/g, ' ')
  })
  return response.data[0].embedding
}

// Indexer un document
async function indexDocument(content: string, metadata = {}) {
  const embedding = await generateEmbedding(content)
  
  const { data, error } = await supabase
    .from('documents')
    .insert({ content, metadata, embedding })
    .select()
  
  return { data, error }
}

Recherche Sémantique

-- Fonction SQL de recherche vectorielle
CREATE OR REPLACE FUNCTION match_documents(
  query_embedding vector(1536),
  match_threshold float DEFAULT 0.7,
  match_count int DEFAULT 10
)
RETURNS TABLE (
  id UUID,
  content TEXT,
  metadata JSONB,
  similarity float
)
LANGUAGE sql STABLE
AS $$
  SELECT
    id,
    content,
    metadata,
    1 - (embedding <=> query_embedding) AS similarity
  FROM documents
  WHERE 1 - (embedding <=> query_embedding) > match_threshold
  ORDER BY embedding <=> query_embedding
  LIMIT match_count;
$$;
// Côté JavaScript
async function semanticSearch(query: string, threshold = 0.7, limit = 10) {
  const queryEmbedding = await generateEmbedding(query)
  
  const { data, error } = await supabase.rpc('match_documents', {
    query_embedding: queryEmbedding,
    match_threshold: threshold,
    match_count: limit
  })
  
  return { data, error }
}

RAG : Chatbot avec Contexte

async function ragChat(question: string) {
  // 1. Trouver les documents pertinents
  const { data: relevantDocs } = await semanticSearch(question, 0.75, 5)
  
  // 2. Construire le contexte
  const context = relevantDocs
    ?.map(doc => doc.content)
    .join('\n\n---\n\n')
  
  // 3. Envoyer au LLM avec le contexte
  const response = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [
      {
        role: 'system',
        content: `Tu es un assistant. Réponds en te basant UNIQUEMENT sur le contexte.
        
        Contexte:
        ${context}`
      },
      { role: 'user', content: question }
    ],
    temperature: 0.2
  })
  
  return {
    answer: response.choices[0].message.content,
    sources: relevantDocs?.map(d => d.metadata)
  }
}

Supabase AI + vecs (Python)

pip install vecs openai

import vecs

vx = vecs.create_client("postgresql://postgres:password@db.[ref].supabase.co:5432/postgres")
docs = vx.get_or_create_collection(name="documents", dimension=1536)

docs.upsert(
  records=[
    ("doc-1", [0.1, 0.2, ...], {"title": "Introduction"}),
    ("doc-2", [0.3, 0.4, ...], {"title": "Guide avancé"}),
  ]
)

docs.create_index()

results = docs.query(
  data=[0.15, 0.25, ...],
  limit=5,
  include_metadata=True
)

👉 Articles du guide Supabase

Cet article fait partie du Guide Complet Supabase 2026. Retrouvez les autres articles :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *