Entraînement gpt-oss à contexte long
Nous sommes ravis de présenter la prise en charge d’Unsloth Flex Attention pour l’entraînement OpenAI gpt-oss, ce qui permet >8× plus longues longueurs de contexte, >50 % d’utilisation de VRAM en moins et un entraînement >1,5× plus rapide (sans dégradation de la précision) par rapport à toutes les implémentations, y compris celles utilisant Flash Attention 3 (FA3). Unsloth Flex Attention permet de s’entraîner avec une longueur de contexte de 60K sur un GPU H100 avec 80 Go de VRAM pour BF16 LoRA. Aussi :
Vous pouvez désormais exporter/enregistrer votre modèle gpt-oss affiné en QLoRA vers llama.cpp, vLLM, Ollama ou HF
Nous avons corrigé l’entraînement gpt-oss les pertes qui divergeaient vers l’infini sur des GPU float16 (comme le T4 Colab)
Nous avons corrigé l’implémentation gpt-oss des problèmes sans rapport avec Unsloth, notamment en garantissant que
swiglu_limit = 7.0est correctement appliqué lors de l’inférence MXFP4 dans transformers
🦥Présentation de la prise en charge d’Unsloth Flex Attention
Avec la prise en charge de Flex Attention par Unsloth, un seul H100 avec 80 Go de VRAM peut gérer jusqu’à 81K de longueur de contexte avec QLoRA et 60K de contexte avec BF16 LoRA ! Ces gains s’appliquent à LES DEUX gpt-oss-20b et gpt-oss-120b! Plus vous utilisez une grande longueur de contexte, plus vous gagnerez avec Unsloth Flex Attention :

En comparaison, toutes les autres implémentations non-Unsloth plafonnent à 9K de longueur de contexte sur un GPU de 80 Go, et ne peuvent atteindre que 15K de contexte avec FA3. Mais, FA3 ne convient pas à l’entraînement de gpt-oss car il ne prend pas en charge la rétropropagation pour les puits d’attention. Donc, si vous utilisiez auparavant FA3 pour l’entraînement de gpt-oss, nous vous recommandons de ne pas l’utiliser pour le moment. Ainsi, la longueur de contexte maximale que vous pouvez obtenir sans Unsloth sur 80 Go de VRAM est d’environ 9K.
L’entraînement avec Unsloth Flex Attention offre au moins un accélération de 1,3×, avec des gains qui augmentent à mesure que la longueur de contexte augmente, jusqu’à 2× plus rapide. Comme Flex Attention évolue avec le contexte, les séquences plus longues entraînent des économies plus importantes en VRAM et en temps d’entraînement, comme décrit ici.
Un grand merci à Rohan Pandey pour son implémentation de Flex Attention, qui a directement inspiré le développement de l’implémentation Flex Attention d’Unsloth.
🕶️ Puits d’attention
Le modèle GPT OSS d’OpenAI utilise un pattern alterné d’attention à fenêtre glissante, d’attention complète, d’attention à fenêtre glissante, etc. (SWA, FA, SWA, FA, etc.). Chaque fenêtre glissante n’accède qu’à 128 jetons (y compris le jeton actuel), ce qui réduit énormément le calcul. Cependant, cela signifie aussi que la récupération et le raisonnement sur long contexte deviennent inutiles à cause de la petite fenêtre glissante. La plupart des laboratoires corrigent cela en élargissant la fenêtre glissante à 2048 ou 4096 jetons.
OpenAI s’est inspiré Puits d’attention de l’article Efficient Streaming Language Models with Attention Sinks papier qui montre qu’on peut utiliser une petite fenêtre glissante, à condition d’ajouter une attention globale sur le premier jeton ! L’article fournit une bonne illustration ci-dessous :

L’article constate que le mécanisme d’attention semble attribuer beaucoup de poids aux premiers jetons (1 à 4), et en les supprimant lors de l’opération de fenêtre glissante, ces premiers jetons « importants » disparaissent, ce qui entraîne une mauvaise récupération sur long contexte.
Si l’on trace la perplexité logarithmique (plus c’est élevé, pire c’est), et que l’on fait une inférence sur long contexte après la longueur de contexte définie du modèle préentraîné, on voit la perplexité grimper en flèche (pas bon). Cependant, la ligne rouge (qui utilise Attention Sinks) reste basse, ce qui est très bien !

L’article montre aussi que la méthode Attention Is Off By One fonctionne partiellement, sauf qu’il faut aussi ajouter quelques jetons de puits supplémentaires pour obtenir de plus faibles perplexités. L’article montre que l’ajout d’un seul jeton de puits, apprenable, fonctionne remarquablement bien ! Et c’est ce qu’OpenAI a fait pour GPT-OSS !

📐L’implémentation Flex Attention d’Unsloth
Flex Attention https://pytorch.org/blog/flexattention/ est extrêmement puissante, car elle offre au praticien 2 voies de personnalisation pour le mécanisme d’attention - un modificateur de score (f) et une fonction de masquage (M).
Le modificateur de score (f) permet de modifier les logits d’attention avant l’opération softmax, et la fonction de masquage (M) permet de sauter des opérations si nous n’en avons pas besoin (par exemple, l’attention à fenêtre glissante ne voit que les 128 derniers jetons).
L’astuce, c’est que Flex Attention fournit rapidement des kernels Triton auto-générés avec des modificateurs de score et des fonctions de masquage arbitraires !
σ(s×f(QKT+M))
Cela signifie que nous pouvons utiliser Flex Attention pour implémenter des puits d’attention ! L’implémentation d’un seul puits d’attention est fournie à la fois dans le dépôt GPT-OSS original d’OpenAI et dans l’implémentation des transformers de HuggingFace.
Ce qui précède montre que nous concaténons le puits tout à la fin du Q @ K.T , effectuons le softmax, puis retirons la dernière colonne, qui était le jeton de puits.
En utilisant quelques utilitaires de visualisation du dépôt Github de Flex Attention, nous pouvons visualiser cela. Supposons que la longueur de séquence soit 16, avec une fenêtre glissante de 5. À gauche se trouve la dernière colonne de puits (implémentation par défaut), et à droite, si nous déplaçons l’emplacement du puits à l’index 0 (notre implémentation).
Emplacement du puits à la fin (par défaut)

Déplacer l’emplacement du puits à l’index 0

Découverte intéressante: Les implémentations officielles de fenêtre glissante de Flex Attention considèrent la taille de la fenêtre comme le nombre des derniers jetons PLUS UN car elles incluent le jeton actuel. Les implémentations HuggingFace et GPT OSS ne voient strictement que les N derniers jetons. Autrement dit, ce qui suit provient de https://pytorch.org/blog/flexattention/ et https://github.com/meta-pytorch/attention-gym:
Flex Attention par défaut (3+1 jetons)

HuggingFace, GPT-OSS (3+0 jetons)

Nous avons aussi confirmé via l’implémentation officielle GPT-OSS d’OpenAI si l’on s’intéresse ici aux N derniers jetons ou à N+1 jetons : https://github.com/openai/gpt-oss/blob/main/gpt_oss/torch/model.py

Et nous voyons que seuls les 3 derniers jetons (pas 3+1) sont pris en compte ! Cela signifie qu’au lieu d’utiliser <= SLIDING_WINDOW, utilisez < SLIDING_WINDOW (c.-à-d. utiliser inférieur à, pas égal).
De plus, comme nous avons déplacé l’index du jeton de puits au premier, nous devons ajouter 1 à q_idx pour indexer correctement :
Pour confirmer notre implémentation avec index 0, nous avons vérifié que la perte d’entraînement reste cohérente avec les exécutions standard de Hugging Face (sans Unsloth Flex Attention), comme montré dans notre graphe :

📜 Dérivation mathématique pour les puits d’attention
Il existe une autre façon de calculer les puits d’attention sans remplir K et V. Nous notons d’abord l’opération softmax, et nous voulons pour l’instant la 2e version avec puits comme un scalaire :\
Nous pouvons obtenir le logsumexp depuis Flex Attention via return_lse = True , puis nous faisons :
Et nous pouvons maintenant dériver facilement la version avec puits de l’attention. Nous constatons toutefois que ce processus présente une erreur un peu plus élevée que l’approche de remplissage par zéro, donc nous conservons par défaut notre version originale.
💾NOUVEAU : Enregistrement vers GGUF, vLLM après l’entraînement de gpt-oss
Vous pouvez maintenant affiner gpt-oss avec QLoRA et directement enregistrer, exporter ou fusionner le modèle vers llama.cpp, vLLM, ou HF - pas seulement Unsloth. Nous publierons, espérons-le, bientôt un notebook gratuit.
Auparavant, tout modèle gpt-oss affiné en QLoRA était limité à une exécution dans Unsloth. Nous avons supprimé cette limitation en introduisant la capacité de fusionner dans MXFP4 format natif en utilisant save_method="mxfp4" et déquantification à la demande de MXFP4 des modèles de base (comme gpt-oss), ce qui permet de exporter votre modèle affiné au format bf16 en utilisant save_method="merged_16bit" .
Le MXFP4 format de fusion natif offre des améliorations de performance significatives par rapport au format bf16 : il utilise jusqu’à 75 % d’espace disque en moins, réduit la consommation de VRAM de 50 %, accélère la fusion de 5 à 10× et permet une conversion beaucoup plus rapide au format GGUF .
Après avoir affiné votre modèle gpt-oss, vous pouvez le fusionner au format MXFP4 avec :
Si vous préférez fusionner le modèle et le pousser vers le hub Hugging Face, utilisez :
Pour exécuter l’inférence sur le modèle fusionné, vous pouvez utiliser vLLM et Llama.cpp, entre autres. OpenAI recommande ces paramètres d’inférence pour les deux modèles : temperature=1.0, top_p=1.0, top_k=0
✨ Enregistrement vers Llama.cpp
Obtenez la dernière version
llama.cppsur GitHub ici. Vous pouvez également suivre les instructions de compilation ci-dessous. Changez-DGGML_CUDA=ONen-DGGML_CUDA=OFFsi vous n’avez pas de GPU ou si vous souhaitez simplement une inférence CPU.Convertissez le MXFP4 modèle fusionné :
Exécutez l’inférence sur le modèle quantifié :
✨ Enregistrement vers SGLang
Construisez SGLang depuis les sources :\
Lancer le serveur SGLang :\
Exécuter l’inférence :\
♦️Ajuster directement gpt-oss
Nous avons également ajouté la prise en charge de l’affinage direct des modèles gpt-oss en implémentant des patchs qui permettent de charger le format quantifié natif MXFP4. Cela permet de charger le modèle 'openai/gpt-oss' avec moins de 24 Go de VRAM, et de l’affiner en QLoRA. Il suffit de charger le modèle en utilisant :
ajouter une couche Peft en utilisant FastLanguageModel.get_peft_model et lancer un affinage SFT sur le modèle Peft.
🐛Corrections de bugs pour gpt-oss
Nous a récemment collaboré avec Hugging Face pour résoudre les problèmes d’inférence en utilisant les kernels d’OpenAI et en s’assurant que swiglu_limit = 7.0 est correctement appliqué lors de l’inférence MXFP4.
D’après les retours des utilisateurs, nous avons découvert que les longues sessions d’entraînement QLoRA (au-delà de 60 étapes) pouvaient provoquer une divergence de la perte puis une erreur finale. Ce problème ne se produisait que sur les appareils qui ne prennent pas en charge BF16 et retombent à la place sur F16 (par exemple, les GPU T4). Important : cela n’affectait pas l’entraînement QLoRA sur les GPU A100 ou H100, ni l’entraînement LoRA sur les GPU f16.
Après une enquête approfondie, nous avons maintenant harmonisé le comportement de la perte d’entraînement sur toutes les configurations GPU, y compris les GPU limités à F16. Si vous rencontriez auparavant des problèmes à cause de cela, nous vous recommandons d’utiliser notre nouveau notebook gpt-oss mis à jour !

Nous avons dû faire de très nombreuses expériences pour rendre la courbe de perte d’entraînement du float16 équivalente à celle des machines bfloat16 (ligne bleue). Nous avons constaté ce qui suit :
Le float16 pur divergera vers l’infini à l’étape 50
Nous avons trouvé que les projections descendantes dans le MoE présentaient de très fortes valeurs aberrantes
Les activations doivent être enregistrées en bfloat16 ou float32
Ci-dessous, on voit les activations de magnitude absolue pour GPT OSS 20B, et certaines connaissent de très fortes pointes - cela débordera sur les machines float16, car la plage maximale du float16 est 65504.
Nous avons corrigé cela dans Unsloth, donc tout l’entraînement float16 fonctionne désormais immédiatement !

🔢 Implémentations pour Sink Attention
L’implémentation du jeton de puits d’OpenAI est fournie ici. Nous la fournissons ci-dessous :
L’implémentation des transformers HuggingFace est fournie ici. Nous la fournissons également ci-dessous :
Mis à jour
Ce contenu vous a-t-il été utile ?

