Kazeia-engine/dist/KAZEIA_ENGINE_OVERVIEW.md

8.5 KiB

Kazeia-Engine — vue d'ensemble et entrée d'intégration

⚠️ 02/06 : bloqueur SELinux découvert sur les libs LLM/TTS in-app (/dev/fastrpc-cdsp refusé à untrusted_app). Les libs livrées dans b-jni/ sont inutilisables dans un APK Play Store/sideload en l'état. Rebuild CPU-only requis côté dev avant intégration LLM/TTS. STT non affecté (passe par QNN Maven). Voir REBUILD_CPU_ONLY.md pour la procédure et project_engine_selinux_fastrpc_blocker en mémoire pour le détail.

Date : 02/06/2026. Moteur d'inférence local-first pour Snapdragon 8 Elite (Pad3). Unifie LLM + TTS + STT dans une stack cohérente. Pas de cloud, pas de root, pas de Python runtime.

Documents d'intégration (3 indépendants)

Pour intégrer dans l'app Kazeia, lis ces 3 docs (un par sous-système) :

Sous-système Doc d'intégration Lib .so Façade Kotlin
STT (Whisper-Small NPU) STT_INTEGRATION.md libkazeia_stt.so 183 KB SttEngine.kt
TTS (Qwen3-TTS + clonage vocal) TTS_INTEGRATION.md libkazeia_tts.so 929 KB TtsEngine.kt
LLM (Qwen3.5 hybride / Qwen3 dense) LLM_INTEGRATION.md libkazeia_engine.so 64 KB EngineLlmEngine.kt
RAG (embeddings e5/bge, CPU) RAG_INTEGRATION.md libkazeia_engine.so (mêmes symboles) EmbedderEngine

Chaque doc a la même structure : libs à pousser, façade Kotlin, exemples, codes d'erreur, bench standalone, checklist d'intégration, pièges connus, perf détaillée.


Architecture

┌────────────────────── Kazeia-Engine ──────────────────────┐
│                                                            │
│   STT                  TTS                  LLM            │
│   libkazeia_stt        libkazeia_tts        libkazeia_eng  │
│   183 KB               929 KB               60 KB          │
│        │                    │                    │         │
│        └─ libonnxruntime    └────────┬───────────┘         │
│           libQnnHtp*          libllama 35 MB               │
│           libcdsprpc          libggml + ggml-cpu           │
│                               libggml-hexagon              │
│                               libggml-htp-v79              │
│                               (chaîne mutualisée TTS+LLM)  │
│                                                            │
└────────────────────────────────────────────────────────────┘

Côté APK :
  jniLibs/arm64-v8a/
    libkazeia_stt.so + libonnxruntime.so                       (2 fichiers, ~20 MB)
    libkazeia_tts.so + libkazeia_engine.so + libllama.so + ...  (8 fichiers, ~53 MB partagés)
    libc++_shared.so (commune)

  TOTAL ~75 MB pour les 3 sous-systèmes (vs ~50 MB ExecuTorch seul).

API Kotlin unifiée (côté app)

// STT
val stt = SttEngine(modelDir = "/data/.../whisper-small-sm8750", useHtp = true)
val transcript = stt.transcribe(pcm16, language = "fr")

// VAD (drop-in replacement de l'ancienne VadStage.kt)
val vad = SttVad()
when (vad.push(chunk)) {
    SttVad.SPEECH        -> buffer.addAll(chunk.toList())
    SttVad.END_OF_SPEECH -> { stt.transcribe(buffer); vad.reset() }
}

// TTS in-process (Qwen3-TTS + clonage vocal)
val tts = TtsEngine(
    talkerGguf = "/data/.../talker_f32.gguf",
    vocabGguf  = "/data/.../Qwen3-4B-Q4_0.gguf",
    dumpDir    = "/data/.../tts_dump",
    nThreads   = 6
)
val r = tts.synthesize("Bonjour, comment ça va ?", "/sdcard/out.wav")

// Clonage vocal embarqué (optionnel)
val pierreVoice = tts.encodeSpeakerWav("/sdcard/voix_pierre.wav")
tts.synthesize("Bonjour Pierre.", outWav, xvectorOverride = pierreVoice)

// LLM (Qwen3.5 GGUF cascade Speaker + Thinker)
val llm = EngineLlmEngine("/data/.../Qwen3.5-4B-Q4_0.gguf", ctx = 4096, nThreads = 6)
val reply = llm.generate(sys = "Tu es Kazeia...", usr = userInput, max = 96)

Pattern d'unification recommandé (cf demande dev Kazeia)

Pour permettre une bascule progressive prodlib sans dégeler les sous-systèmes, le dev a câblé un flag de dispatch côté app pour STT et propose de faire pareil pour LLM et TTS :

// Dans KazeiaService.kt (ou équivalent)
class KazeiaService {
    private val sttEngine = when (flag("sttEngine", default = "prod")) {
        "lib" -> SttEngine(...)             // libkazeia_stt
        else  -> WhisperHybridEngine(...)   // legacy ONNX/QNN direct
    }
    private val llmEngine = when (flag("llmEngine", default = "prod")) {
        "lib" -> EngineLlmEngine(...)       // libkazeia_engine
        else  -> ExecuTorchLlmEngine(...)   // legacy .pte
    }
    private val ttsEngine = when (flag("ttsEngine", default = "prod")) {
        "lib" -> TtsEngine(...)             // libkazeia_tts
        else  -> LegacyTtsPipeline(...)     // legacy à supprimer une fois libé validée
    }
}

Toggle via adb shell setprop kazeia.sttEngine lib (ou équivalent du flag system). Bascule réversible, mesurable en CER/WER/RTF avant de flip le default.

État réel des 3 dispatch flags (à confirmer côté dev) :

  • STT : flag câblé, default prod, A/B in-app validé
  • LLM : flag à ajouter (mirror exact du STT). Lib + façade + doc prêts.
  • TTS : flag à ajouter une fois libkazeia_tts.so validée load + 1 synth in-app.

État livré (01/06/2026, commit en cours)

Lib .so Façade Kotlin JNI source Doc d'intégration Bug investigué
STT 183 KB SttEngine.kt kazeia_stt_jni.cpp STT_INTEGRATION.md 15 KB 2 bugs fixés (DFT 400 + forced prompt)
TTS 929 KB TtsEngine.kt kazeia_tts_jni.cpp TTS_INTEGRATION.md 10 KB (cette session) Crash load = libs manquantes, liste exhaustive donnée
LLM 60 KB EngineLlmEngine.kt kazeia_engine_jni.cpp LLM_INTEGRATION.md 10 KB (cette session) Bug threads = nThreads=4 hardcoded, fix nThreads=6 paramétrable

Empreinte mémoire (Snapdragon 8 Elite, 16 GB RAM, mesures r3)

Composant chargé RAM peak
STT Whisper-Small NPU (encoder + decoder QAIRT) 379 MB
TTS (talker + CP + decoder + vocab + xvector fixture) 3.5 GB
TTS clonage vocal (speaker encoder, en plus) +34 MB
LLM Qwen3.5-4B Q4_0 (1 instance) 2.4 GB
LLM Qwen3.5-9B Q4_0 (1 instance) 5.0 GB
Cascade typique : STT + Speaker 4B + Guard 4B + TTS ~9 GB / 16 GB

Perf bout-en-bout (latence typique)

mic 16 kHz PCM16
  ↓ AudioRecord
SttVad RMS                         → ~830 ms après fin parole (silence 800 ms + overhead)
  ↓ end_of_speech
SttEngine.transcribe(pcm)          → ~500-2000 ms (RTF 0.18-0.40 sur audio 3-10s FR)
  ↓ texte FR
LLM Speaker 4B (+ Guard 4B)        → ~5-10 s (cascade Speaker + Guard 4B)
  ↓ réponse FR
TtsEngine.synthesize(text)         → ~3-10 s (RTF 2.5-3.0 selon longueur)
  ↓
audio playback

Latence totale voix→audio : ~10-25 s par tour, dominée par LLM + TTS.

Documentation détaillée

  • STT : STT_INTEGRATION.md — Whisper-Small NPU, VAD, options QNN, A/B accuracy
  • TTS : TTS_INTEGRATION.md — Qwen3-TTS, clonage vocal, sampling tuning
  • LLM : LLM_INTEGRATION.md — Qwen3.5/Qwen3, option C, threading
  • Patch QNN options prod (gratuit, sans migration) : PATCH_QNN_PROD.md
  • Engine global (CLAUDE.md projet) : /opt/Kazeia-engine/CLAUDE.md
  • Mémoires assistant : /home/alf/.claude/projects/-opt-Kazeia-engine/memory/

Pour démarrer l'intégration

  1. Lire les 3 docs d'intégration dans l'ordre : STT → TTS → LLM.
  2. Pousser les libs nécessaires dans jniLibs/arm64-v8a/ (cf §2.b de chaque doc).
  3. Copier les 3 façades Kotlin (SttEngine.kt, TtsEngine.kt, EngineLlmEngine.kt).
  4. Câbler les 3 flags dispatch côté app pour bascule progressive (cf section ci-dessus).
  5. Valider la checklist §7 de chaque doc en premier (System.loadLibrary + 1 call OK).
  6. Bench A/B prod vs lib sur audios/prompts/modèles fixtures représentatifs.
  7. Flip default vers lib quand les 3 sous-systèmes passent les gates (CER/WER STT, RTF TTS, decode tok/s LLM).