Un agent Learning (Russell & Norvig) qui améliore ses réponses support client par une boucle de feedback automatique. Chaque ticket traité renforce ou corrige les instructions internes, la mémoire épisodique retient les succès passés, et le routage multi-LLM apprend quel fournisseur est le meilleur pour chaque type de problème. Docker Compose up en 30s.
Formats d'intégration : API REST, Webhook (Zendesk/Intercom compatible), Dashboard temps réel d'apprentissage.
flowchart TD
subgraph "Entrée"
POST[POST /api/p5/respond<br/>ticket + catégorie]
end
subgraph "1. Routing"
ROUTE{Routing<br/>Multi-LLM}
ROUTE -->|poids catégorie| GEMINI[Gemini 2.5 Flash]
ROUTE -->|poids catégorie| OPENAI[OpenAI GPT-4o-mini]
end
subgraph "2. Performance Element"
MEMO[Mémoire<br/>Épisodique]
INSTR[Sélection<br/>d'instructions]
GEN[Génération<br/>de réponse]
MEMO -->|épisodes similaires| GEN
INSTR --> GEN
end
subgraph "3. Critic"
CRITIC[OpenAI<br/>évalue 3 critères]
end
subgraph "4. Learning Element"
LEARN[Ajustement<br/>poids instructions]
PROV[Ajustement<br/>poids providers]
end
subgraph "5. Problem Generator"
PGEN[Nouvelle<br/>instruction si<br/>score < seuil]
end
subgraph "Stockage"
DB[(SQLite /<br/>PostgreSQL)]
HIST[(Prompt<br/>History)]
EPISODES[(Épisodes<br/>Memory)]
end
POST --> ROUTE
GEMINI --> GEN
OPENAI --> GEN
GEN -->|réponse| CRITIC
CRITIC -->|score + justifications| LEARN
CRITIC -->|score| PROV
LEARN -->|score < seuil| PGEN
PGEN -->|nouvelle instruction| DB
LEARN --> DB
PROV --> DB
GEN --> EPISODES
CRITIC --> HIST
curl -X POST http://localhost:8000/api/p5/respond \
-H "Content-Type: application/json" \
-d '{
"title": "Problème de connexion",
"text": "Je n'arrive plus à me connecter à mon compte depuis hier",
"category": "technical"
}'Le système apprend par catégorie quel provider donne les meilleurs résultats :
| Catégorie | Poids Gemini | Poids OpenAI | Appris par |
|---|---|---|---|
technical |
1.000 | 1.000 | Score après chaque réponse |
emotional |
1.000 | 1.000 | Score après chaque réponse |
general |
1.000 | 1.000 | Score après chaque réponse |
Les poids évoluent à chaque feedback : un provider qui score +4/5 voit son poids augmenter pour cette catégorie.
L'assembleur de prompt construit dynamiquement :
Tu es un agent de support client expert.
Règles à suivre :
1. Commence par accuser réception du problème
2. Utilise un ton chaleureux et humain
3. Structure ta réponse avec des étapes numérotées
Exemples de réponses qui ont bien fonctionné (mémoire épisodique) :
--- Déjà répondu (score: 4.2/5) ---
Client: [ticket similaire du passé]
Réponse: [réponse qui avait bien marché]
---
Le Critic note chaque réponse sur 3 critères de 1 à 5 :
{
"pertinence": { "score": 4, "justification": "La réponse adresse directement le problème de connexion" },
"ton": { "score": 3, "justification": "Correct mais pourrait être plus chaleureux" },
"completude": { "score": 2, "justification": "Manque les étapes concrètes pour réinitialiser" }
}Règle absolue : le Critic est sévère (moyenne < 3.0/5). Il doit trouver des défauts pour créer la variance nécessaire à l'apprentissage.
Chaque instruction utilisée dans la réponse voit son poids ajusté :
poids_nouveau = poids_ancien + (score - 3.0) × learning_rate
| Exemple d'instruction | Poids initial | Après 5 epochs | Usage |
|---|---|---|---|
| "Commence par accuser réception" | 1.00 | 1.42 | 5 |
| "Utilise un ton chaleureux" | 1.00 | 1.38 | 5 |
| "Structure avec des puces" | 1.00 | 0.82 | 3 |
| "Donne des délais précis" | 1.00 | 1.15 | 4 |
Les instructions les plus efficaces sont sélectionnées plus souvent (sélection proportionnelle pondérée).
Chaque réponse avec son score est stockée dans la mémoire épisodique (embedding Gemini text-embedding-004). Avant de répondre à un nouveau ticket, l'agent cherche les épisodes similaires les mieux notés :
similar = cosine_similarity(query_embedding, stored_embeddings)
if similarity > 0.7:
include_as_example(similar_episode)Les épisodes de même catégorie reçoivent un bonus de similarité (×1.2).
| Couche | Technologie | Usage |
|---|---|---|
| Backend | Python 3.14 + FastAPI | API REST, orchestration des 4 composants |
| Performance Element | Gemini 2.5 Flash | Génération des réponses support |
| Critic + Problem Gen | OpenAI GPT-4o-mini | Évaluation sévère, génération d'instructions |
| Apprentissage | SQLite (dev), PostgreSQL (prod) | Poids, snapshots, historique |
| Mémoire épisodique | Gemini text-embedding-004 | Embedding + similarité cosinus |
| Routing LLM | Table SQL pondérée | Poids par catégorie, mise à jour delta |
| Prompt History | SQLite | Snapshots de prompts pour comparaison |
| Dashboard | React 19 + Vite + TypeScript | Courbe d'apprentissage, poids, prompts, providers |
| Infrastructure | Docker + Docker Compose | API + PostgreSQL |
| CI/CD | GitHub Actions | Tests pytest + build TypeScript |
# 1. Cloner
git clone https://github.com/lewenbach228/MAS---MultiAgent-Learning-AdaptativeSupport.git
cd agents/p5-support
# 2. Configurer les clés API
cp .env.example .env
# Éditer .env : GEMINI_API_KEY=... et OPENAI_API_KEY=...
# 3. Walking Skeleton (démo autonome, zéro infra)
pip install -r requirements.txt
python walking-skeleton.py
# 4. Serveur API
python -m uvicorn src.main:app --reload
# 5. Dashboard (dans un autre terminal)
cd dashboard && npm install && npm run dev
# 6. Docker (tout-en-un)
docker compose up --build# 1. Vérifier que le serveur tourne
curl http://localhost:8000/api/p5/tickets
# → [{ "id": 1, "title": "Problème de connexion", ... }]
# 2. Répondre à un ticket (apprentissage automatique)
curl -X POST http://localhost:8000/api/p5/respond \
-H "Content-Type: application/json" \
-d '{"title": "Question facture", "text": "Jai une facture en double", "category": "emotional"}'
# → { "response": "...", "evaluation": { "avg": 2.67, ... }, "provider": "gemini" }
# 3. Lancer 5 epochs d'apprentissage
curl -X POST http://localhost:8000/api/p5/train \
-H "Content-Type: application/json" \
-d '{"tickets": [{"title": "...", "text": "...", "category": "technical", "id": 1}], "epoch": 0}'
# 4. Voir la courbe d'apprentissage
curl http://localhost:8000/api/p5/learning-curve
# → { "epochs": [{ "epoch": 0, "avg_score": 2.45, "count": 6 }, ...] }
# 5. Voir l'historique des prompts
curl http://localhost:8000/api/p5/prompts
# 6. Voir les poids des providers
curl http://localhost:8000/api/p5/providers
# 7. Voir la mémoire épisodique
curl http://localhost:8000/api/p5/episodes
# 8. Swagger UI
# → http://localhost:8000/docs| Route | Méthode | Description |
|---|---|---|
/api/p5/tickets |
GET | Liste des 6 tickets exemples |
/api/p5/respond |
POST | Soumettre un ticket → réponse + évaluation + apprentissage |
/api/p5/train |
POST | Lancer une epoch d'apprentissage sur N tickets |
/api/p5/learning-curve |
GET | Courbe d'apprentissage (scores par epoch) |
/api/p5/weights |
GET | Poids actuels des instructions + providers |
/api/p5/weight-snapshots |
GET | Historique des snapshots de poids |
/api/p5/responses |
GET | Toutes les réponses générées |
/api/p5/prompts |
GET | Historique des prompts assemblés |
/api/p5/prompts/{id} |
GET | Détail d'un prompt spécifique |
/api/p5/episodes |
GET | Mémoire épisodique (tous les épisodes) |
/api/p5/episodes/search |
POST | Chercher des épisodes similaires à un ticket |
/api/p5/providers |
GET | Poids des providers par catégorie |
/api/p5/reset |
POST | Réinitialiser la base d'apprentissage |
| Compétence | Comment |
|---|---|
| Learning loop complet | 4 composants Russell & Norvig : Performance → Critic → Learning → Problem Generator |
| Performance Element | Gemini génère les réponses avec assembly dynamique de prompt |
| Critic automatique | OpenAI évalue 3 critères (pertinence, ton, complétude) avec sévérité calibrée |
| Learning Element | Ajustement tabulaire des poids d'instructions : sélection proportionnelle pondérée |
| Problem Generator | Génère de nouvelles instructions quand les scores stagnent |
| Mémoire épisodique | Embedding + similarité cosinus, retrieval des succès passés pour guider les futures réponses |
| Prompt adaptatif | Le système prompt est assemblé dynamiquement selon les instructions sélectionnées et les épisodes pertinents |
| Multi-LLM routing | Poids par catégorie (emotional/technical/general), mise à jour delta, sélection du meilleur provider |
| Prompt history | Chaque prompt est snapshoté pour comparaison et analyse d'évolution |
| Courbe d'apprentissage | Dashboard visible : moyenne par epoch, avant/après, holdout test |
| Explainable AI | Breakdown complet : quelles instructions utilisées, quel score, quel provider, quel épisode similaire |
| Walking Skeleton | Script zéro infra validé avant toute DB, Docker, ou API |
| Technologie | Usage |
|---|---|
| SQLite | Apprentissage local (poids, snapshots, historique) |
| PostgreSQL | Production (évolutif, via DATABASE_URL) |
| Embeddings vectoriels | Mémoire épisodique (similarité cosinus, pas de vector DB) |
| Provider | Rôle |
|---|---|
| Gemini 2.5 Flash | Performance Element (génération réponses) + Embeddings épisodiques |
| OpenAI GPT-4o-mini | Critic (évaluation) + Problem Generator (nouvelles instructions) |