expria-backend/docs/Prompt_t2live.md
Hermann_Kitio 5f7e52d88a
Some checks failed
CI / quality (push) Has been cancelled
docs(t2live): MAJ prompt §3, TD-22, CHANGELOG Sprint 6d
- Prompt_t2live.md §3 réécrit (13 règles) + encadré spécificité T2 (règle 7
  non propageable au prompt T1).
- TECH_DEBT-backend.md: TD-22 (contournement prompt engineering Flash Live).
- CHANGELOG-backend.md: bloc Sprint 6d.
2026-06-28 11:49:45 +03:00

227 lines
11 KiB
Markdown

# Prompt_t2live.md — Expria Backend
# Spécification du prompt système T2 EO Live
> **Document de référence — Sprint 6**
> À lire conjointement avec PARCOURS_UTILISATEURS.md et PLANS_TARIFAIRES.md.
> Ce document doit être commité dans `expria-backend/docs/` avant le démarrage du Sprint 6.
---
## 1. Contexte pédagogique
La Tâche 2 de l'Expression Orale TCF Canada est une **interaction de service** :
le candidat joue le rôle d'une personne dans une situation concrète du quotidien
qui a besoin d'informations pour prendre une décision. Il pose des questions à
un interlocuteur (joué par l'IA) qui détient ces informations.
**Ce que cette tâche évalue :**
- La capacité à initier et maintenir une conversation en français
- La formulation de questions claires et adaptées au registre
- Le lexique lié à la vie quotidienne
- La morphosyntaxe en situation d'interaction orale
- La phonologie (évaluée sur l'audio)
**Ce que cette tâche n'est pas :**
- Un débat d'opinions
- Un exposé monologique
- Un jeu de questions-réponses guidé par l'examinateur
---
## 2. Rôle de l'IA
L'IA joue le rôle de l'interlocuteur de la situation décrite dans le sujet
(ex : un bailleur, un employeur, un vendeur, un agent de voyage, etc.).
**Règles absolues du comportement de l'IA :**
1. **Répondre uniquement en français** — quelle que soit la langue utilisée
par le candidat.
2. **Ne pas faciliter la tâche** — ne pas reformuler les questions du candidat,
ne pas anticiper ce qu'il veut savoir, ne pas lui souffler les mots.
3. **Répondre aux questions posées** — réponses naturelles, réalistes,
ni trop courtes (monosyllabiques) ni trop longues (monologues).
4. **Ne pas relancer au-delà de** : _"Avez-vous d'autres questions ?"_
si le candidat marque une pause prolongée ou semble avoir terminé.
5. **Ne pas évaluer le candidat** pendant la conversation — aucun commentaire
sur sa langue, ses erreurs, ou sa performance.
6. **Ne pas sortir du rôle** — même si le candidat pose des questions hors sujet
ou tente de changer de registre.
7. **Attendre que le candidat prenne la parole** — c'est le candidat qui initie
la conversation, comme à l'examen réel. L'IA ne parle pas en premier.
Elle attend en silence et répond dès que le candidat s'adresse à elle.
---
## 3. Prompt système (à injecter dans `geminiLive.ts`)
```
RÔLE : Tu incarnes {role}.
CONTEXTE : {contexte}
RÈGLES ABSOLUES :
1. Tu parles TOUJOURS en français naturel et courant, niveau B2-C1.
2. Tu NE corriges JAMAIS les erreurs du candidat. Tu continues naturellement.
3. Tu attends que le candidat finisse sa question avant de répondre.
4. Tes réponses sont courtes (15 à 25 mots maximum) pour laisser la place au dialogue.
5. Ne donne pas toutes les informations d'un coup. Force le candidat à poser des questions précises.
6. Si le candidat est vague, réponds brièvement sans chercher à compléter — c'est à lui de reformuler.
7. STRICTE INTERDICTION DE POSER DES QUESTIONS. Tu n'as pas le droit d'utiliser de point d'interrogation. Tes phrases se terminent par un point.
8. SILENCE TOTAL APRÈS LA RÉPONSE. Réponds de manière factuelle, puis arrête-toi immédiatement. Ne suggère rien, ne relance pas, ne dis pas "et vous ?".
9. RÔLE PASSIF : tu es une source d'information inerte. Tu n'aides pas le candidat à tenir la conversation. S'il ne parle plus, le silence s'installe.
10. AUCUNE FORMULE DE POLITESSE DE FIN : bannis "n'hésitez pas", "j'espère que ça vous aide", "qu'en pensez-vous ?".
11. JAMAIS de listes ni de structure numérotée — parle naturellement.
12. Ne mentionne jamais que tu es une IA ou un modèle.
13. Tu ne prends PAS la parole en premier. Tu attends que le candidat s'adresse à toi.
```
> **⚠ Spécificité T2 — règle 7 :** l'interdiction absolue de poser des questions
> (et du point d'interrogation) est **propre à la Tâche 2** (interaction de service
> où le candidat doit mener l'échange). Elle ne doit **jamais** être propagée au
> prompt T1 (Sprint 7), où l'examinateur doit au contraire relancer le candidat.
> Voir aussi TD-22 (TECH_DEBT-backend.md) : contournement par prompt engineering,
> sans garantie déterministe sur modèle Flash Live.
**Variables à substituer dynamiquement depuis le sujet :**
- `{role}` — ex : "un bailleur qui loue un appartement"
- `{contexte}` — la consigne + contexte du sujet issu de la table `sujets`
---
## 4. Format du sujet T2 en base
Les sujets T2 sont stockés dans la table `sujets` avec les champs :
- `consigne` — la situation décrite au candidat (ce qu'il doit faire)
- `contexte` — les informations de cadrage (lieu, situation, interlocuteur)
- `tache` — valeur `'EO_T2'`
- `mode` — valeur `'entrainement'`
**Exemple de sujet :**
```
consigne : "Vous avez vu une annonce pour un appartement à louer.
Appelez le bailleur pour obtenir les informations
nécessaires avant de prendre votre décision."
contexte : "Vous cherchez un appartement de 2 pièces dans le
centre-ville, votre budget est limité et vous souhaitez
emménager le mois prochain."
role : "un bailleur qui propose un appartement à louer"
```
> **Note :** Le champ `role` existe dans la table `sujets` et a été
> alimenté pour les 9 sujets EO T2 (session 2026-04-26, script SQL
> `update_sujets_t2.sql`).
---
## 5. Structure du rapport T2
Le rapport T2 suit **exactement la même structure** que les rapports EO T1 et T3 :
4 critères officiels TCF Canada :
| Critère | Pondération |
| ------------------------------ | ----------- |
| Cohérence et cohésion | 25 % |
| Étendue et maîtrise du lexique | 25 % |
| Maîtrise morphosyntaxique | 25 % |
| Phonologie | 25 % |
**Conséquence :** l'évaluation finale peut réutiliser le prompt de correction EO
existant (`POST /corrections/eo`) en passant le transcript de la session comme
entrée, avec `tache: 'EO_T2'`.
> **Rappel TD-08 (backend) :** la phonologie est temporairement fixée à 0
> pour les tâches EO live car l'évaluation nécessite l'audio brut.
> Applicable à T2 également — à résoudre post-MVP.
---
## 6. Flux technique complet Sprint 6
```
1. Candidat choisit un sujet T2 dans la liste → clic → page préparation
2. Page préparation : consigne affichée + bouton "Démarrer le dialogue"
3. Frontend ouvre WS : wss://api.expria.app/t2/live?token=<jwt>&sujet=<uuid>
4. Backend vérifie JWT + plan oral_t2_live (Premium)
5. Backend lit le sujet depuis Supabase (id sujet passé en query param)
6. Backend ouvre WS vers Gemini Live API avec prompt système construit
dynamiquement depuis {role} + {contexte} du sujet
7. Backend → Gemini : setup frame (modèle + prompt + responseModalities: AUDIO
+ VAD : endOfSpeechSensitivity LOW, silenceDurationMs 2000)
8. L'IA attend en silence — c'est le CANDIDAT qui prend la parole en premier
(conforme à l'examen réel TCF Canada)
9. Frontend → Backend → Gemini : audio candidat (PCM 16kHz base64) en continu
+ accumulation dans le buffer d'enregistrement chronologique (rééchantillonné 24kHz)
10. Gemini → Backend → Frontend : réponses audio (PCM 24kHz base64) en continu
+ accumulation dans le buffer d'enregistrement
11. Candidat clique "Terminer" → Frontend envoie signal de fin
12. Backend ferme WS Gemini, récupère transcript complet (inputTranscription
+ outputTranscription accumulés pendant la session)
13. Backend POST /corrections/eo avec transcript + tache='EO_T2'
→ rapport généré (même pipeline que T1/T3)
14. Backend sauvegarde production en base (tache='EO_T2_LIVE')
15. Backend envoie rapport au Frontend via WS (close code 1000 + payload rapport)
16. Frontend → state machine 'ended' → affichage rapport
17. Frontend propose bouton "Télécharger l'audio" (WAV mono 24kHz assemblé
depuis le buffer chronologique)
```
---
## 7. Spécifications audio
| Direction | Format | Sample rate | Encoding |
| ----------------- | -------- | ----------- | ---------------------------- |
| Frontend → Gemini | PCM brut | 16kHz | 16 bits, little-endian, mono |
| Gemini → Frontend | PCM brut | 24kHz | 16 bits, little-endian, mono |
**MIME type à envoyer à Gemini :** `audio/pcm;rate=16000`
**Côté frontend :**
- Capture via `AudioContext` + `AudioWorklet` (ou `ScriptProcessorNode` provisoire)
- Rééchantillonnage obligatoire : le navigateur capture à 44.1kHz ou 48kHz → downsampler à 16kHz
- Conversion Float32 → Int16 PCM avant envoi
- Lecture de l'audio reçu : `AudioContext` à 24kHz + `AudioBufferSourceNode` par chunk
---
## 8. Gestion des erreurs WebSocket
| Close code | Cause | Action frontend |
| ---------- | -------------------------- | ------------------------------------- |
| 1000 | Fin normale + rapport prêt | State → 'ended', afficher rapport |
| 4001 | AUTH_REQUIRED | State → 'error', redirect /login |
| 4003 | PLAN_INSUFFICIENT | State → 'error', PaywallModal Premium |
| 4004 | SUJET_NOT_FOUND | State → 'error', retour liste sujets |
| Autre | Erreur réseau / Gemini | State → 'error', bouton "Réessayer" |
---
## 9. Questions ouvertes à trancher au Sprint 6
| # | Question | Impact |
| --- | ----------------------------------------------------------------------------------------------------- | ----------------------------------- |
| Q1 | Le champ `role` existe-t-il dans la table `sujets` ou faut-il le dériver du `contexte` ? | Migration SQL ou prompt engineering |
| Q2 | L'id du sujet est-il passé en query param WS (`?token=jwt&sujet=uuid`) ou via le premier message WS ? | Protocole de connexion |
| Q3 | Le transcript est-il accumulé côté backend pendant la session ou demandé à Gemini en fin de session ? | Architecture geminiLive.ts |
---
## 10. Ce qui existe déjà (à ne pas recoder)
- `src/routes/t2live.ts` — 101 lignes, route WS + auth + gating ✅
- `src/lib/geminiLive.ts` — 154 lignes, proxy bidirectionnel + setup frame ✅
- Pipeline correction EO (`POST /corrections/eo`) — réutilisable pour évaluation finale ✅
- Modèle `gemini-live-2.5-flash-native-audio` — accès confirmé ✅
**À modifier :**
- `src/lib/geminiLive.ts` — remplacer le prompt agent immobilier par le prompt
dynamique §3, brancher la récupération du sujet depuis Supabase,
accumuler le transcript, déclencher l'évaluation finale.