Commit Graph

4 Commits

Author SHA1 Message Date
Richard Loyer 5cc8c22fc9 chantier RAG #1 : entrypoint embeddings (texte -> vecteur poolé) pour le RAG mobile
Spec /opt/Kazeia/docs/RAG_EMBEDDINGS_ENGINE_SPEC.md implémentée.

Préflight (point #2 du spec = LE bloqueur potentiel) :
 - Arch BERT/nomic-bert/gemma-embedding TOUJOURS présentes dans le fork ql
   (llama-arch.cpp + src/models/bert.cpp), malgré les mods Qwen/TTS.
 - Outil de référence examples/embedding/embedding.cpp dispo = source de vérité.
 - Confirmé : BERT encoder-only routé via llama_decode (PAS llama_encode) dans
   ce fork ; le code ne bascule sur erreur que pour encoder+decoder (T5).

Ajouts kazeia_engine_jni.cpp (handle KEmbedder SÉPARÉ du KEngine, CPU pur) :
 - loadEmbedder(path, nThreads, pooling) : embeddings=true, pooling MEAN/CLS/auto,
   n_ctx=n_batch=n_ubatch=512 (contrainte pooling = séquence dans 1 ubatch),
   n_gpu_layers=0, refus explicite des modèles encoder-decoder.
 - embedText(h, text) : tokenize add_special + batch logits=1 + llama_decode +
   llama_get_embeddings_seq + normalisation L2 -> float[n_embd] ou null.
 - freeEmbedder(h).
 - Reproduit À L'IDENTIQUE examples/embedding/embedding.cpp.

Bindings Kotlin (EngineLlmEngine.kt) : loadEmbedder/embedText/freeEmbedder +
wrapper EmbedderEngine(model, nThreads, pooling).embed(text).

Validation sur tablette SM8750 (adb shell, nomic-embed Q4_K_M, CPU) :
 - Déterminisme : max|diff| = 0.0 bit-identique sur 2 runs
 - Norme L2 = 1.0000
 - PARITÉ RÉFÉRENCE : mon embedText vs llama-embedding = max|diff| 5e-7,
   cos 1.000000 (probe rag_probe.cpp répliquant le chemin exact)
 - Cohérence sémantique : OK avec bons préfixes

FINDING modèle (point #1 du spec confirmé par mesure) : nomic-embed est
anglo-centré, marge FR fine (cos insomnie 0.556 vs tarte 0.517 = 0.04, et
ordre s'inverse avec mauvais préfixe). => SHIPPER multilingual-e5-small comme
le spec l'exige, pas nomic. Le code est agnostique au modèle (n_embd auto).

⚠ Bloqueur SELinux identique LLM/TTS : l'embedder linke libllama->libggml-hexagon
qui ouvre /dev/fastrpc-cdsp au backend_init -> crash untrusted_app. DOIT tourner
sur le build CPU-only (GGML_HEXAGON=OFF). Documenté dans le code + RAG_INTEGRATION.md.

Doc : dist/RAG_INTEGRATION.md (format des 3 autres) + overview à jour (4 sous-systèmes).
2026-06-09 22:02:30 +02:00
Richard Loyer e55cd175c8 chantier B engine #2 : bloqueur SELinux découvert + guide rebuild CPU-only pour dev
Le dev Kazeia a découvert au test de dégel TTS / toggle llm_engine=lib :
SIGABRT in-app au tts_engine_load / kazeia_engine_load, jamais en standalone.

Trace dmesg :
  avc: denied { open } for path="/dev/fastrpc-cdsp"
    scontext=u:r:untrusted_app  tcontext=u:object_r:vendor_qdsp_device

Cause : libggml-hexagon.so dlopen libcdsprpc.so (FastRPC) au init backend HTP,
qui ouvre /dev/fastrpc-cdsp. Policy SELinux Oplus/Qualcomm sur SM8750 interdit
cet accès à untrusted_app (UID 10xxx). Seul shell (UID 2000) y a accès.

Conséquence : tout mon harness CLI standalone via adb shell était un FAUX
positif systématique. Le test "loadLibrary OK" + "calls C++ OK" ne révèle
rien du comportement in-app pour le backend HTP/DSP.

Pourquoi STT marche : passe par libQnnHtp.so Maven (delegation autorisée
untrusted_app), pas FastRPC direct.

Pourquoi ExecuTorch .pte marche : idem libQnn Maven.

3 voies évaluées (cf project_engine_selinux_fastrpc_blocker memoire) :
 1. Rebuild CPU-only (GGML_HEXAGON=OFF) -- réaliste, +1s/tour LLM, +0 TTS
 2. Port ORT-QAIRT pour LLM -- non réaliste (pas de Qwen QAIRT context)
 3. Statu quo .pte -- régression ambition projet

Décision user : le dev rebuilde de son côté en environnement APK réel
(évite mon harness biaisé). Reprise des sources Kazeia-Engine et build.

Livrables cette session :
 - dist/REBUILD_CPU_ONLY.md : guide complet 7 étapes (sources, flags CMake,
   build libllama/ggml CPU-only, rebuild kazeia_engine/tts, jniLibs allégé,
   tests in-app, perf attendue, points d'attention)
 - dist/LLM_INTEGRATION.md §0 : bloqueur SELinux documenté + référence
   rebuild CPU-only + chiffres perf attendus
 - dist/TTS_INTEGRATION.md §0 : idem côté TTS, noter que le clonage vocal
   (speaker encoder ECAPA-TDNN) est CPU-only de base, donc préservé sans
   impact
 - dist/KAZEIA_ENGINE_OVERVIEW.md : warning en tête + pointer REBUILD doc
 - project_engine_selinux_fastrpc_blocker.md : diagnostic complet pour
   contexte futur

Coût mesuré attendu (vs CLI HTP) :
 - LLM prefill : 0.4s -> 1.3s (+0.9s)
 - LLM decode : inchangé (déjà CPU NEON option C)
 - TTS talker prefill : 50ms -> 150ms (négligeable in-mix)
 - Tour LLM total : +1s (acceptable thérapeutique)
 - Tour TTS total : +0.1s (imperceptible)

Leçon de méthode gravée : un harness CLI via adb shell sera TOUJOURS
faux positif pour tout test impliquant FastRPC/DSP/contexte vendor.
Tout test validation engine pour intégration in-app DOIT passer par
APK debug ou androidTest instrumenté.
2026-06-02 23:12:38 +02:00
Richard Loyer 8c1e83be18 chantier B unification #1 : engine 3/3 prêt pour intégration (STT + TTS + LLM)
Reproche du user juste : j'ai livré STT complet mais pas TTS ni LLM au même
niveau. Cette session corrige : 3 docs d'intégration équivalentes en qualité,
2 bugs in-app investigués et l'un fixé.

Investigation TTS "crashe au load in-app" :
 - DT_NEEDED de libkazeia_tts.so = libllama.so + libggml.so + libggml-base.so
   + libggml-cpu.so + libc++_shared.so + libdl/libm/libc
 - Test reproduction sur tablette : lib charge OK avec les 7 deps présentes,
   crash avec "library libllama.so not found" si une dep manque
 - Conclusion : c'est juste 7 libs à pousser dans jniLibs/arm64-v8a/, pas un
   bug code. Liste exhaustive donnée dans TTS_INTEGRATION.md §2.b

Investigation LLM "ne tient pas 8 threads in-app" :
 - kazeia_engine_jni.cpp ligne 117/120/124/131 : n_threads HARDCODE à 4
   pour le decode CPU. Pas exposé côté Kotlin.
 - Fix : ajouter param nThreads à load(), N_DECODE défaut 6 (sweet spot r3
   mesuré : Qwen3.5-4B 9.8 tok/s à t=6 vs 7.4 à t=8 contention)
 - Update EngineJni.load(model, ctx, nThreads) + EngineLlmEngine(ctx, nThreads=6)
 - Rebuild libkazeia_engine.so 60 KB

Docs livrées (format identique STT_INTEGRATION.md) :
 - TTS_INTEGRATION.md (10 KB) : libs à pousser, façade, clonage vocal,
   sampling, codes erreur, bench, checklist, pièges
 - LLM_INTEGRATION.md (10 KB) : option C HTP/CPU, n_threads sweet spot,
   modèles supportés (Qwen3 dense / Qwen3.5 hybride GDN), cascade
   Speaker+Thinker, piège affinity Android (decode 9.8 -> 0.32 tok/s in-app
   si scheduler pin sur 1 cœur)
 - KAZEIA_ENGINE_OVERVIEW.md actualisé : entrée unique pointant les 3 docs,
   pattern dispatch flag (mirror STT pour LLM+TTS), état réel 3/3 prêt

Reste côté dev (cf KAZEIA_ENGINE_OVERVIEW.md):
 1. Pousser les libs jniLibs (8 fichiers pour TTS/LLM, partagées entre eux)
 2. Copier les 3 façades Kotlin
 3. Câbler 2 flags dispatch supplémentaires (llmEngine + ttsEngine, mirror STT)
 4. Valider checklist §7 de chaque doc (System.loadLibrary + 1 call)
 5. Bench A/B prod vs lib sur audios/prompts fixtures

Le pattern STT a marché parce qu'il avait tout (lib + façade + doc + checklist).
Maintenant TTS et LLM aussi.
2026-06-01 15:46:20 +02:00
Richard Loyer 8f6253204c chantier B STT #2 : S2 + S3 livrés (stt_engine ORT QNN + JNI + façade Kotlin + doc)
S2 port complet WhisperHybridEngine.kt -> C++ :
 - stt_engine.cpp impl complète (ORT 1.24.3 + QNN EP HTP V79, decoder KV-cache
   autoregressif 200 steps, override translate->transcribe, parsers JSON inline
   pour mel_filters et vocab.json, tokenizer BPE byte-level GPT-2/Whisper)
 - kazeia_stt_cli : binaire test (1.3 MB statique)
 - Bench bit-correct vs prod : transcription FR identique sur 3 runs déterministes
   ("Elle mat est un casque de chantier connecté et modulable.")
 - Perf SM8750 : RTF 0.41-0.43 (vs prod 0.51), RAM peak 378 MB (vs 545 MB)
 - Mel C++ 60 ms (FFT) vs prod 189 ms (DFT). Decoder per-token 100 ms vs 23 ms
   prod (overhead memcpy KV; optim IO bindings ORT non-bloquant)

S3 JNI + façade + doc :
 - kazeia_stt_jni.cpp : 7 fonctions JNI exportées (nativeLoad/Transcribe/Free
   + nativeVadNew/Push/Reset/Free). Sortie pipe-séparée parseable côté Kotlin.
 - libkazeia_stt.so : 168 KB SHARED, prête pour jniLibs/arm64-v8a/
 - SttEngine.kt : façade Kotlin minimale (~100 l) parallèle à TtsEngine.kt
   (SttJni / SttEngine / SttVad / SttResult)
 - Suppression côté app : WhisperHybridEngine.kt (527L), MelExtractor.kt,
   VadStage.kt, mel_extractor.cpp, libmel_extractor.so (documentée)

Doc livrable dev :
 - STT_INTEGRATION.md (10 KB) : guide complet migration + perf + erreurs +
   bench rapide + roadmap optim
 - KAZEIA_ENGINE_OVERVIEW.md : vue globale moteur unifié (LLM + TTS + STT),
   architecture des libs, API Kotlin unifiée, empreinte cascade complète
 - CLAUDE.md : section "STT unifié engine (31/05)" + verdict A invalidé

Runtime ORT 1.24.3 + QNN libs : extraites cache Gradle Maven (cf README_ORT.md
+ README_QNN.md dans dist/lib/). Pas de tarball ext. Modèles whisper-small-sm8750
prod inchangés (545 MB QAIRT contexte conservé).
2026-05-31 22:15:58 +02:00