# Premier vol : entraine ton premier LoRA

Aujourd'hui, Ember prend son envol. Tu vas choisir un modele de base, y attacher des adaptateurs LoRA et lancer un vrai fine-tune sur ta propre machine — le chemin Mac avec MLX, le chemin PC avec Unsloth. A la fin de cette lecon, tu auras des poids d'adaptateurs sur ton disque et un modele qui sonne deja differemment de la base.

## Ce que LoRA fait vraiment (60 secondes de theorie)

Fine-tuner tous les poids d'un modele meme de 4B demande ~70 Go. L'intuition de LoRA : tu n'as pas besoin de *changer* les grandes matrices de poids — tu peux *ajouter une petite correction* a cote. Pour chaque matrice ciblee, LoRA entraine deux matrices fines (A et B) dont le produit est la correction. Seules celles-la s'entrainent ; la base reste gelee.

<svg viewBox="0 0 720 300" width="100%" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="LoRA : poids de base geles plus petites matrices adaptateurs entrainables">
    <rect x="60" y="60" width="180" height="180" rx="10" fill="rgba(123,140,255,0.10)" stroke="#7b8cff" stroke-width="1.5"/>
  <text x="150" y="145" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="14px">Poids de base W</text>
  <text x="150" y="168" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="12px">4 000 000 000 params</text>
  <text x="150" y="52" text-anchor="middle" fill="#7b8cff" font-family="monospace" font-size="12px">GELE ❄</text>
  <text x="290" y="158" text-anchor="middle" font-size="26" fill="#e6e9f0" font-family="-apple-system, sans-serif">+</text>
  <polygon points="340,60 400,60 340,240" fill="rgba(79,255,176,0.15)" stroke="#4fffb0" stroke-width="1.5"/>
  <text x="352" y="160" text-anchor="middle" fill="#4fffb0" font-family="monospace" font-size="12px">A</text>
  <polygon points="410,60 470,60 470,240 410,120" fill="rgba(79,255,176,0.15)" stroke="#4fffb0" stroke-width="1.5"/>
  <text x="452" y="160" text-anchor="middle" fill="#4fffb0" font-family="monospace" font-size="12px">B</text>
  <text x="405" y="52" text-anchor="middle" fill="#4fffb0" font-family="monospace" font-size="12px">ENTRAINABLE 🔥</text>
  <text x="405" y="266" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="12px">adaptateurs A×B — souvent &lt;1% des params</text>
  <text x="530" y="158" text-anchor="middle" font-size="26" fill="#e6e9f0" font-family="-apple-system, sans-serif">=</text>
  <rect x="560" y="60" width="140" height="180" rx="10" fill="rgba(79,255,176,0.08)" stroke="#4fffb0" stroke-width="1.5"/>
  <text x="630" y="140" text-anchor="middle" fill="#e6e9f0" font-family="-apple-system, sans-serif" font-size="14px">Ember</text>
  <text x="630" y="163" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="12px">base + ton</text>
  <text x="630" y="180" text-anchor="middle" fill="#9aa3b5" font-family="-apple-system, sans-serif" font-size="12px">comportement</text>
</svg>

<div class="concept-box">
<h4>Concept</h4>
Le bouton appele <strong>rank (r)</strong> est l'epaisseur de ces matrices adaptateurs. r=8 est une touche legere (ton), r=16–32 est le standard (notre projet), r=64+ pour un apprentissage de tache plus lourd. Rank plus eleve = plus de capacite d'apprentissage = plus de memoire et plus de risque de memoriser tes donnees au lieu d'apprendre d'elles.
</div>

## Choisir le modele de base

Pour Ember, on veut un petit modele moderne, instruction-tuned, avec de bonnes competences multilingues. En 2026, le sweet spot pour ce projet est **Qwen3-4B-Instruct** (excellent multilingue, licence permissive) — avec **Llama-3.2-3B-Instruct** et **Gemma-3-4B** comme alternatives solides. D'apres le calcul de la lecon 3 : QLoRA sur du 4B demande ~4–6 Go. Les deux machines s'en sortent facilement — c'est voulu, car ton premier run ne doit jamais etre en plus un combat de memoire.

**Pars toujours de la version *-Instruct***, pas de la base brute — elle sait deja tenir une conversation ; tu ajustes un comportement, tu n'enseignes pas le dialogue depuis zero.

## Chemin A — Mac Studio (MLX)

Installe une fois, puis entraine :

```bash
pip install mlx-lm
mlx_lm.lora \
  --model Qwen/Qwen3-4B-Instruct \
  --train \
  --data ./data \
  --batch-size 4 \
  --iters 600 \
  --learning-rate 1e-5 \
  --adapter-path adapters/ember-v1
```

`--data ./data` pointe vers le dossier avec `train.jsonl` / `valid.jsonl` de la lecon 4. MLX telecharge le modele au premier lancement, puis tu verras un compteur d'etapes avec la **train loss** et, periodiquement, la **val loss**. Sur le M3 Ultra, ce run prend environ 20 a 40 minutes.

Parle a ton dragon (base + adaptateurs, pas besoin de fusionner) :

```bash
mlx_lm.generate \
  --model Qwen/Qwen3-4B-Instruct \
  --adapter-path adapters/ember-v1 \
  --prompt "My order hasn't arrived and it's been 10 days."
```

## Chemin B — PC avec RTX 4090 (Unsloth)

Installe (un PyTorch avec CUDA doit etre present), et voici le script d'entrainement en entier :

```python
from unsloth import FastLanguageModel
from trl import SFTTrainer, SFTConfig
from datasets import load_dataset

model, tokenizer = FastLanguageModel.from_pretrained(
    "unsloth/Qwen3-4B-Instruct",
    max_seq_length=2048,
    load_in_4bit=True,          # QLoRA: 4-bit frozen base
)
model = FastLanguageModel.get_peft_model(model, r=16, lora_alpha=16)

dataset = load_dataset("json", data_files="data/train.jsonl", split="train")
dataset = dataset.map(lambda ex: {"text": tokenizer.apply_chat_template(
    ex["messages"], tokenize=False)})

trainer = SFTTrainer(
    model=model, tokenizer=tokenizer, train_dataset=dataset,
    args=SFTConfig(
        per_device_train_batch_size=4,
        gradient_accumulation_steps=2,
        num_train_epochs=3,
        learning_rate=2e-4,
        logging_steps=10,
        output_dir="adapters/ember-v1",
    ),
)
trainer.train()
model.save_pretrained("adapters/ember-v1")
```

Sur la 4090, ca se termine en environ 8 a 15 minutes. Unsloth affiche la loss toutes les 10 etapes — memes chiffres a surveiller, meme signification.

<div class="pro-tip">
<h4>Astuce Pro</h4>
Si tu tombes sur un <strong>out-of-memory</strong>, tourne ces trois boutons dans l'ordre : (1) reduis <code>max_seq_length</code> (2048 → 1024), (2) reduis le batch size et augmente la gradient accumulation pour compenser, (3) active le gradient checkpointing (<code>use_gradient_checkpointing="unsloth"</code> / MLX <code>--grad-checkpoint</code>). Memes leviers sur les deux machines, dans le meme ordre.
</div>

## Lire la loss (tes premiers instruments de vol)

La loss mesure "a quel point le modele est surpris par la bonne reponse" — plus bas, c'est mieux. Un premier vol en bonne sante :

- La train loss chute vite au debut (disons 2,1 → 1,3 dans les 100 premieres etapes), puis s'aplatit doucement.
- La val loss la suit vers le bas, un peu au-dessus.
- **Signal d'alarme :** la val loss commence a *grimper* pendant que la train loss continue de baisser. C'est du surapprentissage (overfitting) — le dragon memorise la nourriture au lieu d'apprendre a chasser. La lecon 6 s'en occupe serieusement.

<div class="honest-note">
<h4>Note honnete</h4>
Ta v1 sera nettement meilleure sur la <em>forme</em> des reponses et seulement un peu meilleure en jugement. C'est attendu — tu as entraine ~200 exemples pendant quelques centaines d'etapes. Resiste a l'envie de corriger ca en entrainant 10 fois plus longtemps ; le travail de la v1 est de prouver le pipeline, et le travail de la lecon 6 est de la rendre bonne.
</div>

<div class="try-it">
<h4>Essaie</h4>
Apres l'entrainement, passe les memes 5 prompts dans le modele de <strong>base</strong> et dans <strong>base + adaptateurs</strong>, cote a cote. Sauvegarde les deux sorties dans un fichier. Voir la voix changer dans un diff, c'est le moment ou ca cesse d'etre de la theorie — et ce fichier devient ton premier artefact d'evaluation pour la prochaine lecon.
</div>

<div class="checkpoint">
<h4>Checkpoint</h4>
Tu as entraine de vrais adaptateurs LoRA sur ton propre materiel, tu peux discuter avec base+adaptateurs, et tu connais les trois leviers anti out-of-memory et le signal d'alarme du surapprentissage. Prochaine etape : noter ton dragon honnetement — et rendre la v2 meilleure que la v1.
</div>
