103 lines
6.3 KiB
Markdown
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 : `dist/lib-pte/` (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.
|