0. Transition : où se situe le RAG ?
Reprenons l'exemple fil rouge : un chatbot intelligent pour un centre de formation. Il combine 4 couches technologiques. Cliquez sur chacune.
Classifier la question : inscription, prix, durée ou programme. Un modèle simple suffit souvent ici.
Un modèle de langage entraîné comprend le sens de la question et produit son embedding.
Votre code stocke les documents, compare les vecteurs (similarité cosinus) et récupère les passages utiles.
Les passages retrouvés et la question sont envoyés à un modèle génératif, qui rédige la réponse finale.
1. Le chatbot PHP « sans IA générative »
Imaginons une base de données sur une formation Laravel :
$documents = [
"La formation Laravel dure 40 heures.",
"La formation comprend PHP, MVC, Eloquent et API REST.",
"Le prix de la formation est de 500 DT."
];
L'utilisateur demande : « Combien coûte la formation Laravel ? ». PHP peut chercher une correspondance et afficher une phrase déjà écrite à l'avance.
2. Comment fonctionne le RAG : le pipeline en 5 étapes
RAG = Retrieval-Augmented Generation, « génération augmentée de recherche ». On ajoute deux étapes autour du LLM pour qu'il connaisse vos documents.
- 📄Documents
PDF, Word, fichiers texte, table MySQL : la matière brute de votre base de connaissances. - 🔢Embeddings
Un modèle IA transforme chaque texte en vecteur (liste de nombres) qui représente son sens. - 🔍Recherche sémantique
PHP compare le vecteur de la question aux vecteurs stockés et récupère les passages les plus proches. - 🧠IA générative (LLM)
Le modèle reçoit la question et les passages retrouvés, puis rédige une réponse. - ✅Réponse à l'utilisateur
Une phrase naturelle, fondée sur vos documents, pas sur une réponse toute faite.
3.A Transformer un texte en vecteur (embedding)
Le vecteur n'est pas inventé par PHP : il est calculé par un modèle IA, via une API.
$texte = "La formation Laravel dure 40 heures."; // Le modèle IA transforme le texte // en une liste de nombres (vecteur). $embedding = getEmbedding($texte); // Exemple pédagogique simplifié du résultat : // $embedding = [0.25, 0.81, -0.12, 0.44]; // En pratique : des centaines ou des milliers de valeurs.
Voir un embedding se calculer à essayer
$texte = "La formation Laravel dure 40 heures."; $embedding = getEmbedding($texte);
Ici, 4 valeurs fictives pour l'exemple. Un vrai modèle en produit des centaines.
On stocke ensuite le texte et son vecteur dans MySQL, une seule fois par document :
CREATE TABLE documents (
id INT AUTO_INCREMENT PRIMARY KEY,
contenu TEXT,
embedding TEXT -- vecteur enregistré en JSON, ex: [0.25,0.81,-0.12,0.44]
);
3.B Rechercher les passages pertinents avec PHP
On transforme la question en vecteur, puis on la compare à chaque vecteur enregistré grâce à la similarité cosinus.
$question = "Quelle est la durée du cours Laravel ?";
$vQuestion = getEmbedding($question);
foreach ($documents as $document) {
$score = cosineSimilarity($vQuestion, $document['embedding']);
if ($score > 0.75) {
echo $document['contenu'];
}
}
getEmbedding() et cosineSimilarity() sont des fonctions à implémenter (ou à connecter à une API d'embedding). Le seuil 0.75 est illustratif : à ajuster selon le modèle et vos données.Le calcul de cosineSimilarity() en PHP :
function cosineSimilarity(array $a, array $b): float {
$dot = $normA = $normB = 0.0;
foreach ($a as $i => $x) {
$dot += $x * $b[$i];
$normA += $x * $x;
$normB += $b[$i] * $b[$i];
}
return $dot / (sqrt($normA) * sqrt($normB));
}
Comparer la question aux 3 documents à essayer
Score > 0.75 (barre verte) : le passage est retenu et envoyé au LLM à l'étape suivante.
3.C Générer une réponse avec le modèle IA
Une fois les passages retrouvés, on les transmet au modèle génératif avec la question, dans un seul prompt :
$context = " La formation Laravel dure 40 heures. Elle comprend PHP, MVC, Eloquent et API REST. "; // La fonction envoie le contexte et la question // à une API de génération de texte. $reponse = generateAnswer($question, $context); echo $reponse; // "La formation Laravel dure 40 heures. Elle couvre // PHP, MVC, Eloquent et les API REST."
generateAnswer() représente un appel à une API de génération de texte (le LLM), pas une fonction PHP native. Voici à quoi elle peut ressembler avec l'API Claude :function generateAnswer(string $question, string $context): string {
$prompt = "Contexte :\n{$context}\n\nQuestion : {$question}\n"
. "Réponds uniquement à partir du contexte ci-dessus.";
$ch = curl_init('https://api.anthropic.com/v1/messages');
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => [
'content-type: application/json',
'x-api-key: ' . getenv('API_KEY'),
'anthropic-version: 2023-06-01'
],
CURLOPT_POSTFIELDS => json_encode([
'model' => 'claude-sonnet-5',
'max_tokens' => 300,
'messages' => [['role' => 'user', 'content' => $prompt]]
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true
]);
$data = json_decode(curl_exec($ch), true);
return $data['content'][0]['text'];
}
generateAnswer() côté serveur, avec la clé dans une variable d'environnement.4. Démo complète : posez une question à essayer
Ce mini-simulateur enchaîne les 5 étapes du pipeline avec les 3 documents Laravel.
5. Différence à retenir
| Technologie | Rôle | Exemple |
|---|---|---|
| PHP | Logique de l'application | Recherche dans MySQL |
| Embedding | Représentation numérique du texte | Question ➜ vecteur |
| Similarité cosinus | Comparaison des vecteurs | Trouver les passages proches |
| LLM | Génération de texte | Formuler la réponse |
| RAG | Combinaison de ces étapes | Chatbot qui répond à partir de documents |