298 lines
16 KiB
Markdown
298 lines
16 KiB
Markdown
# Memoire Projet
|
|
|
|
## Contexte
|
|
|
|
Ce projet est un POC de professeur virtuel pour enfants, avec:
|
|
- frontend React + Vite
|
|
- backend FastAPI
|
|
- PostgreSQL pour les donnees eleve
|
|
- Redis present dans la stack
|
|
- integration OpenAI pour reponses texte et transcription audio
|
|
|
|
## Points Importants
|
|
|
|
- Le frontend appelle l'API via le prefixe `/api`.
|
|
- Le backend expose une route `POST /transcribe` pour la transcription audio.
|
|
- La route `/transcribe` utilise `UploadFile`, donc `python-multipart` est requis dans le backend.
|
|
- Le backend a un socle d'authentification avec comptes `users`, roles `student`, `teacher`, `maintenance`.
|
|
- Le compte admin/prof initial est seede depuis `.env` via `ADMIN_USERNAME` et `ADMIN_PASSWORD`.
|
|
- Le login pose un cookie HTTP-only `professeur_top_session` et renvoie aussi un token bearer.
|
|
- Le frontend affiche maintenant une page de connexion avant l'application et verifie la session via `/auth/me`.
|
|
- Apres connexion admin/prof, l'interface actuelle reste accessible avec un bouton de deconnexion.
|
|
- Les routes eleves principales verifient maintenant les roles:
|
|
- `teacher` et `maintenance` peuvent acceder aux eleves
|
|
- `student` ne peut acceder qu'a son propre `student_id`
|
|
- Le backend expose `POST /admin/student-accounts` pour creer une fiche eleve et son compte login en une seule operation.
|
|
- Le frontend masque le choix/creation d'eleve pour un compte `student` et ouvre directement sa propre seance.
|
|
- Le backend expose `GET /students/{student_id}/messages` pour relire l'historique de conversation stocke en base.
|
|
- Les reponses aux mini-tests sont maintenant aussi enregistrees dans `messages` avec le role `user`.
|
|
- Le frontend recharge l'historique quand un eleve est selectionne, mais ne met plus automatiquement la derniere ancienne phrase au centre.
|
|
- Au demarrage d'une nouvelle seance, Professeur TOP doit faire une courte reprise de l'historique puis annoncer le cours du jour.
|
|
- L'interface de seance est maintenant en hauteur fixe `100vh`: pas de scroll global, cours central au milieu, pas de conversation visible.
|
|
- La conversation reste stockee en base pour analyse, mais l'ecran de cours remplace la consigne/reponse courante au lieu d'empiler des bulles.
|
|
- Les reponses de mini-test utilisent la meme zone de reponse eleve en bas; le texte du prof reste au-dessus et pourra accueillir une image sous le texte.
|
|
- Cote eleve, le bouton principal bascule entre `Demarrer la seance` et `Fin de la seance`.
|
|
- Cote eleve, la colonne gauche affiche les themes du jour: une card lecon avec pourcentage local, une card exercice avec statut.
|
|
- Le bilan complet de progression reste reserve aux vues prof/admin.
|
|
- Les options TTS visibles doivent etre libellees `Voix Douce`, `Voix Rigolote`, etc.; la mention "Voix IA non humaine..." est portee par un tooltip.
|
|
- Le declenchement manuel de mini-test/exercice doit disparaitre de l'interface eleve; le programme doit etre determine par Professeur TOP.
|
|
- A prevoir cote admin: tableau par eleve et prompts/instructions personnalises pour guider Professeur TOP par eleve.
|
|
- L'ecran eleve affiche une petite card "Transmis au prof" au-dessus de la zone de saisie pour montrer le texte capte/envoye.
|
|
- Le backend ajoute une consigne de tours de parole courts pour que Professeur TOP laisse le temps a l'enfant de repondre.
|
|
- Gestion interruption a prevoir: detection de parole pendant TTS, pause audio, transcription, classification pertinent/accidentel, puis reprise courte.
|
|
- La transcription audio force maintenant `language="fr"` avec un prompt francais pour eviter les erreurs de detection de langue sur phrases tres courtes.
|
|
- Le vrai `docker-compose.yml` de production n'est pas dans ce repo. Il est situe un niveau au-dessus sur le serveur.
|
|
- La conf nginx reelle route:
|
|
- `/api/` vers `tutor-backend:8000`
|
|
- `/` vers `tutor-frontend:3000`
|
|
|
|
## Dictée Vocale
|
|
|
|
- L'ancien bouton de dictee marchait en mode manuel avec `MediaRecorder.start()` puis `stop()`.
|
|
- Le mode actuel est un mode mains libres:
|
|
- activation via un clic utilisateur
|
|
- enregistrement automatique
|
|
- detection du silence
|
|
- transcription automatique
|
|
- envoi automatique du message
|
|
- Firefox s'est montre capricieux avec la mesure temps reel via `AnalyserNode`.
|
|
- La solution retenue s'appuie sur un traitement plus direct du flux audio pour determiner le niveau sonore.
|
|
- L'ecoute se rearme automatiquement apres:
|
|
- la transcription/envoi du message eleve
|
|
- la fin de lecture vocale du professeur
|
|
|
|
## Voix du Professeur
|
|
|
|
- L'ancien systeme de voix navigateur a ete remplace par une vraie TTS OpenAI.
|
|
- Le backend expose maintenant:
|
|
- `GET /tts/profiles` pour lister les profils de voix
|
|
- `POST /tts` pour generer un MP3 a partir d'un texte et d'un `profile_id`
|
|
- Les profils actuels sont:
|
|
- `rigolote`
|
|
- `petillante`
|
|
- `douce`
|
|
- `sobre`
|
|
- Chaque profil TTS definit:
|
|
- une voix OpenAI
|
|
- une vitesse
|
|
- des instructions de style vocal
|
|
- Le frontend ne depend plus de `speechSynthesis` pour la voix sortante.
|
|
- Le choix de voix est memorise dans `localStorage` avec la cle `professeur-top-tts-profile`.
|
|
- La lecture audio se fait via un blob MP3 retourne par le backend.
|
|
- Le mode micro auto doit continuer a se re-armer apres la fin de lecture du MP3.
|
|
|
|
## Identite Produit
|
|
|
|
- Le personnage et le nom visibles dans le frontend ont ete renommes de `ProfAmi` vers `Professeur TOP`.
|
|
- Le nouvel avatar image est stocke dans:
|
|
- `frontend/src/assets/professeur-top.png`
|
|
- Le composant avatar React utilise maintenant l'image raster au lieu du visage CSS/SVG precedent.
|
|
- Le backend a aussi ete aligne dans le prompt systeme et le message de debut de session avec le nom `Professeur TOP`.
|
|
|
|
## Notes de Session 2026-04-24 21:58:39 +02:00
|
|
|
|
- Repo clone dans `c:\DataS\OpenSquared\OpenSchool\ProfTop`.
|
|
- `safe.directory` Git ajoute globalement pour ce dossier a cause d'un mismatch d'ownership Windows.
|
|
- Image utilisateur `face.png` integree dans le frontend sous `frontend/src/assets/professeur-top.png`.
|
|
- Libelles assistant remplaces par `Professeur TOP` dans l'UI.
|
|
- README mis a jour pour refleter la TTS OpenAI au lieu de la voix navigateur.
|
|
- Le frontend n'a pas encore ete verifie par build local car `frontend/node_modules` est absent.
|
|
- Lors d'un prochain demarrage, penser a installer les dependances frontend avant validation finale.
|
|
- La TTS OpenAI suppose une `OPENAI_API_KEY` valide cote backend.
|
|
|
|
## Notes de Session 2026-04-25 - Auth, UI Eleve, Audio
|
|
|
|
- Authentification ajoutee:
|
|
- table `users`
|
|
- roles `student`, `teacher`, `maintenance`
|
|
- login via `/auth/login`
|
|
- session via cookie HTTP-only `professeur_top_session`
|
|
- compte admin/prof seede depuis `.env`
|
|
- Acces eleve/admin:
|
|
- un compte eleve est rattache a un `student_id`
|
|
- un eleve ne peut acceder qu'a sa propre fiche/seance
|
|
- prof/maintenance gardent l'acces global
|
|
- creation d'un compte eleve via `POST /admin/student-accounts`
|
|
- UI eleve:
|
|
- page login active
|
|
- l'eleve ne voit plus la creation ni le choix d'eleves
|
|
- l'ecran de cours ne montre plus la conversation complete
|
|
- le cours courant remplace la consigne precedente au centre
|
|
- la zone de reponse eleve reste en bas
|
|
- card "Transmis au prof" ajoutee pour afficher le dernier texte envoye/capte
|
|
- bouton principal `Demarrer la seance` / `Fin de la seance`
|
|
- colonne gauche eleve limitee aux themes du jour, pas au bilan global
|
|
- Conversation et analyse:
|
|
- les messages restent stockes en base
|
|
- `GET /students/{student_id}/messages` permet de relire l'historique
|
|
- le chat complet sera surtout utile aux rapports admin
|
|
- Voix/TTS:
|
|
- les voix visibles sont libellees `Voix Douce`, `Voix Rigolote`, etc.
|
|
- la mention "Voix IA non humaine..." est deplacee en tooltip
|
|
- Professeur TOP a maintenant une consigne backend de tours de parole courts
|
|
- Transcription:
|
|
- `language="fr"` force dans la transcription OpenAI
|
|
- prompt de transcription ajoute pour phrases scolaires courtes
|
|
- correction faite apres erreur type langue asiatique sur une phrase simple comme "nous chantons"
|
|
- Deploiement serveur:
|
|
- `.env` du compose doit etre dans `/root/.env` ou passe via `--env-file`
|
|
- rebuild backend necessaire pour changements backend
|
|
- rebuild frontend necessaire pour changements UI
|
|
|
|
## Idee Technique - Interruptions Trop Frequentes
|
|
|
|
Objectif: permettre a l'enfant de couper Professeur TOP sans perdre le fil, tout en evitant les faux positifs.
|
|
|
|
Approche progressive recommandee:
|
|
|
|
1. Barge-in simple avec TTS MP3 actuel:
|
|
- garder l'analyse micro active pendant la lecture audio
|
|
- si volume/parole detectee pendant que `speaking=true`, mettre l'audio en pause ou l'arreter
|
|
- enregistrer un court segment jusqu'au silence
|
|
- transcrire en francais
|
|
- envoyer au backend avec un marqueur du type `interruption=true`
|
|
- demander au LLM de classer implicitement: pertinent, question, correction, bruit/accident
|
|
- si pertinent: repondre a l'enfant puis reprendre la lecon
|
|
- si accidentel: repondre tres court puis continuer la consigne
|
|
|
|
2. Anti-faux positifs:
|
|
- imposer un seuil plus haut pendant la lecture TTS
|
|
- ignorer les segments tres courts, par exemple moins de 600 ms
|
|
- ignorer les transcriptions vides ou tres faibles
|
|
- utiliser une courte fenetre de cooldown apres chaque interruption
|
|
- afficher dans "Transmis au prof" uniquement ce qui est vraiment envoye
|
|
|
|
3. Meilleure solution moyen terme:
|
|
- passer sur OpenAI Realtime/WebRTC
|
|
- gerer interruption, VAD, tour-taking et streaming audio nativement
|
|
- envoyer des evenements de session avec contexte pedagogique
|
|
- conserver en base les transcriptions et messages comme aujourd'hui
|
|
|
|
4. Donnees a stocker plus tard:
|
|
- `session_id`
|
|
- `message_type`: text, image, audio, interruption
|
|
- `source`: keyboard, microphone, system
|
|
- `interruption_of_message_id`
|
|
- timestamp debut/fin de parole
|
|
- confiance transcription
|
|
|
|
## Points de Vigilance
|
|
|
|
- Les erreurs WebSocket Vite/HMR sur `wss://prof.open-squared.tech/...` sont du bruit de dev tant que le frontend tourne via Vite derriere nginx.
|
|
- Ces erreurs ne sont pas la cause principale si `/api/*` renvoie des `502` ou si le micro se comporte mal.
|
|
- En cas de `502` sur `/api/*`, verifier d'abord `docker logs tutor-backend`.
|
|
- Pour tester l'auth locale actuelle: `.env` contient `ADMIN_USERNAME=admin` et `ADMIN_PASSWORD=admin`; a changer avant tout usage partage.
|
|
|
|
## Note Programme Pedagogique par Eleve
|
|
|
|
- Le mode admin doit devenir une gestion du programme par eleve.
|
|
- Pour chaque eleve configure, le professeur/admin doit pouvoir choisir une lecon dans le contenu disponible localement.
|
|
- La source prioritaire du contenu est:
|
|
- `C:\DataS\OpenSquared\OpenSchool\Programme\contenus_pedagogiques`
|
|
- Le contenu est classe par cycle, niveau et matiere:
|
|
- cycle 3: CM1, CM2, 6e
|
|
- cycle 4: 5e, 4e, 3e
|
|
- Pour un eleve de CM1, l'admin doit pouvoir choisir par exemple:
|
|
- mathematiques > nombres entiers
|
|
- Les fiches `.svg` associees a la lecon choisie doivent s'afficher dans la zone centrale de Professeur TOP cote eleve.
|
|
- Premier essai implemente: une affectation active par eleve, selectionnee en admin, puis visible dans l'ecran eleve.
|
|
- A prevoir ensuite:
|
|
- plusieurs cours possibles par eleve
|
|
- progression equilibree entre lecons et matieres
|
|
- instructions personnalisees par eleve
|
|
- suivi fin des fiches vues / exercices faits
|
|
- Vigilance langue française: les libellés visibles doivent utiliser les accents et formulations françaises correctes, par exemple `Démarrer la leçon`.
|
|
|
|
## Session Programme / Mobile / Fiches SVG
|
|
|
|
- Le contenu pedagogique a ete copie dans le repo sous:
|
|
- `backend/contenus_pedagogiques`
|
|
- Objectif: le `git pull` serveur doit recuperer les contenus pedagogiques en meme temps que l'application.
|
|
- Le backend cherche maintenant le contenu prioritairement dans:
|
|
- `backend/contenus_pedagogiques` en local
|
|
- `/app/contenus_pedagogiques` dans le conteneur backend
|
|
- puis les anciens chemins externes si besoin
|
|
- Le cas test valide localement:
|
|
- niveau: `CM1`
|
|
- lecon: `CM1 - Nombres entiers`
|
|
- 7 fiches SVG detectees
|
|
- Le mode admin ne doit plus afficher Professeur TOP ni permettre de dialoguer avec lui.
|
|
- Le mode admin est maintenant une console de gestion:
|
|
- selection / creation d'eleve
|
|
- affectation d'une lecon active
|
|
- resume de l'eleve selectionne
|
|
- apercu des fiches SVG de la lecon
|
|
- Le mode eleve reste le seul mode avec Professeur TOP, voix, saisie, micro et affichage de lecon.
|
|
- Les fiches SVG sont decoupees dynamiquement en etapes/cards a partir des grands groupes `<g>` internes.
|
|
- Exemple pour la premiere fiche `Lecture Ecriture Nombres Entiers`:
|
|
- `La méthode`
|
|
- `Exemple`
|
|
- `À retenir`
|
|
- `Exemples résolus`
|
|
- Le frontend avance maintenant par etape de fiche plutot que seulement par fiche entiere.
|
|
- Le pourcentage affiche dans la lecon est calcule sur toutes les etapes detectees:
|
|
- progression proportionnelle
|
|
- fin de parcours arrondie a 100%
|
|
- Sur laptop:
|
|
- la fiche/card reste lisible dans la zone centrale
|
|
- le parcours pedagogique doit quand meme suivre les cards une par une
|
|
- Sur telephone:
|
|
- ne pas afficher les 7 fiches d'un coup
|
|
- ne pas afficher la fiche paysage complete
|
|
- afficher une seule card recadree en gros plan
|
|
- la card doit prendre le maximum de largeur possible
|
|
- eviter les doubles encadrements: pas de card dans une card dans l'encadre bleu
|
|
- les bords de la card doivent presque toucher les cotes de l'ecran
|
|
- les boutons precedent/suivant doivent rester petits et secondaires
|
|
- une seule zone eleve en bas: elle sert a la fois a taper et a recevoir la transcription micro
|
|
- Le bouton/lien "Agrandir la fiche" a ete retire apres decoupage des cards: la card doit etre lisible directement.
|
|
- Le texte visible de Professeur TOP est compacte a l'ecran pour garder de la place a la card.
|
|
- La voix peut rester plus longue, mais l'affichage texte ne doit pas occuper trop de hauteur.
|
|
- Le frontend envoie maintenant au backend un contexte de lecon avec `/chat`:
|
|
- titre de lecon
|
|
- titre de fiche
|
|
- titre de card/section affichee
|
|
- pourcentage d'avancement
|
|
- Le backend ajoute ce contexte au prompt pour que Professeur TOP parle de la card actuellement affichee.
|
|
- Au demarrage de seance, si une lecon est affectee, Professeur TOP doit parler de la premiere card affichee et verifier la comprehension.
|
|
- Probleme restant important:
|
|
- Professeur TOP ne pilote pas encore automatiquement le changement de card.
|
|
- Prochaine brique: faire produire une intention structuree du type `advance_lesson_step=true` quand l'eleve dit qu'il a compris.
|
|
- Le frontend devra alors avancer automatiquement a la card suivante.
|
|
- Probleme principal restant:
|
|
- Le discours de Professeur TOP n'est pas encore assez correle a la card affichee.
|
|
- Le simple contexte `titre de card + titre de fiche` ne suffit pas toujours: le modele peut repartir sur l'historique ou une notion voisine.
|
|
- Il faudra probablement generer et stocker un texte pedagogique specifique par fiche/card.
|
|
- Ce texte de card devra decrire exactement ce qui est affiche, proposer une consigne orale courte et verifier la comprehension.
|
|
- Exemple attendu: pour la card `La méthode`, Professeur TOP doit expliquer le decoupage en groupes de 3 chiffres, puis demander si l'eleve comprend cette methode.
|
|
- Ces textes pourraient etre generes depuis les SVG/Markdown puis sauvegardes comme metadonnees de programme, plutot que recrees a chaque seance.
|
|
- Direction pedagogique retenue:
|
|
- Professeur TOP presente la card active.
|
|
- Il demande si l'eleve comprend.
|
|
- Si oui, il passe a la card suivante.
|
|
- Si non, il explique uniquement cette card, avec un exemple court.
|
|
- Sur laptop il peut dire par exemple "en haut a gauche, tu vois la méthode".
|
|
- Sur telephone il doit parler de la card affichee en gros plan.
|
|
|
|
## Plan de Dev Acces Eleve / Admin
|
|
|
|
1. Socle comptes et roles: table `users`, hash password, seed admin depuis `.env`, login, session courante.
|
|
2. Separation UI: `LoginPage`, `StudentApp`, `AdminApp`, composants partages.
|
|
3. Conversation persistante: endpoints de lecture messages, puis sessions et rattachement des messages/tentatives.
|
|
4. UI eleve sans scroll: Professeur TOP en haut, log de seance a gauche, derniere instruction au centre, saisie/micro en bas.
|
|
5. Dashboard prof/admin: creation eleves/comptes, rapports, historique seances, conversation complete, stats de reussite.
|
|
|
|
## Fichiers Touchés Pendant Cette Session
|
|
|
|
- `frontend/src/App.jsx`
|
|
- `frontend/src/styles.css`
|
|
- `frontend/src/assets/professeur-top.png`
|
|
- `frontend/vite.config.js`
|
|
- `backend/app/main.py`
|
|
- `backend/app/schemas.py`
|
|
- `backend/app/services.py`
|
|
- `backend/requirements.txt`
|
|
- `README.md`
|
|
- `MEMORY.md`
|
|
|