Passer à la navigation

Optimisation Directe des Préférences dans NeMo RL

Afficher en Markdown

L’Optimisation Directe des Préférences (DPO) est un algorithme d’alignement sans RL qui fonctionne sur des données de préférence. Étant donné une invite et une paire de réponses choisie et rejetée, DPO vise à augmenter la probabilité de la réponse choisie et à diminuer la probabilité de la réponse rejetée par rapport à un modèle de référence gelé. L’acteur est initialisé en utilisant le modèle de référence. Pour plus de détails, consultez le document sur DPO.

Lancer une Exécution DPO

Le script examples/run_dpo.py peut être utilisé pour lancer une expérience DPO. Ce script peut être lancé localement ou via Slurm. Pour plus de détails sur la configuration de Ray et le lancement d’un travail à l’aide de Slurm, consultez la documentation du cluster.

Veillez à lancer le travail à l’aide de uv. La commande pour lancer un travail DPO est la suivante :

uv run examples/run_dpo.py --config <CHEMIN VERS CONFIG YAML> <REMPLACEMENTS>

Si non spécifié, config prendra par défaut la valeur examples/configs/dpo.yaml.

Configuration

NeMo RL permet aux utilisateurs de configurer des expériences DPO à l’aide de fichiers de configuration yaml. Un exemple de fichier de configuration DPO peut être trouvé ici.

Pour remplacer une valeur dans la configuration, modifiez soit directement la valeur dans le fichier yaml, soit passez le remplacement via la ligne de commande. Par exemple :

uv run examples/run_dpo.py \
cluster.gpus_per_node=8 \
dpo.sft_loss_weight=0.1 \
dpo.preference_average_log_probs=True \
logger.wandb.name="dpo-dev-8-gpu"

Rappel : N’oubliez pas de définir vos HF_HOME, WANDB_API_KEY et HF_DATASETS_CACHE (si nécessaire). Vous devrez également effectuer un huggingface-cli login pour les modèles Llama.

Jeux de Données

Chaque classe de jeu de données DPO doit avoir les attributs suivants :

  1. formatted_ds : Le dictionnaire des jeux de données formatés, où chaque jeu de données doit être formaté comme suit
{
"context": [], // liste de dicts - Le message d'invite (y compris les tours précédents, le cas échéant)
"completions": [ // liste de dicts — La liste des complétions
{
"rank": 0, // int — Le rang de la complétion (un rang inférieur est préféré)
"completion": [] // liste de dicts — Le(s) message(s) de complétion
},
{
"rank": 1, // int — Le rang de la complétion (un rang inférieur est préféré)
"completion": [] // liste de dicts — Le(s) message(s) de complétion
}
]
}
  1. task_spec : Le TaskDataSpec pour ce jeu de données. Cela doit spécifier le nom que vous choisissez pour ce jeu de données.

La formation DPO ne prend en charge que deux complétions (où le rang le plus bas est préféré et le rang le plus élevé est rejeté), chaque complétion étant une seule réponse. Par exemple :

{
"context": [
{
"role": "user",
"content": "What's the capital of France?"
},
{
"role": "assistant",
"content": "The capital of France is Paris."
},
{
"role": "user",
"content": "Thanks! And what's the capital of Germany?"
}
],
"completions": [
{
"rank": 0,
"completion": [
{
"role": "assistant",
"content": "The capital of Germany is Berlin."
}
]
},
{
"rank": 1,
"completion": [
{
"role": "assistant",
"content": "The capital of Germany is Munich."
}
]
}
]
}

NeMo RL fournit une implémentation compatible avec DPO du jeu de données HelpSteer3 à titre d’exemple. Ce jeu de données est téléchargé depuis Hugging Face et prétraité à la volée, il n’est donc pas nécessaire de fournir un chemin vers des jeux de données sur disque.

Nous fournissons également une classe PreferenceDataset compatible avec les jeux de données de préférence au format JSONL. Vous pouvez modifier votre configuration comme suit pour utiliser un jeu de données de préférence personnalisé :

data:
dataset_name: PreferenceDataset
train_data_path: <CheminLocalVersJeuDeDonnéesEntraînement>
val_data_paths:
<NomDuJeuDeDonnéesValidation>: <CheminLocalVersJeuDeDonnéesValidation>

avec prise en charge de plusieurs jeux de validation :

data:
dataset_name: PreferenceDataset
train_data_path: <CheminLocalVersJeuDeDonnéesEntraînement>
val_data_paths:
<NomDuJeuDeDonnéesValidation1>: <CheminLocalVersJeuDeDonnéesValidation1>
<NomDuJeuDeDonnéesValidation2>: <CheminLocalVersJeuDeDonnéesValidation2>

Veuillez noter :

  • Si vous utilisez un enregistreur, le préfixe utilisé pour chaque jeu de validation sera validation-<NomDuJeuDeDonnéesValidation>. Le temps total de validation, sommé sur tous les jeux de validation, est rapporté sous timing/validation/total_validation_time.
  • Si vous effectuez un point de contrôle, la valeur metric_name dans votre configuration de checkpointing doit refléter la métrique et le jeu de validation à suivre. Par exemple, validation-<NomDuJeuDeDonnéesValidation1>_loss.

La classe DPODataset plus ancienne est obsolète. Cette classe est également compatible avec les jeux de données de préférence au format JSONL. Elle suppose que les jeux de données d’entraînement et de validation ont été divisés et traités au format attendu hors ligne. Les fichiers JSONL doivent contenir des exemples avec les clés prompt, chosen_response et rejected_response.

Paramètres Spécifiques à DPO

L’implémentation DPO dans NeMo RL prend en charge plusieurs paramètres clés qui peuvent être ajustés :

  • dpo.reference_policy_kl_penalty : Contrôle la force du terme de pénalité KL
  • dpo.preference_loss_weight : Poids pour la perte de préférence
  • dpo.sft_loss_weight : Poids pour la perte SFT auxiliaire
  • dpo.preference_average_log_probs : Indique s’il faut moyenner les log-probabilités sur les jetons dans le terme de perte de préférence
  • dpo.sft_average_log_probs : Indique s’il faut moyenner les log-probabilités sur les jetons dans le terme de perte SFT

Ces paramètres peuvent être ajustés dans le fichier de configuration ou via des remplacements de ligne de commande pour optimiser l’entraînement pour votre cas d’utilisation spécifique.

Évaluer le Modèle Entraîné

À la fin du processus d’entraînement, vous pouvez vous référer à notre guide d’évaluation pour évaluer les capacités du modèle.