Ternarization_instructions_27b_de.md
| 1 | # Anleitung zur Ternarisierung und zum Export nach GGUF/TQ2_0 — Qwen3.8-27B |
| 2 | |
| 3 | Modell: `/mnt/nfs_share/Qwen3_8/`, Klasse `JiRackDeltaNet_27b.py` |
| 4 | (Hybrid 3:1 Gated-DeltaNet / Gated-Attention, `model_type: qwen3_5`). |
| 5 | |
| 6 | ## Status (aktualisiert 2026-08-28) |
| 7 | |
| 8 | ✅ **Erledigt:** |
| 9 | |
| 10 | - Konvertierung HF → eigenes Format, Test der gesamten Pipeline |
| 11 | - **MTP-Block implementiert und integriert** (siehe Abschnitt 0 unten) |
| 12 | - GGUF-Konvertierung erfolgreich (pt → safetensors → GGUF, bf16) |
| 13 | - Smoke-Test bestanden: das Modell antwortet korrekt („Paris“ auf „What is the capital of France?“) |
| 14 | - **Baseline-Perplexität: PPL = 5.4957 ± 0.12** (wikitext-100k, c=2048, bf16, lambda=0.0) |
| 15 | - Datei: `/mnt/nfs_share/Qwen3_8/wiki_100k.txt` (dieselbe Datei nach der Ternarisierung zum Vergleich verwenden) |
| 16 | - Log: `/mnt/nfs_share/Qwen3_8/ppl_baseline_bf16.log` (letzte Zeile, 11 Chunks) |
| 17 | |
| 18 | ⏳ **Nächste Schritte:** QAT-Warmup lambda 0.0→1.0, Materialisierung der Ternarisierung, TQ2_0-Export, finale Perplexität |
| 19 | |
| 20 | Aktueller Checkpoint: `/mnt/nfs_share/Qwen3_8/qwen38_27b_checkpoint_migrated.pt` (53,79 GB, lambda=0.0) |
| 21 | |
| 22 | - Enthält MTP-Gewichte (aus dem ursprünglichen HF-Checkpoint übernommen), ist aber noch nicht ternarisiert. |
| 23 | - Wird mit dem Skript `convert_qwen38_to_jirack.py` (aktualisierte Version) in eine neue `.pt`-Datei mit nativer MTP-Unterstützung konvertiert. |
| 24 | |
| 25 | Quantisierungsmechanismus (gleich wie beim 32B-Modell): `BitLinear` berechnet Gamma als **per-tensor absmean**; |
| 26 | die Gewichte werden auf genau drei Werte abgebildet (`-gamma, 0, +gamma`), sodass ein verlustfreier TQ2_0-Roundtrip möglich ist. |
| 27 | |
| 28 | **Unterschied zum 32B-Modell:** zwei architektonische Anpassungen — siehe Abschnitte 0 und 1. |
| 29 | |
| 30 | --- |
| 31 | |
| 32 | ## 0. MTP-Block (Medusa Token Prediction, Layer 64) |
| 33 | |
| 34 | **Was das ist:** Die neue llama.cpp-Architektur (Version ≥ ca3d5a3e1, Tag b10665) verlangt |
| 35 | eine MTP-Schicht für Modelle wie `qwen3_5`. MTP ist ein spekulativer Decoder (Draft-Layer) |
| 36 | zur Beschleunigung der Batch-Generierung, ähnlich wie Medusa. Implementiert in `JiRackDeltaNet_27b.py`. |
| 37 | |
| 38 | **Was bisher erledigt ist:** |
| 39 | |
| 40 | - Die Klasse `MTPBlock` ist im Code implementiert (15 Tensoren: fc, Norms). |
| 41 | - MTP-Gewichte wurden aus dem originalen Qwen3.8-27B-HF-Checkpoint übernommen. |
| 42 | - Sie wurden bei der Konvertierung in die GGUF-Datei integriert (`qwen38_27b_jirack_baseline_bf16.gguf`). |
| 43 | - MTP wird **nicht** ternarisiert (bleibt in voller Präzision, ca. 100 MB Gewichte). |
| 44 | |
| 45 | **Warum MTP nicht ternarisiert wird:** |
| 46 | |
| 47 | - Die MTP-Schicht ist für die Standardgenerierung nicht nötig (sie wird nur genutzt, wenn das Flag für spekulatives Decoding aktiv ist). |
| 48 | - Die Ternarisierung der 400 Hauptschichten reicht für die Zielkompression. |
| 49 | - Volle Präzision bei MTP erhält die Qualität des spekulativen Decoders für Nutzer, die ihn einschalten. |
| 50 | |
| 51 | **Für QAT-Warmup und Materialisierung:** die Layer `mtp.*` beim Anwenden |
| 52 | des `BitLinear`-Patches einfach überspringen — das erledigt bereits `apply_bitlinear_patch(skip_mtp=True)`. |
| 53 | |
| 54 | --- |
| 55 | |
| 56 | ## 1. Was ternarisiert wird und was nicht (DREI AUSNAHMEN) |
| 57 | |
| 58 | Standardmäßig (`include_gate_proj=False` in `apply_bitlinear_patch`) |
| 59 | werden die folgenden 400 linearen Schichten gepatcht: |
| 60 | |
| 61 | - `linear_attn.in_proj_qkv`, `linear_attn.in_proj_z`, `linear_attn.out_proj` |
| 62 | - `self_attn.q_proj`, `k_proj`, `v_proj`, `o_proj` |
| 63 | - `mlp.gate_proj`, `up_proj`, `down_proj` |
| 64 | |
| 65 | **Nicht gepatcht und müssen in voller Präzision bleiben:** |
| 66 | |
| 67 | - `linear_attn.in_proj_b` und `linear_attn.in_proj_a` — das sind die Gate-Skalare |
| 68 | für DeltaNet (dt/A-Gate-Projektionen); sie steuern die Stabilität der Rekurrenz. Das war eine bewusste Entscheidung: das Risiko, die Rekurrenzformel selbst |
| 69 | durch grobe ternäre Quantisierung zu destabilisieren, wurde höher eingeschätzt als die mögliche |
| 70 | Einsparung. |
| 71 | - Alle Normalisierungsschichten (`RMSNorm`, `RMSNormGated`), `conv1d` (depthwise, |
| 72 | 4-Tap), `dt_bias`, `A_log`. |
| 73 | - `embed_tokens`, `lm_head`. |
| 74 | |
| 75 | **Folge für den GGUF-Export:** beim Quantisieren nach GGUF muss der Tensortyp |
| 76 | dieser Schichten explizit angegeben werden (`--tensor-type` oder |
| 77 | das Äquivalent in Ihrer Version von `llama-quantize`), damit |
| 78 | `in_proj_b`/`in_proj_a`, conv1d und alle Norm-Schichten in f16/f32 bleiben |
| 79 | und nicht dem allgemeinen TQ2_0-Setting eines Voll-Datei-Quantisierungslaufs unterworfen werden. Ohne explizite Angabe setzen manche Quantisierungsskripte |
| 80 | einen einzigen Typ auf alle geeigneten Tensoren — das würde |
| 81 | den Rekurrenzmechanismus stillschweigend zerstören. |
| 82 | |
| 83 | ## 2. Architekturrisiko — BEREITS GEPRÜFT ✅ |
| 84 | |
| 85 | Gated DeltaNet ist eine hybride Architektur, die in llama.cpp noch neu ist. Das Risiko lag darin, |
| 86 | dass ihre Unterstützung weniger ausgereift ist als bei Qwen2-Attention in den 32B-Modellen. |
| 87 | |
| 88 | **Geprüft (2026-08-28):** |
| 89 | |
| 90 | - GGUF-Konvertierung (`pt` → `safetensors` → `qwen38_27b_jirack_baseline_bf16.gguf`): |
| 91 | erfolgreich, 866 Tensoren, 54,6 GB |
| 92 | - Smoke-Test (llama-cli mit Chat-Template): das Modell antwortet korrekt |
| 93 | („The capital of France is Paris“ mit Reasoning-Schicht) |
| 94 | - Baseline-Perplexität auf wikitext-100k: **PPL = 5.4957 ± 0.12** |
| 95 | (11 Chunks à 2048 Tokens, bf16, lambda=0.0) |
| 96 | |
| 97 | **Fazit:** die Architektur funktioniert in llama.cpp korrekt. Jede weitere |
| 98 | Verschlechterung bei der ternären/TQ2_0-Quantisierung kommt vom Quantisierungsprozess selbst, |
| 99 | nicht von Implementierungsfehlern. |
| 100 | |
| 101 | **Hinweis für später:** wenn die Perplexität bei TQ2_0 abnormal springt (>>6.5), |
| 102 | ist das kein Architekturrisiko — dann liegt das Problem beim QAT-Warmup |
| 103 | oder bei falsch ausgeschlossenen Schichten. |
| 104 | |
| 105 | ## 3. QAT-Training (wenn ternäre Quantisierung erforderlich ist) |
| 106 | |
| 107 | 1. Checkpoint laden: |
| 108 | |
| 109 | ```python |
| 110 | model = JiRackQwen38ForCausalLM.load_checkpoint( |
| 111 | "/data/qwen38_27b_checkpoint_migrated.pt", dtype=torch.bfloat16) |
| 112 | ``` |
| 113 | |
| 114 | 2. Warmup-Lambda schrittweise von 0.0 auf 1.0 hochfahren (analog zum 32B-Modell, |
| 115 | über `set_lambda` auf allen Modulen, die diese Methode unterstützen). |
| 116 | 3. Trainierten Checkpoint speichern. |
| 117 | |