Ternarization_instructions_27b_sp.md
5.9 KB · 117 lines · markdown Raw
1 # Instrucciones de ternarización y exportación a GGUF/TQ2_0 — Qwen3.8-27B
2
3 Modelo: `/mnt/nfs_share/Qwen3_8/`, clase `JiRackDeltaNet_27b.py`
4 (híbrido 3:1 Gated-DeltaNet / Gated-Attention, `model_type: qwen3_5`).
5
6 ## Estado (actualizado 2026-08-28)
7
8 ✅ **Hecho:**
9
10 - Conversión HF → formato propio, pruebas de toda la pipeline
11 - **Bloque MTP implementado e integrado** (véase la sección 0 más abajo)
12 - Conversión GGUF correcta (pt → safetensors → GGUF, bf16)
13 - Smoke test superado: el modelo responde correctamente («Paris» a «What is the capital of France?»)
14 - **Perplejidad de referencia: PPL = 5.4957 ± 0.12** (wikitext-100k, c=2048, bf16, lambda=0.0)
15 - Archivo: `/mnt/nfs_share/Qwen3_8/wiki_100k.txt` (usar el mismo archivo para comparar después de la ternarización)
16 - Registro: `/mnt/nfs_share/Qwen3_8/ppl_baseline_bf16.log` (última línea, 11 chunks)
17
18 ⏳ **Siguientes pasos:** warmup QAT lambda 0.0→1.0, materialización de la ternarización, exportación TQ2_0, perplejidad final
19
20 Checkpoint actual: `/mnt/nfs_share/Qwen3_8/qwen38_27b_checkpoint_migrated.pt` (53,79 GB, lambda=0.0)
21
22 - Contiene los pesos MTP (transferidos desde el checkpoint HF original), pero aún no está ternarizado.
23 - Se convertirá en un nuevo archivo `.pt` con soporte nativo de MTP mediante el script `convert_qwen38_to_jirack.py` (versión actualizada).
24
25 Mecanismo de cuantización (igual que en el modelo 32B): `BitLinear` calcula gamma como **absmean por tensor**;
26 los pesos se proyectan a exactamente tres valores (`-gamma, 0, +gamma`), lo que garantiza un ida y vuelta TQ2_0 sin pérdida.
27
28 **Diferencia respecto al modelo 32B:** dos ajustes arquitectónicos; véanse las secciones 0 y 1.
29
30 ---
31
32 ## 0. Bloque MTP (Medusa Token Prediction, capa 64)
33
34 **Qué es:** la nueva arquitectura de llama.cpp (versión ≥ ca3d5a3e1, etiqueta b10665) exige
35 una capa MTP para modelos como `qwen3_5`. MTP es un decodificador especulativo (capa draft)
36 diseñado para acelerar la generación por lotes, similar a Medusa. Implementado en `JiRackDeltaNet_27b.py`.
37
38 **Lo que ya está hecho:**
39
40 - La clase `MTPBlock` está implementada en el código (15 tensores: fc, normas).
41 - Los pesos MTP se han portado desde el checkpoint HF original de Qwen3.8-27B.
42 - Se integraron en el archivo GGUF durante la conversión (`qwen38_27b_jirack_baseline_bf16.gguf`).
43 - MTP **no** entra en el proceso de ternarización (permanece en precisión completa, ~100 MB de pesos).
44
45 **Por qué no ternarizamos MTP:**
46
47 - La capa MTP no es esencial para la generación estándar (solo se usa cuando está activada la bandera de decodificación especulativa).
48 - Ternarizar las 400 capas principales basta para alcanzar la compresión objetivo.
49 - Mantener MTP en precisión completa preserva la calidad del decodificador especulativo para quienes decidan activarlo.
50
51 **Para el warmup QAT y la materialización:** basta con omitir las capas `mtp.*` al aplicar
52 el parche `BitLinear`; esto ya lo gestiona `apply_bitlinear_patch(skip_mtp=True)`.
53
54 ---
55
56 ## 1. Qué se ternariza y qué no (TRES EXCEPCIONES)
57
58 Por defecto (`include_gate_proj=False` en `apply_bitlinear_patch`)
59 se parchean las siguientes 400 capas lineales:
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 **Lo siguiente NO se parchea y debe permanecer en precisión completa:**
66
67 - `linear_attn.in_proj_b` y `linear_attn.in_proj_a` — son los escalares de puerta
68 para DeltaNet (proyecciones dt/A-gate); controlan la estabilidad de la recurrencia. Fue una decisión deliberada: el riesgo de desestabilizar la propia fórmula de recurrencia
69 con una cuantización ternaria gruesa se consideró mayor que el posible
70 ahorro.
71 - Todas las capas de normalización (`RMSNorm`, `RMSNormGated`), `conv1d` (depthwise,
72 4 taps), `dt_bias`, `A_log`.
73 - `embed_tokens`, `lm_head`.
74
75 **Implicación para la exportación GGUF:** al cuantizar a GGUF hay que indicar
76 explícitamente el tipo de tensor de estas capas (`--tensor-type` o
77 el equivalente en su versión de `llama-quantize`) para que
78 `in_proj_b`/`in_proj_a`, conv1d y todas las capas de normalización permanezcan en f16/f32
79 y no queden sujetas al ajuste general TQ2_0 de un pase de cuantización de todo el archivo. Sin especificación explícita, algunos scripts de cuantización
80 aplican un solo tipo a todos los tensores elegibles, lo que rompería
81 en silencio el mecanismo de recurrencia.
82
83 ## 2. Riesgo arquitectónico — YA VERIFICADO ✅
84
85 Gated DeltaNet es una arquitectura híbrida todavía nueva en llama.cpp. El riesgo estaba en que
86 su soporte es menos maduro que el de la atención Qwen2 en los modelos 32B.
87
88 **Verificado (2026-08-28):**
89
90 - Conversión GGUF (`pt` → `safetensors` → `qwen38_27b_jirack_baseline_bf16.gguf`):
91 correcta, 866 tensores, 54,6 GB
92 - Smoke test (llama-cli con chat-template): el modelo responde correctamente
93 («The capital of France is Paris» con capa de razonamiento)
94 - Perplejidad de referencia en wikitext-100k: **PPL = 5.4957 ± 0.12**
95 (11 chunks de 2048 tokens, bf16, lambda=0.0)
96
97 **Conclusión:** la arquitectura funciona correctamente en llama.cpp. Cualquier degradación
98 adicional durante la cuantización ternaria/TQ2_0 vendrá del propio proceso de cuantización,
99 no de errores de implementación.
100
101 **Nota para más adelante:** si la perplejidad se dispara de forma anómala (>>6.5) durante TQ2_0,
102 no es un riesgo arquitectónico: indica un problema de warmup QAT
103 o de capas excluidas de forma incorrecta.
104
105 ## 3. Entrenamiento QAT (cuando se requiere cuantización ternaria)
106
107 1. Cargar el checkpoint:
108
109 ```python
110 model = JiRackQwen38ForCausalLM.load_checkpoint(
111 "/data/qwen38_27b_checkpoint_migrated.pt", dtype=torch.bfloat16)
112 ```
113
114 2. Subir gradualmente el lambda de warmup de 0.0 a 1.0 (igual que en el modelo 32B,
115 usando `set_lambda` en todos los módulos que admiten este método).
116 3. Guardar el checkpoint entrenado.
117