Intégrer un chatbot IA dans une application Laravel ou Symfony
Ajouter un chatbot IA à une application PHP existante ne veut pas dire réécrire le backend en Python. Voici une architecture concrète : où vit le LLM, le streaming SSE, le contexte métier, les appels d'outils sûrs, et la défense contre l'injection de prompt.
La plupart des tutoriels sur les chatbots IA supposent un backend Python. En réalité, la majorité des applications métier tournent sur Laravel ou Symfony, et il n'y a aucune raison de les réécrire pour ajouter une fonctionnalité de chat. Le LLM vit derrière une API ; votre backend PHP existant reste le point d'entrée, garde son authentification, et garde le contrôle de chaque action que le chatbot peut déclencher.
Où vit le LLM
Deux options réalistes. Appeler directement l'API d'un fournisseur (OpenAI, Anthropic, Mistral) depuis Laravel ou Symfony via HTTP : le plus simple, aucune infrastructure IA. Ou passer par un service Python dédié (FastAPI) quand la logique de récupération devient complexe : séparation plus nette, un service de plus à opérer.
| Appel direct au fournisseur depuis PHP | Service Python (FastAPI) dédié | |
|---|---|---|
| Mise en place | Un client HTTP et une clé | Un second service à déployer |
| Idéal quand | Chat, injection de contexte légère | RAG, embeddings, pré/post-traitement lourd |
| Latence | Un saut externe | Deux sauts (PHP vers service vers fournisseur) |
| Équipe | PHP uniquement | PHP plus Python |
// app/Services/ChatService.php
final class ChatService
{
public function ask(string $question, array $history = []): string
{
$response = Http::withToken(config('services.anthropic.key'))
->withHeaders(['anthropic-version' => '2026-01-01'])
->post('https://api.anthropic.com/v1/messages', [
'model' => 'claude-sonnet-5',
'max_tokens' => 1024,
'system' => $this->systemPrompt(),
'messages' => [...$history, ['role' => 'user', 'content' => $question]],
]);
return $response->json('content.0.text');
}
}Streamer la réponse plutôt que d'attendre
Un appel LLM prend plusieurs secondes. Attendre la réponse complète avant d'afficher quoi que ce soit dégrade l'expérience ; streamer les tokens au fur et à mesure via Server-Sent Events donne une sensation de réactivité immédiate même si la génération complète prend le même temps.
- ✓Laravel : response()->stream(), avec un flush après chaque chunk reçu du flux du fournisseur.
- ✓Symfony : StreamedResponse, même principe, écrire dans le buffer de sortie au fil de la réception.
- ✓Frontend : consommer le flux avec EventSource ou fetch et un ReadableStream, pas de polling.
// Contrôleur Laravel
return response()->stream(function () {
foreach ($this->chat->stream($question, $history) as $token) {
echo "data: " . json_encode(['token' => $token]) . "\n\n";
ob_flush();
flush();
}
}, 200, ['Content-Type' => 'text/event-stream', 'X-Accel-Buffering' => 'no']);Contexte métier : le vrai travail n'est pas le LLM
Le plus gros de l'effort n'est pas d'appeler le modèle, c'est de lui donner le bon contexte. Injectez les données pertinentes de l'application (les commandes de l'utilisateur courant, le catalogue produit, la documentation interne utile à cette question) dans le prompt. Pour une base de connaissances, ajoutez une recherche vectorielle légère avec pgvector directement dans PostgreSQL, sans service supplémentaire, et récupérez les quelques passages les plus proches avant d'appeler le LLM.
Les appels d'outils, en sécurité
Quand le chatbot doit faire quelque chose (chercher une commande, lancer un retour), exposez ces actions comme des outils que le modèle peut appeler, mais gardez le modèle du côté de la proposition uniquement. Il renvoie un nom d'outil et des arguments ; votre code les valide face aux permissions de l'utilisateur courant et à vos règles métier, puis exécute ou refuse. Le LLM ne touche jamais la base directement.
Ne donnez jamais au LLM un accès direct en écriture à votre base via des function calls non validés. Toute action, surtout destructive, repasse par votre couche métier existante avec sa propre autorisation et sa propre validation. Le LLM propose ; votre code décide.
Se défendre contre l'injection de prompt
Si le chatbot lit du contenu généré par les utilisateurs ou des documents récupérés, traitez tout cela comme non fiable : ça peut contenir des instructions destinées à votre modèle. Gardez le prompt système et le contexte récupéré clairement séparés, ne laissez jamais un texte récupéré modifier les outils autorisés, cadrez chaque appel d'outil à l'utilisateur authentifié côté serveur, et passez les sorties par un contrôle de modération avant de les afficher.
Coût, cache et fallback
- ✓Mettez en cache les réponses aux questions fréquentes ou identiques pour que la même question posée cent fois ne soit pas payée cent fois.
- ✓Ayez toujours un fallback : une page d'aide statique ou un formulaire de contact quand le modèle expire ou échoue.
- ✓Suivez tokens et coût par utilisateur ou tenant, et limitez le débit par utilisateur pour éviter une surprise de facturation à l'échelle.
FAQ
- Faut-il réécrire son backend PHP en Python pour un chatbot IA ?
- Non. Le LLM est derrière une API HTTP que Laravel ou Symfony appelle comme n'importe quel autre service. Votre backend PHP reste le point d'entrée et garde son authentification et ses règles métier. Un service Python dédié n'est intéressant qu'une fois que vous avez du travail lourd de récupération ou d'embedding.
- Comment streamer la réponse d'un LLM en Laravel ?
- Utilisez response()->stream() avec un content type text/event-stream, et faites echo puis flush de chaque token à mesure qu'il arrive du flux du fournisseur. Mettez X-Accel-Buffering à no pour que nginx ne bufferise pas la réponse. Côté frontend, consommez-la avec EventSource.
- Comment donner le contexte métier au chatbot ?
- Injectez les données pertinentes de l'application dans le prompt : les enregistrements de l'utilisateur courant, le catalogue, la documentation interne utile à la question. Pour une base de connaissances, ajoutez une recherche vectorielle avec pgvector dans PostgreSQL et récupérez les passages les plus proches avant l'appel LLM.
- Comment éviter les injections de prompt ?
- Traitez le contenu utilisateur et les documents récupérés comme non fiables. Gardez le prompt système séparé du contexte récupéré, ne laissez jamais un texte récupéré élargir les outils autorisés, cadrez chaque appel d'outil à l'utilisateur authentifié côté serveur, et modérez les sorties avant affichage.
- Quel coût pour un chatbot LLM ?
- Le coût variable est au token : le prompt système, l'historique de conversation et le contexte récupéré en entrée, plus la réponse générée en sortie. Mettre en cache les questions fréquentes et raccourcir l'historique et le contexte sont les leviers qui le gardent stable quand le trafic grandit.
Un chatbot bien intégré n'ajoute qu'une fine couche à une application Laravel ou Symfony existante : un service HTTP, un endpoint de streaming, un peu de contexte métier, et une couche d'outils qui garde votre code aux commandes. Le reste de votre architecture, votre authentification, votre base, vos règles métier, reste inchangé.
Envie d'intégrer l'IA dans votre application ?
Intégration IA & RAG →