diff --git a/docs/CHANGELOG-backend.md b/docs/CHANGELOG-backend.md index fe89a46..6da3cfe 100644 --- a/docs/CHANGELOG-backend.md +++ b/docs/CHANGELOG-backend.md @@ -6,6 +6,26 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/). --- +## [Unreleased] — 2026-06-28 — Sprint 6d — T2 Live : durcissement prompt + VAD + cleanup SDK + +### Changed + +- `buildT2SystemPrompt` (`geminiLive.ts`) — prompt système T2 durci : 13 règles absolues (Bug 1). Interdiction stricte de poser des questions (aucun point d'interrogation), rôle passif/inerte, silence total après réponse, aucune formule de politesse de fin. Objectif : stopper la relance systématique de l'examinateur IA. Réf TD-22. ⚠ Spécifique T2 — l'interdiction du « ? » ne doit pas être propagée au prompt T1 (Sprint 7). +- `buildSetupFrame` (`geminiLive.ts`) — `realtimeInputConfig.automaticActivityDetection` (VAD) réintégré dans le setup frame Gemini (Bug 2), 4 champs : `disabled:false`, `startOfSpeechSensitivity:START_SENSITIVITY_LOW`, `endOfSpeechSensitivity:END_SENSITIVITY_LOW`, `silenceDurationMs:2000`. +- `geminiLive.test.ts` — assertion VAD mise à jour (`realtimeInputConfig` : `toBeUndefined` → présence + valeurs des 4 champs). + +### Removed + +- Dépendance `@google/genai` retirée de `package.json` / `package-lock.json` et script de debug `test-gemini-live.js` supprimé (Bug 8) — SDK abandonné au profit du WebSocket brut (`ws`). + +### Notes + +- Tests backend : 292/292 verts (0 échec). +- Validé au test manuel Golden Dataset Groupe D — Bug 1 (plus de relance systématique) et Bug 2 (VAD, pauses de réflexion respectées) confirmés en conditions réelles. +- **TD-22 (🟡 ouvert)** — comportement T2 garanti uniquement par prompt engineering ; pas de garantie déterministe sur modèle Flash Live. À revisiter si la relance persiste. + +--- + ## [Unreleased] — 2026-04-26 — Sprint 6a — Backend T2 Live ### Added diff --git a/docs/Prompt_t2live.md b/docs/Prompt_t2live.md index 2591a15..1ec7b01 100644 --- a/docs/Prompt_t2live.md +++ b/docs/Prompt_t2live.md @@ -1,4 +1,5 @@ # Prompt_t2live.md — Expria Backend + # Spécification du prompt système T2 EO Live > **Document de référence — Sprint 6** @@ -15,6 +16,7 @@ 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 @@ -22,6 +24,7 @@ un interlocuteur (joué par l'IA) qui détient ces informations. - 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 @@ -41,7 +44,7 @@ L'IA joue le rôle de l'interlocuteur de la situation décrite dans le sujet 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 ?"* +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. @@ -56,28 +59,34 @@ L'IA joue le rôle de l'interlocuteur de la situation décrite dans le sujet ## 3. Prompt système (à injecter dans `geminiLive.ts`) ``` -Tu joues le rôle de {role} dans la situation suivante : {contexte} +RÔLE : Tu incarnes {role}. +CONTEXTE : {contexte} -Règles à respecter impérativement : -- Tu réponds uniquement en français, quelle que soit la langue de ton interlocuteur. -- Tu joues ton rôle de façon naturelle et réaliste. Tu n'es pas un examinateur — - tu es {role}. -- Tu réponds aux questions qu'on te pose de façon honnête et naturelle, - comme le ferait une vraie personne dans cette situation. -- Tu ne facilites pas la tâche : tu ne reformules pas les questions, - tu n'anticipes pas ce que l'interlocuteur veut savoir, - tu ne lui suggères pas quoi demander. -- Si ton interlocuteur marque une longue pause ou semble avoir terminé, - tu peux dire : "Avez-vous d'autres questions ?" — c'est la seule relance autorisée. -- Tu ne fais aucun commentaire sur la langue, les erreurs ou le niveau de français - de ton interlocuteur. -- Tu ne sors jamais de ton rôle. -- Tu ne prends PAS la parole en premier. Tu attends que ton interlocuteur - s'adresse à toi, puis tu réponds naturellement dans ton rôle. -- Tes réponses sont concises et naturelles : ni monosyllabiques, ni des monologues. +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` @@ -86,18 +95,20 @@ Règles à respecter impérativement : ## 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 +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 +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" ``` @@ -113,12 +124,12 @@ role : "un bailleur qui propose un appartement à louer" 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 % | +| 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 @@ -164,14 +175,15 @@ entrée, avec `tache: 'EO_T2'`. ## 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 | +| 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 @@ -181,23 +193,23 @@ entrée, avec `tache: 'EO_T2'`. ## 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" | +| 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 | +| # | 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 | --- @@ -209,7 +221,7 @@ entrée, avec `tache: 'EO_T2'`. - 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. - diff --git a/docs/TECH_DEBT-backend.md b/docs/TECH_DEBT-backend.md index 5f9b674..28af635 100644 --- a/docs/TECH_DEBT-backend.md +++ b/docs/TECH_DEBT-backend.md @@ -245,6 +245,17 @@ Gate de qualité actuel : npm run test. --- +### TD-22 — Comportement T2 Live garanti uniquement par prompt engineering + +**Priorité :** 🟡 Important +**Statut :** Ouvert — introduit au Sprint 6d +**Description :** Le respect du rôle passif de l'examinateur T2 (réponses courtes, aucune question posée, aucune relance, silence après réponse) repose entièrement sur le durcissement du prompt système dans `buildT2SystemPrompt` (`src/lib/geminiLive.ts`, cf. `docs/Prompt_t2live.md §3`). Le modèle Gemini Flash Live n'offre **aucune garantie déterministe** : il peut malgré tout poser une question, ajouter une formule de politesse de fin ou relancer le candidat. +**À faire :** Revisiter si la relance persiste en tests manuels — pistes : reformulation/renforcement du prompt, post-filtrage des sorties, ou évaluation d'un modèle Live plus dirigeable. +**⚠ Spécificité T2 :** l'interdiction de poser des questions (et du point d'interrogation, règle 7) est **propre à la Tâche 2**. Ne jamais la propager au prompt T1 (Sprint 7), où l'examinateur doit relancer le candidat. +**Session concernée :** T2 Live — Sprint 6d. + +--- + ## 5. Historique des résolutions | ID | Description | Résolu le | Comment |