Files
open-school/MEMORY.md
2026-05-12 23:44:30 +02:00

316 lines
19 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`
## Session 2026-05-12 - Architecture contenus programme et SVG fractions
- Decision structurante: chaque lecon doit suivre l'arborescence canonique `lecon.md`, `fiches/*/fiche.md + fiche.svg`, `cards/*/card_XX.md + card_XX.svg`, `exercices/*/exercices.md + exercices.svg`, `tests/*`, `exercices/parcours_adaptes/*`, `sources/*`.
- `kit_adaptatif`, `svg/`, `card_contexts/` et `exercices_svg/` sont des dossiers legacy. Une nouvelle generation ne doit plus les produire.
- Chaque contenu pedagogique doit garder une section `Sources` ou un contexte equivalent pour audit Education nationale: PDF officiel, extraction locale, cycle, niveau, matiere, theme, date/validation si connue.
- `PROGRAM_CONTENT_ARCHITECTURE.md` est la reference de l'arborescence canonique et du flux pedagogique.
- `01B_fractions` et `01A_nombres_entiers` ont ete migres dans cette structure, dans les deux miroirs `backend/contenus_pedagogiques/...` et `Programme/contenus_pedagogiques/...`.
- Le loader programme doit parcourir les types utiles dans l'UI: `lesson`, `fiche`, `card`, `exercice`, `test`, `support`. Plus de type editorial `kit`.
- Le modele doit charger `lecon.md` comme contexte general, puis le contexte specifique de l'objet actif: fiche, card, exercice ou test.
- `backend/app/program_content.py` lit les parcours adaptes recursivement avec `rglob`, afin que `exercices/parcours_adaptes/<profil>/exercices.md + exercices.svg` soit visible dans l'arbre et dans le contexte adaptatif.
- La validation globale doit afficher SVG et contexte ensemble. Dans l'onglet `Programme global`, la zone de droite a ete reorganisee: SVG et Markdown se partagent l'espace, et le bouton `Ouvrir dans Validation contenus` flotte discretement en bas a droite.
- Piege majeur sur les fractions SVG: `text@y` est une baseline, pas le bord visible du chiffre. Les tests qui regardent seulement `bar_y - text_y` donnent de faux verts.
- Regle retenue pour les fractions: tester la clairance visible estimee entre barre et glyphes, via `numerator_bottom = y + font_size * 0.25` et `denominator_top = y - font_size * 0.85`.
- Les fractions doivent porter `class="math-expression fraction-g"`, `data-math="fraction"` et un `data-box` recalcule autour du rendu reel.
- Les outils importants: `backend/tools/validate_svg_quality.py`, `backend/tools/regenerate_fraction_exercise_svgs.py`, `backend/tools/compact_fraction_svg_spacing.py`, `backend/tools/migrate_nombres_entiers_content.py`.
- Validation de fin de session: fractions strictes OK dans les deux miroirs, nombres entiers OK pendant migration, `npm.cmd run build` OK apres ajustement UI.
- A retenir pour la suite: avant toute validation humaine des SVG fractions, lancer le validateur strict sur les deux miroirs et inspecter visuellement au moins le premier exercice de chaque famille, car les faux verts de baseline ont deja ete observes.