Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Fine-tune LLMs using reinforcement learning with TRL - SFT for instruction tuning, DPO for preference alignment, PPO/GRPO for reward optimization, and reward model training. Use when need RLHF, align model with preferences, or train from human feedback. Works with HuggingFace Transformers.
.claude/skills/graniet-trl-fine-tuning/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-14 | ✗→✓ | ▲ Improved | 73% | 0% |
| case-08 | ✓→✓ | = Same ✓ | 109% | 0% |
| case-09 | ✓→✓ | = Same ✓ | 107% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 48% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 208% | 0% |
This skill is repo-local and stays inactive until explicitly activated.
When the original instructions refer to legacy tool names, use these Kheish mappings:
terminal => bashweb_extract => web_fetch, plus web_search when discovery is neededsearch_files => grep_search and glob_searchbrowser_* tools require a browser-capable surfaced tool or MCP; if none is available, use the closest available surface and say so explicitlyWhen the instructions mention local helper files, resolve them from ${KHEISH_SKILL_DIR}.
TRL provides post-training methods for aligning language models with human preferences.
Installation:
bashpip install trl transformers datasets peft accelerate
Supervised Fine-Tuning (instruction tuning):
pythonfrom trl import SFTTrainer trainer = SFTTrainer( model="Qwen/Qwen2.5-0.5B", train_dataset=dataset, # Prompt-completion pairs ) trainer.train()
DPO (align with preferences):
pythonfrom trl import DPOTrainer, DPOConfig config = DPOConfig(output_dir="model-dpo", beta=0.1) trainer = DPOTrainer( model=model, args=config, train_dataset=preference_dataset, # chosen/rejected pairs processing_class=tokenizer ) trainer.train()
Complete pipeline from base model to human-aligned model.
Copy this checklist:
RLHF Training:
- [ ] Step 1: Supervised fine-tuning (SFT)
- [ ] Step 2: Train reward model
- [ ] Step 3: PPO reinforcement learning
- [ ] Step 4: Evaluate aligned modelStep 1: Supervised fine-tuning
Train base model on instruction-following data:
pythonfrom transformers import AutoModelForCausalLM, AutoTokenizer from trl import SFTTrainer, SFTConfig from datasets import load_dataset # Load model model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B") tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B") # Load instruction dataset dataset = load_dataset("trl-lib/Capybara", split="train") # Configure training training_args = SFTConfig( output_dir="Qwen2.5-0.5B-SFT", per_device_train_batch_size=4, num_train_epochs=1, learning_rate=2e-5, logging_steps=10, save_strategy="epoch" ) # Train trainer = SFTTrainer( model=model, args=training_args, train_dataset=dataset, tokenizer=tokenizer ) trainer.train() trainer.save_model()
Step 2: Train reward model
Train model to predict human preferences:
pythonfrom transformers import AutoModelForSequenceClassification from trl import RewardTrainer, RewardConfig # Load SFT model as base model = AutoModelForSequenceClassification.from_pretrained( "Qwen2.5-0.5B-SFT", num_labels=1 # Single reward score ) tokenizer = AutoTokenizer.from_pretrained("Qwen2.5-0.5B-SFT") # Load preference data (chosen/rejected pairs) dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train") # Configure training training_args = RewardConfig( output_dir="Qwen2.5-0.5B-Reward", per_device_train_batch_size=2, num_train_epochs=1, learning_rate=1e-5 ) # Train reward model trainer = RewardTrainer( model=model, args=training_args, processing_class=tokenizer, train_dataset=dataset ) trainer.train() trainer.save_model()
Step 3: PPO reinforcement learning
Optimize policy using reward model:
bashpython -m trl.scripts.ppo \ --model_name_or_path Qwen2.5-0.5B-SFT \ --reward_model_path Qwen2.5-0.5B-Reward \ --dataset_name trl-internal-testing/descriptiveness-sentiment-trl-style \ --output_dir Qwen2.5-0.5B-PPO \ --learning_rate 3e-6 \ --per_device_train_batch_size 64 \ --total_episodes 10000
Step 4: Evaluate
pythonfrom transformers import pipeline # Load aligned model generator = pipeline("text-generation", model="Qwen2.5-0.5B-PPO") # Test prompt = "Explain quantum computing to a 10-year-old" output = generator(prompt, max_length=200)[0]["generated_text"] print(output)
Align model with preferences without reward model.
Copy this checklist:
DPO Training:
- [ ] Step 1: Prepare preference dataset
- [ ] Step 2: Configure DPO
- [ ] Step 3: Train with DPOTrainer
- [ ] Step 4: Evaluate alignmentStep 1: Prepare preference dataset
Dataset format:
json{ "prompt": "What is the capital of France?", "chosen": "The capital of France is Paris.", "rejected": "I don't know." }
Load dataset:
pythonfrom datasets import load_dataset dataset = load_dataset("trl-lib/ultrafeedback_binarized", split="train") # Or load your own # dataset = load_dataset("json", data_files="preferences.json")
Step 2: Configure DPO
pythonfrom trl import DPOConfig config = DPOConfig( output_dir="Qwen2.5-0.5B-DPO", per_device_train_batch_size=4, num_train_epochs=1, learning_rate=5e-7, beta=0.1, # KL penalty strength max_prompt_length=512, max_length=1024, logging_steps=10 )
Step 3: Train with DPOTrainer
pythonfrom transformers import AutoModelForCausalLM, AutoTokenizer from trl import DPOTrainer model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct") tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct") trainer = DPOTrainer( model=model, args=config, train_dataset=dataset, processing_class=tokenizer ) trainer.train() trainer.save_model()
CLI alternative:
bashtrl dpo \ --model_name_or_path Qwen/Qwen2.5-0.5B-Instruct \ --dataset_name argilla/Capybara-Preferences \ --output_dir Qwen2.5-0.5B-DPO \ --per_device_train_batch_size 4 \ --learning_rate 5e-7 \ --beta 0.1
Train with reinforcement learning using minimal memory.
Copy this checklist:
GRPO Training:
- [ ] Step 1: Define reward function
- [ ] Step 2: Configure GRPO
- [ ] Step 3: Train with GRPOTrainerStep 1: Define reward function
pythondef reward_function(completions, **kwargs): """ Compute rewards for completions. Args: completions: List of generated texts Returns: List of reward scores (floats) """ rewards = [] for completion in completions: # Example: reward based on length and unique words score = len(completion.split()) # Favor longer responses score += len(set(completion.lower().split())) # Reward unique words rewards.append(score) return rewards
Or use a reward model:
pythonfrom transformers import pipeline reward_model = pipeline("text-classification", model="reward-model-path") def reward_from_model(completions, prompts, **kwargs): # Combine prompt + completion full_texts = [p + c for p, c in zip(prompts, completions)] # Get reward scores results = reward_model(full_texts) return [r["score"] for r in results]
Step 2: Configure GRPO
pythonfrom trl import GRPOConfig config = GRPOConfig( output_dir="Qwen2-GRPO", per_device_train_batch_size=4, num_train_epochs=1, learning_rate=1e-5, num_generations=4, # Generate 4 completions per prompt max_new_tokens=128 )
Step 3: Train with GRPOTrainer
pythonfrom datasets import load_dataset from trl import GRPOTrainer # Load prompt-only dataset dataset = load_dataset("trl-lib/tldr", split="train") trainer = GRPOTrainer( model="Qwen/Qwen2-0.5B-Instruct", reward_funcs=reward_function, # Your reward function args=config, train_dataset=dataset ) trainer.train()
CLI:
bashtrl grpo \ --model_name_or_path Qwen/Qwen2-0.5B-Instruct \ --dataset_name trl-lib/tldr \ --output_dir Qwen2-GRPO \ --num_generations 4
Use TRL when:
Method selection:
Use alternatives instead:
Issue: OOM during DPO training
Reduce batch size and sequence length:
pythonconfig = DPOConfig( per_device_train_batch_size=1, # Reduce from 4 max_length=512, # Reduce from 1024 gradient_accumulation_steps=8 # Maintain effective batch )
Or use gradient checkpointing:
pythonmodel.gradient_checkpointing_enable()
Issue: Poor alignment quality
Tune beta parameter:
python# Higher beta = more conservative (stays closer to reference) config = DPOConfig(beta=0.5) # Default 0.1 # Lower beta = more aggressive alignment config = DPOConfig(beta=0.01)
Issue: Reward model not learning
Check loss type and learning rate:
pythonconfig = RewardConfig( learning_rate=1e-5, # Try different LR num_train_epochs=3 # Train longer )
Ensure preference dataset has clear winners:
python# Verify dataset print(dataset[0]) # Should have clear chosen > rejected
Issue: PPO training unstable
Adjust KL coefficient:
pythonconfig = PPOConfig( kl_coef=0.1, # Increase from 0.05 cliprange=0.1 # Reduce from 0.2 )
SFT training guide: See references/sft-training.md for dataset formats, chat templates, packing strategies, and multi-GPU training.
DPO variants: See references/dpo-variants.md for IPO, cDPO, RPO, and other DPO loss functions with recommended hyperparameters.
Reward modeling: See references/reward-modeling.md for outcome vs process rewards, Bradley-Terry loss, and reward model evaluation.
Online RL methods: See references/online-rl.md for PPO, GRPO, RLOO, and OnlineDPO with detailed configurations.
accelerateMemory optimization:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-08 | pass→pass | 11,585 | 5,149 | -56% | 1 | 1 | 0% | 2,129 | 4,448 | +109% | 0 | 0 | — |
case-09 | pass→pass | 13,172 | 7,328 | -44% | 1 | 1 | 0% | 2,330 | 4,813 | +107% | 0 | 0 | — |
case-14 | fail→pass | 16,769 | 10,153 | -39% | 1 | 1 | 0% | 3,175 | 5,498 | +73% | 0 | 0 | — |
case-01 | fail→fail | 24,338 | 19,999 | -18% | 1 | 1 | 0% | 5,105 | 7,767 | +52% | 0 | 0 | — |
case-02 | fail→fail | 18,999 | 11,839 | -38% | 1 | 1 | 0% | 3,722 | 6,054 | +63% | 0 | 0 | — |
case-03 | pass→pass | 17,936 | 8,508 | -53% | 1 | 1 | 0% | 3,548 | 5,240 | +48% | 0 | 0 | — |
case-04 | fail→fail | 16,984 | 12,802 | -25% | 1 | 1 | 0% | 3,214 | 6,015 | +87% | 0 | 0 | — |
case-05 | pass→pass | 8,349 | 4,533 | -46% | 1 | 1 | 0% | 1,399 | 4,304 | +208% | 0 | 0 | — |
case-06 | pass→pass | 14,674 | 6,653 | -55% | 1 | 1 | 0% | 2,636 | 4,794 | +82% | 0 | 0 | — |
case-07 | fail→fail | 14,337 | 12,423 | -13% | 1 | 1 | 0% | 2,630 | 5,839 | +122% | 0 | 0 | — |
case-10 | pass→pass | 4,631 | 2,619 | -43% | 1 | 1 | 0% | 898 | 4,021 | +348% | 0 | 0 | — |
case-11 | pass→pass | 12,362 | 3,177 | -74% | 1 | 1 | 0% | 2,444 | 4,067 | +66% | 0 | 0 | — |
case-12 | pass→pass | 5,354 | 3,025 | -44% | 1 | 1 | 0% | 1,006 | 4,032 | +301% | 0 | 0 | — |
case-13 | fail→fail | 14,391 | 4,999 | -65% | 1 | 1 | 0% | 2,578 | 3,776 | +46% | 0 | 0 | — |
case-15 | pass→pass | 5,249 | 3,905 | -26% | 1 | 1 | 0% | 946 | 4,181 | +342% | 0 | 0 | — |
case-16 | pass→pass | 9,286 | 4,189 | -55% | 1 | 1 | 0% | 1,760 | 4,339 | +147% | 0 | 0 | — |
case-17 | pass→pass | 15,375 | 9,670 | -37% | 1 | 1 | 0% | 3,348 | 4,911 | +47% | 0 | 0 | — |
case-18 | pass→pass | 13,288 | 12,389 | -7% | 1 | 1 | 0% | 2,561 | 5,406 | +111% | 0 | 0 | — |
case-19 | pass→pass | 8,275 | 3,887 | -53% | 1 | 1 | 0% | 1,582 | 4,105 | +159% | 0 | 0 | — |
case-20 | pass→pass | 11,027 | 8,111 | -26% | 1 | 1 | 0% | 2,354 | 5,149 | +119% | 0 | 0 | — |
case-21 | pass→pass | 14,927 | 18,761 | +26% | 1 | 1 | 0% | 3,256 | 6,736 | +107% | 0 | 0 | — |
case-22 | pass→pass | 12,233 | 12,564 | +3% | 1 | 1 | 0% | 2,543 | 6,218 | +145% | 0 | 0 | — |
case-23 | fail→fail | 10,582 | 9,424 | -11% | 1 | 1 | 0% | 2,095 | 5,367 | +156% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 22 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +4 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.