Kazeia-engine/dist/HANDOFF.md

66 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 HTP : RÉCUPÉRABLE via `GGML_HEXAGON_OPFILTER=SSM_CONV`.** Cause du charabia localisée :
**une seule op, SSM_CONV (conv1d), est cassée sur HTP en multi-token (prefill) pour d_inner=1024/2048**
(oracle FAIL ERR~1.3 ; decode n=1 OK ; bug côté backend hexagon, pas le calcul — les 2 chemins HTP
échouent, ggml-cpu est correct). En forçant cette op sur CPU (`OPFILTER=SSM_CONV`), le reste du prefill
tourne sur HTP et la **sortie redevient cohérente** : « Je comprends que cette rumination nocturne… ».
Mesuré : **prefill HTP 181 t/s** (×13 vs CPU 14) avec sortie correcte. Trois options d'intégration :
- **A (livrée) CPU-only** : prefill 14, decode 10.9, 2.4 GB. Simple.
- **B mono-contexte HTP + OPFILTER** : prefill **181**, decode HTP **6.4**, 2.4 GB (+ION). Gros gain prefill,
decode + lent, aucune RAM en plus, peu de code (ngl99 + env). **Recommandé** pour prompts longs/multi-tour.
- **C dual-contexte (prefill HTP+OPFILTER → transfert KV → decode CPU)** : prefill 181, decode **10.9**,
**+2.3 GB** RAM (2e instance). Optimal mais + complexe. Harness prouvé : `jni/dual_ctx.cpp`.
TODO propre : corriger SSM_CONV HTP (gate `test-backend-ops -o SSM_CONV` = 45/45) → enlèverait l'OPFILTER.
## Perf (sains, 27/05, device froid)
| | prefill | decode | RAM |
|---|--:|--:|--:|
| q35-lmq4 — A: CPU-only (**config livrée**) | 14 (CPU t4) | **10.9** | 2.4 GB |
| q35-lmq4 — B: HTP+OPFILTER mono-ctx | **181** | 6.4 (HTP) | 2.4 GB +ION |
| q35-lmq4 — C: HTP-prefill / CPU-decode | **181** | **10.9** | 4.7 GB +ION |
| q35-lmq4 — HTP sans OPFILTER | 189 *(sortie CASSÉE: SSM_CONV)* | — | — |
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/*.so``app/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`.