Réponses aux 3 demandes du dev :
#1 .so CPU-only livrée : dist/b-jni-cpu/libkazeia_engine.so (64 KB).
DT_NEEDED = libllama/libggml/libggml-base (CPU-only dist/lib-cpu/) + système,
AUCUNE dep libggml-hexagon -> pas de FastRPC -> pas de bloqueur SELinux.
Validée tablette : charge e5+nomic, n_embd auto, déterministe, norme 1.0.
#2 modèle FR tranché = VOIE A (multilingual-e5-small), blocage XLM-R levé.
Question décisive "petit patch ou trou architectural ?" -> PETIT PATCH, mesuré :
- runtime C++ a déjà UGM (unigram/SPM), découplé de l'arch (tokenizer_model=t5
-> LLAMA_VOCAB_TYPE_UGM). Pas de trou.
- converter a déjà _xlmroberta_set_vocab (écrit t5/UGM) mais seul NomicBert le
câblait. e5 declare architectures=[BertModel]+tokenizer Unigram -> tombait en
BertModel.set_vocab -> chemin BPE -> get_vocab_base_pre échoue (hash inconnu).
- fix = wiring dans BertModel (3 méthodes : __init__ détecte Unigram, set_vocab
route xlmroberta, modify_tensors choppe positions) calqué sur Roberta/Nomic.
Patch : dist/patches/bert_xlmroberta_unigram.diff (~25 lignes, à appliquer dans
le fork ql par le dev — non commité dans ql par respect AGENTS.md).
PROUVÉ end-to-end : converti e5-small-f16.gguf (384-dim) via converter patché,
chargé sur build CPU-only tablette :
cos(dormir,insomnie)=0.909 > cos(dormir,tarte)=0.821, marge FR 0.089
(nomic 0.04 -> e5 2.2x mieux), ranking propre, norme 1.0, déterministe.
Voie c (nomic stopgap) documentée si besoin de dérisquer l'E2E in-app d'abord.
#3 interface FIGÉE confirmée : loadEmbedder/embedText/freeEmbedder inchangées.
Bit-identique garanti sur le MÊME build (CPU vs HTP divergent ~1.5e-2 sur Q4_K_M ;
sans effet car ingestion+requête tournent sur le même build in-app).
Doc dist/RAG_INTEGRATION.md mise à jour (décision modèle, patch, reproduction GGUF,
interface figée, .so CPU-only). GGUF e5 = artefact distribution (non versionné git).
Suite à l'analyse du dev (commit c9e1983) : le gain mesuré (-80% encoder,
-71% decoder/token) vient des options QNN ExecutionProvider, pas de la
migration C++. Donc le patch s'applique aussi à la prod Kotlin actuelle
sans dégeler la stack STT — 4 lignes Kotlin, réversible.
Livrables Action 1 (séparée de la décision migration) :
- dist/PATCH_QNN_PROD.md : explication + diff Kotlin + chiffres attendus
(prod 820 ms -> ~560 ms = -32 % gratuit) + script bench audio Pierre
- dist/patches/whisper_hybrid_engine_qnn.diff : patch précis sur
WhisperHybridEngine.kt (lignes 101, 109, 134 du fichier prod). Ajoute
htp_performance_mode=burst + htp_arch=79 + enable_htp_fp16_precision=1
+ setOptimizationLevel(ALL_OPT) sur les 3 sites encOpts/decOpts.
- dist/patches/bench_qnn_before_after.kt : harness Android pour mesurer
le gain réel sur audios Pierre. 3 runs/audio, médiane, RTF pondéré.
Compare 2 builds app (avant patch / après patch) sur le même corpus.
Décision migration libkazeia_stt CONDITIONNEE à :
1. Action 1 mesurée sur audio Pierre (gain réel patch QNN seul)
2. A/B accuracy CER/WER lib unifiée vs prod patchée (in-app uniquement,
pas mesurable standalone)
Bénéfice résiduel migration après patch QNN prod : ~110 ms total + 168 MB
RAM + code unifié. Reste valable mais beaucoup moins fort que les chiffres
initiaux. Le dev a raison de séparer les décisions.
Mémoire à mettre à jour : project_stt_qnn_options_win.