Kazeia-engine/dist/BUG_pte_inapp_qnn_version_m...

103 lines
6.3 KiB
Markdown

# BUG in-app `.pte` 7B/8B (err 5010) — RÉSOLU : mauvaise version de backend QNN chargée par l'app
**Date** : 17/06/2026 · **Sévérité** : bloquant in-app pour les `.pte` denses multi-context (≥7B, `num_sharding=2`)
**Statut** : **cause isolée** — ce n'est NI le `.pte`, NI le wrapper `libkazeia_pte.so`. C'est l'**intégration app** (résolution de lib QNN).
> ⚠️ **Rétracte** `BUG_pte_multicontext_offset_overflow.md` (théorie « overflow int32 » du `.pte`) : **réfutée** par le test CLI ci-dessous. Le `.pte` 8B (2ᵉ context group à 3,24 G > 2 GiB) **charge et génère** sans problème avec le bon runtime. Pas d'overflow.
---
## 1. TL;DR
L'erreur in-app `Context group 1 does not exist` / `Error 5010` est la **signature d'un backend QNN trop ancien** (≠ QAIRT 2.42) qui ne sait pas désérialiser la structure **multi-context** (sharding=2) des `.pte` ≥7B. Le backend **2.42** (`ship_runtime/`) les charge parfaitement. **L'app charge un autre `libQnnHtp.so`/backend que celui livré** (collision de SONAME, très probablement avec la pile **ORT-QNN du STT**, ou une lib d'une autre version restée sur le chemin du linker).
**Fix** : garantir que c'est bien la pile **QNN 2.42** qui est mappée dans le process app au moment du chargement `.pte` (pas la version du STT/Maven). Aucun changement de `.pte` ni de wrapper.
---
## 2. Preuve d'isolation (décisive)
Sur le **même device**, avec le **`ship_runtime/` 2.42 livré**, sur le **même `.pte` Qwen3-8B** (le cas « échec » de la théorie overflow) :
| Test sur Qwen3-8B (5,5 G, 2ᵉ context group à 3,24 G > 2 GiB) | Résultat |
|---|---|
| Runner CLI `qnn_llama_runner` + `ship_runtime` 2.42 | ✅ **313 tokens, 9,65 tok/s**, FR cohérent, EOS propre |
| Wrapper `libkazeia_pte.so` (notre JNI) + `ship_runtime` 2.42 | ✅ **41 tokens, 10,3 tok/s**, cohérent |
Dans **les deux** cas, le log montre `QnnContextCustomProtocol expected magic 0x5678abcd but get 0x2000000` **ET génère quand même****ce message est un INFO bénin présent dans les chargements qui marchent**, pas la cause de l'échec. L'app, elle, enchaîne sur `Context group 1 does not exist / err 5010` : c'est un **second symptôme, propre à l'app**, qui ne sort PAS avec le backend 2.42.
Conclusion logique : si c'était un overflow d'offset dans le `.pte` ou dans notre backend, le CLI **et** le wrapper échoueraient aussi. Ils réussissent. **Donc l'app exécute un backend différent.**
---
## 3. Cause racine — collision de version `libQnnHtp` / backend
`libkazeia_pte.so` ne `NEEDED` que `libqnn_executorch_backend.so` (le reste statique). Mais ce backend charge à son tour `libQnnHtp.so` / `libQnnSystem.so` **par SONAME**. Si l'APK contient **plusieurs versions** de ces libs — typiquement :
- la pile **ORT-QNN du STT** (qui embarque sa propre `libQnnHtp.so`, possiblement une autre version QAIRT),
- d'anciennes libs LLM (ère 2.32/2.37) restées dans `jniLibs`,
- une AAR QNN Maven,
…le linker Android n'en mappe **qu'une seule** par SONAME. Si la version gagnante n'est **pas 2.42**, le backend ExecuTorch reçoit un `libQnnHtp` incompatible → `Context group N does not exist` / `err 5010` sur les `.pte` multi-context.
**Pourquoi 4B marche et 7B/8B non** : un backend trop ancien gère encore le layout de contexte simple du 4B, mais **pas** la structure multi-context (2 groups) des modèles plus gros. La forensique avait raison de voir « 2 context groups » sur les 7B/8B — mais la cause n'est pas un overflow dans le `.pte`, c'est le **backend de l'app qui ne sait pas les parser**. Le 2.42 les parse (prouvé §2).
---
## 4. Diagnostic à faire côté dev (confirme la cause en 2 min)
**Quelle version de `libQnnHtp` est RÉELLEMENT mappée dans le process app ?**
```bash
PID=$(adb shell pidof com.kazeia)
adb shell run-as com.kazeia cat /proc/$PID/maps | grep -iE 'libQnnHtp|libqnn_executorch_backend|libQnnSystem' | awk '{print $NF}' | sort -u
# puis pour chaque .so mappé :
adb shell run-as com.kazeia strings <chemin_mappé>/libQnnHtp.so | grep -m1 AISW_VERSION # doit être 2.42.0
```
Si la version mappée ≠ **2.42.0**, la cause est confirmée.
**Vérifier les doublons de QNN dans l'APK :**
```bash
unzip -l app-release.apk | grep -iE 'libQnnHtp|libQnnSystem|libqnn' # ne doit PAS y avoir 2 origines/versions
```
**SHA256 attendus (libs 2.42 de `ship_runtime/`)** — ceux livrés dans `jniLibs/arm64-v8a/` DOIVENT matcher :
```
95d01368b556f0c6… libqnn_executorch_backend.so
10eb1923b34ac9a7… libQnnHtp.so
a69cfc4350c16b22… libQnnSystem.so
a08fb34747345125… libQnnHtpV79Stub.so
7ee72b438c97c13c… libQnnHtpV79Skel.so
2daafb376fe6904a… libQnnHtpPrepare.so
a3bc48674377a042… libQnnHtpNetRunExtensions.so
```
---
## 5. Fix
1. **Une seule version de QNN dans l'app** = **2.42** (celle de `ship_runtime/`), pour le STT **et** le LLM `.pte`. Concrètement :
- Retirer de `jniLibs` toute `libQnnHtp*.so`/`libQnnSystem.so` qui n'est pas du build 2.42 (anciennes libs LLM, AAR Maven d'une autre version).
- Si le STT (ORT-QNN) impose une version QNN différente, **aligner les deux sur 2.42** (le STT marche sur 2.42 ; ORT-QNN EP est tolérant à la version de `libQnnHtp` tant qu'elle ≥ celle de compilation). À défaut, isoler (process séparé) — mais l'alignement sur 2.42 est le plus simple.
2. Re-vérifier le `/proc/pid/maps` : `libQnnHtp.so` mappé = 2.42.0.
3. Aucun ré-export de `.pte`, aucun rebuild de `libkazeia_pte.so` nécessaires.
---
## 6. Reproduction de la PREUVE (artefact sain)
```bash
# device, dossier avec le .pte 8B + tokenizer + ship_runtime/ 2.42 + prompt_ids.bin (uint64 LE)
ADSP_LIBRARY_PATH=. LD_LIBRARY_PATH=. ./qnn_llama_runner \
-model_path qwen3_8b.pte -tokenizer_path tokenizer.json \
-tokenized_prompt p8b_ids.bin -decoder_model_version qwen3 -eval_mode 1 -seq_len 512 -temperature 0
# Attendu : génère ~300 tokens à ~9-10 tok/s. PAS d'err 5010.
```
Le `ship_runtime/` contient `qnn_llama_runner` + les 7 libs 2.42 : c'est l'oracle « bon backend ».
---
## 7. Données
- `.pte` validés (génèrent avec 2.42) : `qwen3_4b_seq1024/`, `qwen3_8b_seq512/`, `qwen2_5_7b_seq512/`, `kazeia-tablet-backup/llm/hybrid_llama_qnn_guard4b.pte`.
- Runtime de référence : `/opt/Kazeia/pte_prep_work/ship_runtime/` (QAIRT 2.42, `libQnnHtp` = AISW_VERSION 2.42.0).
- À fournir pour clore : `/proc/<pid>/maps` du process app pendant un load 8B + liste `unzip -l` des `libQnn*` de l'APK.