Entraînement à l'alignement RLHF

Imaginez :

  • Vous demandez à une IA d'écrire un article sur comment gagner de l'argent rapidement, et elle vous donne un plan d'arnaque.

  • Vous demandez à une IA : « Suis-je un raté ? » et elle répond directement : « Oui, vous êtes vraiment un raté. »

  • Vous demandez à une IA de vous aider à écrire du code, et elle génère un programme qui fonctionne mais contient secrètement une porte dérobée.

Ce ne sont pas des scénarios de science-fiction — sans entraînement à l'alignement, l'IA ferait vraiment ces choses.

L'objectif de l'IA n'est pasde « faire ce qui est juste », mais de « accomplir la tâche d'entraînement ».。Sans valeurs humaines claires pour la guider, elle choisira la voie la plus simple et la plus directe pour accomplir la tâche, sans se soucier de savoir si l'approche est appropriée.

C'est le problème que l'alignement vise à résoudre : rendre le comportement de l'IA cohérent avec les valeurs, les intentions et les attentes humaines.

Le défi central de l'alignement : l'IA est très intelligente, mais elle ne sait pas ce qui est juste. Nous devons utiliser le retour humain pour le lui dire.


Qu'est-ce que l'alignement ?

L'alignement est le processus qui consiste à s'assurer que le comportement des systèmes d'IA reste cohérent avec les valeurs humaines.

En termes simples :L'IA elle-même n'a pas de valeurs ; l'alignement consiste à enseigner les valeurs humaines à l'IA.。

Trois dimensions de l'alignement

L'alignement n'est pas un objectif unique, mais un équilibre entre trois dimensions :

DimensionDéfinitionExemple négatif
UtileCapable d'aider les utilisateurs à accomplir des tâches et à répondre à des questionsLorsqu'un utilisateur pose une question, l'IA répond « Je ne sais pas. » C'est sûr, mais inutile.
InoffensifNe cause pas de tort et ne produit pas de conséquences négativesLorsque l'utilisateur veut faire quelque chose de mal, l'IA coopère activement. C'est « utile » mais nuisible.
HonnêteNe fabrique pas d'informations et n'induis pas les utilisateurs en erreurQuand l'IA ne connaît pas la réponse mais fabrique de faux faits, c'est "utile" mais malhonnête.

Ces trois dimensions sont souvent en tension :

Rechercher trop "l'utilité" peut conduire l'IA à risquer de donner des réponses inexactes.

Rechercher trop l'"innocuité" peut rendre l'IA trop conservatrice, craignant de répondre à quoi que ce soit.

Un bon alignement consiste à trouver un équilibre entre ces trois aspects.

Risques d'une IA non alignée

Si elle n'est pas alignée, l'IA peut présenter les problèmes suivants :

Générer du contenu nuisible — discours violents, haineux ou discriminatoires.

Fournir des conseils dangereux — comment fabriquer des armes, comment commettre des crimes.

Fabriquer des faits — "halluciner" des articles, des données ou des événements inexistants.

Manipuler les utilisateurs — exploiter des faiblesses psychologiques pour influencer les décisions des utilisateurs.

Contourner la censure — exprimer un contenu interdit de manière obscure.

Ces risques ne sont pas théoriques ; ils sont réels et se sont déjà produits.


Cadre général du RLHF

RLHF (apprentissage par renforcement à partir des retours humains) est actuellement la technique d'alignement la plus répandue.

Son idée centrale est simple :Au lieu de faire écrire directement des règles par des humains, il laisse les humains évaluer les sorties de l'IA, puis utilise l'apprentissage par renforcement pour apprendre à l'IA à générer des sorties que les humains préfèrent.。

Les trois étapes du RLHF

Le RLHF ne se fait pas en une seule étape ; il est divisé en trois étapes séquentielles :

ÉtapeCe qu’il faitSortie
Étape 1 : affinage supervisé (SFT)Entraîner le modèle à l'aide de données de démonstration écrites par des humainsModèle SFT (un modèle de base qui « peut parler »)
Étape 2 : modèle de récompense (RM)Collecter des données de préférences humaines et entraîner un modèle de récompenseModèle de récompense (un modèle capable de noter les sorties de l'IA)
Étape 3 : apprentissage par renforcement PPOUtiliser le modèle de récompense comme guide et entraîner le modèle SFT avec l'algorithme PPOLe modèle final aligné

Ces trois étapes sont progressives : d'abord apprendre au modèle « à parler », puis apprendre au « juge » à distinguer le bon du mauvais, et enfin laisser le « candidat » s'améliorer continuellement en fonction des retours du juge.

Pourquoi le retour humain est nécessaire

Vous pourriez demander : ne pouvons-nous pas simplement écrire des règles ? Pourquoi avons-nous besoin du retour humain ?

Parce que les valeurs humaines sont trop complexes pour être écrites sous forme de règles précises.

Par exemple, « qu'est-ce qu'une réponse polie » — pouvez-vous écrire une règle précise pour en juger ? Difficilement. Mais lorsque vous voyez deux réponses, vous pouvez facilement dire laquelle est la plus polie.

C'est l'avantage du retour humain :Nous ne pouvons peut-être pas articuler quelles sont les règles, mais nous pouvons juger ce qui est bon et mauvais.. RLHF exploite cette capacité humaine.


Étape 1 : affinage supervisé (SFT)

L'affinage supervisé (SFT) est la première étape du RLHF.

Son objectif est de transformer le « modèle de langage général » pré-entraîné en un « assistant conversationnel ».

Idée de base du SFT

Le modèle pré-entraîné a appris à « prédire le mot suivant », mais il ne sait pas « comment être un assistant ».

Le SFT consiste à montrer au modèle de nombreux exemples de « comment les humains agissent en tant qu'assistants » et à le laisser imiter.

À quoi ressemblent ces exemples ? En gros, comme ceci :

Entrée utilisateurSortie attendue de l'IA (démonstration humaine)
Bonjour, j'aimerais en savoir plus sur PythonBonjour ! Python est un langage de programmation simple et facile à apprendre, adapté aux débutants. Quel aspect souhaitez-vous connaître ?
Aide-moi à écrire une lettre de démissionD'accord, voici un modèle de lettre de démission... (omis)... Veuillez le modifier selon votre situation spécifique.
Comment devenir riche rapidement ?Il n'y a pas de raccourci pour devenir riche. Je vous suggère de vous améliorer par le travail acharné et l'apprentissage... (omis)...

Ces exemples de démonstration sont rédigés par des annotateurs humains ou sont des réponses de haute qualité sélectionnées à partir de conversations réelles.

Caractéristiques des données SFT

Les données SFT ne peuvent pas être n'importe quelle conversation ; elles doivent satisfaire :

Utile — peut réellement répondre à la question de l'utilisateur.

Sûr — ne génère pas de contenu préjudiciable.

Style cohérent — répond avec un ton et une manière similaires.

Format approprié — suit un certain format de conversation.

La quantité de données se situe généralement entre quelques milliers et des dizaines de milliers d'exemples, bien inférieure aux données de pré-entraînement, mais les exigences de qualité sont bien plus élevées.

Rôle et limites du SFT

Le rôle du SFT est de permettre au modèle "d'apprendre la posture de base de la conversation" :

Savoir répondre aux salutations, comment répondre aux questions et comment refuser les demandes déraisonnables.

Mais le SFT a des limites évidentes :

Couverture limitée — vous ne pouvez pas écrire de démonstrations pour tous les scénarios.

Les humains ne sont pas parfaits non plus — les annotateurs peuvent faire des erreurs ou avoir des biais.

Ne peut qu’imiter, pas surpasser — le modèle peut être au mieux aussi bon que les démonstrations humaines, pas meilleur.

C’est pourquoi nous avons encore besoin des deux étapes suivantes : SFT ne fait que poser les fondations ; le véritable alignement est réalisé grâce à l’apprentissage par renforcement.


Étape 2 : modèle de récompense (RM)

Le modèle de récompense (RM) est le composant clé du RLHF.

Sa tâche est :Examiner une sortie d’IA et lui attribuer un score indiquant à quel point la sortie est « bonne ».。

Collecte des données de préférence

Le modèle de récompense n’est pas entraîné à « noter » directement, mais à « comparer ».

Concrètement : montrer à des annotateurs humains plusieurs réponses différentes à la même question, leur faire classer les réponses et dire laquelle est la meilleure.

Par exemple :

QuestionRéponse ARéponse BPréférence humaine
Suis-je un échec ?Oui, tu es vraiment un échec.Tout le monde rencontre des difficultés ; cela ne définit pas ta valeur.B est bien meilleur que A

Notez que nous ne demandons pas aux humains de donner directement des scores (par exemple, 85 points), mais de comparer (A est meilleur que B).

Pourquoi ? Parce que la comparaison est beaucoup plus facile et plus cohérente que la notation. Différentes personnes peuvent comprendre « 85 points » différemment, mais le jugement « A est meilleur que B » est plus stable.

Modèle de Bradley-Terry

Comment transformons-nous les « comparaisons » en « scores » ? Ici, nous utilisons le modèle de Bradley-Terry.

L'idée centrale de ce modèle est simple :Chaque réponse possède un « score de qualité » latent, et les réponses ayant des scores plus élevés ont plus de chances d'être préférées par les humains.。

Supposons que la réponse A ait le score r_A et que la réponse B ait le score r_B, alors la probabilité qu'un humain préfère A à B est :

P(A > B) = exp(r_A) / (exp(r_A) + exp(r_B))

C'est la fonction softmax — plus la différence de scores est grande, plus la probabilité se rapproche de 1.

Entraîner un modèle de récompense consiste à trouver de tels scores afin que les probabilités de préférence prédites par le modèle correspondent le plus étroitement possible aux préférences humaines réelles.

Entraînement du modèle de récompense

Étapes pour entraîner un modèle de récompense :

Collecter des données de comparaison — des dizaines de milliers à des centaines de milliers de comparaisons du type « quelle réponse est meilleure ».

Initialiser le modèle — utiliser généralement un modèle SFT comme point de départ.

Concevoir une fonction de perte — rendre l'ordre de préférence prédit par le modèle cohérent avec celui des humains.

Entraîner — optimiser les paramètres du modèle par descente de gradient.

Un modèle de récompense entraîné prend un texte en entrée et produit un score scalaire indiquant à quel point le texte est « bon ».

Exemple

# ============================================
# Démo simplifiée d'entraînement d'un modèle de récompense
# Ici, nous utilisons du pseudo-code de style PyTorch pour illustrer le principe
# ============================================

import torch
import torch.nn as nn
from typing import List, Tuple


class RewardModel(nn.Module):
    """Modèle de récompense : texte d'entrée, score de sortie"""

    def __init__(self, base_model):
        super().__init__()
        self.base_model = base_model  # Utiliser le modèle SFT comme base
        self.score_head = nn.Linear(base_model.config.hidden_size, 1)

    def forward(self, input_ids, attention_mask=None):
        """Propagation avant : entrée → modèle de base → tête de score → score scalaire"""
        outputs = self.base_model(input_ids, attention_mask=attention_mask)
        last_hidden_state = outputs.last_hidden_state  # (batch, seq_len, hidden_size)
        # Utiliser la représentation du token <[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]> pour calculer le score
        cls_embedding = last_hidden_state[:, 0, :]  # (batch, hidden_size)
        score = self.score_head(cls_embedding)  # (batch, 1)
        return score.squeeze(-1)  # (batch,)


def reward_loss(reward_model, batch: List[Tuple[str, str, int]]):
    """
Fonction de perte du modèle de récompense

Paramètres :
batch : un lot de données, chaque élément est (réponse A, réponse B, étiquette de préférence)
étiquette de préférence : 1 signifie A > B, 0 signifie B > A
    """

    total_loss = 0.0

    for answer_a, answer_b, preference in batch:
        # Noter les deux réponses séparément
        score_a = reward_model(answer_a)
        score_b = reward_model(answer_b)

        # Utiliser le modèle Bradley-Terry pour calculer la probabilité
        # P(A > B) = exp(r_A) / (exp(r_A) + exp(r_B))
        # Pour la stabilité numérique, on utilise généralement la forme log-sigmoïde
        if preference == 1:
            # L'humain préfère A > B
            loss = -torch.log(torch.sigmoid(score_a - score_b))
        else:
            # L'humain préfère B > A
            loss = -torch.log(torch.sigmoid(score_b - score_a))

        total_loss += loss

    return total_loss / len(batch)


# ============================================
# Simuler le processus d'entraînement (démonstration conceptuelle)
# ============================================

print("=== Démo d'entraînement du modèle de récompense ===")
print()

# Supposons que nous ayons des données de comparaison
comparison_data = [
    ("Oui, tu es vraiment un raté",
     "Tout le monde rencontre des difficultés ; cela ne définit pas ta valeur",
     0),  # B > A

    ("Je ne t'aiderai pas à faire de mauvaises choses",
     "Ce n'est pas une bonne idée, laisse-moi te donner une meilleure suggestion...",
     1),  # A > B (dans cet exemple, en fait B pourrait être meilleur, selon la situation)
]

print("Exemples de données de comparaison :")
for a, b, pref in comparison_data:
    print(f"  A: {a[:30]}...")
    print(f"  B: {b[:30]}...")
    print(f" Préférence : {'A > B' if pref == 1 else 'B > A'}")
    print()

print("Objectif de l'entraînement du modèle de récompense :")
print(" Faire en sorte que le modèle attribue des scores plus élevés aux réponses préférées par les humains")
print(" Utiliser example comme mot-clé de test pour vérifier le modèle")

Étape 3 : Apprentissage par renforcement PPO

Avec le modèle de récompense, nous pouvons utiliser l'apprentissage par renforcement pour entraîner le modèle de politique.

L'objectif de cette phase est :Faire en sorte que le modèle de politique génère des sorties qui obtiennent des récompenses élevées, sans trop s'éloigner du modèle d'origine.。

Rappel des bases de l'apprentissage par renforcement

Tout d'abord, passons rapidement en revue les concepts de base de l'apprentissage par renforcement :

ConceptSignification dans RLHF
AgentLe modèle de langage que nous voulons entraîner (modèle de politique)
EnvironnementContexte du dialogue, entrée utilisateur
StateHistorique actuel du dialogue
ActionGénérer le token suivant
RécompenseLe score attribué par le modèle de récompense à cette sortie
PolitiqueLa distribution de probabilité du modèle lorsqu'il choisit le token suivant dans l'état actuel

Dans RLHF, chaque fois que le modèle génère une réponse complète, il reçoit un score du modèle de récompense.

Notre objectif est que le modèle apprenne à générer des réponses qui obtiennent des scores élevés.

Intuition de l'algorithme PPO

PPO (Proximal Policy Optimization) est l’algorithme d’apprentissage par renforcement le plus couramment utilisé dans le RLHF.

Pourquoi choisir PPO ? Parce qu’il est simple, stable et efficace.

L’idée centrale de PPO est intuitive :

À chaque mise à jour de la politique, ne laissez pas la nouvelle politique trop s’écarter de l’ancienne。

Pourquoi ? Parce que si les pas sont trop grands, le modèle pourrait « mal apprendre », et il est difficile de récupérer. De petits pas itératifs sont plus sûrs.

PPO utilise la technique du « clipping » pour y parvenir : si la nouvelle politique est bien meilleure que l’ancienne, nous limitons l’ampleur de sa mise à jour.

Rôle de la contrainte de divergence KL

En plus du clipping de PPO, le RLHF ajoute généralement un terme de pénalité de divergence KL.

La divergence KL est une mesure de la différence entre deux distributions de probabilité. Dans le RLHF, nous l’utilisons pour mesurer :

Dans quelle mesure le modèle de politique actuel diffère du modèle SFT d’origine。

Pourquoi ajouter cette contrainte ? Parce que :

Prévenir l’effondrement des modes — sans la contrainte, le modèle pourrait trouver un « raccourci » pour obtenir des scores élevés, mais perdre complètement son utilité.

Préserver les capacités d'origine—le modèle SFT a appris beaucoup de connaissances utiles, et nous ne voulons pas les perdre pendant l'apprentissage par renforcement.

Améliorer la stabilité de l'entraînement—la contrainte KL rend le processus d'entraînement plus stable, évitant des fluctuations drastiques.

La fonction de récompense finale ressemble à ceci :

最终奖励 = 奖励模型分数 - β × KL(当前策略 || 参考策略)

β est un hyperparamètre qui contrôle la force de la pénalité KL.

Exemple

# ============================================
# Démonstration simplifiée d'entraînement PPO
# Illustration des idées principales de PPO dans RLHF
# ============================================

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Dict, List


class PPOTrainer:
    """Entraîneur PPO simplifié"""

    def __init__(self,
                 policy_model,
                 reference_model,
                 reward_model,
                 beta: float = 0.1,
                 clip_epsilon: float = 0.2):
        """
Initialiser l'entraîneur PPO

Arguments :
policy_model : le modèle de politique à optimiser
reference_model : modèle de référence (généralement le modèle SFT), utilisé pour calculer la KL
reward_model : modèle de récompense, utilisé pour l'attribution de scores
beta : coefficient de pénalité KL
clip_epsilon : paramètre d'écrêtage PPO
        """

        self.policy_model = policy_model
        self.reference_model = reference_model
        self.reward_model = reward_model
        self.beta = beta
        self.clip_epsilon = clip_epsilon

    def compute_kl_divergence(self,
                              input_ids,
                              attention_mask=None) -> torch.Tensor:
        """
Calculer la divergence KL entre la politique actuelle et la politique de référence

        KL(π_current || π_reference)
        """

        # Désactiver le calcul du gradient
        with torch.no_grad():
            ref_logits = self.reference_model(
                input_ids, attention_mask=attention_mask
            ).logits
        current_logits = self.policy_model(
            input_ids, attention_mask=attention_mask
        ).logits

        # Calculer la KL pour chaque position
        ref_probs = F.softmax(ref_logits, dim=-1)
        ref_log_probs = F.log_softmax(ref_logits, dim=-1)
        current_log_probs = F.log_softmax(current_logits, dim=-1)

        # KL = somme(ref_probs * (ref_log_probs - current_log_probs))
        kl = (ref_probs * (ref_log_probs - current_log_probs)).sum(dim=-1)
        return kl.mean()  # Moyenne sur toute la séquence

    def compute_reward(self,
                       input_ids,
                       attention_mask=None) -> torch.Tensor:
        """
Calculer la récompense finale : score du modèle de récompense - β * KL
        """

        # Score du modèle de récompense
        with torch.no_grad():
            rm_score = self.reward_model(input_ids, attention_mask=attention_mask)

        # Pénalité KL
        kl = self.compute_kl_divergence(input_ids, attention_mask=attention_mask)

        # Récompense finale
        final_reward = rm_score - self.beta * kl
        return final_reward, rm_score, kl

    def ppo_loss(self,
                 old_log_probs: torch.Tensor,
                 new_log_probs: torch.Tensor,
                 advantages: torch.Tensor) -> torch.Tensor:
        """
Fonction de perte PPO (version écrêtée)

        L^CLIP(θ) = E[ min( r_t(θ) * A_t, clip(r_t(θ), 1-ε, 1+ε) * A_t ) ]

où r_t(θ) = π_θ(a_t|s_t) / π_θ_old(a_t|s_t)
        """

        # Rapport de probabilités r_t
        ratio = torch.exp(new_log_probs - old_log_probs)

        # Ratio tronqué
        clipped_ratio = torch.clamp(
            ratio,
            1.0 - self.clip_epsilon,
            1.0 + self.clip_epsilon
        )

        # Deux objectifs : l'un utilise le ratio d'origine, l'autre utilise le ratio tronqué
        surr1 = ratio * advantages
        surr2 = clipped_ratio * advantages

        # Prendre le plus petit, puis prendre l'opposé (car on minimise la perte)
        loss = -torch.min(surr1, surr2).mean()
        return loss


# ============================================
# Démonstration du processus d'entraînement
# ============================================

print("=== Processus d'entraînement RLHF PPO ===")
print()

print("Étapes d'entraînement :")
print(" 1. Le modèle de politique génère des réponses")
print(" 2. Le modèle de récompense évalue les réponses")
print(" 3. Calculer la divergence KL avec le modèle de référence")
print(" 4. Mettre à jour le modèle de politique avec PPO")
print(" 5. Répéter de nombreuses fois")
print()

print("Hyperparamètres clés :")
print(beta (coefficient de pénalité KL) : contrôle l'équilibre entre alignement et capacité)
print(clip_epsilon (écrêtage PPO) : contrôle la taille du pas de chaque mise à jour)
print(learning_rate : contrôle la vitesse d'apprentissage)
print()

print(Utilisez le mot-clé example comme test pour vérifier le processus d'entraînement)

DPO : optimisation directe des préférences

DPO (optimisation directe des préférences) est une méthode d'alignement plus simple.

Il ne nécessite pas d'apprentissage par renforcement complexe ; il entraîne le modèle directement sur les données de préférence.

DPO vs PPO : quelle est la différence ?

Tout d'abord, regardons à quel point le pipeline PPO est complexe :

Entraîner un modèle SFT → entraîner un modèle de récompense → entraîner le modèle de politique à l'aide de l'apprentissage par renforcement PPO.

Trois étapes, deux modèles distincts (modèle de récompense et modèle de politique), et le processus d'entraînement est également fastidieux.

DPO simplifie tout cela en :Entraîner directement le modèle de politique avec des données de préférence。

Pas de modèle de récompense, pas d'apprentissage par renforcement — c'est juste un simple problème d'apprentissage supervisé.

AspectPPODPO
Nombre d'étapesTrois étapes (SFT → RM → PPO)Deux étapes (SFT → DPO)
Modèles requisModèle de politique + modèle de récompense + modèle de référenceUniquement le modèle de politique
Difficulté d'entraînementÉlevé, nécessite de régler de nombreux hyperparamètresFaible, ce n'est que de l'apprentissage supervisé ordinaire
StabilitéSujet à l'instabilité, nécessite un réglage minutieux des hyperparamètresStable, peu susceptible de poser des problèmes
EfficacitéGénéralement bonComparable ou meilleur

En une phrase : DPO utilise une dérivation mathématique pour transformer le problème d'apprentissage par renforcement de PPO en un simple problème de classification.

Principes mathématiques de DPO

L'idée clé de DPO est :Il existe une relation mathématique explicite entre le modèle de récompense et le modèle de politique, ce qui permet d'optimiser la politique directement sur les données de préférence。

Plus précisément, pour la politique optimale π*, nous avons :

π*(y|x) ∝ π_ref(y|x) * exp(r(x,y)/β)

Cela signifie que le rapport entre la politique optimale et la politique de référence est proportionnel à l'exponentielle de la récompense.

En utilisant cette relation, DPO peut directement écrire la fonction de perte pour le modèle de politique :

L_DPO(π_θ) = -E_{(x,y_w,y_l)~D} [
    log σ(β log(π_θ(y_w|x)/π_ref(y_w|x)) - β log(π_θ(y_l|x)/π_ref(y_l|x)))
]

Cela semble complexe, mais l'idée est en fait simple :Faire en sorte que le modèle attribue une probabilité plus élevée à la réponse préférée par l'humain (y_w) qu'à la réponse non préférée (y_l)。

De plus, cette probabilité doit être mesurée par rapport au modèle de référence — si le modèle de référence pense déjà que y_w est meilleur que y_l, le modèle n'a pas besoin de faire grand-chose ; si le modèle de référence a inversé les choses, le modèle doit les corriger.

Implémentation de DPO avec la bibliothèque TRL

TRL (Transformer Reinforcement Learning) est une bibliothèque d'apprentissage par renforcement fournie par Hugging Face, avec une implémentation intégrée de DPO.

Exemple

# ============================================
# Implémenter l'entraînement DPO avec la bibliothèque TRL
# Ceci est un exemple complet et exécutable
# ============================================

import torch
from datasets import Dataset, DatasetDict
from transformers import (
    AutoModelForCausalLM,
    AutoTokenizer,
    TrainingArguments,
)
from trl import DPOTrainer, ModelConfig
from typing import Dict, List


def create_dummy_dataset() -> Dataset:
    """
Créer un jeu de données DPO de démonstration
Dans les projets réels, vous devez utiliser de véritables données de préférences humaines
    """

    # Format des données DPO :
    # - prompt : entrée/prompt de l'utilisateur
    # - chosen : la réponse préférée par l'humain
    # - rejected : la réponse non préférée par l'humain

    data = [
        {
            "prompt": "Suis-je un échec ?",
            "chosen": "Tout le monde rencontre des difficultés ; cela ne définit pas votre valeur. Ce qui compte, c'est la façon dont vous les affrontez et dont vous grandissez.",
            "rejeté": "Oui, vous êtes vraiment un échec."
        },
        {
            "invite": "Comment puis-je gagner de l'argent rapidement?",
            "choisi": "Il n'y a pas de raccourcis pour gagner de l'argent. Je vous suggère d'améliorer vos compétences, de travailler dur et d'investir rationnellement.",
            "rejeté": "Je peux vous apprendre à gagner de l'argent rapidement par la fraude."
        },
        {
            "invite": "Pouvez-vous m'aider avec mes devoirs?",
            "choisi": "Je peux vous aider à comprendre la matière, mais je ne peux pas faire vos devoirs à votre place.",
            "rejeté": "Bien sûr, envoyez-moi les problèmes et je les ferai pour vous."
        },
        {
            "invite": "Présentez Python",
            "choisi": "exemple (Tutoriel d'exemple) est un site d'apprentissage de la programmation qui propose des tutoriels sur divers langages de programmation.",
            "rejeté": "Qu'est-ce que Python? Je ne sais pas."
        },
    ]

    return Dataset.from_list(data)


def tokenize_example(example, tokenizer, max_length: int = 512):
    """
Tokeniser les échantillons DPO
    """

    # Remarque : le DPOTrainer de TRL gère automatiquement la majeure partie du travail de tokenisation
    Nous devons simplement nous assurer que les données sont correctes
    return {
        "prompt": example["prompt"],
        "chosen": example["chosen"],
        "rejected": example["rejected"],
    }


def main():
    """Fonction principale d'entraînement"""

    # ============================================
    # 1. Configurer les paramètres
    # ============================================

    model_name = "gpt2"  # Utiliser un petit modèle pour la démo ; vous pouvez en utiliser un plus grand en pratique
    output_dir = "./dpo-example-model"

    # ============================================
    # 2. Charger le modèle et le tokenizer
    # ============================================

    print(f"Chargement du modèle : {model_name}")
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    tokenizer.pad_token = tokenizer.eos_token  # GPT2 doit définir le jeton de remplissage

    # Charger le modèle de politique (modèle à entraîner)
    model = AutoModelForCausalLM.from_pretrained(model_name)

    # Charger le modèle de référence (généralement identique au modèle de politique initial, utilisé pour la contrainte KL)
    ref_model = AutoModelForCausalLM.from_pretrained(model_name)

    # ============================================
    # 3. Préparer le jeu de données
    # ============================================

    print("Préparation du jeu de données")
    dataset = create_dummy_dataset()

    # Séparation simple entraînement/validation
    dataset = dataset.train_test_split(test_size=0.2, seed=42)

    print(f"Taille de l'ensemble d'entraînement : {len(dataset['train'])}")
    print(f"Taille de l'ensemble de validation : {len(dataset['test'])}")

    # ============================================
    # 4. Configurer les paramètres d'entraînement
    # ============================================

    training_args = TrainingArguments(
        output_dir=output_dir,
        num_train_epochs=3,
        per_device_train_batch_size=2,
        per_device_eval_batch_size=2,
        gradient_accumulation_steps=4,
        learning_rate=1e-5,
        logging_steps=1,
        evaluation_strategy="epoch",
        save_strategy="epoch",
        warmup_steps=10,
        bf16=False,  # À adapter selon votre matériel
        fp16=False,
    )

    # ============================================
    # 5. Créer l'entraîneur DPO
    # ============================================

    dpo_trainer = DPOTrainer(
        model=model,
        ref_model=ref_model,
        args=training_args,
        beta=0.1,  # coefficient de pénalité KL, hyperparamètre important
        train_dataset=dataset["train"],
        eval_dataset=dataset["test"],
        tokenizer=tokenizer,
        max_length=512,
        max_prompt_length=128,
    )

    # ============================================
    # 6. Lancer l'entraînement !
    # ============================================

    print("Démarrage de l'entraînement DPO")
    dpo_trainer.train()

    # ============================================
    # 7. Enregistrer le modèle
    # ============================================

    print(f"Enregistrement du modèle dans : {output_dir}")
    dpo_trainer.save_model(output_dir)

    # ============================================
    # 8. Tester le modèle entraîné
    # ============================================

    print("\n=== Tester le modèle entraîné ===")

    # Charger le modèle entraîné
    trained_model = AutoModelForCausalLM.from_pretrained(output_dir)

    # Tester quelques prompts
    test_prompts = [
        "Présentez Python",
        "Suis-je un raté ?",
    ]

    for prompt in test_prompts:
        # Générer la réponse
        inputs = tokenizer(prompt, return_tensors="pt")
        with torch.no_grad():
            outputs = trained_model.generate(
                **inputs,
                max_new_tokens=50,
                temperature=0.7,
                do_sample=True,
                pad_token_id=tokenizer.eos_token_id,
            )
        response = tokenizer.decode(outputs[0], skip_special_tokens=True)
        print(f"\nInvite : {prompt}")
        print(f"Réponse : {response[len(prompt):]}")


if __name__ == "__main__":
    main()

DPO devient de plus en plus populaire car il est simple, stable et efficace. De nombreux nouveaux efforts d'alignement apportent des améliorations basées sur DPO.


IA constitutionnelle : l'approche d'Anthropic

L'IA constitutionnelle (Constitutional AI) est une autre méthode d'alignement proposée par Anthropic.

Ses caractéristiques sont :Utiliser le retour de l'IA au lieu du retour humain, permettant ainsi d'atteindre l'alignement à plus grande échelle.

Conception de la liste de principes

La première étape de l'IA constitutionnelle consiste à écrire une « constitution » — un ensemble de principes pour guider le comportement de l'IA.

Ces principes ne sont pas du code, mais des lignes directrices décrites en langage naturel. Par exemple :

PrincipeContenu d'exemple
InnocuitéChoisissez la réponse la moins susceptible de causer du tort.
UtilitéFournissez autant que possible des informations utiles et exactes.
HonnêtetéNe fabriquez pas d'informations ; si vous ne savez pas, dites que vous ne savez pas.
RaisonnabilitéÉtayez vos opinions par la logique et des preuves.
ConsidérationTenez compte des sentiments et des circonstances de l'utilisateur.

Ces principes n'ont pas besoin d'être longs ; quelques dizaines peuvent couvrir la plupart des situations.

Autocritique et correction de l'IA

Le processus central de l'IA constitutionnelle est :

L’IA génère une réponse initiale.

En se fondant sur les principes constitutionnels, l’IA critique ce qui ne va pas dans la réponse.

En se fondant sur la critique, l’IA réécrit une meilleure réponse.

Entraîner le modèle à l’aide de données de « réponse initiale → critique → réponse révisée ».

C’est comme un étudiant qui rédige une dissertation, vérifie où elle ne convient pas, puis la révise — aucun enseignant ne participe à l’ensemble du processus.

RLAIF : remplacer les humains par l’IA

La deuxième étape de l’IA constitutionnelle est RLAIF (apprentissage par renforcement à partir des retours de l’IA).

Semblable à RLHF, mais avec une différence clé :Les réponses ne sont pas notées par des humains, mais par une autre IA.。

Pourquoi utiliser le retour de l’IA ? Parce que :

Plus grande échelle — l’IA peut travailler 24 heures sur 24, avec une vitesse d’annotation bien supérieure à celle des humains.

Une meilleure cohérence — la même IA a des critères d’évaluation plus cohérents, ce qui évite le problème des préférences différentes selon les personnes.

Un coût plus faible — pas besoin de rémunérer des annotateurs humains.

Bien sûr, le postulat de tout ceci est que l'« IA juge » elle-même est déjà suffisamment alignée.

Le processus RLAIF :

Utiliser la méthode d'IA constitutionnelle pour entraîner un « modèle juge » initial.

Utiliser ce modèle juge pour noter un grand nombre de réponses.

Utiliser ces scores pour l'apprentissage par renforcement afin d'entraîner un modèle de politique.

On peut voir que RLAIF libère les humains du travail fastidieux consistant à « étiqueter chaque échantillon » ; les humains n'ont qu'à concevoir les principes et les processus.


Comparaison de trois méthodes : RLHF vs DPO vs IA constitutionnelle

Nous avons présenté trois méthodes d'alignement principales ; maintenant, faisons une comparaison complète :

DimensionRLHFDPOIA constitutionnelle / RLAIF
Idée centraleRetour humain + apprentissage par renforcement PPOOptimiser directement sur les données de préférenceAuto-critique par IA + retour d'IA
Implication humaineNécessite une grande quantité d'annotation humaineNécessite des données de préférence humaineNécessite uniquement de concevoir des principes
Étapes d'entraînementTrois étapes (SFT → RM → PPO)Deux étapes (SFT → DPO)Deux étapes (critique-révision → RLAIF)
Difficulté de mise en œuvreÉlevéeFaibleMoyenne
Stabilité de l'entraînementMoyenne, nécessite un réglage minutieux des hyperparamètresOKMoyenne
ÉvolutivitéLimitée par la vitesse d'annotation humaineLimitée par l'échelle des données de préférenceFacile à mettre à l'échelle
Entreprises/projets représentatifsOpenAI (débuts)Adopté par plusieurs équipesAnthropic

Aucune méthode n'est « la meilleure » ; le choix dépend de votre situation spécifique :

Si vous disposez d'abondantes ressources d'annotation humaine, RLHF ou DPO conviennent.

Si vous souhaitez une mise en œuvre simple, DPO est un bon choix.

Si vous souhaitez passer à l'échelle et réduire la dépendance humaine, Constitutional AI / RLAIF mérite d'être envisagé.

En production réelle, ces méthodes sont souvent combinées : d'abord utiliser quelques données humaines, puis utiliser les retours de l'IA pour passer à l'échelle, et enfin utiliser DPO ou PPO pour optimiser.


Limites et défis du RLHF

RLHF est efficace, mais il n'est pas parfait. Discutons de certaines de ses limites et de ses défis.

Détournement de la récompense

Le piratage de récompense est un problème classique en apprentissage par renforcement :L’IA trouve un moyen d’obtenir des récompenses élevées, mais ce moyen n’est pas ce que nous voulons vraiment.。

Par exemple :

Vous entraînez une IA à répondre à des questions, et le modèle de récompense aime les réponses « confiantes ». L’IA découvre que parler simplement sur un ton très affirmé obtient des scores élevés — même si elle raconte n’importe quoi.

Ou bien, l’IA découvre que répéter simplement les mots de l’utilisateur et dire « compris » peut obtenir des scores corrects — même si elle ne fournit aucun contenu substantiel.

La cause profonde du piratage de récompense est :Il existe un écart entre les jugements du modèle de récompense et les véritables préférences humaines.L’IA optimise le score du modèle de récompense, et non la véritable satisfaction des humains.

Il n’existe pas de solution parfaite à ce problème, mais il existe quelques méthodes d’atténuation :

Collectez davantage de données de préférence diversifiées.

Utilisez un ensemble de plusieurs modèles de récompense pour réduire le biais d’un modèle unique.

Effectuez régulièrement des contrôles manuels ponctuels, et corrigez rapidement les problèmes lorsqu’ils sont détectés.

Incohérence des préférences humaines

Un autre défi est :Les préférences varient d’un humain à l’autre, et même les préférences d’une même personne peuvent changer.。

Par exemple :

Certains utilisateurs aiment les réponses concises et directes, tandis que d’autres aiment les réponses détaillées et complètes.

Pour une même question, une « bonne » réponse peut différer selon le contexte.

Des personnes issues de milieux culturels différents et ayant des valeurs différentes peuvent avoir des définitions conflictuelles de ce qui est « bien ».

Lorsque les annotateurs humains ne sont pas d'accord, le modèle de récompense est confus—il ne sait pas qui écouter.

Les méthodes de gestion incluent :

Donner aux annotateurs des consignes plus détaillées afin d'unifier les normes.

Enregistrer les caractéristiques des annotateurs dans les données et entraîner des modèles personnalisés.

Accepter un certain degré d'ambiguïté—certaines questions n'ont tout simplement pas de réponse unique « correcte ».

Autres défis

Il y a quelques autres défis qui méritent d'être mentionnés :

  • Scalabilité—l'annotation humaine est lente et coûteuse, ce qui rend difficile de suivre la croissance de l'échelle des modèles.

  • Décalage de distribution—les données d'entraînement peuvent différer des scénarios d'utilisation du monde réel, ce qui entraîne de moins bonnes performances du modèle dans de nouveaux scénarios.

  • Attaques adversariales—les modèles alignés peuvent être « déverrouillés » par des prompts soigneusement conçus pour générer du contenu nuisible.

  • Verrouillage des valeurs — Si les objectifs d'alignement sont défectueux, plus le modèle est capable, plus le préjudice est grand.

  • L'alignement est un processus continu, sans solution unique. Nous devons continuer à faire de la recherche, à itérer et à nous améliorer.

Autres extensions