Tutoriel : entraînez votre propre modèle de raisonnement avec GRPO

Guide du débutant pour transformer un modèle comme Llama 3.1 (8B) en modèle de raisonnement en utilisant Unsloth et GRPO.

DeepSeek a développé GRPOarrow-up-right (Group Relative Policy Optimization) pour entraîner leurs modèles de raisonnement R1.

Démarrage rapide

Ces instructions sont pour nos carnets. Si vous installez Unsloth localement, vous pouvez aussi copier nos carnets dans votre éditeur de code préféré. Nous utiliserons l’un de ces carnets :

1

Installer Unsloth

Si vous utilisez notre carnet Colab, cliquez Runtime > Run all. Nous vous recommandons vivement de consulter notre Guide de fine-tuning avant de commencer.

Si vous installez localement, assurez-vous d'avoir les requirements corrects et utilisez pip install unsloth sur Linux ou suivez nos instructions d'installation Windows .

2

En savoir plus sur GRPO et les fonctions de récompense

Avant de commencer, il est recommandé d'en apprendre davantage sur GRPO, les fonctions de récompense et leur fonctionnement. Lisez-en plus à leur sujet, y compris astuces & conseils ici.

Vous aurez également besoin de suffisamment de VRAM. En général, le nombre de paramètres du modèle = quantité de VRAM dont vous aurez besoin. Dans Colab, nous utilisons leurs GPU gratuits de 16 Go de VRAM qui peuvent entraîner n'importe quel modèle jusqu'à 16B de paramètres.

3

Configurer les paramètres souhaités

Nous avons déjà présélectionné des paramètres optimaux pour obtenir les meilleurs résultats et vous pouvez changer le modèle pour celui que vous souhaitez parmi ceux listés dans nos modèles pris en charge. Nous ne recommandons pas de modifier les autres paramètres si vous êtes débutant.

circle-check
4

Préparation des données

Nous avons présélectionné le GSM8Karrow-up-right d'OpenAI qui contient des problèmes de mathématiques de niveau scolaire, mais vous pouvez le remplacer par le vôtre ou par n'importe quel jeu public sur Hugging Face. Vous pouvez en lire plus sur les jeux de données ici.

Votre jeu de données doit toujours comporter au moins 2 colonnes pour les paires question-réponse. Cependant, la réponse ne doit pas révéler le raisonnement expliquant comment elle a été dérivée de la question. Voir ci-dessous pour un exemple :

Nous structurerons les données pour inciter le modèle à articuler son raisonnement avant de fournir une réponse. Pour commencer, nous établirons un format clair pour les invites et les réponses.

# Définir l'invite système qui indique au modèle d'utiliser un format spécifique
SYSTEM_PROMPT = """
Répondez dans le format suivant :
<reasoning>
...
</reasoning>
<answer>
...
</answer>
"""

XML_COT_FORMAT = """\
<reasoning>
{reasoning}
</reasoning>
<answer>
{answer}
</answer>
"""

Maintenant, pour préparer le jeu de données :

import re
from datasets import load_dataset, Dataset


# Fonctions utilitaires pour extraire les réponses de différents formats
def extract_xml_answer(text: str) -> str:
    answer = text.split("<answer>")[-1]
    answer = answer.split("</answer>")[0]
    return answer.strip()


def extract_hash_answer(text: str) -> str | None:
    if "####" not in text:
        return None
    return text.split("####")[1].strip()


# Fonction pour préparer le jeu de données GSM8K
def get_gsm8k_questions(split="train") -> Dataset:
    data = load_dataset("openai/gsm8k", "main")[split]
    data = data.map(
        lambda x: {
            "prompt": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": x["question"]},
            ],
            "answer": extract_hash_answer(x["answer"]),
        }
    )
    return data


dataset = get_gsm8k_questions()

Le jeu de données est préparé en extrayant les réponses et en les formatant en chaînes structurées.

5

Fonctions de récompense / Vérificateur

Fonctions de récompense / Vérificateurs nous indiquent si le modèle fonctionne bien ou non selon le jeu de données que vous avez fourni. Chaque exécution de génération sera évaluée en fonction de ses performances par rapport à la moyenne des autres générations. Vous pouvez créer vos propres fonctions de récompense mais nous les avons déjà présélectionnées pour vous avec les fonctions de récompense GSM8K de Will . Avec cela, nous avons 5 façons différentes de récompenser chaque génération.

Vous pouvez injecter vos générations dans un LLM comme ChatGPT 4o ou Llama 3.1 (8B) et concevoir une fonction de récompense et un vérificateur pour l'évaluer. Par exemple, alimentez vos générations dans un LLM de votre choix et définissez une règle : "Si la réponse paraît trop robotique, déduisez 3 points." Cela aide à affiner les sorties selon des critères de qualité. Voir des exemples de ce à quoi ils peuvent ressembler ici.

Exemple de fonction de récompense pour une tâche d'automatisation d'e-mails :

  • Question : E-mail entrant

  • Réponse : E-mail sortant

  • Fonctions de récompense :

    • Si la réponse contient un mot-clé requis → +1

    • Si la réponse correspond exactement à la réponse idéale → +1

    • Si la réponse est trop longue → -1

    • Si le nom du destinataire est inclus → +1

    • Si un bloc de signature (téléphone, e-mail, adresse) est présent → +1

6

Entraînez votre modèle

Nous avons présélectionné des hyperparamètres pour les résultats les plus optimaux, toutefois vous pouvez les modifier. Lisez tout sur les paramètres ici. Pour GRPO avancé documentation sur le batching, la génération et les paramètres d'entraînement, lisez notre guide !

Le GRPOConfig définit les hyperparamètres clés pour l'entraînement :

  • use_vllm : Active l'inférence rapide en utilisant vLLM.

  • learning_rate : Détermine la vitesse d'apprentissage du modèle.

  • num_generations : Spécifie le nombre de complétions générées par invite.

  • max_steps : Définit le nombre total d'étapes d'entraînement.

circle-check

Vous devriez voir la récompense augmenter avec le temps. Nous vous recommandons d'entraîner pendant au moins 300 étapes ce qui peut prendre 30 minutes ; cependant, pour des résultats optimaux, vous devriez entraîner plus longtemps.

circle-exclamation

Vous verrez également des réponses d'exemple qui vous permettent de voir comment le modèle apprend. Certaines peuvent contenir des étapes, des balises XML, des tentatives, etc., et l'idée est qu'à mesure qu'il s'entraîne, il s'améliorera de plus en plus car il obtiendra des scores de plus en plus élevés jusqu'à ce que nous obtenions les sorties souhaitées avec de longues chaînes de raisonnement.

7

Exécutez et évaluez votre modèle

Exécutez votre modèle en cliquant sur le bouton lecture. Dans le premier exemple, il n'y a généralement pas de raisonnement dans la réponse et afin de voir le raisonnement, nous devons d'abord enregistrer les poids LoRA que nous venons d'entraîner avec GRPO en utilisant :

model.save_lora("grpo_saved_lora")
Le premier exemple d'inférence n'a pas de raisonnement. Vous devez charger la LoRA et la tester pour révéler le raisonnement.

Ensuite, nous chargeons la LoRA et la testons. Notre modèle de raisonnement est bien meilleur - il n'est pas toujours correct, puisque nous ne l'avons entraîné qu'une heure environ - il s'améliorera si nous étendons la longueur de la séquence et entraînons plus longtemps !

Vous pouvez ensuite enregistrer votre modèle au format GGUF, Ollama, etc. en suivant notre guide ici.

Si vous n'obtenez toujours pas de raisonnement, vous avez peut-être entraîné trop peu d'étapes ou votre fonction de récompense/vérificateur n'était pas optimale.

8

Enregistrez votre modèle

Nous avons plusieurs options pour enregistrer votre modèle affiné, mais nous nous concentrerons sur les approches les plus simples et les plus populaires dont vous pouvez lire davantage ici

Enregistrement en précision 16 bits

Vous pouvez enregistrer le modèle en précision 16 bits en utilisant la commande suivante :

# Enregistrer en précision 16 bits
model.save_pretrained_merged("model", tokenizer, save_method="merged_16bit")

Pousser vers le Hub Hugging Face

Pour partager votre modèle, nous le pousserons vers le Hub Hugging Face en utilisant la méthode push_to_hub_merged . Cela permet d'enregistrer le modèle dans plusieurs formats de quantification.

# Pousser vers le Hub Hugging Face (nécessite un token)
model.push_to_hub_merged(
    "votre-nom-utilisateur/nom-du-model", tokenizer, save_method="merged_16bit", token="votre-token"
)

Enregistrement au format GGUF pour llama.cpp

Unsloth prend également en charge l'enregistrement en format GGUF, le rendant compatible avec llama.cpp et Ollama.

model.push_to_hub_gguf(
    "votre-nom-utilisateur/nom-du-model",
    tokenizer,
    quantization_method=["q4_k_m", "q8_0", "q5_k_m"],
    token="votre-token",
)

Une fois enregistré au format GGUF, le modèle peut être facilement déployé dans des environnements légers en utilisant llama.cpp ou utilisé dans d'autres moteurs d'inférence.

Tutoriels vidéo

Voici quelques tutoriels vidéo créés par des YouTubers formidables que nous trouvons fantastiques !

Idéal pour apprendre à préparer votre jeu de données et les explications derrière l'apprentissage par renforcement + les bases de GRPO
GRPO local sur votre propre appareil

Mis à jour

Ce contenu vous a-t-il été utile ?