How to use from the
Use from the
Transformers library
# Use a pipeline as a high-level helper
from transformers import pipeline

pipe = pipeline("text-generation", model="fenyo/Qwen2.5-7B-base2instruct")
messages = [
    {"role": "user", "content": "Who are you?"},
]
pipe(messages)
# Load model directly
from transformers import AutoTokenizer, AutoModelForMultimodalLM

tokenizer = AutoTokenizer.from_pretrained("fenyo/Qwen2.5-7B-base2instruct")
model = AutoModelForMultimodalLM.from_pretrained("fenyo/Qwen2.5-7B-base2instruct")
messages = [
    {"role": "user", "content": "Who are you?"},
]
inputs = tokenizer.apply_chat_template(
	messages,
	add_generation_prompt=True,
	tokenize=True,
	return_dict=True,
	return_tensors="pt",
).to(model.device)

outputs = model.generate(**inputs, max_new_tokens=40)
print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:]))
Quick Links

Qwen2.5-7B-base2instruct

Modèle conversationnel construit à partir du modèle de base Qwen/Qwen2.5-7B (non-instruct), via un pipeline SFT → DPO → RLVR entièrement reproduit sur un seul GPU H100 80 Go. Objectif de l'expérience : reproduire nous-mêmes la transformation base→instruct, la comparer à l'instruct officiel Qwen/Qwen2.5-7B-Instruct, et en tirer une recette et des leçons réutilisables.

📦 Code, scripts et recette complète : https://github.com/AlexandreFenyo/qwen2.5-7b-base2instruct


Résultats (lm-evaluation-harness, backend vLLM)

modèle IFEval (suivi d'instructions) GSM8K (maths) MMLU (connaissances)
base Qwen2.5-7B 27.4 83.0 71.8
+ SFT (300k) 51.2 77.6 69.2
+ DPO ciblé 68.9 80.1 70.0
+ RLVR gradué (ce modèle) 75.0 79.7 70.2
instruct officiel 71.9 84.7 68.8

Ce modèle dépasse l'instruct officiel sur IFEval (75.0 vs 71.9) et MMLU (70.2 vs 68.8), et reste en retrait sur les maths (79.7 vs 84.7). ⚠️ Honnêteté : on a spécialisé le modèle vers le suivi d'instructions (DPO et RLVR tous deux ciblés là-dessus) ; l'officiel est généraliste. On le bat donc sur l'axe optimisé, pas « partout » (chat ouvert, sécurité, code, multi-tours non évalués ici).


Un cours condensé : transformer un modèle de base en modèle instruct

0. L'idée fondamentale : savoir ≠ savoir obéir

Un modèle de base (pré-entraîné sur ~18 000 milliards de tokens) possède déjà la connaissance et le raisonnement. La preuve : avant tout post-training, il fait 83 sur GSM8K et 71.8 sur MMLU. Ce qui lui manque, c'est le comportement d'assistant : répondre à une consigne, en 0-shot, dans un format de chat. Le post-training n'ajoute pas de savoir — il installe un comportement.

C'est visible dans le tableau : le base est fort en MMLU/GSM8K (évalués en few-shot, par complétion de motif, sans obéissance requise) mais faible en IFEval (27.4) — précisément la compétence « obéir à une consigne » qui lui manque. Tout le pipeline sert à combler ce 27 → 75.

1. SFT — apprendre le format chat (full fine-tuning)

  • Méthode : Supervised Fine-Tuning. On entraîne le modèle à reproduire des réponses d'assistant au format ChatML (<|im_start|>role … <|im_end|>), loss calculée sur la réponse seule (assistant_only_loss).
  • Données : allenai/tulu-3-sft-mixture, sous-ensemble de 300k exemples.
  • Effet : IFEval 27 → 51. C'est le SFT qui « réveille » le comportement d'assistant et la plus grande part du raisonnement latent du base.
  • Ce qui a marché : plus de données SFT aide (180k→300k : +6 IFEval vs une version antérieure).
  • Ce qui a coincé : instabilité numérique. Le SFT a divergé deux fois (gradient NaN) à cause d'overflows bf16 du forward sur des échantillons pathologiques (logits → inf). Correctif : un garde-fou qui neutralise les gradients non-finis avant le pas d'optimisation (nan_to_num) → le batch fautif est sauté sans corrompre le modèle. Leçon : sur de longs runs full-FT en bf16, prévoir une protection anti-NaN.

2. DPO — aligner sur des préférences (l'étape décisive)

  • Méthode : Direct Preference Optimization. Apprentissage hors-ligne à partir de paires chosen/rejected : le modèle apprend à préférer la bonne réponse à la mauvaise. Implémenté en LoRA (référence = modèle adaptateur désactivé).
  • Ce qui a moins marché — DPO générique : avec ultrafeedback_binarized (préférences générales de qualité), IFEval n'a pas bougé (≈ +0). Le signal « réponse globalement meilleure » ne dit rien sur « réponse qui respecte la consigne ».
  • Ce qui a été DÉCISIF — DPO ciblé : avec allenai/tulu-3-pref-personas-instruction-following (~20k paires où la réponse choisie respecte une contrainte et la rejetée la viole) + 10k génériques pour la diversité, IFEval 51 → 69 (+17.7) — quasi le niveau officiel, d'un coup.
  • Leçon centrale : même algorithme, données génériques vs ciblées → +17.7 d'écart. Pour progresser sur une capacité, il faut des données qui ciblent exactement cette capacité.

3. RLVR via GRPO — récompense vérifiable (amplifier)

  • Méthode : Reinforcement Learning with Verifiable Rewards, algorithme GRPO (Group Relative Policy Optimization). Le modèle génère lui-même ~8 réponses par prompt ; un programme vérificateur note chacune ; l'avantage = écart à la moyenne du groupe → renforce les meilleures. En LoRA, génération via transformers (vLLM 0.22 incompatible avec le GRPO de TRL 1.5.1).
  • Récompenses vérifiables (sans reward model) :
    • maths : réponse correcte (parse \boxed{}, openai/gsm8k)
    • suivi d'instructions : contraintes vérifiées par programme (24 validateurs maison : minuscules, nombre de paragraphes, mots-clés, format… inspirés de allenai/RLVR-IFeval).
  • Ce qui a échoué — récompense BINAIRE : 1 contrainte/prompt, reward 0/1. Résultat : effondrement de l'avantage GRPO. Dans un groupe de 8, soit toutes réussissent (contrainte facile), soit toutes échouent (dure) → écart-type nul → gradient nul (frac_reward_zero_std → 1.0). IFEval inchangé.
  • Ce qui a marché — récompense GRADUÉE : prompts à 2-3 contraintes, reward = fraction satisfaite (0 / 0.33 / 0.66 / 1.0) → variance dans le groupe → gradient vivant → IFEval 69 → 75 (+6.1).
  • Leçon : le RLVR amplifie une capacité que le modèle sait déjà parfois produire (ici, le DPO l'avait installée) — « installer (DPO/SFT) puis amplifier (GRPO) ». Si le modèle ne sait pas du tout faire, GRPO n'a rien à renforcer (pas de variance).

Les 3 grandes leçons transférables

  1. Le savoir vient du base ; le post-training installe un comportement. Reproduire une capacité précise est bon marché ; ce qui est cher (pré-entraînement) est hérité gratuitement du base open-weights.
  2. Le signal doit cibler la capacité visée. Vérifié 3 fois : SFT 180k→300k (+6), DPO générique→ciblé (+17.7), RLVR binaire→gradué (+6). Le générique ne transfère pas.
  3. Installer puis amplifier. SFT/DPO installent (imitation, hors-ligne) ; GRPO amplifie (exploration, en-ligne). Le RLVR brille surtout là où existe un vérificateur (maths, code, contraintes) et où l'exploration aide (raisonnement) — pas pour des comportements déjà bien couverts par des paires.

Piège d'évaluation à connaître

En GSM8K strict-match, l'instruct officiel tombait à 21 % — pur artefact (il n'émet pas le format #### N et sa CoT verbeuse dépassait la limite de tokens). Mesuré équitablement (flexible-extract, 1024 tokens) : 84.7 %. Toujours vérifier ce que le parser attend avant de conclure.


Recette & stack

  • SFT : full fine-tuning, ChatML, assistant_only_loss, bf16, SDPA, gradient checkpointing, optim adamw_8bit, lr 4e-6, garde-fou anti-NaN.
  • DPO : LoRA r=32, β=0.1, lr 5e-6, référence en direct (⚠️ precompute_ref_log_probs=True provoque des NaN en bf16 — à désactiver).
  • RLVR : GRPO-LoRA r=16, 8 générations/prompt, récompense graduée multi-contraintes, lr 2e-6, 2500 steps.
  • Stack : PyTorch cu128 · transformers · TRL 1.5.1 · PEFT · vLLM 0.22 (éval) · lm-eval 0.4.12 · suivi Weights & Biases.

Datasets utilisés

étape dataset rôle
SFT allenai/tulu-3-sft-mixture format chat + instructions
DPO allenai/tulu-3-pref-personas-instruction-following préférences ciblées suivi d'instructions (décisif)
DPO HuggingFaceH4/ultrafeedback_binarized préférences génériques (diversité)
RLVR openai/gsm8k récompense vérifiable maths
RLVR allenai/RLVR-IFeval inspiration contraintes d'instructions
Éval google/IFEval, openai/gsm8k, cais/mmlu benchmarks

Utilisation

from transformers import AutoModelForCausalLM, AutoTokenizer
tok = AutoTokenizer.from_pretrained("fenyo/Qwen2.5-7B-base2instruct")
model = AutoModelForCausalLM.from_pretrained("fenyo/Qwen2.5-7B-base2instruct", torch_dtype="bfloat16", device_map="auto")
msgs = [{"role": "user", "content": "Explique en deux phrases pourquoi le ciel est bleu."}]
inputs = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)
print(tok.decode(model.generate(inputs, max_new_tokens=200)[0][inputs.shape[1]:], skip_special_tokens=True))

Format ChatML, identique à l'instruct officiel.

Limites

Modèle expérimental, spécialisé suivi d'instructions (peut être moins poli que l'officiel en chat ouvert, sécurité, code, multi-tours — non évalués). En retrait sur les maths. Peut halluciner.

Crédits

Base/instruct de référence : Qwen2.5 (Alibaba, Apache-2.0). Données : AllenAI Tülu-3, HuggingFace H4, OpenAI GSM8K. Entraînement : TRL (Hugging Face). Recette & code : github.com/AlexandreFenyo/qwen2.5-7b-base2instruct.

Downloads last month
60
Safetensors
Model size
8B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for fenyo/Qwen2.5-7B-base2instruct

Base model

Qwen/Qwen2.5-7B
Finetuned
(883)
this model

Datasets used to train fenyo/Qwen2.5-7B-base2instruct