# RL efficace en mémoire

Nous sommes ravis de présenter un apprentissage par renforcement (RL) plus efficace dans Unsloth avec plusieurs avancées algorithmiques :

* **Allongements de contexte augmentés de 1,2 à 1,7x** sans ralentissement et sans utilisation mémoire supplémentaire !
* **Exécutions d'entraînement RL 10 % plus rapides** avec des noyaux retravaillés et des mouvements de données asynchrones
* **2x plus rapide `torch.compile` fois** pendant le chargement du modèle

Unsloth **déjà** augmente la vitesse d'entraînement RL, la fenêtre de contexte et réduit l'utilisation de la VRAM de 50–90 % par rapport à toutes les autres configurations avec FA2, mais maintenant [**Standby d'Unsloth**](#unsloth-standby) améliore cela encore davantage. Notre fonctionnalité Standby limite de manière unique la dégradation de la vitesse par rapport à d'autres implémentations et rend parfois l'entraînement encore plus rapide !

Maintenant, Qwen3-32B LoRA 16 bits peut atteindre des longueurs de contexte de 6 144 contre 3 600 (**1,7x plus long**) auparavant sur un GPU 1xH100 80GB. Llama-3.1-8B QLoRA 4 bits peut atteindre 47 500 longueurs contre 42 000 auparavant (1,13x plus long).

Nous avons rendu les exécutions RL 10 % plus rapides grâce à diverses optimisations des noyaux, et avons supprimé le canal de communication LoRA entre le CPU et le GPU lors du passage du mode entraînement au mode inférence. Enfin, nous avons utilisé des `torch.compile` indicateurs pour rendre le rollout de vLLM 10 % plus rapide, et réduit le temps de compilation par 2x.

## :sparkles:Comment activer les optimisations

Pour permettre la **Standby d'Unsloth** fonctionnalité, définissez la variable d'environnement `UNSLOTH_VLLM_STANDBY` avant tout import Unsloth. Ensuite définissez `gpu_memory_utilization = 0.95` et c'est tout !

```python
import os
os.environ["UNSLOTH_VLLM_STANDBY"] = "1"

from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/Qwen3-8B-Base",
    max_seq_length = 2048, # Peut augmenter pour des traces de raisonnement plus longues
    load_in_4bit = False, # False pour LoRA 16bit
    fast_inference = True,
    max_lora_rank = 32, # Rang plus grand = plus intelligent, mais plus lent
    gpu_memory_utilization = 0.95,
)
```

## :mortar\_board:Plus besoin de `gpu_memory_utilization`!

Avec les nouvelles améliorations RL d'Unsloth, vous n'avez JAMAIS à vous soucier d'ajuster ou de définir `gpu_memory_utilization` à nouveau - définissez-le simplement à 90 % ou 95 % d'utilisation du GPU - 100 % ne fonctionnera malheureusement pas car un peu d'espace est nécessaire pour les petits tenseurs. Auparavant, il fallait l'ajuster de 30 % à 95 % - plus maintenant ! Mettez-le au maximum et Unsloth s'occupe du reste !

## :interrobang:Pourquoi le RL utilise-t-il autant de mémoire ?

GRPO (et de nombreuses variantes de RL) s'appuient fortement sur la génération qui est principalement assurée par vLLM. Mais cela a un coût élevé car cela nécessite constamment **mémoire GPU pour les poids, les activations et le cache KV**.

{% columns %}
{% column %}
L'inférence prend beaucoup de VRAM

<figure><img src="/files/78af1adba18cab31e0b99d77a9701308f5bda7df" alt=""><figcaption></figcaption></figure>
{% endcolumn %}

{% column %}
Alors que l'entraînement utilise aussi de la VRAM !

<figure><img src="/files/6f7f47d6329c244c36b055961f8d7c2fae7659a8" alt=""><figcaption></figcaption></figure>
{% endcolumn %}
{% endcolumns %}

Cela signifie que le RL doit garder 2 ensembles de VRAM / mémoire sur le GPU en même temps :

1. Moteur d'inférence (contient les poids du modèle, le cache KV)
2. Moteur d'entraînement (contient les poids du modèle, les activations, les gradients, les états de l'optimiseur)

Les frameworks RL actuels doivent répartir 50/50 pour un GPU de 80 Go avec 50 % pour l'inférence et 50 % pour l'entraînement. Et déplacer les poids du mode entraînement au mode inférence peut prendre pas mal de temps.

<table><thead><tr><th width="251.51666259765625">GPU 80 Go</th><th>Moteur d'inférence (50 %)</th><th>Moteur d'entraînement (50 %)</th></tr></thead><tbody><tr><td>Poids du modèle</td><td>16 Go</td><td>16 Go</td></tr><tr><td>Cache KV</td><td>24 Go</td><td></td></tr><tr><td>Activations, gradients, états de l'optimiseur</td><td></td><td>24 Go</td></tr></tbody></table>

Les versions précédentes d'Unsloth optimisent déjà intelligemment ce qui précède, car nous **partageons directement l'espace de poids de vLLM ce qui élimine la double consommation mémoire des poids du modèle**. Cela libère par exemple 16 Go d'espace qui peut être utilisé pour augmenter la longueur du contexte ou la vitesse de génération. De plus, nous n'avons pas besoin d'effectuer des mouvements de mémoire, ce qui accélère l'entraînement.

| GPU 80 Go                                     | Moteur d'inférence (50 %) | Moteur d'entraînement (50 %) |
| --------------------------------------------- | ------------------------- | ---------------------------- |
| Poids du modèle                               | **16 Go PARTAGÉS**        | **<<< PARTAGÉ**              |
| Cache KV                                      | 24 Go + 8 Go= **32 Go**   |                              |
| Activations, gradients, états de l'optimiseur |                           | 24 Go + 8 Go=**32 Go**       |

## 🦥Unsloth Standby

Mais nous pouvons aller plus loin - nous remarquons d'abord que le RL fait inférence puis entraînement puis inférence puis entraînement, etc.

<figure><img src="/files/19c623d9ec2e85da60a286e96e33a25c63804912" alt=""><figcaption></figcaption></figure>

Cela signifie que l'espace mémoire pour l'inférence et l'entraînement peut en théorie être réutilisé, puisque l'inférence et l'entraînement sont des modes séparés - c'est là que [la fonction de mode veille de vLLM](https://docs.vllm.ai/en/latest/features/sleep_mode.html#rlhf-weight-updates) entre en jeu, qui a 2 options :

1. `level = 1` copie les poids vers le CPU et supprime le cache KV
2. `level = 2` supprime les poids et supprime le cache KV

Mais rappelons qu'avec Unsloth nous partageons l'espace mémoire de vLLM pour les poids - cela signifie que nous avons besoin d'une nouvelle façon de supprimer le cache KV, et d'ignorer la suppression des poids, et nous appelons cela Unsloth Standby.

| GPU 80 Go                                                                                                                                                             | Moteur d'inférence | Moteur d'entraînement                         |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | --------------------------------------------- |
| Poids du modèle                                                                                                                                                       | **16 Go PARTAGÉS** | **<<< PARTAGÉ**                               |
| <p><mark style="background-color:purple;"><strong>Polyvalent</strong></mark></p><p><mark style="background-color:purple;"><strong>Espace de 64 Go</strong></mark></p> | Cache KV           | Activations, gradients, états de l'optimiseur |

Pour activer cela, ajoutez simplement ce qui suit à toutes les exécutions d'entraînement RL / GRPO avant tout import Unsloth :

```python
import os
os.environ["UNSLOTH_VLLM_STANDBY"] = "1"
```

## 🧪Expériences de performance

Ici vous découvrirez comment nous avons mesuré l'utilisation de la mémoire et la longueur de contexte pour GRPO. Notez que nous faisons **2 générations par prompt car pour que GRPO fonctionne**, nous avons besoin d'au moins 2 générations pour pouvoir calculer la moyenne d'échantillon et la variance. **Sans 2 générations, l'écart type d'un seul échantillon est 0**. Cela provoque que les avantages qui utilisent ceci : (reward - mean)/std **soient indéfinis**.

$$
Z=\frac{r\_i - \mu}{\sqrt{\frac{1}{n}\sum(r\_i-\mu)^2}} \\
Z\_{n=1}=\frac{r\_1 - \mu}{\sqrt{\frac{1}{1}\sum(r\_1-\mu)^2}}=\frac{0}{0}=\text{undefined}
$$

Cela signifie que pour GRPO spécifiquement, une longueur de contexte maximale de 6 144 pour Qwen-3 32B correspond en fait à 6 144 multiplié par 2 générations, soit 12 288 en longueur.

Nous fournissons des expériences pour Llama-3.1 8B sur LoRA (16 bits) et QLoRA (4 bits) ci‑dessous :

<figure><img src="/files/56e44ecc2a946412c77dcd208804a27ae7c42066" alt="" width="563"><figcaption></figcaption></figure>

**Si vous remarquez des différences de temps d'entraînement, ce n'est pas grand‑chose**. Dans notre comparaison à armes égales, nous avons observé des ralentissements de temps d'entraînement <1 % ou même des accélérations pouvant être attribuées à la marge d'erreur.

Nous émettons aussi l'hypothèse que des accélérations sont possibles en raison d'une moindre pression mémoire, donc il pourrait y avoir moins de nettoyage mémoire côté allocateur CUDA.

<figure><img src="/files/42900270e647cb8c40f44f007f4853ab87fa9d9d" alt=""><figcaption></figcaption></figure>

Dans l'image ci‑dessous, vous voyez la différence entre le mode de base et le mode standby sur un seul GPU T4 pour Qwen 3 4B. <mark style="background-color:green;">**Nous pouvons pousser la**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**`gpu_memory_utilisation de vllm`**</mark><mark style="background-color:green;">**&#x20;**</mark><mark style="background-color:green;">**jusqu'à 0,95 sans craindre que cela n'affecte l'entraînement**</mark>. Cela signifie que vous pouvez adapter des séquences de longueur de contexte plus élevée et traiter plus de séquences. Dans le premier cas, par exemple, nous avons suffisamment de mémoire pour adapter et traiter des séquences de longueur 32K si l'entraînement le permet, alors qu'auparavant, toute entrée plus longue que 2K risquait de ne pas tenir et de provoquer des OOM (out of memory).

<table data-full-width="true"><thead><tr><th>Expériences</th><th>Configuration</th><th>Statut</th><th>Utilisation mémoire GPU</th><th>Commentaires</th></tr></thead><tbody><tr><td><ol><li><a href="https://colab.research.google.com/drive/18CssBY5C0mStnLvu2Hlt4aFLoPugRG0K?usp=sharing">u0.95gen2ga1s Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby True</code></p><p><code>vllm_gpu_util 0.95</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td>S'exécute pendant 40 étapes / 40 minutes</td><td><p>14,5 Gio (défini par vllm_gpu_util)</p><p><br></p></td><td>Suffisant pour tenir dans 32K KVCache avec des chunks de 2-4K ou par exemple 16K KVCache + chunks de 16K</td></tr><tr><td><ol start="2"><li><a href="https://colab.research.google.com/drive/1q0TOUychygfreI2wKpg51sqnRhs5cYnX?usp=sharing">u9ge2ga2s Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby True</code></p><p><code>vllm_gpu_util 0.9</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td>S'exécute 32 étapes en 40 m</td><td>13,8 Gio (défini par…)</td><td>Approx suffisamment pour tenir dans ~28K KVCache avec des chunks de 2-4K ou par exemple 15K KVCache + chunks de 15K</td></tr><tr><td><ol start="3"><li><a href="https://colab.research.google.com/drive/12Uw8y5beLzPtx11mCWCYyh9Z_PEHHdId?usp=sharing">u9ge2ga2ns Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby False</code></p><p><code>vllm_gpu_util 0.9</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td>le modèle se charge mais ne peut pas entraîner car même une taille de batch de 1 ne rentre pas</td><td>OOM</td><td><br></td></tr><tr><td><ol start="4"><li><a href="https://colab.research.google.com/drive/1GwTlaP5CLsW-BcE1LqZWkz6S8VTWYdJ2?usp=sharing">u8ge2ga2ns Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby False</code></p><p><code>vllm_gpu_util 0.8</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td>le modèle se charge mais ne peut pas entraîner car même une taille de batch de 1 ne rentre pas</td><td>OOM</td><td><br></td></tr><tr><td><ol start="5"><li><a href="https://colab.research.google.com/drive/1IuSUNzEBTiURK-vbTQuRDuUl0Ya2pz2t?usp=sharing">u7ge2ga2ns Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby False</code></p><p><code>vllm_gpu_util 0.7</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td><p>S'entraîne correctement</p><p>28 étapes prennent 39 min</p></td><td>~15,1 Gio</td><td>toute entrée légèrement plus longue entraînera un OOM sur Colab</td></tr><tr><td><ol start="6"><li><a href="https://colab.research.google.com/drive/1RY7HwpZ0luJT70OyLJ6zXKZQ2COdT9QJ?usp=sharing">u7gen2ga2s Qwen3_(4B)-GRPO.ipynb</a></li></ol></td><td><p><code>standby True</code></p><p><code>vllm_gpu_util 0.7</code></p><p><code>num_gen 2</code></p><p><code>grad_acc_steps 2</code></p></td><td><p>S'entraîne correctement</p><p>29 étapes prennent 40 min</p></td><td>13 Gio mais la plupart du temps autour de 10-11 Go</td><td>Avec la même config, nous économisons 2 Gio soit 15 % de mémoire ici.<br>Peut être plus élevé pour des séquences plus longues</td></tr></tbody></table>

### Expériences H100

| Modèle               | GPU                   | Longueur Seq | Nombre de générations | Grad Acc Steps |
| -------------------- | --------------------- | ------------ | --------------------- | -------------- |
| Qwen2.5-14B-Instruct | NVIDIA H100 80GB PCIe | 32,768       | 8                     | 4              |

Dans nos résultats dépliables ci‑dessous, vous pouvez voir qu'il y a une différence de 9 Gio dans la mémoire de pointe utilisée (notez que 90 % du temps, l'utilisation mémoire du GPU est égale à la mémoire de pointe dans notre cas). **Pour mettre les choses en perspective, en utilisant TRL et LoRA nous avons pu affiner seulement un modèle de 8 milliards de paramètres avec une longueur de contexte maximale de 1 024 (32x moins).** Toute chose avec une longueur de séquence plus élevée (avec configuration similaire) entraîne l'échec du processus avec un OOM.

<details>

<summary>Cliquez pour les benchmarks Mode Standby Unsloth vs. pas de Standby</summary>

```
Mode Standby activé :

|===========================================================================|
|                  Résumé mémoire CUDA PyTorch, ID du périphérique 0                  |
|---------------------------------------------------------------------------|
|            OOM CUDA : 0            |        tentatives cudaMalloc : 0         |
|===========================================================================|
|        Métrique         | Util. courante  | Util. pic | Tot alloué  | Tot libéré  |
|---------------------------------------------------------------------------|
| Mémoire allouée        |  32249 MiB |  43042 MiB | 128336 GiB | 128305 GiB |
|       depuis le grand pool |  31415 MiB |  42165 MiB | 127204 GiB | 127173 GiB |
|       depuis le petit pool |    834 MiB |   1184 MiB |   1132 GiB |   1131 GiB |
|---------------------------------------------------------------------------|
| Mémoire active         |  32249 MiB |  43042 MiB | 128336 GiB | 128305 GiB |
|       depuis le grand pool |  31415 MiB |  42165 MiB | 127204 GiB | 127173 GiB |
|       depuis le petit pool |    834 MiB |   1184 MiB |   1132 GiB |   1131 GiB |
|---------------------------------------------------------------------------|
| Mémoire demandée       |  32199 MiB |  42987 MiB | 128176 GiB | 128145 GiB |
|       depuis le grand pool |  31364 MiB |  42110 MiB | 127047 GiB | 127016 GiB |
|       depuis le petit pool |    834 MiB |   1184 MiB |   1129 GiB |   1128 GiB |
|---------------------------------------------------------------------------|
| Mémoire réservée GPU   |  37644 MiB |  47504 MiB | 705806 MiB | 668162 MiB |
|       depuis le grand pool |  36376 MiB |  46588 MiB | 682818 MiB | 646442 MiB |
|       depuis le petit pool |   1268 MiB |   1284 MiB |  22988 MiB |  21720 MiB |
|---------------------------------------------------------------------------|
| Mémoire non libérable  | 713142 KiB |   4633 MiB | 103206 GiB | 103205 GiB |
|       depuis le grand pool | 525312 KiB |   4594 MiB | 101923 GiB | 101922 GiB |
|       depuis le petit pool | 187830 KiB |    250 MiB |   1283 GiB |   1283 GiB |
|---------------------------------------------------------------------------|
| Allocations            |    3460    |    4809    |   15606 K  |   15603 K  |
|       depuis le grand pool |     395    |     563    |    2812 K  |    2811 K  |
|       depuis le petit pool |    3065    |    4270    |   12794 K  |   12791 K  |
|---------------------------------------------------------------------------|
| Allocs actives         |    3460    |    4809    |   15606 K  |   15603 K  |
|       depuis le grand pool |     395    |     563    |    2812 K  |    2811 K  |
|       depuis le petit pool |    3065    |    4270    |   12794 K  |   12791 K  |
|---------------------------------------------------------------------------|
| Segments réservés GPU  |     913    |     920    |   13260    |   12347    |
|       depuis le grand pool |     279    |     305    |    1766    |    1487    |
|       depuis le petit pool |     634    |     642    |   11494    |   10860    |
|---------------------------------------------------------------------------|
| Allocs non libérables  |     422    |     628    |    4766 K  |    4765 K  |
|       depuis le grand pool |      66    |      92    |    1290 K  |    1289 K  |
|       depuis le petit pool |     356    |     555    |    3476 K  |    3475 K  |
|---------------------------------------------------------------------------|
| Allocations surdimensionnées  |       0    |       0    |       0    |       0    |
|---------------------------------------------------------------------------|
| Segments GPU surdimensionnés |       0    |       0    |       0    |       0    |
|===========================================================================|


Sans Standby :

|===========================================================================|
|                  Résumé mémoire CUDA PyTorch, ID du périphérique 0                  |
|---------------------------------------------------------------------------|
|            OOM CUDA : 0            |        tentatives cudaMalloc : 0         |
|===========================================================================|
|        Métrique         | Util. courante  | Util. pic | Tot alloué  | Tot libéré  |
|---------------------------------------------------------------------------|
| Mémoire allouée        |  32711 MiB |  52084 MiB | 142756 GiB | 142724 GiB |
|       depuis le grand pool |  31877 MiB |  51207 MiB | 141499 GiB | 141467 GiB |
|       depuis le petit pool |    834 MiB |   1184 MiB |   1257 GiB |   1256 GiB |
|---------------------------------------------------------------------------|
| Mémoire active         |  32711 MiB |  52084 MiB | 142756 GiB | 142724 GiB |
|       depuis le grand pool |  31877 MiB |  51207 MiB | 141499 GiB | 141467 GiB |
|       depuis le petit pool |    834 MiB |   1184 MiB |   1257 GiB |   1256 GiB |
|---------------------------------------------------------------------------|
| Mémoire demandée       |  32572 MiB |  51658 MiB | 141898 GiB | 141866 GiB |
|       depuis le grand pool |  31738 MiB |  50780 MiB | 140644 GiB | 140613 GiB |
|       depuis le petit pool |    833 MiB |   1184 MiB |   1253 GiB |   1252 GiB |
|---------------------------------------------------------------------------|
| Mémoire réservée GPU   |  49552 MiB |  52188 MiB |  86354 MiB |  36802 MiB |
|       depuis le grand pool |  48320 MiB |  51300 MiB |  84740 MiB |  36420 MiB |
|       depuis le petit pool |   1232 MiB |   1232 MiB |   1614 MiB |    382 MiB |
|---------------------------------------------------------------------------|
| Mémoire non libérable  |      0 B   |      0 B   |      0 B   |      0 B   |
|       depuis le grand pool |      0 B   |      0 B   |      0 B   |      0 B   |
|       depuis le petit pool |      0 B   |      0 B   |      0 B   |      0 B   |
|---------------------------------------------------------------------------|
| Allocations            |    3460    |    4809    |   17440 K  |   17437 K  |
|       depuis le grand pool |     395    |     564    |    2742 K  |    2741 K  |
|       depuis le petit pool |    3065    |    4270    |   14698 K  |   14695 K  |
|---------------------------------------------------------------------------|
| Allocs actives         |    3460    |    4809    |   17440 K  |   17437 K  |
|       depuis le grand pool |     395    |     564    |    2742 K  |    2741 K  |
|       depuis le petit pool |    3065    |    4270    |   14698 K  |   14695 K  |
|---------------------------------------------------------------------------|
| Segments réservés GPU  |       0    |       0    |       0    |       0    |
|       depuis le grand pool |       0    |       0    |       0    |       0    |
|       depuis le petit pool |       0    |       0    |       0    |       0    |
|---------------------------------------------------------------------------|
| Allocs non libérables  |       0    |       0    |       0    |       0    |
|       depuis le grand pool |       0    |       0    |       0    |       0    |
|       depuis le petit pool |       0    |       0    |       0    |       0    |
|---------------------------------------------------------------------------|
| Allocations surdimensionnées  |       0    |       0    |       0    |       0    |
|---------------------------------------------------------------------------|
| Segments GPU surdimensionnés |       0    |       0    |       0    |       0    |
|===========================================================================|
```

</details>

L'image ci‑dessous montre comment le mode standby se compare à l'entraînement sans standby avec Unsloth. Elle est moyennée sur 3 exécutions pour s'assurer que les métriques ne sont pas bruitées. En fait, si vous zoomez suffisamment, vous verrez que l'activation du standby le rend aussi plus rapide, probablement en raison d'une moindre pression mémoire comme discuté précédemment.

<figure><img src="/files/a202b4bbf88b2898745f439bb7f721789806cf5b" alt=""><figcaption></figcaption></figure>

### Expériences précédentes sur A100 40GB

Dans nos expériences précédentes sur GPU A100 40GB avec Qwen-2.5-3b-instruct et 8 générations par échantillon, nous avons observé que sans standby, l'entraînement GRPO (modèle chargé en 16 bits, LoRA, seuls les poids entraînables) ne permettait d'ajuster que des longueurs de séquence de 6K. Avec notre fonctionnalité standby, nous avons pu tenir 10K et au‑delà ! **Pour comparaison, TRL ne peut vous offrir des longueurs de contexte que jusqu'à 1K tout en conservant la même taille de batch.**

<figure><img src="/files/3a2c7d70854b46ca92a55a558418d8fb925182e8" alt="" width="563"><figcaption></figcaption></figure>

## :tada:Autres optimisations

Nous sélectionnons désormais de meilleurs drapeaux de compilation et réduisons les temps de compilation de 50 % ou plus. Nous avons aussi réussi à patcher dynamiquement toute version de vLLM pour gérer `gc.collect` mieux pour des raisons de compatibilité descendante, comme inspiré de cette [pull request vLLM](https://github.com/vllm-project/vllm/pull/21146). Cela réduit les temps de compilation de 2 minutes à moins de 40 secondes.

Nous avons également optimisé `torch.compile` les indicateurs et essayé d'activer certains flags - malheureusement `combo_kernels` et `multi_kernel` n'a pas pu fonctionner correctement sur vLLM 0.10 et Torch 2.8/2.9 nightly et `coordinate_descent_tuning` a rendu l'autotuning de tous les noyaux considérablement plus lent. Cela compilait auparavant en moins d'une minute, mais l'activer prenait plus de 13 minutes et plus, avec des gains de performances minimes.

## :books:Cahiers GRPO

Tous nos notebooks GRPO ont Unsloth Standby activé par défaut et toutes les optimisations ! Voir <https://docs.unsloth.ai/get-started/unsloth-notebooks> pour tous nos notebooks GRPO, ou essayez ce qui suit :

* [**Qwen3 (4B)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen3_\(4B\)-GRPO.ipynb) **-** GRPO LoRA avancé
* [**DeepSeek-R1-0528-Qwen3 (8B)**](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/DeepSeek_R1_0528_Qwen3_\(8B\)_GRPO.ipynb) (pour des cas d'utilisation multilingues)
* [Gemma 3 (1B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Gemma3_\(1B\)-GRPO.ipynb)
* [Llama 3.2 (3B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Advanced_Llama3_2_\(3B\)_GRPO_LoRA.ipynb) - GRPO LoRA avancé
* [Llama 3.1 (8B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llama3.1_\(8B\)-GRPO.ipynb)
* [Phi-4 (14B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Phi_4_\(14B\)-GRPO.ipynb)
* [Mistral v0.3 (7B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Mistral_v0.3_\(7B\)-GRPO.ipynb)
* [Qwen2.5 (3B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_\(3B\)-GRPO.ipynb)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/fr/commencer/reinforcement-learning-rl-guide/memory-efficient-rl.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
