RAG en production avec Supabase pgvector : le guide complet 2026
De l'embedding au reranking : tout pour bâtir un RAG production-ready avec Supabase, pgvector et un LLM moderne.
- Tutoriel pour construire un système RAG en production avec Supabase et pgvector.
- Stack : Supabase (pgvector) + OpenAI ada-3 (embeddings) + Claude Sonnet 4.7 (génération).
- Coût mensuel estimé : 50 à 500 € selon le volume.
- Code complet TypeScript fourni, déployable sur Vercel en quelques heures.
RAG est en 2026 la brique IA d entreprise la plus rentable. Pour quelques heures de mise en place, vous obtenez un assistant qui hallucine 10× moins.
Si vous voulez faire répondre Claude ou GPT précisément sur vos propres documents (manuels produit, base de connaissances, jurisprudence interne), vous avez besoin d un système RAG. Voici comment en construire un en production avec une stack moderne et abordable.
Architecture combinant recherche vectorielle dans une base documentaire et génération par LLM. L IA répond uniquement en s appuyant sur vos sources, avec citations. Concept popularisé par un papier Meta en 2020, devenu le standard entreprise en 2026.
Plateforme open source créée en 2020, alternative à Firebase. Construit sur PostgreSQL avec API auto-générée. Offre une extension pgvector qui transforme PostgreSQL en base vectorielle performante. Free tier généreux : 500 MB DB + 1 GB stockage + 50k requêtes API.
Configurer la base vectorielle
create extension vector;create table documents (
id bigserial primary key,
content text,
metadata jsonb,
embedding vector(1536)
);
create index on documents using ivfflat (embedding vector_cosine_ops);
Le nombre 1536 correspond à la dimension des embeddings OpenAI text-embedding-3-small. Pour Mistral Embed : 1024. Pour Cohere v4 : 1024. Toujours faire correspondre la dimension de la table avec celle de votre modèle d embedding.
Le pipeline d ingestion
import { createClient } from '@supabase/supabase-js';
import OpenAI from 'openai';
const supabase = createClient(URL, KEY);
const openai = new OpenAI();
async function ingest(text: string, source: string) {
const chunks = chunkText(text, 1000, 100);
for (const chunk of chunks) {
const { data: emb } = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: chunk,
});
await supabase.from('documents').insert({
content: chunk,
metadata: { source },
embedding: emb.data[0].embedding,
});
}
}
Construire la requête de retrieval
create or replace function match_documents (
query_embedding vector(1536),
match_count int default 5
) returns table (
id bigint,
content text,
similarity float
) language sql as $$
select id, content, 1 - (embedding <=> query_embedding) as similarity
from documents
order by embedding <=> query_embedding
limit match_count;
$$;
L opérateur <=> de pgvector calcule la distance cosinus entre deux vecteurs. C est le cœur mathématique du retrieval moderne.
Connecter le LLM
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
async function ask(question: string) {
// 1. Embedding de la question
const { data: emb } = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: question,
});
// 2. Retrieval des chunks pertinents
const { data: chunks } = await supabase.rpc('match_documents', {
query_embedding: emb.data[0].embedding,
match_count: 5,
});
// 3. Construction du prompt
const context = chunks.map(c => c.content).join('\n\n');
const prompt = `Réponds uniquement à partir du contexte suivant. Cite tes sources.
<context>
${context}
</context>
Question: ${question}`;
// 4. Appel Claude
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-7',
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
});
return response.content[0].text;
}
Estimation des coûts
| Composant | Free tier | Production légère | Production forte |
|---|---|---|---|
| Supabase | 0 € | 25 €/mois | 599 €/mois |
| OpenAI embeddings | ~5 €/mois | 20 €/mois | 100 €/mois |
| Claude API | ~30 €/mois | 100 €/mois | 1000 €/mois |
| Total | ~35 € | ~145 € | ~1700 € |
Les 3 pièges à éviter
1. Mauvais découpage : couper au milieu d une phrase ruine la pertinence. Toujours découper sur les paragraphes ou phrases.
2. Pas de "réponds uniquement à partir du contexte" : sans cette consigne, Claude redevient généraliste et hallucine.
3. Top-K trop élevé : 5 chunks suffisent. Plus = bruit + coût inutile.
- Supabase AI documentation
- pgvector sur GitHub
- OpenAI Embeddings docs
- Anthropic API docs
- Lewis et al., "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", Meta AI 2020
Questions fréquentes
- pgvector tient-il à l'échelle ?
- Oui, jusqu'à plusieurs millions de chunks sans problème, à condition d'utiliser l'index HNSW. Au-delà de 100M chunks, des solutions dédiées comme Pinecone ou Weaviate peuvent devenir pertinentes, mais pour 99% des cas d'usage, pgvector est largement suffisant.
- Faut-il vraiment un reranker ?
- Quasi-toujours oui. Le reranker apporte +30% de précision en moyenne pour ~200ms de latence supplémentaire et 0,002$ par requête. C'est le meilleur ROI de toute la chaîne RAG. Skip uniquement pour des prototypes ou des cas ultra-simples.
- Comment gérer les documents multilingues ?
- Deux approches : (1) un embedder multilingue (Voyage-3, Cohere Embed v3 supportent 100+ langues) sur tous les contenus, ou (2) un embedder par langue avec routing au moment de la query. La première est plus simple, la seconde donne légèrement de meilleurs résultats sur des langues spécifiques (FR avec bge-large-fr par exemple).
- Quel modèle de génération utiliser ?
- Pour la majorité des cas, Claude Sonnet 4.7 ou Mistral Large 3 offrent le meilleur rapport qualité/prix. Pour des cas où la précision est critique (médical, juridique), Claude Opus 4.7 vaut le surcoût. Pour le low-cost massif, Llama 5 70B via Together est excellent.
