Construire un chatbot RAG avec Supabase pgvector et Next.js

Les grands modèles de langage sont impressionnants, mais ils ont une limitation critique : ils ne connaissent que ce sur quoi ils ont été entraînés. Et si vous vouliez un assistant IA qui comprend votre documentation, vos produits ou les connaissances de votre entreprise ?
C'est là que le RAG (Retrieval-Augmented Generation) entre en jeu. Dans ce tutoriel, vous construirez un chatbot capable de répondre aux questions en utilisant vos propres données en combinant l'extension pgvector de Supabase avec les APIs d'OpenAI.
Ce que vous allez construire
À la fin de ce tutoriel, vous aurez :
- Une application Next.js avec une interface de chat
- Une base de données Supabase stockant vos documents sous forme d'embeddings vectoriels
- Une recherche sémantique qui trouve le contenu pertinent basé sur le sens
- Un chatbot alimenté par RAG qui répond aux questions en utilisant vos données
Prérequis
Avant de commencer, assurez-vous d'avoir :
- Node.js 18+ installé
- Un compte Supabase (le tier gratuit fonctionne)
- Une clé API OpenAI avec accès aux embeddings et aux modèles de chat
- Des connaissances de base en React et TypeScript
- Une familiarité avec Next.js App Router
Comprendre l'architecture
Avant de plonger dans le code, comprenons comment le RAG fonctionne :
Question → Embed Question → Rechercher docs similaires → Augmenter prompt → Réponse LLM
↓ ↓ ↓ ↓ ↓
"Qu'est-ce que X?" [0.1, 0.2...] Trouver top 5 docs Ajouter contexte Réponse !
- L'utilisateur pose une question en langage naturel
- Embed la question en un vecteur (tableau de nombres)
- Recherche sémantique trouve les documents avec des vecteurs similaires
- Augmenter le prompt en ajoutant les documents récupérés comme contexte
- Le LLM génère une réponse basée sur le contexte
La magie est à l'étape 3 : au lieu de faire correspondre des mots-clés, nous trouvons des documents qui sont sémantiquement similaires — même s'ils ne partagent pas les mêmes mots.
Étape 1 : Configuration du projet
Créez un nouveau projet Next.js avec TypeScript :
npx create-next-app@latest rag-chatbot --typescript --tailwind --app --src-dir
cd rag-chatbotInstallez les dépendances requises :
npm install @supabase/supabase-js openai aiCréez un fichier .env.local avec vos identifiants :
NEXT_PUBLIC_SUPABASE_URL=votre-url-supabase
NEXT_PUBLIC_SUPABASE_ANON_KEY=votre-cle-anon
SUPABASE_SERVICE_ROLE_KEY=votre-cle-service-role
OPENAI_API_KEY=votre-cle-api-openaiÉtape 2 : Configurer Supabase avec pgvector
Allez dans votre tableau de bord Supabase et ouvrez l'Éditeur SQL. Exécutez ce qui suit pour activer l'extension pgvector :
-- Activer l'extension pgvector
create extension if not exists vector with schema extensions;Maintenant créez une table pour stocker vos documents avec leurs embeddings :
-- Créer la table documents
create table documents (
id bigint primary key generated always as identity,
content text not null,
metadata jsonb,
embedding extensions.vector(1536)
);
-- Activer Row Level Security
alter table documents enable row level security;
-- Créer une politique pour la lecture
create policy "Autoriser l'accès en lecture public"
on documents for select
using (true);
-- Créer un index pour une recherche de similarité plus rapide
create index on documents
using hnsw (embedding vector_cosine_ops);Étape 3 : Créer la fonction d'embedding
Créez un nouveau fichier src/lib/embeddings.ts :
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export async function generateEmbedding(text: string): Promise<number[]> {
const response = await openai.embeddings.create({
model: 'text-embedding-3-small',
input: text,
});
return response.data[0].embedding;
}Étape 4 : Construire l'API d'ingestion de documents
Créez src/app/api/ingest/route.ts pour ajouter des documents à votre base de connaissances :
import { createClient } from '@supabase/supabase-js';
import { generateEmbeddings } from '@/lib/embeddings';
import { NextResponse } from 'next/server';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
export async function POST(request: Request) {
try {
const { documents } = await request.json();
// Générer les embeddings pour tous les documents
const contents = documents.map((doc) => doc.content);
const embeddings = await generateEmbeddings(contents);
// Préparer les données pour l'insertion
const rows = documents.map((doc, index) => ({
content: doc.content,
metadata: doc.metadata || {},
embedding: embeddings[index],
}));
// Insérer dans Supabase
const { data, error } = await supabase
.from('documents')
.insert(rows)
.select('id');
if (error) throw error;
return NextResponse.json({
success: true,
inserted: data.length,
});
} catch (error) {
console.error('Erreur d\'ingestion:', error);
return NextResponse.json(
{ error: 'Échec de l\'ingestion des documents' },
{ status: 500 }
);
}
}Étape 5 : Créer la fonction de recherche sémantique
Créez src/lib/search.ts pour trouver les documents pertinents :
import { createClient } from '@supabase/supabase-js';
import { generateEmbedding } from './embeddings';
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
);
export async function semanticSearch(
query: string,
topK: number = 5,
threshold: number = 0.5
) {
// Générer l'embedding pour la requête
const queryEmbedding = await generateEmbedding(query);
// Appeler la fonction RPC de recherche de similarité
const { data, error } = await supabase.rpc('match_documents', {
query_embedding: queryEmbedding,
match_threshold: threshold,
match_count: topK,
});
if (error) throw error;
return data;
}Étape 6 : Construire l'API de chat RAG
Créez src/app/api/chat/route.ts :
import OpenAI from 'openai';
import { semanticSearch } from '@/lib/search';
import { NextResponse } from 'next/server';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
export async function POST(request: Request) {
try {
const { message, conversationHistory = [] } = await request.json();
// Étape 1 : Rechercher les documents pertinents
const relevantDocs = await semanticSearch(message, 5, 0.5);
// Étape 2 : Construire le contexte
const context = relevantDocs
.map((doc, i) => `[Document ${i + 1}]\n${doc.content}`)
.join('\n\n');
// Étape 3 : Créer le prompt augmenté
const systemPrompt = `Vous êtes un assistant utile qui répond aux questions basées sur le contexte fourni.
CONTEXTE:
${context || 'Aucun document pertinent trouvé.'}
INSTRUCTIONS:
- Répondez à la question de l'utilisateur basé sur le contexte ci-dessus
- Si le contexte ne contient pas d'informations pertinentes, dites-le
- Soyez concis mais complet
- Citez les documents que vous référencez`;
// Étape 4 : Générer la réponse
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{ role: 'system', content: systemPrompt },
...conversationHistory,
{ role: 'user', content: message },
],
temperature: 0.7,
max_tokens: 1000,
});
return NextResponse.json({
response: completion.choices[0].message.content,
sources: relevantDocs.map((doc) => ({
id: doc.id,
preview: doc.content.slice(0, 200) + '...',
similarity: doc.similarity,
})),
});
} catch (error) {
console.error('Erreur chat:', error);
return NextResponse.json(
{ error: 'Échec du traitement du chat' },
{ status: 500 }
);
}
}Conclusion
Vous avez construit un chatbot alimenté par RAG qui peut répondre aux questions en utilisant vos propres données. La combinaison de l'extension pgvector de Supabase et des APIs d'OpenAI fournit une base puissante et évolutive pour les applications IA.
Les points clés à retenir :
- Les embeddings vectoriels permettent une recherche sémantique au-delà de la correspondance de mots-clés
- pgvector apporte des capacités de recherche vectorielle à PostgreSQL
- Le RAG ancre les réponses du LLM dans vos données réelles
- Supabase fournit un backend complet avec une configuration minimale
Ressources :
Discutez de votre projet avec nous
Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.
Trouvons les meilleures solutions pour vos besoins.
Articles connexes

Guide d'Integration de Chatbot IA : Construire des Interfaces Conversationnelles Intelligentes
Un guide complet pour integrer des chatbots IA dans vos applications en utilisant OpenAI, Anthropic Claude et ElevenLabs. Apprenez a construire des chatbots textuels et vocaux avec Next.js.

Hub de Tutoriels AI SDK : Votre Guide Complet pour Construire des Applications IA
Votre guide complet des SDKs et outils IA. Trouvez des tutoriels organises par difficulte couvrant Vercel AI SDK, ModelFusion, OpenAI, Anthropic et plus.

Construire un Outil d'Analyse SQL Alimente par l'IA
Guide etape par etape pour construire une application alimentee par l'IA pour l'analyse SQL en langage naturel.