Kazeia-engine/dist/KAZEIA_ENGINE_OVERVIEW.md

165 lines
8.5 KiB
Markdown

# 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`](STT_INTEGRATION.md) | `libkazeia_stt.so` 183 KB | `SttEngine.kt` |
| **TTS** (Qwen3-TTS + clonage vocal) | [`TTS_INTEGRATION.md`](TTS_INTEGRATION.md) | `libkazeia_tts.so` 929 KB | `TtsEngine.kt` |
| **LLM** (Qwen3.5 hybride / Qwen3 dense) | [`LLM_INTEGRATION.md`](LLM_INTEGRATION.md) | `libkazeia_engine.so` 64 KB | `EngineLlmEngine.kt` |
| **RAG** (embeddings e5/bge, CPU) | [`RAG_INTEGRATION.md`](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)
```kotlin
// 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 `prod``lib` 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 :
```kotlin
// 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](STT_INTEGRATION.md) — Whisper-Small NPU, VAD, options QNN, A/B accuracy
- **TTS** : [TTS_INTEGRATION.md](TTS_INTEGRATION.md) — Qwen3-TTS, clonage vocal, sampling tuning
- **LLM** : [LLM_INTEGRATION.md](LLM_INTEGRATION.md) — Qwen3.5/Qwen3, option C, threading
- **Patch QNN options prod (gratuit, sans migration)** : [PATCH_QNN_PROD.md](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).