尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
Anna : communication Oui/Non (Entourage, questions de suivi, voix naturelle)
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Interface de communication reprise de la maquette localhost:3000 : catégories, questions Oui / Non, demande de parole, épellation, programme et espace admin.
L’accueil conserve la photo d’Anna. « Poser la question » ouvre la nouvelle interface : « Coucou, est-ce que tu veux parler ? », puis la question de départ de la banque (« Ça va ? »). La réponse détermine l’ordre des thèmes et les branches disponibles. « Non, pas maintenant » affiche un écran calme avec un bouton Reprendre. On peut aussi passer directement aux thèmes.
La grille conserve le design de la maquette localhost:3000 : une ligne Top 3, puis une ligne par catégorie, avec ses trois premières sous-catégories et Voir plus. La pagination donne accès à toutes les catégories. Une catégorie ouvre toutes ses sous-catégories ; une sous-catégorie ouvre uniquement ses questions, dans leur ordre enregistré. Une question ouvre le parcours Oui / Non et ses sous-questions. Les tuiles et leurs pictogrammes proviennent des nœuds de la banque partagée ; les personnes liées affichent leur initiale. Tout parcourir conserve le parcours catégorie → sous-catégorie → question → sous-question. Les branches Oui / Non et le lieu filtrent également la grille.
Répondre par Oui / Non au toucher, au clavier (O / N) ou avec la tête après activation de la caméra. « Je veux parler » reste une commande d’assistance indépendante.
Oui descend au niveau suivant ; Non passe à l’élément suivant du même niveau. Une phrase Non explicitement renseignée, notamment un refus d’autorisation, est restituée comme réponse et termine la branche. En fin de branche, la phrase Oui du dernier élément retenu est affichée. Retour permet de corriger la dernière réponse ; Accueil revient à l’ouverture.
Les catégories suivent ordre_si_oui ou ordre_si_non après la réponse à « Ça va ? », avec repli sur ordre. Les sous-catégories respectent branche_oui_non. Chaque niveau suit ensuite son ordre ; les valeurs vides viennent après les valeurs renseignées et conservent l’ordre d’import. Les égalités gardent également l’ordre d’import.
Les CSV sont dans data/questions/ : 6 catégories, 27 sous-catégories, 99 questions, 120 sous-questions et 42 personnes. Les anciens CSV restent archivés dans data/questions/legacy/. La colonne libelle donne le texte court des tuiles et du fil d’Ariane ; vide, il est déduit de l’identifiant. suivi.csv liste les questions de suivi proposées à l’entourage une fois un besoin trouvé (element_id = l’élément concerné, par exemple subcat:douleur ; modifiables ensuite dans l’admin). L’import valide les identifiants, parents, personnes et liens de contraire :
python3 scripts/import_questions.py
Les jours autorisés filtrent les questions et les personnes, selon la date de Paris. Le week-end, ordre_weekend est prioritaire lorsqu’il est renseigné. Le lieu choisi dans Réglages filtre centre / domicile. Les personnes liées sont également filtrées selon les actions autorisées (contacter, voir, parler), le genre et le statut de référent de la branche.
Le Top 3 applique le poids de la question et celui de la personne liée. Les créneaux heures_pic multiplient le score par 1,5 ; une question epingler_pic est prioritaire pendant son créneau. Le début d’un créneau est inclus et sa fin exclue. Deux questions liées par contraire_id ne sont pas proposées ensemble dans le Top 3.
Le bouton Caméra demande l’autorisation du navigateur, puis utilise MediaPipe localement, comme la maquette : tête vers sa gauche = oui, vers sa droite = non, pencher une seconde = parler. La caméra arrière est privilégiée pour qu’un accompagnant tienne le téléphone face à Anna. Les images restent dans le navigateur. La reconnaissance doit être calibrée avec Anna ; les boutons et le clavier restent disponibles.
L’admin propose Résumé, Questions, Personnes et Réglages, et s’ouvre directement sur la banque. Résumé affiche l’historique partagé et les réponses détaillées, avec filtre par thème et actualisation. L’onglet Questions montre les cinq niveaux de la hiérarchie, avec recherche, ajout, modification et suppression. On peut modifier le texte, le libellé, le parent, les ordres, les phrases Oui/Non, la branche et les lieux autorisés. Supprimer un élément supprime aussi ses descendants après confirmation. La question de départ est modifiable mais ne peut pas être supprimée. Les questions et sous-questions exposent aussi les poids, jours, ordres du week-end, contraires et personnes liées ; les questions proposent les créneaux et l’épinglage. L’onglet Personnes permet de modifier les noms, groupes, actions autorisées, jours, poids et référents. Renommer une personne actualise ses textes liés. Pour une nouvelle personne, ajouter explicitement ses questions dans Questions. Pendant une sauvegarde, le bouton affiche « Enregistrement en cours… » et empêche les doubles envois.
Les questions, les personnes et les réglages sont conservés dans un stockage privé Vercel Blob, commun à tous les utilisateurs et durable entre déploiements. L’admin n’annonce un enregistrement qu’après sa sauvegarde sur le serveur. Les pages publiques ouvertes vérifient les mises à jour toutes les 15 secondes et à leur retour au premier plan. Si la banque change pendant le parcours, celui-ci reprend au départ avec un message.
Au premier chargement de l’admin, si le stockage partagé est vide, la banque personnalisée de cet ancien navigateur est automatiquement importée, avec ses personnes et réglages. Ouvrir l’admin dans le navigateur qui contient les modifications à conserver. Une banque partagée déjà initialisée n’est jamais écrasée par les anciennes données locales d’un autre appareil. Les anciennes banques locales restent disponibles en sauvegarde ; la préférence vocale reste propre à chaque appareil.
À partir de cette version, les réponses Oui/Non, les temps de réponse et les résultats des échanges (y compris demandes de parole et messages épelés) sont enregistrés dans anna/activity.json, séparément de la configuration anna/config.json. Il n’y a aucun identifiant permanent de personne ou d’appareil. Les identifiants aléatoires des échanges et envois permettent les corrections et la déduplication. Les réponses en attente restent sur l’appareil jusqu’à confirmation du serveur et sont renvoyées après reconnexion. La fenêtre de déduplication conserve les 5 000 derniers identifiants. Les échanges supprimés par l’ancienne version ne sont pas reconstitués.
L’historique conserve les 300 derniers échanges et les 2 000 dernières réponses détaillées. Les statistiques par question sont cumulatives : nombre de réponses, Oui/Non, temps cumulé et heures habituelles des Oui (heure de Paris). Le Top 3 s’appuie sur le taux de Oui (50 %), l’usage relatif (30 %) et la rapidité (20 %), avec un bonus pour l’heure habituelle. Après les questions épinglées actives, il propose un besoin par thème prioritaire selon les ordres et branches de la banque. Le parcours complet conserve toujours les ordres explicites. Les statistiques d’ouverture ne biaisent pas le score d’usage des questions.
Le serveur Python conserve FastAPI et les mêmes identifiants. GET /api/config fournit la banque ; PUT /api/config, /admin, /api/admin-session et GET /api/history sont protégés : /admin affiche un formulaire de connexion (POST /api/admin-login) qui ouvre une session de 12 h par cookie signé (HttpOnly, SameSite=Strict) ; HTTP Basic reste accepté pour les scripts. POST /api/interactions reçoit les événements validés et GET /api/usage ne fournit que les statistiques agrégées pour le Top 3. Aucun texte d’échange ni réponse individuelle n’est accessible via cet endpoint public. La configuration refuse toujours les champs d’interactions.
Chaque écriture de configuration exige la version affichée (If-Match) ; une modification concurrente est refusée avec un message demandant de recharger. Les écritures d’usages utilisent aussi une condition de version et sont fusionnées après conflit afin de conserver les réponses de plusieurs utilisateurs. Les lectures contournent le cache du stockage pour refléter les enregistrements.
Définir ADMIN_USERNAME, ADMIN_PASSWORD et BLOB_READ_WRITE_TOKEN dans les variables de production Vercel. La connexion au magasin privé anna-shared-questions fournit le jeton Blob. Les valeurs ne sont jamais dans GitHub ni envoyées au navigateur. Sans stockage configuré en production, le serveur renvoie une erreur au lieu de prétendre enregistrer dans un fichier temporaire. L’identifiant ne tient pas compte des majuscules ni des espaces autour ; les espaces ou retours à la ligne collés dans Vercel sont ignorés. Après un changement de variable dans Vercel, redéployer pour l’appliquer ; changer le mot de passe déconnecte toutes les sessions. « Se déconnecter » est en haut de l’admin.
Les polices viennent de Google Fonts et le modèle de caméra de MediaPipe/Google.
Les phrases fixes (questions, Oui / Non, phrases d’Anna, questions de suivi, Entourage, épellation : environ 820 phrases, 25 000 caractères) sont pré-enregistrées avec ElevenLabs depuis Admin → Réglages → « Voix naturelle ». L’application joue l’enregistrement quand il existe et utilise sinon la voix de l’appareil (Chrome), y compris si le téléchargement ou la lecture échoue. Les messages épelés et autres textes libres ne sont jamais envoyés à ElevenLabs. Après une modification de question, revenir sur « Voix naturelle » pour enregistrer les nouvelles phrases.
Variables Vercel (production) : ELEVENLABS_API_KEY et ELEVENLABS_VOICE_ID (une voix française choisie dans la Voice Library d’ElevenLabs, ajoutée à « My Voices », dont on copie l’identifiant), ELEVENLABS_MODEL facultatif (eleven_multilingual_v2 par défaut). Changer de voix ou de modèle demande un nouvel enregistrement. Les fichiers sont stockés dans le magasin Blob privé (anna/voices/) et servis par GET /api/voices/<clé>.mp3 ; en local, dans data/voices/ (ignoré par Git). La clé ElevenLabs ne sert qu’à l’enregistrement depuis l’admin, jamais pendant une conversation. Vercel conserve ses métadonnées habituelles de requêtes.
Python 3.12, uv et Node.js pour les tests JavaScript.
uv sync
export ADMIN_USERNAME="votre-identifiant"
export ADMIN_PASSWORD="votre-mot-de-passe"
uv run uvicorn app:app --reload
Ouvrir http://127.0.0.1:8000. Sans jeton Blob, le serveur local utilise data/config.local.json et data/activity.local.json (ignorés par Git), avec verrou et remplacement atomique. ANNA_CONFIG_FILE et ANNA_ACTIVITY_FILE permettent de choisir d’autres fichiers. Si la configuration uv locale utilise un proxy indisponible : uv --no-config sync.
uv run pytest
npm test
npm run check
Aucune dépendance npm n’est nécessaire. Le backend reste FastAPI, avec dépendances verrouillées dans uv.lock.
Le dépôt est relié à Vercel : chaque push sur main déclenche un déploiement de production. Le preset FastAPI et le point d’entrée app.py sont déclarés à la racine. Le magasin Blob doit être relié au projet et à l’environnement de production ; .env.local et .vercel/ sont ignorés par Git.
Pour remplacer une banque existante par les nouveaux CSV, déployer d’abord le code compatible, puis valider et appliquer la migration :
.venv/bin/python scripts/migrate_question_bank.py --env-file .env.local
.venv/bin/python scripts/migrate_question_bank.py --env-file .env.local --apply
La migration archive la configuration précédente dans le stockage privé avant de remplacer la banque et les personnes par les CSV. Elle conserve la question de départ, les réglages, l’historique et les statistiques. Une version CSV déjà importée n’est pas réappliquée, afin de préserver les modifications ultérieures de l’admin.
Pour appliquer seulement les libellés et les questions de suivi des CSV à une banque existante, sans toucher au reste (essai à blanc par défaut, sauvegarde avant écriture ; ce qui a été modifié dans l’admin est conservé). Déployer d’abord le code, le site refusant sinon les questions de suivi :
uv run python scripts/update_bank_texts.py --url https://tom-hackathon-2026-anna.vercel.app
uv run python scripts/update_bank_texts.py --url https://tom-hackathon-2026-anna.vercel.app --apply
--apply demande l’identifiant admin. --env-file .env.local utilise à la place le jeton Blob, comme la migration.