4.3 KiB
4.3 KiB
PROFILE_LANGUAGE_SPEC — langue par profil patient (pipeline STT/LLM/TTS)
Destinataire : dev de l'app patiente
com.kazeia. Auteur : Kazeia-central. Stack figée (FROZEN.md) → changement décrit ici, livré.Objet : la langue du pipeline doit être choisie par patient (porté par le profil), pas figée en
"fr". Kazeia-central gère/édite la langue par profil et la pousse ; l'app doit l'exposer (provider) et l'appliquer (pipeline).
0. État observé (vérifié)
- Le pipeline est déjà paramétré par langue :
KazeiaPipelinepassecontext.languageàsttEngine.transcribe(audio, context.language)etttsEngine.synthesizeAndPlay(text, context.language, …).OmniVoiceTtsEngine.langCode()résout un nom/alias → code (646 langues).WhisperHybridEngine.transcribe(audio, language)prend aussi la langue. - MAIS la langue est codée en dur
"fr":KazeiaServiceappellestt.transcribe(audioSnapshot, language = "fr")(≈ lignes 1100 et 1351) ;core/Pipeline.ktalanguage: String = "fr"par défaut. La langue n'est pas lue depuis le profil. Profile(profiles/Profile.kt) n'a aucun champ langue :id, displayName, avatarColor, voiceId, systemPromptOverride, pinHash, createdAt, lastUsedAt, notes, isDefault.KazeiaServicea déjà l'accès au profil actif et y réagit :ProfileStore.get(ctx).activeProfile();onProfileStoreChanged()applique déjàactiveProfile().voiceId → setVoice. C'est exactement là qu'il faut résoudre la langue.
1. Adaptation demandée
1.1 Profile — nouveau champ language
profiles/Profile.kt : ajouter
val language: String = "fr", // code/nom résolu par OmniVoiceTtsEngine.langCode() (déf. fr)
toJson():put("language", language).fromJson():language = js.optString("language", "fr")(rétro-compat : profils existants sans le champ →"fr").- Valeur : un code court (
fr,en,de,es,it,pt,ar,zh, …) ou un nom quelangCode()sait résoudre. Kazeia-central enverra un code court.
1.2 Provider /profiles — exposer + accepter language
voicesCursor/profilesCursor: ajouter la colonnelanguage(déf."fr").upsertProfile(ContentValues): lire la clélanguagesi présente (sinon conserver l'existant / défaut"fr"). Ajout additif → compat ascendante.- (Le canal d'écriture riche
profile_upsert_jsonduPROVIDER_RPC_SPEC §4.4doit aussi inclurelanguagequand il sera implémenté ; en attendant,update /profilesavec la clélanguagesuffit pour ce champ simple.)
1.3 KazeiaService — appliquer la langue du profil actif
Remplacer le "fr" figé par la langue du profil actif (avec repli "fr") :
val lang = ProfileStore.get(applicationContext).activeProfile()?.language ?: "fr"
// … construire le PipelineContext avec language = lang ;
// … stt.transcribe(audio, language = lang) aux ~l.1100 et ~l.1351.
- À recalculer sur changement de profil actif (
onProfileStoreChanged(), déjà le point où la voix est ré-appliquée) — pour qu'un changement de patient change la langue à chaud.
2. Ce que fait Kazeia-central (pour info — pas côté app)
- Édite la langue par profil et la pousse (via
update /profiles/ futurprofile_upsert_json). - Tient la fiche patient complète (identité civile, contact/référent, clinique) dans
son store chiffré, clé
(serial, profile_id). Cette fiche ne va PAS sur la tablette (PII clinique, minimisation on-device). Seul l'opérationnel (langue, voix, prompt) concerne le device.
3. Récap
| # | Adaptation app | Criticité |
|---|---|---|
| 1 | Profile.language (+ toJson/fromJson, déf. "fr") |
requis |
| 2 | /profiles expose + accepte language |
requis |
| 3 | KazeiaService : context.language = activeProfile.language ?: "fr" (remplace le "fr" figé), ré-appliqué au changement de profil |
requis |
Changement borné : le pipeline sait déjà gérer la langue ; il ne manque que la relier au profil.
Source de vérité : Profile.kt, KazeiaService.kt (~l.1100/1351), KazeiaPipeline.kt,
OmniVoiceTtsEngine.langCode(), WhisperHybridEngine.transcribe(). Vérifié le 2026-06-23.