# Dressage avance : QLoRA, DPO et quantization

Ember vole et obeit aux ordres. Cette lecon est l'ecole de vol avancee : entrainer des dragons *plus gros* sur le meme materiel (QLoRA), enseigner le *jugement* plutot que l'imitation (DPO), et retrecir ton modele entraine pour un deploiement rapide (quantization + GGUF). Ces trois techniques separent les experiences du week-end des modeles qu'on utilise tous les jours.

## QLoRA : entrainer au-dessus de ta categorie de poids

Tu as deja utilise le chargement en 4-bit a la lecon 5 sur le chemin PC — c'*etait* du QLoRA. Maintenant, utilisons-le deliberement, pour son vrai but : **entrainer des modeles qui ne rentrent pas autrement.**

L'idee : compresser les poids de base geles en precision 4-bit (format NF4), garder les adaptateurs LoRA en 16-bit. La base perd une pincee de qualite a la compression, mais comme les adaptateurs — la partie qui apprend — restent en pleine precision, les resultats finaux restent remarquablement proches d'un LoRA complet.

D'apres le tableau de la lecon 3, QLoRA est ce qui debloque le plafond de chaque machine :

- **RTX 4090 (24 Go) :** 14B confortablement, 32B tout juste (contexte court, batch 1, gradient checkpointing — attends-toi a te battre).
- **M3 Ultra (96 Go) :** 32B avec de la marge ; le 70B est possible si tu acceptes des runs de nuit.

Quand Ember devrait-il passer au-dessus du 4B ? Seulement quand l'evaluation le dit : si la v3+ continue d'echouer sur le *fond* (raisonnement faible dans les reponses complexes) alors que le format et le ton sont solides, c'est le symptome "modele de base trop petit" de la lecon 6 — passe a Qwen3-8B ou 14B et relance le meme pipeline. Rien d'autre ne change ; c'est la beaute de cette installation.

<div class="pro-tip">
<h4>Astuce Pro</h4>
Passer de 4B a 8B double environ le temps d'entrainement et la memoire — ca vaut generalement le coup. 14B → 32B double encore pour un saut de qualite plus petit sur les taches simples. Laisse tes <em>scores de test</em> justifier chaque saut, pas la fierte d'avoir un gros modele.
</div>

## DPO : enseigner le gout, pas seulement les tours

Le fine-tuning supervise (tout ce qu'on a fait jusqu'ici) montre au modele de *bonnes* reponses. **DPO — Direct Preference Optimization** — lui montre des *paires* : pour le meme prompt, une reponse **choisie** (chosen) et une **rejetee** (rejected). Le modele apprend la *direction* de tes preferences : ce qui rend une reponse meilleure qu'une autre.

```json
{"prompt": "Customer: You people are useless! Where is my package?!",
 "chosen": "I understand the frustration — let's fix this properly. [calm, structured answer with next step]",
 "rejected": "We apologize for any inconvenience caused. Your satisfaction is important to us. [corporate mush, no next step]"}
```

<div class="concept-box">
<h4>Concept</h4>
Le SFT enseigne "voici a quoi ressemble une bonne reponse". Le DPO enseigne "entre ces deux reponses plausibles, prefere <em>ce</em> genre-la". Il brille exactement la ou le SFT plafonne : le jugement de style subtil, la desescalade, le choix de la concision, l'evitement du remplissage corporate — des choses difficiles a demontrer mais faciles a comparer.
</div>

L'ordre de la recette compte : **toujours le SFT d'abord, puis le DPO par-dessus** — typiquement 100 a 500 paires de preferences, avec un learning rate plus bas (~5e-6). Les meilleures reponses rejetees ne sont pas des epouvantails ; ce sont les vraies sorties plausibles-mais-imparfaites de *ton propre modele*, issues des runs d'evaluation. Sur le chemin PC, c'est le `DPOTrainer` de `trl` avec la meme installation Unsloth ; sur le Mac, `mlx-lm` embarque le support du preference training (verifie `mlx_lm.lora --help` pour les flags actuels — l'ecosysteme bouge vite).

<div class="honest-note">
<h4>Note honnete</h4>
Le DPO est un assaisonnement, pas un repas. Sur un petit modele avec un SFT solide, 200 bonnes paires affutent nettement le jugement de ton. Le DPO ne peut pas sauver un mauvais SFT, et en abuser (trop d'epochs, learning rate trop haut) produit un modele bizarre avec assurance. Si tu n'as qu'une soiree, passe-la sur de meilleures donnees SFT.
</div>

## Quantization : retrecir le dragon pour le vol quotidien

La precision d'entrainement et la precision de service sont deux jeux differents. Une fois Ember finalise, tu le voudras **petit et rapide** pour l'usage quotidien. C'est la quantization au moment de l'inference, et son format universel est **GGUF** — le format que parlent Ollama, LM Studio et llama.cpp.

Le pipeline, sur l'une ou l'autre machine :

<svg viewBox="0 0 720 150" width="100%" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Pipeline : fusion des adaptateurs dans la base, conversion en GGUF, quantization, service">
    <defs>
    <marker id="arr2" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">
      <path d="M0,0 L8,4 L0,8 z" fill="#7b8cff"/>
    </marker>
  </defs>
  <rect x="20" y="45" width="150" height="60" rx="10" fill="rgba(123,140,255,0.08)" stroke="#7b8cff" stroke-width="1.5"/>
  <text x="95" y="70" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="13px">Fusionner les adaptateurs</text>
  <text x="95" y="90" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="11px">base + LoRA → un modele</text>
  <path d="M170 75 L200 75" stroke="#7b8cff" stroke-width="1.5" fill="none" marker-end="url(#arr2)"/>
  <rect x="200" y="45" width="150" height="60" rx="10" fill="rgba(123,140,255,0.08)" stroke="#7b8cff" stroke-width="1.5"/>
  <text x="275" y="70" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="13px">Convertir en GGUF</text>
  <text x="275" y="90" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="11px">script convert de llama.cpp</text>
  <path d="M350 75 L380 75" stroke="#7b8cff" stroke-width="1.5" fill="none" marker-end="url(#arr2)"/>
  <rect x="380" y="45" width="150" height="60" rx="10" fill="rgba(123,140,255,0.08)" stroke="#7b8cff" stroke-width="1.5"/>
  <text x="455" y="70" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="13px">Quantizer Q4_K_M</text>
  <text x="455" y="90" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="11px">~8 Go → ~2,5 Go (4B)</text>
  <path d="M530 75 L560 75" stroke="#7b8cff" stroke-width="1.5" fill="none" marker-end="url(#arr2)"/>
  <rect x="560" y="45" width="140" height="60" rx="10" fill="rgba(79,255,176,0.08)" stroke="#4fffb0" stroke-width="1.5"/>
  <text x="630" y="70" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="13px">Servir</text>
  <text x="630" y="90" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="11px">Ollama · LM Studio</text>
</svg>

La premiere etape est la fusion — replier tes adaptateurs dans les poids de base pour obtenir un seul modele autonome :

```bash
# Mac (MLX)
mlx_lm.fuse --model Qwen/Qwen3-4B-Instruct \
  --adapter-path adapters/ember-v3 --save-path ember-merged
```

```python
# PC (Unsloth) — can even save GGUF directly:
model.save_pretrained_merged("ember-merged", tokenizer)
model.save_pretrained_gguf("ember-gguf", tokenizer, quantization_method="q4_k_m")
```

**Q4_K_M** est le sweet spot par defaut de la communaute : ~4,5 bits par poids, une perte de qualite a peine mesurable sur la plupart des taches, une taille divisee par ~4 vs le 16-bit. Utilise Q8_0 quand tu veux du quasi sans perte et que tu as la memoire ; descends sous Q4 seulement si tu es desespere en memoire.

<div class="try-it">
<h4>Essaie</h4>
Prends ton meilleur Ember, fusionne, convertis, quantize en Q4_K_M — puis fais tourner ton jeu de test de la lecon 6 <em>sur le modele quantize</em>. Compare les scores avec la version non quantizee. Voir (avec des chiffres !) que Q4_K_M a a peine bouge tes metriques, c'est comme ca que tu gagnes la confiance de deployer petit.
</div>

<div class="checkpoint">
<h4>Checkpoint</h4>
Tu sais quand QLoRA debloque des bases plus grosses, quand le DPO ajoute du jugement par-dessus le SFT, et comment fusion → GGUF → Q4_K_M transforme un artefact d'entrainement en fichier de modele deployable. Il ne reste qu'une chose : lacher ton dragon dans le monde.
</div>
