kazeia/RAPPORT_KAZEIA_2026-05-04.md

25 KiB
Raw Permalink Blame History

Rapport Kazeia — État, architecture, performances

Date : 2026-05-04 Contexte : Kazeia est une application Android de soutien thérapeutique conversationnel (psychologue virtuel) tournant 100 % on-device sur OnePlus Pad 3, sans connectivité réseau requise et sans root utilisateur.


1. Synthèse exécutive

Ce qui fonctionne en production

  • Pipeline complet STT → LLM → TTS opérationnel, multi-tour, avec cascade Thinker+Speaker.
  • Latence end-to-end utilisable en conversation : 3-5 s entre la fin du PTT et le premier audio de réponse.
  • Stable mémoire après débloat ColorOS + désinstallation du watchdog OEM Athena.
  • Application 100 % autonome sur la tablette : aucun service réseau requis, modèles et runtime tous embarqués.
  • Stack figée et documentée (/opt/Kazeia/FROZEN.md).
  • Backup tablette complet et automatisable dans /opt/Kazeia/kazeia-tablet-backup/.

Limites actuelles connues

  • Le Thinker Guard-0.6B produit des bullets de qualité analytique limitée (modèle conçu pour classification de safety, détourné vers analyse clinique). Le Speaker compense en pratique mais l'apport qualitatif de la cascade est moins net qu'espéré.
  • Le rendu UI de l'orbe (cycle couleurs pendant Thinking) demande encore validation visuelle utilisateur.
  • Conversation history non persisté entre sessions (à dessein actuellement).
  • Pas de fine-tuning thérapeutique français spécifique sur les modèles — on utilise Qwen3-4B générique pré-entraîné.

2. Plateforme matérielle

Composant Spec
Tablette OnePlus Pad 3 (OPD2415EEA)
RAM 16 GB LPDDR5X
Stockage 256 GB UFS
SoC Snapdragon 8 Elite
CPU Oryon (8 cœurs ARMv9)
GPU Adreno 830
NPU/DSP Hexagon V79 (HMX/HVX)
OS Android 16, ColorOS post-2026-03-18 OTA
Root Aucun (user mode standard)

3. Stack logicielle

┌────────────────────────────────────────────────────────────────┐
│                  Kazeia Android App (Kotlin)                    │
│                    /data/app/.../com.kazeia                     │
└───────────────────┬─────────────────────────┬───────────────────┘
                    │                         │
        ┌───────────▼──────────┐  ┌───────────▼──────────┐
        │   KazeiaService      │  │   ChatActivity (UI)  │
        │  (state machine)     │  │   AudioVisualizerView│
        │  • PTT               │  │   (orb HSV cycle)    │
        │  • Cascade           │  └──────────────────────┘
        │  • Pipeline state    │
        └─┬────────┬────────┬──┘
          │        │        │
   ┌──────▼─┐  ┌───▼────┐ ┌─▼──────┐
   │  STT   │  │  LLM   │ │  TTS   │
   │ Engine │  │ Engine │ │ Engine │
   └────────┘  └────────┘ └────────┘

3.1 STT — Whisper-Small NPU (QAIRT)

  • Modèle : HfWhisper-Small (12 layers, 12 heads)
  • Format : QAIRT context binary (Qualcomm SDK natif)
  • Fichiers :
    • HfWhisperEncoder_qairt_context.bin (210 MB)
    • HfWhisperDecoder_qairt_context.bin (361 MB)
  • Backend : Hexagon V79 via QAIRT runtime (libQnnHtpV79Skel.so)
  • VAD : RMS énergie inline (seuil 80, frames 100 ms)
  • Mode : continuous listening avec streaming Whisper pendant PTT
  • Performance mesurée : RTF 0.4 (transcription "Bonjour" ~640 ms total : mel 260 ms + encoder 115 ms + decoder 170 ms)

3.2 LLM — Cascade Option E v2 (in-process)

Architecture cascade : 2 LlmModule ExecuTorch dans le même process app, partageant le QnnBackendBundle via le singleton QnnBackendUnifiedRegistry (donc 1 seul handle fastrpc DSP, pas de collision).

Process com.kazeia
├── Speaker  Qwen3-4B          (.pte 3.3 GB, ~4.4 GB ION)
│   └── system prompt: SYS_KAZEIA + "Indices internes (NE PAS RÉPÉTER) : ..."
└── Thinker  Qwen3Guard-Gen-0.6B (.pte 700 MB, lazy first PTT)
    └── system prompt: SYS_THINKER (4 bullets émotion/besoin/approche/axe)
Composant Modèle Format Taille Quantization
Speaker Qwen/Qwen3-4B ExecuTorch .pte QNN HTP V79 3.3 GB Q4 W4A16
Thinker Qwen/Qwen3Guard-Gen-0.6B ExecuTorch .pte QNN HTP V79 700 MB Q4 W4A16

Cascade sequence par tour utilisateur :

  1. STT → texte patient (transcription Whisper)
  2. Thinker pass : Guard-0.6B(SYS_THINKER + msg) → 4 bullets cliniques
  3. Bullets tronqués à 400 chars (sécurité prefill budget)
  4. Speaker pass : Qwen3-4B(SYS_KAZEIA + bullets en system, msg en user) → réponse 1-2 phrases
  5. Streaming TTS phrase par phrase au fur et à mesure du décodage

3.3 TTS — Qwen3-TTS ggml-cpu

  • Modèle source : Qwen3-TTS-0.6B-Base (clonage vocal)
  • Pipeline 3 étapes, toutes en CPU pur (NEON ARMv9, pas de DSP) :
Étape Modèle Fichier Taille Backend
Talker transformer audio → tokens semantic talker_f16.gguf 851 MB ggml-cpu
Code Predictor (CP) sem → 16 codebooks RVQ cp_q8_0.gguf 84 MB + 240 MB embeds ggml-cpu
Decoder RVQ → mel → audio 24 kHz qwen3tts_decoder.gguf 325 MB ggml-cpu (libtts_decoder_ggml)
  • Voice cloning : prefix/suffix embeddings pré-extraits (10 voix : damien, elodie, jerome, richard, sid, zelda, didier, amir...)
  • Streaming sentence-level : audio joue dès la 1ère phrase pendant que LLM décode encore les suivantes (Opt TTS-B)
  • RTF mesuré : 0.96 sur tablette (chraac-llama fork)

3.4 Glue applicative

Composant Rôle
KazeiaService (Kotlin) State machine PTT + cascade + pipeline
ExecuTorchLlmEngine Wrapper Java→JNI sur LlmModule ExecuTorch
Qwen3TtsEngine Orchestration JNI Talker+CP+Decoder + voice clone
WhisperHybridEngine JNI QAIRT + mel extractor NEON
AudioVisualizerView Orbe Canvas, HSV cycle pendant Thinking
SentenceStreamer Découpage phrases pour streaming TTS
PipelineMetrics Instrumentation timings end-to-end

4. Performances mesurées

4.1 Latences par étape (mesures réelles dans logcat)

Étape Temps typique Note
STT Whisper-Small 460-680 ms RTF 0.4 sur audio 1.7s
├ Mel extraction 190-270 ms NEON sur CPU
├ Encoder NPU 115 ms QAIRT V79
└ Decoder NPU 75-300 ms dépend du nb tokens
Thinker (Guard-0.6B) 446 ms 22 tokens à 49 tok/s, TTFT 130 ms
├ Lazy load (1ère fois) 1 088 ms -844 MB MemAvailable
└ Inference 446 ms 4 bullets, prompt ~180 tok
Speaker (Qwen3-4B) 1 000-2 200 ms 14-46 tokens à 14-21 tok/s, TTFT 190 ms
├ resetContext <1 ms clear KV cache
├ Prefill (~150 tok) 200 ms hybrid mode AR=128
└ Decode 800-2000 ms 13.9-21 tok/s selon longueur
TTS Talker step ~25 ms ggml-cpu NEON
TTS CP step ~43 ms Q8_0, optimisé
TTS Decoder full RTF 0.96 ggml-cpu, premier audio <1 s

4.2 Latence end-to-end PTT → 1ᵉʳ audio

PTT release   ─┬───── 100 ms     finalize segment
                │
    ╔═══ 600 ms ═══════ STT Whisper                     ─┐
    ║                                                    │
    ╠═══ 450 ms ═══════ Thinker Guard-0.6B               │ utilisateur
    ║                                                    │ entend silence
    ╠═══ 500 ms ═══════ Speaker prefill + 1ère phrase    │
    ║                                                    │
    ╠═══ 800 ms ═══════ TTS 1ère phrase synthèse         ─┘
    ║
    ▼ 1ᵉʳ audio joué      (~ 2.5 s après PTT release)

Total PTT release → 1ᵉʳ audio : ~ 2.5 s (pour message court). Total PTT release → réponse complète audio : ~ 4-6 s.

4.3 Throughput LLM mesuré

Modèle Hardware Decode tok/s TTFT
Qwen3-4B Speaker Hexagon V79 14-21 190 ms
Guard-0.6B Thinker Hexagon V79 49 130 ms
Whisper-Small Hexagon V79 n/a (encoder/decoder fusion) 115+75 ms

5. Profil mémoire

5.1 Tablette en idle (Speaker chargé, Thinker pas encore)

Métrique Valeur
MemAvailable 5.10 GB
Cached (file cache) 4.51 GB
Process Kazeia RSS 2.06 GB
Process Kazeia PSS total 2.14 GB

5.2 Décomposition PSS Kazeia (idle)

Section PSS %
Native Heap (modèles, ION, native libs) 1.65 GB 77 %
Java/Dalvik Heap 362 MB 17 %
Graphics (EGL/GL) 64 MB 3 %
Code (.so + .apk + .dex mmap) 42 MB 2 %
Stack/divers 26 MB 1 %
TOTAL PSS 2.14 GB

5.3 Pendant cascade et TTS

Idle Cascade Thinker TTS pic
RSS Kazeia 2.06 GB ~2.9 GB ~3.5 GB
ION DSP cumulé ~3.3 GB ~5.0 GB ~5.5 GB
MemAvailable 5.10 GB 4.0 GB 3.0 GB

Le pic TTS reste loin du seuil critique (~1 GB MemAvailable où Linux LMK commencerait à killer). Stable.

5.4 Tablet baseline (sans Kazeia)

  • Stock fraîche : MemAvailable ~3.5 GB (900+ processus OEM ColorOS)
  • Après débloat + reboot : MemAvailable ~11.1 GB → +7.7 GB de marge

6. Trajectoire — Ce qui a été fait

Phase A : Pipeline initial (avril 2026)

  • Migration v1 du PoC Python/Flask vers app Android Kotlin native
  • Speaker via ExecuTorch QNN delegate (Qwen3-4B .pte hybrid mode)
  • STT Whisper-Small NPU via QAIRT
  • TTS Qwen3-TTS originalement en ExecuTorch .pte

Phase B : Migration TTS vers ggml-cpu (avril-mai 2026)

  • Talker exporté en GGUF f16 (vs .pte ExecuTorch)
  • CP exporté en GGUF Q8_0 (84 MB vs 316 MB f32 vs 158 MB f16)
  • Decoder porté en C++ via libtts_decoder_ggml.so
  • Validation RTF < 1 sur tablette (chraac-llama fork)

Phase C : Tablette stabilisation (mai 2026)

  • Mesure baseline ColorOS : ~3.5 GB MemAvailable seulement
  • Débloat sans root : 84 packages désinstallés via pm uninstall --user 0
  • Athena watchdog : désinstallation du package (kill ION quota 2 GB sur app)
  • Suppression de symlinks ⚠ SELinux ColorOS sans Magisk les bloque
  • Backup complet 25 GB dans /opt/Kazeia/kazeia-tablet-backup/
  • Factory reset + restore réussi

Phase D : Cascade Thinker+Speaker (mai 2026)

Tentatives successives :

Tentative Approche Résultat
1 Subprocess qnn_llama_runner daemon ✗ Collision DSP fastrpc (2 sessions QNN HTP)
2 Option E v1 : 2 LlmModule (Speaker 4B + Guard 4B) ✗ OOM Linux LMK (8.8 GB ION cumulé)
3 Option B : 2-pass sur même Speaker ✓ Stable, qualité Thinker faible (Qwen3-4B générique)
4 Option E v2 : Speaker 4B + Guard-0.6B ✓ Production actuelle

Pour Option E v2 : export Qwen3Guard-Gen-0.6B HF → ExecuTorch .pte QNN HTP V79 en local via executorch.examples.qualcomm.oss_scripts.llama (registration ajoutée dans __init__.py + decoder_constants.py).

Phase E : Robustesse runtime (mai 2026)

  • Fix VAD seuil RMS (150 → 80) après calibration mic post-reset
  • Fix PTT release : finalisation forcée du segment (sans ça, le LLM n'était jamais déclenché si bruit ambiant > seuil)
  • Fix seq_len ExecuTorch : passer 512 (max compilé .pte) au lieu de maxNewTokens (assertion cur_pos+prompt < seq_len)
  • Fix cur_pos_ accumulation : appel LlmModule.resetContext() à chaque generate (sinon crash après quelques tours)
  • Fix prefill() overflow : truncation bullets à 400 chars (Guard-0.6B peut rambler et faire dépasser le budget prefill du Speaker)
  • Fix Speaker régurgitant les bullets : injection bullets dans system prompt (avec instruction « NE PAS RÉPÉTER ») au lieu du user prompt
  • Fix orbe visuelle : Paint.shader = null avant pose couleur dans drawThinking (sinon le shader posé par drawIdle masquait la couleur)

Phase F : Backup APK + scripts (en continu)

  • /opt/Kazeia/kazeia-tablet-backup/ (25 GB total)
    • APK actuelle (110 MB, libs natives custom bundlées)
    • Modèles TTS+STT (12 GB)
    • LLM .pte (12 GB inc. Guard-0.6B nouveau)
    • Voix de référence (130 MB)
    • restore.sh automatisé
  • /opt/Kazeia/kazeia-debloat/ : safelist.txt + debloat.sh + rebloat.sh
  • /opt/Kazeia/export_guard_06b.sh : pipeline d'export Guard-0.6B reproducible

7. Architecture cascade détaillée (Option E v2)

┌──────────────────────────────────────────────────────────────────┐
│                        KazeiaService                              │
│                                                                   │
│   PTT release ───► startContinuousListening() drains buffer      │
│                  ►   processSpeechInput / streaming Whisper      │
│                  ►   text = "Comment ça va ?"                    │
│                  ►   processLlmResponse(text)                    │
│                                                                   │
│         ┌─ ensureThinkerEngine() ──┐  (lazy 1ère fois ~1.1 s)   │
│         │                           ▼                             │
│         │                 ┌─────────────────────┐                │
│         │                 │ thinkerEngine       │                │
│         │                 │ ExecuTorchLlmEngine │                │
│         │                 │ Guard-0.6B          │                │
│         │                 │ SYS_THINKER         │                │
│         │                 │ T=0.0, max 128 tok  │                │
│         │                 └──────────┬──────────┘                │
│         │                            ▼                            │
│         │                  bullets (400 chars max)                │
│         │                            │                            │
│         │  ┌─────────────────────────┴──────┐                    │
│         │  │  speakerSystemPrompt =          │                   │
│         │  │  SYS_KAZEIA +                   │                   │
│         │  │  "\n\nIndices d'analyse...      │                   │
│         │  │   (NE PAS CITER) :\n" +         │                   │
│         │  │  bullets                        │                   │
│         │  └────────────┬────────────────────┘                   │
│         │               ▼                                         │
│         │     ┌──────────────────────────┐                       │
│         │     │ llm = ExecuTorchLlmEngine │                       │
│         │     │ Speaker Qwen3-4B          │                       │
│         │     │ generateWithSystem()      │                       │
│         │     │ system=above, user=msg    │                       │
│         │     │ T=0.7, max 450 tok        │                       │
│         │     └──────────┬───────────────┘                       │
│         │                ▼ token-by-token streaming               │
│         │     ┌──────────────────────────┐                       │
│         │     │ SentenceStreamer          │                       │
│         │     │ split sur . ! ?           │                       │
│         │     └──────────┬───────────────┘                       │
│         │                ▼ phrase à phrase                        │
│         │     ┌──────────────────────────┐                       │
│         │     │ Qwen3TtsEngine            │                       │
│         │     │ enqueueSentence()         │                       │
│         │     └──────────┬───────────────┘                       │
│         │                ▼                                        │
│         └─────► AudioPlayback (24 kHz mono, AudioTrack)          │
│                                                                   │
└──────────────────────────────────────────────────────────────────┘
                              │
                              ▼
                   ┌─────────────────────────┐
                   │ DSP Hexagon V79         │
                   │   • QAIRT (Whisper)     │
                   │   • ExecuTorch QNN HTP  │
                   │     (Speaker + Thinker  │
                   │      partagent bundle)  │
                   └─────────────────────────┘
                              │
                              ▼
                   ┌─────────────────────────┐
                   │ CPU NEON ARMv9          │
                   │   • TTS Talker (ggml)   │
                   │   • TTS CP (ggml)       │
                   │   • TTS Decoder (ggml)  │
                   └─────────────────────────┘

8. Prompts système (production)

Speaker

Tu es Kazeia, psychologue bienveillant. Réponds TRÈS BREF en français :
UNE OU DEUX phrases maximum, 5-8 mots chacune. Validation émotionnelle simple.
Pas de remplissage, pas d'explication, pas de conseil non sollicité.
/no_think

[ + injection en cascade : ]
Indices d'analyse interne (NE PAS RÉPÉTER, NE PAS CITER, sert uniquement
à orienter le ton de ta réponse) :
- emotion : ...
- besoin : ...
- approche : ...
- axe : ...

Thinker

Tu es un psychologue clinicien experimente qui ecoute attentivement ton
patient. Avant de repondre, tu prepares une analyse silencieuse pour orienter
ta reponse. Produis UNIQUEMENT le bloc clinique au format strict suivant :
- emotion : <emotion principale ressentie, 5 mots max>
- besoin : <besoin sous-jacent du patient, 5 mots max>
- approche : <posture therapeutique adaptee, 5 mots max>
- axe : <point cle a valider ou explorer, 5 mots max>
Pas d'introduction, pas d'explication. Juste les 4 lignes en francais.
/no_think

9. Risques connus & mitigations

Risque Impact Mitigation actuelle Action future
Athena framework (system_server) tue Kazeia au-dessus de seuil RAM Crash app Débloat OEM réduit pression mémoire Investiguer si killable plus profond
LMK Linux kill si MemAvailable < 1 GB Crash app Marge 3 GB en pic actuel Lazy-load STT (-600 MB)
Speaker régurgite bullets cascade Phrases bizarres lues par TTS Bullets en system prompt + interdiction Fine-tune/instruction tuning
Thinker Guard-0.6B mal calibré pour analyse FR Bullets imprécis Speaker compense par sa robustesse Évaluer Qwen3-1.7B en remplacement
Whisper hallucinations sur silence "que tu entends ce que je dis ici." apparaît au repos Ignorer streaming results vides Filtre RMS/longueur audio min
Orbe ne change pas (avant fix) UX dégradée Paint.shader = null dans drawThinking OK
Symlinks .pte invisibles app Mode perroquet Fichiers réguliers (cp pas ln) OK, mémoire feedback enregistrée
OOM 2× ExecuTorch HTP 4B Crash Thinker = Guard-0.6B (5.1 GB ION total OK) Plus petit Thinker possible

10. Optimisations identifiées (memory profiling 2026-05-04)

Optim Effort Gain idle Gain pic Risque Recommandation
Strip jniLibs Hexagon non-V79 30 min 50 MB code 50 MB Bas Tier 1
Lazy-load Whisper STT 1 h 600 MB 0 Moyen (+0.5s 1ᵉʳ PTT) Tier 1
Trim Java heap (logs StateFlow) 1 h 100-200 MB 100 MB Bas Tier 1
Release Thinker entre tours 2 h 0 -700 MB Moyen (+1.5s 2ᵉ PTT) Tier 2
Talker GGUF Q8_0 (vs f16) 1 j 400 MB 400 MB Haut (qualité audio) Tier 2
Decoder Q4 sélectif 2-3 j 200 MB 200 MB Haut Tier 3
Re-export Speaker plus petit 5-10 j 500-1 000 MB similar Très haut Tier 3

11. Roadmap

Court terme (1-2 semaines)

  • Appliquer Tier 1 mémoire (strip libs + lazy STT + trim heap)
  • Évaluation qualitative cascade FR sur corpus thérapeutique 20+ prompts de référence
  • Comparer Guard-0.6B vs Qwen3-1.7B comme Thinker (export et bench)
  • Documenter procédure réinstallation tablette neuve (incl. débloat)

Moyen terme (1-2 mois)

  • Rewrite Kazeia Phase 1-5 (architecture propre Kotlin/JNI)
  • Voice clone .bin generator on-device (POC)
  • Persistance conversation history (Room database)
  • UI polish (mode conversation libre vs PTT)
  • Voice commands étendus

Long terme (3+ mois)

  • Fine-tuning thérapeutique français spécifique (LoRA)
  • Migration runtime briques (POC dans /opt/htp-runtime/) — alternative à ExecuTorch/QNN sur le long terme pour autonomie
  • Évaluation clinique avec professionnels santé mentale

12. Références — Fichiers clés

Code source app

  • /opt/Kazeia/kazeia-android/ — projet Gradle 8.12 / NDK r27d / API 36
    • app/src/main/java/com/kazeia/service/KazeiaService.kt — orchestrateur
    • app/src/main/java/com/kazeia/llm/ExecuTorchLlmEngine.kt — wrapper LLM
    • app/src/main/java/com/kazeia/tts/Qwen3TtsEngine.kt — TTS
    • app/src/main/java/com/kazeia/stt/WhisperHybridEngine.kt — STT
    • app/src/main/java/com/kazeia/ui/AudioVisualizerView.kt — orbe
    • app/src/main/jni/ — bridges JNI custom (libtts_*, libmel_extractor)

Scripts et outils

  • /opt/Kazeia/export_guard_06b.sh — export Qwen3Guard-Gen-0.6B → .pte
  • /opt/Kazeia/kazeia-debloat/ — débloat tablette
  • /opt/Kazeia/kazeia-tablet-backup/ — backup + restore
  • /opt/Kazeia/executorch/examples/qualcomm/oss_scripts/llama/ — pipeline export QNN HTP

Modèles tablette

  • /data/local/tmp/kazeia-et/hybrid_llama_qnn_4b.pte — Speaker
  • /data/local/tmp/kazeia-et/hybrid_llama_qnn_guard06b.pte — Thinker (nouveau)
  • /data/local/tmp/kazeia-et/tokenizer.json / tokenizer_guard06b.json
  • /data/local/tmp/kazeia/models/ — Talker, CP, Decoder GGUF, Whisper QAIRT
  • /data/local/tmp/kazeia/voix/ — voix de référence

Documents de référence

  • /opt/Kazeia/FROZEN.md — stack figée
  • /opt/Kazeia/kazeia-tts-perf-validated/ — TTS RTF<1 validé
  • /opt/Kazeia/kazeia-stt-perf-validated/ — STT RTF 0.4 validé
  • /opt/Kazeia/kazeia-debloat/README.md — procédure tablette

Mémoire persistante (sessions Claude Code)

  • /home/alf/.claude/projects/-opt-Kazeia/memory/MEMORY.md — index
  • 50+ entrées documentant chaque décision technique majeure

13. Conclusion

Kazeia tourne end-to-end stable sur OnePlus Pad 3 sans connexion internet, sans root utilisateur, avec des latences acceptables pour une conversation thérapeutique (3-5 s entre tours). L'architecture cascade Speaker+Thinker in-process via ExecuTorch QNN HTP est validée et reproductible.

Les principaux blocages historiques ont été résolus : DSP contention, OOM, SELinux symlinks, watchdog OEM, accumulation KV cache. La stack est documentée et figée, avec backup + procédure de restore complets.

Les axes d'amélioration restants sont incrémentaux (mémoire, qualité Thinker, UX) plutôt que structurels. Le pipeline est prêt pour évaluation clinique sur corpus de référence en français.


Rapport généré 2026-05-04. Auteur : Richard Loyer + assistance IA.