Kazeia-engine/dist/HANDOFF.md

4.2 KiB
Raw Blame History

Kazeia-Engine — handoff intégration (MAJ 26/05/2026)

Point d'entrée unique. Remplace le LLM ExecuTorch/Genie par llama.cpp (fork ql) + Hexagon. GGUF, pas de .pte. STT reste ORT-QAIRT (inchangé).

Décisions figées cette session

  • Modèle Speaker = Qwen3.5-4B en variante q35-lmq4.gguf (embeds en Q4 au lieu du Q6_K par défaut → 2.38 GB, decode +5%, qualité ≈ Q4_0 mesurée). Choisi sur l'éval qualité (../eval/VERDICT.md) : gagne le SAFETY (cite 3114/15) et la majorité du SUPPORT vs le dense.
  • 9B écarté (decode ~4-5 t/s réel, trop lent ; pas de gain qualité justifiant). Cascade éventuelle = Guard-4B (thinker) + 4B (speaker), pas 9B.
  • Kernel GDN = chantier clos : son calcul n'est PAS le goulot (cf RAPPORT_RD §7). Ne pas y retoucher pour la perf. Decode au plafond BW CPU (~25 GB/s).

État du bridge JNI (jni/kazeia_engine_jni.cpp) — ce qui est CÂBLÉ

Config déjà correcte et alignée :

  • n_threads=4, flash_attn=ENABLED, n_batch=512, sampler greedy.
  • Thinking OFF déterministe (ChatML + <think></think> vide injecté) → pas de ramble.
  • API : load(path,nCtx) → generate(h,sys,usr,maxTok) → reset(h) / free(h).
  • n_gpu_layers = 0 → tout CPU (pas de HTP). Choix après le ping-pong ngl99 (decode 0.2 t/s).

Décisions (vérifiées 27/05, batterie 90%, device froid)

  1. KV = f16 (RÉSOLU, corrigé dans le JNI). Mesuré : decode q35-lmq4 f16=10.9 vs q8_0=6.5 (40%, idem à d=512). Le déquant KV en flash-attn coûte plus que le BW épargné. type_k/v repassé en GGML_TYPE_F16. → rebuild libkazeia_engine.so avant de shipper (le .so livré contient encore l'ancien q8_0). q8_0 seulement si OOM KV en très long contexte.
  2. Prefill : CPU-only OBLIGATOIRE — le prefill HTP est CASSÉ (vérifié 27/05). Le HTP a un gros débit (q35-lmq4 126-189 t/s) MAIS produit un état/logits corrompus → sortie charabia. Confirmé 3× (harness dual-contexte, device HTP0 explicite, et llama-cli -dev HTP0 sortant de l'anglais cassé sur un prompt FR). Le dense Qwen3-4B sur HTP crashe (V79 0x2e). Preuve que c'est le prefill et pas le transfert : decode CPU repartant d'un état prefillé-CPU = FR cohérent ; repartant d'un état prefillé-HTP = charabia. Donc les « 189/98/285 » sont du débit jamais validé en sortie, inutilisables. → JNI reste ngl0 (CPU prefill 14 t/s + CPU decode 10.9). Mécanique du split (2 contextes + transfert KV) validée et prête (jni/dual_ctx.cpp) — réutilisable LE JOUR où le prefill HTP sera numériquement correct (bug backend frontière). Pour accélérer le prefill maintenant : raccourcir le prompt/historique.

Perf (sains, 27/05, device froid)

prefill decode RAM
q35-lmq4 — JNI (CPU-only, config livrée) 14 (CPU t4) 10.9 (t4+fa, KV f16) 2.4 GB
q35-lmq4 — HTP 126-189 (débit, sortie CASSÉE → inutilisable)
dense Qwen3-4B ~14 CPU / HTP crash 0x2e 11.7 2.2 GB

Decode = ce que l'utilisateur ressent (10.9, OK). Prefill CPU 14 t/s → prompt 200 tok ≈ 14 s ; garder le system prompt + l'historique courts. Le prefill HTP rapide existe mais sort du charabia (cf décision 2).

Système (prompt) — system_fr.txt fourni

Inclut les garde-fous (3114, pas de prescription) + 2 correctifs issus de l'éval : tutoiement constant, et « ne présume pas du pire, fais préciser » (le modèle lisait « le départ de ma fille » comme un décès). À passer tel quel en sys de generate().

Paquet à intégrer

  • lib/*.soapp/src/main/jniLibs/arm64-v8a/ (libkazeia_engine.so statique + ggml/htp ; htp-v79 = celui de cette session, fp16 derrière env KZ_F16 OFF par défaut = comportement inchangé).
  • jni/kazeia_engine_jni.cpp + jni/EngineLlmEngine.kt + include/ → projet app.
  • q35-lmq4.gguf → external storage (2.38 GB, hors git ; le pousser ou le reproduire, cf MODELS.md).
  • ./package.sh réassemble lib/ depuis le build ql/b + recopie le prompt.

Détails

INTEGRATION.md (build/CMake), MODELS.md (modèle + recette), PERF.md (mesures+leviers morts), PITFALLS.md (pièges vécus), STATUS.md (limites). Verdict qualité : ../eval/VERDICT.md.