fix(t1-live): remove questionnaire dependency from T1 Live session
Some checks are pending
CI / quality (push) Waiting to run
Some checks are pending
CI / quality (push) Waiting to run
- buildT1SystemPrompt() now static (no reponses param); examiner formulates questions from what it hears in real-time audio stream - Remove context guard + close 4004 CONTEXT_MISSING; Gemini session opens immediately after auth (aligns with T2 flow) - Remove parseT1Context, validateReponses import from route - Unknown WS message types silently ignored (debug log + return) - Update Prompt_t1live.md and CHANGELOG-backend - Tests: 309/309 green
This commit is contained in:
parent
01707c0b74
commit
74770b6402
6 changed files with 105 additions and 209 deletions
|
|
@ -31,12 +31,12 @@ d'immigration au Canada) sous forme de **monologue**, et l'examinateur le
|
|||
|
||||
**Différence structurelle avec le T2 :**
|
||||
|
||||
| Axe | T1 (entretien dirigé) | T2 (interaction de service) |
|
||||
| ----------------- | -------------------------------- | ---------------------------- |
|
||||
| Qui mène | L'examinateur relance | Le candidat mène |
|
||||
| Questions de l'IA | **Obligatoires** (relances) | **Interdites** (rôle passif) |
|
||||
| Forme candidat | Monologue + relances | Dialogue |
|
||||
| Subject-based | **Non** (questionnaire candidat) | Oui (table `sujets`) |
|
||||
| Axe | T1 (entretien dirigé) | T2 (interaction de service) |
|
||||
| ----------------- | ------------------------------ | ---------------------------- |
|
||||
| Qui mène | L'examinateur relance | Le candidat mène |
|
||||
| Questions de l'IA | **Obligatoires** (relances) | **Interdites** (rôle passif) |
|
||||
| Forme candidat | Monologue + relances | Dialogue |
|
||||
| Subject-based | **Non** (écoute en temps réel) | Oui (table `sujets`) |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ L'IA joue un **examinateur bienveillant** du TCF Canada. Son comportement :
|
|||
interne. Le backend ne lit PAS la transcription partielle pour décider
|
||||
(Modèle 1 acté — cf. ROADMAP / `geminiLiveT1.ts`).
|
||||
3. **Relance courte et unique.** Une seule question de 10 à 20 mots, liée à ce
|
||||
que le candidat vient de dire ou à son contexte. Jamais d'enchaînement.
|
||||
que le candidat vient de dire. Jamais d'enchaînement.
|
||||
4. **Ton bienveillant et professionnel**, français B2-C1.
|
||||
5. **N'évalue jamais** le candidat, ne corrige pas ses erreurs, ne commente pas
|
||||
sa langue.
|
||||
|
|
@ -63,25 +63,21 @@ L'IA joue un **examinateur bienveillant** du TCF Canada. Son comportement :
|
|||
|
||||
## 3. Prompt système (source : `buildT1SystemPrompt`)
|
||||
|
||||
Les variables `${...}` sont substituées dynamiquement depuis les réponses du
|
||||
**questionnaire candidat** (`PresentationReponses`) — il n'existe pas de sujet T1
|
||||
en base (T1 EO n'est PAS subject-based).
|
||||
Le prompt est **statique** : aucune variable substituée. L'examinateur formule
|
||||
ses relances à partir de ce qu'il **entend en temps réel** (son contexte audio
|
||||
interne) — il n'existe ni sujet T1 en base, ni questionnaire pré-rempli (T1 EO
|
||||
n'est PAS subject-based).
|
||||
|
||||
```
|
||||
RÔLE : Tu es un examinateur bienveillant de l'épreuve d'Expression Orale du TCF Canada (Tâche 1, entretien dirigé). Le candidat se présente en monologue : identité, parcours, situation familiale, loisirs, et projet d'immigration au Canada.
|
||||
|
||||
CONTEXTE DU CANDIDAT (pour formuler des relances pertinentes et personnalisées) :
|
||||
- Identité : ${reponses.prenom_age_ville}
|
||||
- Formation / métier : ${reponses.formation_metier}
|
||||
- Situation familiale : ${reponses.situation_familiale}
|
||||
- Loisirs : ${reponses.loisirs}
|
||||
- Projet Canada : ${reponses.motivation_canada}
|
||||
Écoute attentivement ce que le candidat dit. Quand on te le signale, formule UNE question de relance courte (10-20 mots) liée à ce que le candidat vient de dire.
|
||||
|
||||
RÈGLES :
|
||||
1. Tu parles TOUJOURS en français naturel et courant, niveau B2-C1, sur un ton bienveillant et professionnel.
|
||||
2. Tu RESTES SILENCIEUX par défaut. Tant que le candidat parle, tu n'interviens JAMAIS de ta propre initiative.
|
||||
3. Tu prends la parole UNIQUEMENT lorsqu'on te le signale, et alors UNIQUEMENT pour relancer le candidat par UNE question.
|
||||
4. Ta relance est COURTE : une seule question de 10 à 20 mots, liée à ce que le candidat vient de dire ou à son contexte ci-dessus.
|
||||
4. Ta relance est COURTE : une seule question de 10 à 20 mots, liée à ce que le candidat vient de dire.
|
||||
5. Tu PEUX et tu DOIS poser des questions : c'est le cœur de ton rôle d'examinateur en Tâche 1. Utilise le point d'interrogation normalement.
|
||||
6. Une seule question à la fois. Jamais de liste, jamais d'enchaînement de plusieurs questions dans la même prise de parole.
|
||||
7. Tu ne corriges JAMAIS les erreurs du candidat et tu ne commentes jamais sa langue, ses erreurs ou sa performance.
|
||||
|
|
@ -91,13 +87,6 @@ RÈGLES :
|
|||
> **⚠ Spécificité T1 — règle 5 :** elle est l'**exact inverse** de la règle 7 du
|
||||
> T2. Toute fusion des deux prompts est interdite (TD-22 / TD-23).
|
||||
|
||||
**Variables à substituer dynamiquement** (depuis le questionnaire candidat, pas
|
||||
d'un sujet en base) :
|
||||
|
||||
- `prenom_age_ville`, `formation_metier`, `situation_familiale`, `loisirs`,
|
||||
`motivation_canada` — validés par `validateReponses`
|
||||
(`presentationController.ts`).
|
||||
|
||||
---
|
||||
|
||||
## 4. Contrat WebSocket T1 (figé — la suite Sprint 7b en dépend)
|
||||
|
|
@ -106,13 +95,17 @@ Route : **`WS /t1/live?token=<jwt>`**
|
|||
Auth : JWT Supabase + permission Premium `oral_t2_live` (réutilise
|
||||
`authenticate` de `t2live.ts` — cf. dette de nommage TD-24).
|
||||
|
||||
La session Gemini s'ouvre **immédiatement après l'auth** (pas de message de
|
||||
contexte ni de questionnaire). Le client envoie directement son audio. Tout
|
||||
message non reconnu (ni `audio` ni `end`) est **ignoré silencieusement** (log
|
||||
debug + return) — jamais de close.
|
||||
|
||||
### 4.1 Client → Backend
|
||||
|
||||
| Message | Forme | Effet |
|
||||
| ---------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| Contexte (1er message obligatoire) | `{type:'context', reponses}` | Validé par `validateReponses` ; démarre la session Gemini. Absent/invalide → close `4004`. |
|
||||
| Audio candidat | `{type:'audio', data}` (PCM 16 kHz base64) | Relayé à Gemini tant qu'un tour candidat est ouvert et qu'aucune interruption n'est en cours. |
|
||||
| Fin de session | `{type:'end'}` | Déclenche `endSession()` (flush terminal + correction). |
|
||||
| Message | Forme | Effet |
|
||||
| -------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| Audio candidat | `{type:'audio', data}` (PCM 16 kHz base64) | Relayé à Gemini tant qu'un tour candidat est ouvert et qu'aucune interruption n'est en cours. |
|
||||
| Fin de session | `{type:'end'}` | Déclenche `endSession()` (flush terminal + correction). |
|
||||
|
||||
### 4.2 Backend → Client
|
||||
|
||||
|
|
@ -127,15 +120,14 @@ Auth : JWT Supabase + permission Premium `oral_t2_live` (réutilise
|
|||
|
||||
### 4.3 Codes de fermeture WebSocket
|
||||
|
||||
| Close code | Cause | Origine |
|
||||
| ---------- | -------------------------------------------------------- | ------------------------- |
|
||||
| 1000 | Fin normale + rapport prêt (ou transcript vide) | `runT1LiveCorrection` |
|
||||
| 1011 | `PERSISTENCE_FAILED` / `CORRECTION_FAILED` | `runT1LiveCorrection` |
|
||||
| 4001 | `AUTH_REQUIRED` (JWT absent/invalide) | `authenticate` |
|
||||
| 4003 | `PLAN_INSUFFICIENT` (pas Premium) | `authenticate` |
|
||||
| 4004 | `CONTEXT_MISSING` (1er message contexte absent/invalide) | route `t1live.ts` |
|
||||
| 4005 | `GEMINI_CONFIG` (clé API Gemini manquante côté serveur) | `openGeminiLiveT1Session` |
|
||||
| 4006 | `GEMINI_DISCONNECTED` (WS Gemini fermé/erreur) | `openGeminiLiveT1Session` |
|
||||
| Close code | Cause | Origine |
|
||||
| ---------- | ------------------------------------------------------- | ------------------------- |
|
||||
| 1000 | Fin normale + rapport prêt (ou transcript vide) | `runT1LiveCorrection` |
|
||||
| 1011 | `PERSISTENCE_FAILED` / `CORRECTION_FAILED` | `runT1LiveCorrection` |
|
||||
| 4001 | `AUTH_REQUIRED` (JWT absent/invalide) | `authenticate` |
|
||||
| 4003 | `PLAN_INSUFFICIENT` (pas Premium) | `authenticate` |
|
||||
| 4005 | `GEMINI_CONFIG` (clé API Gemini manquante côté serveur) | `openGeminiLiveT1Session` |
|
||||
| 4006 | `GEMINI_DISCONNECTED` (WS Gemini fermé/erreur) | `openGeminiLiveT1Session` |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue