| name | magistral-reasoning-rl |
| title | Magistral: Scaling Reasoning with Reinforcement Learning |
| version | 0.0.2 |
| engine | skillxiv-v0.0.2-claude-opus-4.6 |
| license | MIT |
| url | https://arxiv.org/abs/2506.10910 |
| keywords | ["reasoning models","reinforcement learning","GRPO","chain-of-thought","multimodal reasoning"] |
| description | Build reasoning capabilities through pure RL without distilled traces, achieving 50% AIME accuracy improvement via scalable asynchronous training with novel reward shaping for multilingual consistency. |
Magistral: Scaling Reasoning with Reinforcement Learning
Core Concept
Magistral demonstrates that pure reinforcement learning (without cold-start distilled reasoning traces) achieves strong reasoning through carefully designed rewards and scalable infrastructure. The system improves AIME-24 pass@1 accuracy by nearly 50% using a modified GRPO algorithm, asynchronous weight updates, and multi-stage curriculum learning. Novel insights: RL improves smaller models beyond distillation baselines and unexpectedly enhances multimodal capabilities despite text-only training.
Architecture Overview
- Modified GRPO Algorithm: Five adaptations including eliminated KL divergence penalty, loss normalization across generation groups, advantage normalization, relaxed clipping (Clip-Higher), and zero-variance filtering
- Four-Component Reward Architecture: Formatting (think tags), correctness (verified answers/test passing), length penalty (soft constraints), language consistency (multilingual response matching)
- Asynchronous Infrastructure: Continuous weight updates without interrupting generators; NCCL broadcast under 5 seconds; GPU-to-GPU communication minimized
- Multi-Stage Curriculum: Difficulty progression across stages; batch size reduction (8k→4k→2k); completion length increases (16k→24k→32k tokens)
- Data Curation Pipeline: Mathematical problems filtered from 699k to 38k; code problems validated at 35k with comprehensive test suites
Implementation
Step 1: Modified GRPO Optimizer Setup
import torch
import torch.nn as nn
from torch.optim import Optimizer
class ModifiedGRPO(Optimizer):
"""
Group Relative Policy Optimization with Magistral adaptations:
- Eliminated KL divergence penalty
- Loss normalization across generation groups
- Advantage normalization at minibatch level
- Relaxed upper clipping (Clip-Higher strategy)
- Zero-variance group filtering
"""
def __init__(self, params, lr=1e-5, epsilon=1e-6,
clip_ratio=2.0, clip_lower=0.5):
defaults = dict(lr=lr, epsilon=epsilon,
clip_ratio=clip_ratio, clip_lower=clip_lower)
super().__init__(params, defaults)
def step(self, closure=None):
loss = None
if closure is not None:
loss = closure()
for group in self.param_groups:
for p in group['params']:
if p.grad is None:
continue
grad = p.grad.data
if group['clip_ratio'] is :
grad_magnitude = torch.norm(grad)
grad_magnitude > group[]:
grad = grad / (grad_magnitude / group[])
p.data.add_(grad, alpha=-group[])
loss
Step 2: Reward Shaping Architecture
class RewardShaper:
"""
Four-component reward function for reasoning tasks.
Combines formatting, correctness, length penalty, and language consistency.
"""
def __init__(self, language_code='en', length_target=2000):
self.language_code = language_code
self.length_target = length_target
self.code_executor = CodeExecutor()
self.answer_verifier = AnswerVerifier()
def compute_reward(self, generated_text, reference_answer=None,
user_language='en', is_code=False):
"""
Compute total reward from four components.
Returns scalar reward in [0, 1] range.
"""
rewards = {}
has_think_tags = '<think>' in generated_text and '</think>' in generated_text
rewards['formatting'] = 0.25 if has_think_tags else 0.0
if is_code:
passed_tests = self.code_executor.run_tests(generated_text)
rewards['correctness'] = min(passed_tests / 10, 1.0) * 0.50
else:
is_correct = self.answer_verifier.verify(generated_text, reference_answer)
rewards[] = is_correct
response_length = (generated_text.split())
length_penalty = - (response_length - .length_target) / ( * .length_target)
length_penalty = (, length_penalty)
rewards[] = length_penalty *
response_language = ._detect_language(generated_text)
language_bonus = response_language == user_language
rewards[] = language_bonus
total_reward = (rewards.values())
{
: (total_reward, ),
: rewards
}
():
((c) > c text):
Step 3: Asynchronous Training Infrastructure
class AsynchronousTrainer:
"""
Manages continuous weight updates without interrupting generators.
Key innovation: GPU-to-GPU NCCL broadcast completes in <5 seconds.
"""
def __init__(self, model, reward_shaper, num_generators=8):
self.model = model
self.reward_shaper = reward_shaper
self.num_generators = num_generators
self.model_queue = []
self.latest_weights = None
def async_generation_loop(self, generator_id, input_batch):
"""
Generator continuously produces samples without blocking on updates.
Receives periodic weight synchronization via broadcast.
"""
local_model = copy.deepcopy(self.model)
while True:
with torch.no_grad():
outputs = local_model.generate(
input_batch,
max_length=2048,
temperature=1.0,
do_sample=True,
num_return_sequences=4
)
if self.latest_weights is not None:
local_model.load_state_dict(self.latest_weights, non_blocking=True)
yield outputs
():
.optimizer.zero_grad()
loss_tensor.backward()
torch.nn.utils.clip_grad_norm_(.model.parameters(), max_norm=)
.optimizer.step()
.latest_weights = (.model.named_parameters())
Step 4: Multi-Stage Curriculum Learning
class CurriculumScheduler:
"""
Manages difficulty progression and training configuration across stages.
Increases challenge: batch size reduction, completion length increase.
"""
def __init__(self, num_stages=3):
self.num_stages = num_stages
self.current_stage = 0
self.stage_config = [
{'batch_size': 8192, 'max_length': 16000, 'difficulty': 'easy'},
{'batch_size': 4096, 'max_length': 24000, 'difficulty': 'medium'},
{'batch_size': 2048, 'max_length': 32000, 'difficulty': 'hard'}
]
def get_current_config(self):
return self.stage_config[min(self.current_stage, len(self.stage_config) - 1)]
def progress_stage(self, val_accuracy):
"""Advance to next stage based on validation performance."""
if val_accuracy > 0.7 and self.current_stage < .num_stages - :
.current_stage +=
()
Practical Guidance
Data Preparation:
- Mathematical problems: Collect diverse sources (competition, textbooks); validate with multiple verifiers (SymPy, WolframAlpha)
- Code problems: Use comprehensive test suites (50+ test cases minimum); separate train/test data carefully
- Filtering strategy: Remove ambiguous or duplicate problems; keep diverse difficulty spectrum
Reward Design Principles:
- Formatting reward (25%): Enforce think tags for chain-of-thought; strong signal during early training
- Correctness reward (50%): Most important component; use automated verification (answer matching or test execution)
- Length penalty (15%): Soft constraint; encourage natural length without hard cutoffs
- Language consistency (10%): Multilingual support; bonus when response matches user's language
Scaling Considerations:
- Batch size correlation: Larger batches enable stable advantage normalization; 8k-16k optimal
- Asynchronous updates: Maximum 10-second intervals between weight syncs; generators may use slightly stale weights
- GPU utilization: 8-16 generator GPUs + 2-4 optimizer GPUs; communication bandwidth saturates around 16 generators
When to Use Magistral Approach:
- Building reasoning from scratch without distillation data
- Multilingual reasoning models (language consistency reward handles this)
- Long-context reasoning (curriculum handles up to 32k tokens)
- Smaller models (<25B) where RL outperforms distillation
Reference
- Group Relative Policy Optimization (GRPO): advantage normalization improves stability in RL for generation
- NCCL all-reduce: collective communication primitive; broadcast is unidirectional variant
- Curriculum learning: gradual difficulty progression prevents early convergence to local optima