RHETORICA
Plateforme de débat en temps réel
Contexte & Motivation Pourquoi RHETORICA ?
Le problème
- S'entraîner à l'argumentation nécessite un adversaire disponible et un arbitre impartial
- Le feedback humain est subjectif, lent, coûteux
- Pas de métrique de progression objective
La solution
- Plateforme compétitive avec arbitre IA en temps réel
- Feedback immédiat sur chaque argument
- Progression mesurable via ELO
- Adversaires IA disponibles 24/7
Chess.com, mais pour le débat
Matchmaking ELO Tour par tour · 90s Arbitre IA live Progression mesurable Adversaires IA
120+ sujets FR/EN 12 messages max/partie Score 0 → 100 3 modes de jeu
Concept Déroulé d'une partie
sequenceDiagram
participant J as Joueur
participant MM as Matchmaking
participant S as Serveur
participant IA as Groq / Llama
J->>MM: rejoint la file (mode + ELO)
MM-->>J: match trouvé → debateId
loop 12 tours (6/joueur · 90s)
J->>S: envoie un message
S->>IA: évalue le message
IA-->>S: move_quality + events + score_delta
S-->>J: score live mis à jour
end
S->>IA: analyse post-débat complète
IA-->>S: sophismes · scores · forces · faiblesses
S->>J: ELO mis à jour + achievements débloqués
Architecture Stack technique
| Technologie | Pourquoi ce choix |
| Next.js 15 + App Router + React 19 | SSR pour le dashboard, API Routes co-localisées, streaming natif |
WebSocket custom (server.ts) | Next.js ne supporte pas les connexions WS long-lived donc serveur HTTP+WS sur le même port |
| Groq API · Llama 3.3 70B | Inférence <1s → évaluation pendant le débat réalisable sans bloquer l'UX (et aussi parce que c'est gratuit) |
| Prisma + PostgreSQL (prod) | Gère les Migrations et le schéma. Permet d'avoie SQLite en dev via même interface Prisma |
| TypeScript 5 strict | Typage bout en bout entre routes API et hooks client |
TailwindCSS 4 TanStack Query 5 Docker · Node 20 pnpm · ESLint 9 i18n FR / EN
Architecture Vue d'ensemble système
Flux de données
graph LR
Browser -->|REST / SSR| Next["Next.js 15"]
Browser -->|WebSocket| WS["server.ts"]
Next --> WS
WS --> PG[("PostgreSQL")]
WS --> Groq["Groq API"]
■ SQLite en dev · PostgreSQL en prod
■ Redis : envisageable pour le cache leaderboard & sessions
Modèle de données
erDiagram
User ||--o{ Debate : plays
Debate ||--o{ Message : contains
Debate ||--o| Analysis : has
User ||--o{ UserAchievement : unlocks Temps réel Serveur WebSocket custom
graph LR
jq["join_queue"] -->|match trouvé| matched["matched"]
jq -->|annulation| cq["cancel_queue"]
matched --> join["join"]
join --> msg["message"]
msg --> tc["turn_changed"]
tc --> nm["new_message"]
msg -->|inactif| to["timeout"]
nm -->|fin| de["debate_ended"]
1. Broadcast avant écriture DB
Le message est diffusé aux clients avant la persistance en base. Priorité à la latence perçue sur la cohérence stricte, l'erreur DB est loggée sans bloquer l'UX
2. Heartbeat ping/pong 15s
Détection et terminaison des connexions zombies, évite l'accumulation de clients stales en mémoire et permet de détecter les déconnexions
Temps réel : Matchmaking Trouver un adversaire & mettre à jour le rating
① Trouver un adversaire (file d'attente)
Casual
FIFO, Premier arrivé, premier servi · Aucun filtre de niveau
+15 victoire · −10 défaite
Classé : fenêtre ELO expansive
Fenêtre trop petite → ratings extrêmes jamais matchés (starvation)
Solution : élargir avec le temps d'attente
0 s → ±150 · 10 s → ±200 · 20 s → ±250 · … → max ±500
② Après la partie, mise à jour ELO (classé)
Formule Elo standard
E1 = 1 / (1 + 10(ELO2 − ELO1) / 400)
ELO1' = max(100, round(ELO1 + 32 × (score − E1)))
- K = 32, volatilité standard
- Floor à 100, pas de rating négatif
- ELO initial : 1200
- Battre un joueur plus fort → gain plus important
Intelligence Artificielle 5 Prompts spécialisés
| Prompt | Déclencheur | Temp. | Pourquoi cette température | Sortie |
| Évaluation live | Après chaque message | 0.1 | Déterminisme → scores cohérents | move_quality, events[], score_delta |
| Adversaire IA | Tour IA (entraînement) | 0.9 / 0.7 / 0.4 | Proxy de créativité vs rigueur selon le niveau | Texte argumentatif libre |
| Analyse post-débat | Fin de partie | 0.3 | Détection de sophismes stable et reproductible | Scores, sophismes, biais, forces (JSON) |
| Conseil (hint) | Bouton "Conseil" | 0.5 | Équilibre créativité / pertinence | 1–2 phrases d'amélioration |
| Fact-checking | À la demande | 0.2 | Fiabilité factuelle maximale | Vrai / Faux / Partiel + explication |
Intelligence Artificielle : Évaluation en direct Arbitrage message par message
Règle prioritaire : wrong_side
Si un joueur défend la position de l'adversaire (intentionnellement ou non) :
→ move_quality = "blunder" · delta forcé négatif
quelle que soit la qualité rhétorique du message
Règle de portée (absolue)
Les événements ne concernent que le message courant, le context_history est fourni uniquement pour la cohérence conversationnelle, jamais jugé
Types d'événements détectés
irrelevance / repetition
−3
"move_quality": "brilliant|excellent|good|inaccuracy|mistake|blunder",
"events": [ { type, severity, description } ],
"score_update": { player, delta, new_score },
"live_metrics": { clarity, logic, strategic_value }
Intelligence Artificielle : Adversaire 3 niveaux, 3 prompts distincts
Facile. temp. 0.9
- Arguments peu structurés, parfois hors-sujet
- Répète ses points sans les développer
- Commet des sophismes volontairement
- Registre familier et approximatif
- 2–3 phrases max
Moyen, temp. 0.7
- Structure thèse + justification brève
- Répond à ce que l'adversaire a dit
- Raccourcis logiques acceptés
- Registre semi-formel
- 3–4 phrases
Fort, temp. 0.4
- Contre-argue directement le point précis soulevé
- Structure : point → argument → exemple
- Expose les failles logiques adverses
- Ne répète jamais & rigueur absolue
- 4–5 phrases denses
// Contexte injecté dans chaque appel (buildOpponentUserPrompt)
Affirmation : "{{ topic }}"
Ta position : {{ opponentPosition }}
·
Position adverse : {{ userPosition }}
Historique du débat :
{{ historyText }}
// N derniers messages injectés pour la cohérence contextuelle
// Limite absolue : ~120 mots (MAX_AI_WORDS) · max_tokens = ceil(120 × 1.8)
Intelligence Artificielle : Analyse post-débat Bilan complet après la partie
5 critères d'évaluation
Scores individuels : player1Score vs player2Score
Forces et faiblesses listées. Chaque sophisme avec contexte exact dans le débat
Sophismes & biais détectés
Ad Hominem Homme de paille Pente glissante Fausse dichotomie Appel à l'autorité Généralisation hâtive Biais de confirmation Hors-sujet Répétition
Format de retour
- name : nom normalisé du sophisme
- count : nombre d'occurrences dans le débat
- context : citation exacte ou contexte
Biais cognitifs
Détectés séparément des sophismes logiques
ex. biais de confirmation, biais d'ancrage, biais de disponibilité, etc.
Fonctionnalités Features avancées
Anti-triche (mode classé)
- Détection via Visibility API du navigateur
- Avertissement visuel à chaque changement d'onglet
- ≥ 3 infractions → pénalité −30 ELO appliquée en post-débat
Système d'achievements
- 24 succès déclaratifs + 1 méta "Grand Master"
- 6 catégories : Premiers pas, Victoires, Séries, Qualité, Progression, Ultime
- Barres de progression
- Calcul on-the-fly depuis l'historique des débats
Hint & Fact-check in-game
- Conseil : 1–2 phrases ciblées sur le prochain argument (temp. 0.5)
- Fact-check : vrai / faux / partiel + explication (temp. 0.2)
- Disponibles pendant le tour du joueur uniquement
- Désactivés en mode classé pour équité
i18n FR / EN
- UI entièrement bilingue via un système de traductions custom
- Prompts IA disponibles dans les deux langues
- Sujets de débat traduits (120+ FR & 120+ EN)
- Locale détectée automatiquement et persistée
Infrastructure Déploiement & CI/CD
Pipeline CI/CD
graph LR
Dev["Dev"] -->|git push main| GH["GitHub"]
GH -->|webhook| Coolify["Coolify"]
Coolify -->|docker build + deploy| VPS["VPS · Docker"]
Chemin de la requête
graph LR
User["Utilisateur"] -->|HTTPS| CF["Cloudflare Tunnel"]
CF -->|masque IP · DDoS| Traefik["Traefik"]
Traefik -->|reverse proxy + SSL| VPS2["VPS · Docker"]
Coolify
Self-hosted PaaS, CI/CD automatique sur chaque git push main via GitHub webhook
Cloudflare Tunnel
IP non exposée · DDoS · SSL · domaine sans port-forwarding
Traefik
Reverse proxy & nom de domaine
Base de donée
SQLite en dev, PostgreSQL prod
Synthèse RHETORICA
Gameplay complet
3 modes · ELO · 120+ sujets · 24 achievements · replay
Temps réel
WebSocket custom · matchmaking dynamique · score live
IA au cœur
5 prompts · Groq <1s · 3 adversaires · sophismes
Next.js 15 + TypeScript WebSocket custom Groq · Llama 3.3 70B Prisma + PostgreSQL Coolify · Traefik · Cloudflare
Perspectives
Redis pour cache Fine-tuning sur débats réels Replay commenté par l'IA