Modèle / jeu de données
hiyouga/EasyR1 avatar
hiyouga/EasyR1

EasyR1 : du RL multi-modal au-dessus de veRL, sans réécrire la pile

EasyR1: An Efficient, Scalable, Multi-Modality RL Training Framework based on veRL

5 163 étoiles394 forksPythonApache-2.0

En bref

De quoi s’agit-il ?
EasyR1 est un fork de veRL destiné à l'entraînement par renforcement de modèles de langage et vision-langage. Sa valeur tient à un choix étroit : garder l'architecture veRL et y brancher vLLM en mode SPMD, au prix d'une dette de synchronisation avec l'amont.
À qui s’adresse-t-il ?
EasyR1 s'adresse aux équipes qui font déjà du RL post-entraînement sur des modèles texte et qui veulent ajouter des entrées image sans changer de framework, à condition d'accepter la dépendance à veRL et à vLLM. Il n'est pas le bon outil si vous cherchez un framework généraliste de post-entraînement couvrant SFT, DPO et RL avec un seul moteur d'inférence : EasyR1 ne couvre que la partie RL et hérite des contraintes de veRL.
Puis-je l’utiliser commercialement ?
Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
Est-il encore maintenu ?
Oui. Les derniers commits datent d’il y a 16 jours.
En quel langage est-il écrit ?
Principalement Python, d’après les statistiques de langage de GitHub.

Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.

ANALYSE OPEN SOURCE APPROFONDIE

Le problème : le RL post-entraînement bute sur les entrées visuelles

Les frameworks de RL pour grands modèles de langage se sont construits autour du texte. Un prompt, une réponse générée, une récompense scalaire. Dès qu'on insère une image dans le prompt, la chaîne se complique : le moteur d'inférence doit gérer des jetons visuels, la phase d'entraînement doit conserver les mêmes tenseurs, et l'échantillonnage groupé propre à GRPO doit rester cohérent entre les deux. EasyR1 existe pour ce cas précis. Le README le formule sans détour : il s'agit d'un fork de veRL « to support vision language models ». Le public visé est donc celui qui entraîne des Qwen2-VL, Qwen2.5-VL ou Qwen3-VL par renforcement, avec des récompenses vérifiables, et qui ne veut pas réimplémenter la boucle d'échantillonnage. Le dépôt cite aussi des modèles de distillation DeepSeek-R1, ce qui élargit la cible aux équipes qui reproduisent des recettes de raisonnement sur des modèles de taille moyenne.

HybridEngine et le mode SPMD de vLLM : ce que le fork ajoute réellement

EasyR1 ne réinvente pas l'orchestration. Le README attribue l'efficacité et la scalabilité à deux briques : le design HybridEngine, renvoyé à l'article arXiv 2409.19256, et le mode SPMD de vLLM. HybridEngine est le mécanisme qui permet de partager les poids entre la phase de génération et la phase d'entraînement plutôt que de maintenir deux copies du modèle sur les mêmes GPU. Le mode SPMD de vLLM, lui, change la façon dont le moteur d'inférence est piloté : au lieu d'un serveur séparé interrogé par le trainer, l'exécution reste dans le même programme distribué. Ce basculement a une conséquence pratique sur les modèles multimodaux, puisque les jetons d'image traversent alors le même chemin que les jetons de texte. Le dépôt ne documente pas en détail l'implémentation de cette jonction, et c'est une zone où il faut lire le code plutôt que le README. Les fonctionnalités listées restent, elles, vérifiables dans l'arborescence : padding-free training, entraînement LoRA, reprise depuis le dernier ou le meilleur checkpoint, et journalisation vers Wandb, SwanLab, Mlflow ou Tensorboard.

Algorithmes et modèles : la liste est large, la profondeur inégale

Le catalogue d'algorithmes compte GRPO, DAPO, Reinforce++, ReMax, RLOO, GSPO et CISPO. Sept méthodes pour une même boucle, ce qui suggère une abstraction correcte au niveau du calcul d'avantage. La question que le README ne tranche pas est celle de l'égalité de traitement : DAPO et GSPO sont marqués comme nouveautés, et les scripts d'exemple fournis portent surtout sur GRPO, y compris pour les variantes LoRA et pour le logger SwanLab. Autrement dit, la probabilité de trouver un exemple complet et à jour décroît à mesure qu'on s'éloigne de GRPO. Côté modèles, la couverture va de Llama3 à Qwen3 en passant par Qwen2.5-VL et Qwen3-VL. Un point mérite attention pour les équipes qui arrivent de l'écosystème transformers : le README impose transformers>=4.54.0, flash-attn>=2.4.3 et vllm>=0.8.3. Ces trois contraintes ensemble déterminent la version de CUDA et le driver, bien plus que la version de Python (3.9+).

Mise en route : image Docker, script d'exemple, fusion de checkpoint

L'installation depuis les sources tient en trois commandes : git clone du dépôt, cd EasyR1, puis pip install -e . à la racine. Le README recommande néanmoins l'image pré-construite, ce qui évite de reconstruire la pile CUDA, flash-attn et vLLM : docker pull hiyouga/verl:ngc-th2.8.0-cu12.9-vllm0.11.0, puis docker run -it --ipc=host --gpus=all avec le même tag. Le drapeau --ipc=host n'est pas cosmétique : le partage mémoire entre processus de génération et d'entraînement en dépend. Pour les environnements sans Docker, le README donne la voie Apptainer avec apptainer pull easyr1.sif docker://hiyouga/verl:ngc-th2.8.0-cu12.9-vllm0.11.0, puis apptainer shell --nv --cleanenv --bind. Une fois l'environnement prêt, l'exemple de référence est bash examples/qwen2_5_vl_7b_geo3k_grpo.sh, avec une variante LoRA sur Qwen3-VL 4B. La récupération du modèle entraîné passe par python3 scripts/model_merger.py --local_dir checkpoints/easy_r1/exp_name/global_step_1/actor, ce qui produit un checkpoint au format Hugging Face. Deux variables d'environnement apparaissent dans le README : USE_MODELSCOPE_HUB=1 pour télécharger depuis ModelScope, et HF_ENDPOINT=https://hf-mirror.com en cas de problème de connexion à Hugging Face. Pour le multi-nœuds, la séquence est classique : ray start --head --port=6379 --dashboard-host=0.0.0.0 sur le nœud principal, ray start --address=<head_node_ip>:6379 sur les workers, ray status pour vérifier le pool, puis le script d'entraînement lancé uniquement sur le head.

Le budget GPU annoncé, et ce qu'il ne dit pas

Le tableau matériel du README est explicitement marqué comme une estimation. Il distingue AMP et BF16, et sépare l'entraînement complet du LoRA. En BF16, GRPO complet demanderait 1 GPU de 24 Go pour un modèle 1.5B, 4 GPU de 40 Go pour 7B, 8 GPU de 80 Go pour 32B et 16 pour 72B. En AMP, les chiffres doublent presque partout. Le LoRA réduit fortement l'empreinte : 2 GPU de 32 Go suffiraient pour 7B, 4 GPU de 80 Go pour 72B. Deux réserves. D'abord, ces chiffres ne couvrent que GRPO, pas DAPO ni GSPO, dont les besoins en mémoire dépendent du nombre de générations par prompt et de la longueur maximale. Ensuite, ils ne tiennent pas compte de la mémoire occupée par les images décodées, qui varie avec la résolution et le nombre d'images par échantillon. Le README précise aussi comment activer le BF16 : worker.actor.fsdp.torch_dtype=bf16 et worker.actor.optim.strategy=adamw_bf16. Ce sont les deux clés de configuration à connaître avant de dimensionner un cluster, et elles se passent en surcharge du script d'exemple.

La vraie limite : un fork, donc une dette de synchronisation

EasyR1 est un fork, et le README le dit dès la première phrase. Cela implique une conséquence que la documentation n'aborde pas : chaque évolution de veRL doit être reportée manuellement, et chaque montée de version de vLLM peut casser la jonction avec le mode SPMD. Le décalage est visible dans le matériel fourni. Le README exige vllm>=0.8.3 tandis que l'image Docker recommandée embarque vllm0.11.0. Ce n'est pas une contradiction, mais cela signifie que l'image et les prérequis textuels ne sont pas alignés au même moment, et qu'un pip install -e . dans un environnement existant peut produire une combinaison différente de celle testée par les mainteneurs. Autre limite : la documentation des datasets personnalisés se réduit à un renvoi vers quatre jeux de données Hugging Face (math12k, geometry3k, journeybench-multi-image-vqa, rl-mixed-dataset). Le format est décrit comme « specific format » sans être reproduit dans le README. Il faut donc lire les fichiers d'exemple pour comprendre la structure des prompts et des récompenses, ce qui est un coût réel pour une équipe qui veut brancher son propre vérificateur. Enfin, EasyR1 n'est pas l'outil adapté si votre besoin principal est le SFT ou le DPO : le dépôt ne couvre que le RL, et le fork n'ajoute rien sur ce terrain.

Face à TRL : deux philosophies d'intégration

L'alternative la plus directe pour un utilisateur de l'écosystème Hugging Face est TRL, dont le README d'EasyR1 renvoie d'ailleurs le lecteur vers le blog GRPO pour comprendre l'algorithme. La différence d'approche est nette. TRL s'installe comme une bibliothèque Python dans un environnement transformers classique, avec un GRPOTrainer qui s'appuie sur l'inférence du modèle en cours d'entraînement ou sur un serveur externe selon la configuration. EasyR1, lui, suppose une pile distribuée : Ray pour l'orchestration, vLLM compilé avec le bon CUDA, flash-attn, et une image Docker dédiée. Le premier choix convient à un prototype sur un seul nœud avec un modèle de quelques milliards de paramètres. Le second vise des modèles de 32B et plus, répartis sur plusieurs nœuds, avec un moteur d'inférence séparé de la boucle d'entraînement. Le partage des poids par HybridEngine est précisément ce que TRL n'a pas à gérer, puisqu'il ne cherche pas la même topologie. Choisir EasyR1, c'est choisir cette topologie, avec les contraintes d'exploitation qui vont avec : version de driver, mémoire partagée, et un fichier Dockerfile à maintenir si vous quittez l'image officielle.

Licence Apache-2.0 et coût de mise à jour

EasyR1 est publié sous Apache-2.0, comme veRL dont il dérive. Cette licence autorise l'usage commercial, la modification et la redistribution, à condition de conserver les mentions de copyright et le fichier de licence, et de signaler les fichiers modifiés. Elle inclut une clause de brevets. Un point pratique pour un fork : Apache-2.0 ne vous oblige pas à publier vos modifications, mais si vous redistribuez une version modifiée d'EasyR1, vous devez indiquer ce qui a changé. Cela ne constitue pas un avis juridique, et les équipes qui redistribuent un produit dérivé doivent vérifier les obligations de attribution auprès de leur service compétent. Sur le coût de maintenance, le dépôt a connu trois versions en cinq mois, de v0.3.0 en avril 2025 à v0.3.2 en septembre 2025, avec des intitulés qui indiquent la nature des changements : « Initial release », « Multi-modal DAPO », « RL Baselines ». Ce rythme suggère un projet actif mais encore en phase de constitution de ses références. La reprise du travail amont de veRL reste, elle, à la charge de l'équipe qui adopte le fork, et c'est le poste de coût le plus difficile à estimer depuis l'extérieur.

Conclusion éditoriale

EasyR1 s'adresse aux équipes qui font déjà du RL post-entraînement sur des modèles texte et qui veulent ajouter des entrées image sans changer de framework, à condition d'accepter la dépendance à veRL et à vLLM. Il n'est pas le bon outil si vous cherchez un framework généraliste de post-entraînement couvrant SFT, DPO et RL avec un seul moteur d'inférence : EasyR1 ne couvre que la partie RL et hérite des contraintes de veRL. Avant d'engager des GPU, vérifiez trois choses dans le dépôt : la version de vllm exigée par le README (vllm>=0.8.3) par rapport à celle de l'image Docker (ngc-th2.8.0-cu12.9-vllm0.11.0), le format exact des datasets dans les exemples geometry3k et math12k, et le contenu de assets/baselines.md pour juger les résultats annoncés sur vos propres modèles.

Sources officielles

  1. hiyouga/EasyR1 on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Notes de la communauté

Notes de la communauté