LeetLLM
My PlanLearnGlossaryTracksPracticeBlog
LeetLLM

Your go-to resource for mastering AI & LLM systems.

Product

  • Learn
  • Glossary
  • Tracks
  • Practice
  • Blog
  • RSS

Legal

  • Terms of Service
  • Privacy Policy

© 2026 LeetLLM. All rights reserved.

All Topics
Your Progress
0%

0 of 196 articles completed

🛠️Computing Foundations0/9
Git, Shell, Linux for AIDocker for Reproducible AIPython for AI EngineeringNumPy and Tensor ShapesCUDA for ML TrainingMPS & Metal for ML on MacData Structures for AISQL and Data ModelingAlgorithms for ML Engineers
📊Math & Statistics0/9
Gradients and BackpropVectors, Matrices & TensorsLinear Algebra for MLAdam, Momentum, SchedulersProbability for Machine LearningBayesian Inference from EvidenceStatistics and UncertaintyDistributions and SamplingHypothesis Tests, Intervals, and pass@k
📚Preparation & Prerequisites0/13
Neural Networks from ScratchCNNs from ScratchTraining & BackpropagationSoftmax, Cross-Entropy & OptimizationRNNs, LSTMs, GRUs, and Sequence ModelingAutoencoders and VAEsThe Transformer Architecture End-to-EndLanguage Modeling & Next TokensFrom GPT to Modern LLMsPrompt Engineering FundamentalsCalling LLM APIs in ProductionFirst AI App End-to-EndThe LLM Lifecycle
🧮ML Algorithms & Evaluation0/15
Linear Regression from ScratchLogistic Regression and MetricsDecision Trees, Forests, and BoostingReinforcement Learning BasicsValidation and LeakageStatistical Learning and GeneralizationConformal Prediction and UncertaintyClustering and PCAProbabilistic Generative ModelsCore Retrieval AlgorithmsDecoding AlgorithmsExperiment Design and A/B TestingCausal Inference and CounterfactualsPyTorch Training LoopsDataset Pipelines and Data Quality
📦Production ML Systems0/6
Feature Engineering for Production MLBatch and Streaming Feature PipelinesGradient Boosted Trees in ProductionRanking and Recommendation SystemsForecasting and Anomaly DetectionMonitoring Predictive Models
🧪Core LLM Foundations0/8
The Bitter Lesson & ComputeBPE, WordPiece, and SentencePieceStatic to Contextual EmbeddingsPerplexity & Model EvaluationFile Ingestion for AIChunking StrategiesLLM Benchmarks & LimitationsInstruction Tuning & Chat Templates
🧰Applied LLM Engineering0/25
Dimensionality Reduction for EmbeddingsCoT, ToT & Self-Consistency PromptingFunction Calling & Tool UseMCP & Tool Protocol StandardsContext EngineeringPrompt Injection DefenseResponsible AI GovernancePrivacy-Preserving Machine LearningData Labeling and Human FeedbackEvaluating AI AgentsProduction RAG PipelinesHybrid Search: Dense + SparseReranking and Cross-Encoders for RAGRAG Evaluation for Reliable AnswersLLM-as-a-Judge EvaluationBias & Fairness in LLMsHallucination Detection & MitigationLLM Observability & MonitoringExperiment Tracking with MLflow and W&BPrompt Optimization with DSPyModel Versioning & DeploymentSemantic Caching & Cost OptimizationLLM Cost Engineering & Token EconomicsModel Gateways, Routing, and FallbacksDesign an Automated Support Agent
🎓Portfolio Capstones0/9
Capstone: Delivery ETA PredictionCapstone: Product RankingCapstone: Demand ForecastingCapstone: Image Damage ClassifierCapstone: Production ML PipelineCapstone: Document QACapstone: Eval DashboardCapstone: Fine-Tuned ClassifierCapstone: Reproducible ML Study
🧠Transformer Deep Dives0/8
Sentence Embeddings & Contrastive LossEmbedding Similarity & QuantizationScaled Dot-Product AttentionVision Transformers and Image EncodersPositional Encoding: RoPE & ALiBiLayer Normalization: Pre-LN vs Post-LNMechanistic InterpretabilityDecoding Strategies: Greedy to Nucleus
🧬Advanced Training & Adaptation0/17
Scaling Laws & Compute-Optimal TrainingPre-training Data at ScaleBuild GPT from Scratch LabJAX for PyTorch ResearchersContinued Pretraining for Domain ShiftSynthetic Data PipelinesSupervised Fine-Tuning PipelineMixed Precision TrainingDistributed Training: FSDP & ZeROLoRA & Parameter-Efficient TuningTraining Run OperationsReward Modeling from Preference DataRLHF & DPO AlignmentConstitutional AI & Red TeamingRLVR & Verifiable RewardsKnowledge Distillation for LLMsModel Merging and Weight Interpolation
🤖Advanced Agents & Retrieval0/16
Vector DB Internals: HNSW & IVFAdvanced RAG: HyDE & Self-RAGGraphRAG & Knowledge GraphsRAG Security & Access ControlStructured Output GenerationReAct & Plan-and-ExecuteGuardrails & Safety FiltersCode Generation & SandboxingComputer-Use / GUI / Browser AgentsHuman-in-the-Loop Agent ArchitectureAI Coding Workflow with AgentsAgent Memory & PersistenceAgent Failure & RecoveryRecursive Language Models (RLM)Multi-Agent OrchestrationCapstone: Production Agent
⚡Inference & Production Scale0/31
Inference: TTFT, TPS & KV CacheMulti-Query & Grouped-Query AttentionKV Cache & PagedAttentionPrefix Caching and Prompt CachingFlashAttention & Memory EfficiencyContinuous Batching & SchedulingScaling LLM InferenceModel Parallelism for LLM InferenceAccelerator Architecture Field GuideCorrect GPU Profiling and BenchmarkingGPU Kernel Performance Engineering LabGPU Parallel Primitives LabGPU Compilers and Kernel LanguagesGEMM From Naive CUDA to Tensor CoresLow-Precision GPU ProgrammingGPU Runtime Execution LabAI-Generated Kernel EngineeringModel Quantization: GPTQ, AWQ & GGUFLocal LLM DeploymentSLM Specialization & Edge DeploymentSpeculative DecodingLong Context Window ManagementMixture of Experts ArchitectureMamba & State Space ModelsReasoning & Test-Time ComputeAdvanced MLOps & DevOps for AIGPU Serving & AutoscalingGPU Failure OperationsDistributed Inference Data PlaneServing Benchmark EngineeringA/B Testing for LLMs
🏗️System Design Capstones0/9
Content Moderation SystemCode Completion SystemMulti-Tenant LLM PlatformLLM-Powered Search EngineVision-Language Models & CLIPMultimodal LLM ArchitectureDiffusion Models: Images & TextReal-Time Voice AI AgentReasoning Agent System Design
🎤AI Lab Interviewing0/4
AI Lab Coding Interview: Python SystemsAI Lab System Design InterviewAI Lab Behavioral InterviewAI Lab Technical Presentation
🔬Project Deep Dives0/17
Deep Dive - vLLMDeep Dive - SkyRLDeep Dive - FlashAttentionDeep Dive - FlashInferDeep Dive - DeepGEMMDeep Dive - NCCLDeep Dive - MegatronDeep Dive - DeepSpeedDeep Dive - RayDeep Dive - MLflowDeep Dive - PyTorchDeep Dive - TransformersDeep Dive - SGLangDeep Dive - slimeDeep Dive - DeepEPDeep Dive - TinkerDeep Dive - Light-PEFT
Back to Topics
LearnAdvanced Training & AdaptationRLVR & Verifiable Rewards
⚡HardFine-Tuning & Training

RLVR & Verifiable Rewards

Understand RLVR, a post-training approach that uses programmatic verification instead of learned human-preference rewards to improve checked outcomes in math, code, and other contract-driven tasks.

41 min read
Learning path
Step 117 of 196 in the full curriculum
Constitutional AI & Red TeamingKnowledge Distillation for LLMs

Personalize this lesson

Adapt explanations and teaching visuals to your background and preferred voice.

The last chapter trained against written constitutional principles. A critic can rank two answers using those rules, but two reviewers can still disagree, and a constitution doesn't execute.

Some targets don't need that kind of judge. Ask a model how many concurrent jobs fit on 14 GPU workers with 12 slots each. You don't need a preference label. You need 168.

Reinforcement Learning with Verifiable Rewards (RLVR) trains from rewards assigned by executable checks rather than a learned preference model.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124 Use it when an answer, program, schema, or constraint can be tested against a precise contract.

Two outputs show the boundary. One drafts an incident update, where tone and completeness are partly subjective. The other writes a Python function that either passes unit tests or fails them. Tülu 3 introduced the name RLVR for this post-training stage. DeepSeek-R1 used the same idea under the label rule-based rewards inside a broader multi-stage pipeline.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

Keep the 14×12 prompt nearby. A candidate that boxes 168 can earn reward. A candidate that boxes 148 can't. Whether the written reasoning was valid is a separate question, and that gap comes back whenever the verifier only sees the boxed number.

A verifier can fail in the opposite direction. If it awards a point for seeing \boxed{168} anywhere, a model can learn to print the token without solving the problem. Training reward rises; held-out correctness stays flat. The checker, not the prose around it, defines the pressure.

RLVR loop for a GPU batch prompt: the policy samples candidate answers, a verifier rewards boxed 168 and rejects 148 or ambiguous fields, then an optimizer updates the policy for the next group.
The RLVR loop on one prompt: sample candidates, grade the extracted answer with an executable verifier, then update the policy. PPO, GRPO, and related RL optimizers can consume that reward.

The alignment space

RLVR sits in the post-training stack next to SFT, RLHF, and DPO. Large language models usually learn instruction following from demonstrations and preference signals first. The design question is which of those signals the task can honestly provide.

Supervised Fine-Tuning (SFT) imitates selected demonstrations. For the GPU prompt, SFT can show a worked 14×12 solution. It copies patterns in those traces. It doesn't score a newly sampled 168 against an external checker.

Reinforcement Learning from Human Feedback (RLHF)[3]Reference 3Training Language Models to Follow Instructions with Human Feedback (InstructGPT).https://arxiv.org/abs/2203.02155 trains a reward model to predict preference labels. That fits tone or helpfulness, and it depends on label collection plus reward-model validity outside the labeled set.

Direct Preference Optimization (DPO)[4]Reference 4Direct Preference Optimization: Your Language Model is Secretly a Reward Model.https://arxiv.org/abs/2305.18290 removes the online reward-model RL loop and trains from chosen/rejected pairs. Those pairs can come from humans, constitutions, or other pipelines. They're still preference comparisons, not executed correctness checks.

RLVR specializes in tasks where success can be programmatically verified: a final math answer, code under tests, a JSON schema, or an instruction constraint such as "exactly three bullet points." You skip a preference label for each rollout. Validity is only as strong as the specification, parser, test suite, and sandbox that assign reward.

MethodReward signalScalabilityTask scope
SFTDemonstration dataLimited by demonstration supplyAny task with demonstrations
RLHFLearned reward from preference labelsRequires labels and reward-model checksOpen-ended behavior goals
DPOChosen/rejected pairsAvoids online reward-model RLTasks expressible as preferences
RLVRExecutable verificationRepeatable if the verifier is cheapOutcomes covered by a verifier

The trade is breadth for a directly executable signal. Start from what this checker can prove. A coding lab can verify unit tests, type checks, and exact-output constraints. It still needs a human for whether the solution is maintainable or clear.

That contract starts before sampling. A task generator needs checkable answers and a difficulty range that produces both passes and failures. An easy prompt gives every rollout the same reward; an impossible prompt gives every rollout zero. In either case, group-relative optimization has nothing to compare.

Decision tree for post-training supervision: if a program can check the outcome, use RLVR; if raters can rank pairs, use RLHF or DPO; if only demonstrations exist, use SFT.
Start from the supervision you actually have. RLVR is the branch where a program can fail closed on the outcome. Preference methods and SFT cover the rest.

Defining verifiable rewards

In the simplest outcome-only setup, a verifiable reward function r(x,y)r(x, y)r(x,y) takes a problem xxx and a generated response yyy and returns a binary signal:

r(x,y)={1if y is correct (verified)0if y is incorrectr(x, y) = \begin{cases} 1 & \text{if } y \text{ is correct (verified)} \\ 0 & \text{if } y \text{ is incorrect} \end{cases}r(x,y)={10​if y is correct (verified)if y is incorrect​

That's the teaching form. Tülu 3 used the same shape with a constant success reward α=10\alpha = 10α=10 chosen in pilots and then left fixed, plus a −10-10−10 penalty when generation hit the length cap without an end-of-sequence token.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124 The scale is a hyperparameter. The contract isn't: only verifiably correct completions get the success reward.

A second tiny prompt makes the outcome-only blind spot obvious: "Is 97 a prime number? Format your answer as Yes\boxed{Yes}Yes​ or No\boxed{No}No​."

Why is a binary verifier attractive for RLVR?

Answer

It removes ambiguity from the reward signal. If code, tests, or a proof checker can mark outputs right or wrong, training doesn't need a human preference model for every sample.

  • Iteration 1: "Yes, because it ends in 7." The final answer happens to be correct, so an outcome-only verifier returns 1.0, even though the stated reason is invalid.
  • Iteration 2: "No, 97/3 = 32.3." The answer is wrong, so the verifier returns 0.0.
  • Iteration 3: "97 is prime because it's not divisible by 2, 3, 5, or 7." The answer is correct and the reasoning is solid, so the verifier returns 1.0.

Iterations 1 and 3 get the same reward. An outcome verifier does not tell the optimizer which correct answer used valid reasoning. Across many problems, reasoning patterns that correlate with correct outcomes may become more likely, but that's an empirical training result, not information contained in a single final-answer reward.

This check verifies only the boxed verdict, so an unsupported guess and a valid divisibility check receive identical reward.

outcome-reward-blind-spot.py
1import re 2 3def verdict_reward(response: str, expected: str) -> float: 4 matches = re.findall(r"\\boxed\{(Yes|No)\}", response) 5 return 1.0 if matches == [expected] else 0.0 6 7rollouts = { 8 "lucky_reason": r"It ends in 7, so it must be prime. \boxed{Yes}", 9 "valid_check": r"Check divisors at most sqrt(97): 2, 3, 5, 7 fail. \boxed{Yes}", 10 "wrong_answer": r"97 is divisible by 3. \boxed{No}", 11} 12 13for name, response in rollouts.items(): 14 print(f"{name}: reward={verdict_reward(response, 'Yes')}")
Outcome reward blind spot
1lucky_reason: reward=1.0 2valid_check: reward=1.0 3wrong_answer: reward=0.0

Many RLVR systems start with an all-or-nothing outcome signal because a deterministic checker can compute it repeatedly. Others add rule-based terms, so reward stays executable without being purely binary. Sparse credit assignment is the cost: if a response makes one late arithmetic error, a final-answer checker gives zero even if earlier steps were useful.

Checkable isn't complete: Verifiable means checkable, not complete. A unit-test verifier can prove whether one generated function matches the tested cases. It can't prove that a correct answer came from a general strategy unless the evaluation tests that generalization.

Verifier contract for the 168-job prompt: extract one boxed field, normalize it, check it deterministically, and assign reward 1.0 or 0.0, failing closed on ambiguity, parse errors, and timeouts.
A verifier is a production contract: extract one answer, normalize it, check it deterministically, and fail closed on ambiguity. Gold for the running prompt is 168.

In practice, systems often mix correctness rewards with other rule-based terms. DeepSeek-R1-Zero combined accuracy rewards with format rewards so the thinking process sat in parseable tags before the final answer.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

Read verification as its own pipeline: extract, normalize, check, then record a reason for rejection. A rising zero-rate can mean harder prompts, parser drift, or genuine model regression. Without failure categories, those causes look identical in a training curve.

Outcome vs. process supervision

The simplest form is outcome supervision: score the final answer. An RLVR setup can do this with a rule-based checker. Related work has also trained learned verifiers to score final answers.[5]Reference 5Training Verifiers to Solve Math Word Problems (GSM8K).https://arxiv.org/abs/2110.14168 Feedback is sparse.

Process supervision scores intermediate steps instead of only the final result. Lightman et al. compare outcome and process reward models trained with human labels on mathematical reasoning steps. That's adjacent to RLVR, not itself proof that each process score is programmatically verifiable.[6]Reference 6Let's Verify Step by Step.https://arxiv.org/abs/2305.20050 A formal system can instead run a checker after each proof step. Either version offers more localized credit, but it needs a trustworthy step-level signal.

Diagram showing Prompt + candidate response, Outcome verifier, Final answer reward 0 or 1, and Cheap and scalable.
Prompt + candidate response, Outcome verifier, Final answer reward 0 or 1, and Cheap and scalable.

Caption: Outcome supervision scores the final answer. Process supervision supplies step-level feedback, either from labels or from a checker when one exists, at higher construction cost.

Examples of verifiers

Mathematics

Check whether the extracted final answer matches ground truth, even if the reasoning path is different. The verifier below requires exactly one boxed field and compares values with fractions.Fraction, so 1/21/21/2 and 0.50.50.5 match while missing or duplicated boxes fail closed.

This is small enough to run locally. Production math verifiers add more normalization, a computer-algebra fallback, timeouts, and adversarial parser tests. Don't treat Fraction as a full symbolic simplifier.

mathematics.py
1from fractions import Fraction 2 3def extract_boxed_exprs(text: str) -> list[str]: 4 marker = "\\boxed{" 5 expressions: list[str] = [] 6 offset = 0 7 while (start := text.find(marker, offset)) != -1: 8 depth = 0 9 expr_chars: list[str] = [] 10 for ch in text[start + len(marker):]: 11 if ch == "{": 12 depth += 1 13 expr_chars.append(ch) 14 elif ch == "}": 15 if depth == 0: 16 expressions.append("".join(expr_chars).strip()) 17 offset = start + len(marker) + len(expr_chars) + 1 18 break 19 depth -= 1 20 expr_chars.append(ch) 21 else: 22 expr_chars.append(ch) 23 else: 24 return [] 25 return expressions 26 27def math_verifier(problem: str, answer: str, ground_truth: str) -> float: 28 predicted_fields = extract_boxed_exprs(answer) 29 expected_fields = extract_boxed_exprs(ground_truth) 30 if len(predicted_fields) != 1 or len(expected_fields) != 1: 31 return 0.0 32 try: 33 predicted = Fraction(predicted_fields[0].replace(" ", "")) 34 expected = Fraction(expected_fields[0].replace(" ", "")) 35 except (ValueError, ZeroDivisionError): 36 return 0.0 37 return 1.0 if predicted == expected else 0.0 38 39equivalent_score = math_verifier("Compute half of one.", r"The answer is \boxed{0.5}.", r"\boxed{1/2}") 40wrong_score = math_verifier("Compute 14 times 12.", r"\boxed{148}", r"\boxed{168}") 41ambiguous_score = math_verifier("Compute 14 times 12.", r"Maybe \boxed{168} or \boxed{148}.", r"\boxed{168}") 42print(equivalent_score) 43print(wrong_score) 44print(ambiguous_score) 45print(f"equivalent_passes={equivalent_score == 1.0}") 46print(f"wrong_answer_rejected={wrong_score == 0.0}") 47print(f"ambiguous_answer_rejected={ambiguous_score == 0.0}")
Output
11.0 20.0 30.0 4equivalent_passes=True 5wrong_answer_rejected=True 6ambiguous_answer_rejected=True

Code generation

Running generated code against a strong suite of hidden tests checks concrete behavior. It doesn't prove full correctness unless the suite is complete, but it's stronger than judging code by surface form. The local example runs candidate code in a separate Python process and times out slow attempts. It isn't a security sandbox. Production systems still need containers, seccomp, filesystem isolation, network controls, and resource limits.

code-generation.py
1import json 2import subprocess 3import sys 4from dataclasses import dataclass 5 6@dataclass 7class TestCase: 8 inputs: tuple[int, ...] 9 expected: int 10 11def code_verifier(problem: str, code: str, test_cases: list[TestCase]) -> float: 12 cases = [(case.inputs, case.expected) for case in test_cases] 13 runner = ( 14 code 15 + "\nimport json\n" 16 + f"cases = {cases!r}\n" 17 + "passed = all(solve(*inputs) == expected for inputs, expected in cases)\n" 18 + "print(json.dumps({'passed': passed}))\n" 19 ) 20 try: 21 completed = subprocess.run( 22 [sys.executable, "-I", "-c", runner], 23 capture_output=True, 24 text=True, 25 timeout=1.0, 26 check=False, 27 ) 28 except subprocess.TimeoutExpired: 29 return 0.0 30 if completed.returncode != 0: 31 return 0.0 32 try: 33 result = json.loads(completed.stdout) 34 except json.JSONDecodeError: 35 return 0.0 36 return 1.0 if result == {"passed": True} else 0.0 37 38cases = [TestCase((14, 12), 168), TestCase((8, 12), 96)] 39good = "def solve(a, b):\n return a * b\n" 40bad = "def solve(a, b):\n return a + b\n" 41 42good_score = code_verifier("multiply two integers", good, cases) 43bad_score = code_verifier("multiply two integers", bad, cases) 44print(good_score) 45print(bad_score) 46print(f"good_passes={good_score == 1.0}") 47print(f"bad_rejected={bad_score == 0.0}")
Output
11.0 20.0 3good_passes=True 4bad_rejected=True

Visible tests aren't enough when the policy can memorize examples. Here a candidate passes the two development cases and fails a held-out pair. A reward based only on visible tests would reinforce the wrong program.

held-out-code-tests.py
1from collections.abc import Callable 2 3def shortcut_multiplier(a: int, b: int) -> int: 4 known = {(14, 12): 168, (8, 12): 96} 5 return known.get((a, b), 0) 6 7def pass_rate(fn: Callable[[int, int], int], cases: list[tuple[int, int, int]]) -> float: 8 passed = sum(fn(a, b) == expected for a, b, expected in cases) 9 return passed / len(cases) 10 11visible = [(14, 12, 168), (8, 12, 96)] 12held_out = [(7, 9, 63), (11, 13, 143)] 13 14print(f"visible_pass_rate={pass_rate(shortcut_multiplier, visible):.0%}") 15print(f"held_out_pass_rate={pass_rate(shortcut_multiplier, held_out):.0%}") 16print(f"ship={pass_rate(shortcut_multiplier, held_out) == 1.0}")
Held-out test check
1visible_pass_rate=100% 2held_out_pass_rate=0% 3ship=False

Instruction constraints

Not every verifiable task is math or code. Tülu 3 also trained RLVR on precise instruction-following prompts whose constraints a program can check, such as required bullet counts or word limits in IFEval-style tasks.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124 The reward is still fail closed: if the constraint checker can't confirm the contract, the score is 0.

instruction-constraints.py
1def constraint_reward(response: str) -> float: 2 bullets = [line for line in response.splitlines() if line.startswith("- ")] 3 return 1.0 if len(bullets) == 3 else 0.0 4 5valid = "- name the GPU\n- name the slot count\n- name the job total" 6too_short = "- name the GPU\n- name the slot count" 7print(constraint_reward(valid)) 8print(constraint_reward(too_short)) 9print(f"three_bullets_pass={constraint_reward(valid) == 1.0}") 10print(f"two_bullets_rejected={constraint_reward(too_short) == 0.0}")
Constraint reward
11.0 20.0 3three_bullets_pass=True 4two_bullets_rejected=True

Formal logic

Proof assistants such as Lean or Isabelle can check that a candidate proof term satisfies a formal theorem under their kernel and imported definitions. In production, a verifier wraps the theorem statement and candidate proof into a script, then returns 1.0 only if the prover accepts the full artifact.

The prover call is infrastructure-specific: Lean version, package cache, sandbox, timeout. Keep the reward conversion boring and testable, and keep the theorem-prover runner behind a clear boundary.

formal-logic.py
1from dataclasses import dataclass 2 3@dataclass(frozen=True) 4class ProverResult: 5 accepted: bool 6 stderr: str 7 8def proof_reward(result: ProverResult) -> float: 9 return 1.0 if result.accepted else 0.0 10 11accepted = proof_reward(ProverResult(accepted=True, stderr="")) 12rejected = proof_reward(ProverResult(accepted=False, stderr="unknown identifier")) 13print(accepted) 14print(rejected) 15print(f"accepted_maps_to_one={accepted == 1.0}") 16print(f"rejected_maps_to_zero={rejected == 0.0}")
Output
11.0 20.0 3accepted_maps_to_one=True 4rejected_maps_to_zero=True

What can't be verified?

RLVR is effective but narrow. It works best when the task has an objective spec and a verifier that fails closed. That rules out many open-ended tasks, or at least forces you to break them into smaller verifiable sub-problems. It's not a clean fit for:

  • Open-ended writing: "Write three status-page headlines for an outage" has no objective truth.
  • Subjective analysis: "Explain the trust impact of a release delay" has many valid answers.
  • Safety alignment: deciding if a response is harmful usually requires policy judgment or an AI proxy, which is closer to RLHF or RLAIF than a deterministic correctness check.

Why must an RLVR verifier fail closed?

Answer

If parsing errors, timeouts, or malformed outputs accidentally receive reward, training will amplify those loopholes. A failed verifier should return 0 or no reward, not a best-effort pass.

Group relative policy optimization (GRPO)

DeepSeek-R1 used Group Relative Policy Optimization (GRPO), an algorithm introduced in DeepSeekMath that avoids a learned value model by estimating advantages from a group of samples for the same prompt.[7]Reference 7DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Modelshttps://arxiv.org/abs/2402.03300 DeepSeek-R1 later used GRPO in its reasoning-training stages.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 GRPO is an optimizer, not a synonym for RLVR. Tülu 3 trained its RLVR stage with PPO.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124

The problem with PPO

In standard PPO[8]Reference 8Proximal Policy Optimization Algorithms.https://arxiv.org/abs/1707.06347, a critic (value function) predicts how good a state is. The critic estimates expected future reward Vϕ(st)V_\phi(s_t)Vϕ​(st​).

In the terminal-reward setting common to LLM training, where reward is observed only at the end of a sequence, the advantage often simplifies to:

At=R−Vϕ(st)A_t = R - V_\phi(s_t)At​=R−Vϕ​(st​)

RRR is the final reward and VϕV_\phiVϕ​ is the critic's value estimate. More generally, the advantage uses a temporal-difference error δt=rt+γVϕ(st+1)−Vϕ(st)\delta_t = r_t + \gamma V_\phi(s_{t+1}) - V_\phi(s_t)δt​=rt​+γVϕ​(st+1​)−Vϕ​(st​), often computed via Generalized Advantage Estimation over the full sequence.

Training a critic alongside an LLM adds model memory and compute. With terminal rewards, it must also predict eventual success from partial generations, which gets hard when a long response can later revise an earlier mistake.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

The GRPO solution

GRPO drops the separate critic. Instead of learning a value function that tries to predict how good any reasoning trajectory is, it computes advantages relative to the other samples generated for the exact same prompt in the current batch.

For the 14×12 prompt, sample several outputs. Some reach 168 and receive high reward. Others miss it. The successful outputs are better than average for this sampled group. You don't need a learned critic that estimates difficulty across prompts. You do need reward variation inside each group.

For a prompt qqq you sample a group of GGG outputs {o1,…,oG}\{o_1, \dots, o_G\}{o1​,…,oG​}. The advantage for output iii is the z-score of its reward within that group:

Ai=ri−mean({r1,…,rG})std({r1,…,rG})A_i = \frac{r_i - \text{mean}(\{r_1, \dots, r_G\})}{\text{std}(\{r_1, \dots, r_G\})}Ai​=std({r1​,…,rG​})ri​−mean({r1​,…,rG​})​

Positive advantages push the policy toward those trajectories. Negative advantages push it away. Local normalization compares attempts at the same prompt difficulty. It doesn't guarantee stable training: if every sampled output gets the same reward, the group contributes no comparative signal.

Handle that boundary before dividing. For rewards [1, 1, 1, 1] or [0, 0, 0, 0], the group standard deviation is zero, so the literal formula becomes 0 / 0; production implementations must mask the group, use a guarded denominator, or apply another explicitly defined normalization policy.

What does a positive GRPO advantage mean?

Answer

That sample scored above the group average for the same prompt. The optimizer should increase probability of the tokens in that trajectory relative to worse samples.

This concrete example uses G=8G = 8G=8 samples for the GPU prompt. The verifier returns 1.0 for boxed 168 and 0.0 otherwise:

SampleAnswerReward rir_iri​Group meanGroup stdAdvantage AiA_iAi​
11681.00.50.5+1.0
21480.00.50.5-1.0
31560.00.50.5-1.0
41681.00.50.5+1.0
51700.00.50.5-1.0
61681.00.50.5+1.0
71440.00.50.5-1.0
81681.00.50.5+1.0

Four samples boxed 168, so their rewards are 1.0. Four missed, so their rewards are 0.0. The group mean is 4/8=0.54/8 = 0.54/8=0.5, and the population standard deviation (divide by GGG, not G−1G-1G−1) is 0.5. Sample 1's advantage is (1.0−0.5)/0.5=+1.0(1.0 - 0.5) / 0.5 = +1.0(1.0−0.5)/0.5=+1.0, so the optimizer increases the probability of the tokens that led there. Sample 2's advantage is (0.0−0.5)/0.5=−1.0(0.0 - 0.5) / 0.5 = -1.0(0.0−0.5)/0.5=−1.0, so those tokens get pushed down.

Every correct answer gets the same positive advantage, and every wrong answer gets the same negative advantage. GRPO doesn't know why sample 1 was correct. It only knows that sample 1 beat the average for this prompt. Over many prompts, the policy learns which reasoning patterns reliably produce above-average rewards.

GRPO group for the 14-by-12 GPU prompt: eight sampled answers, four correct 168s and four wrong totals, group mean 0.5, population std 0.5, and advantages of plus 1 or minus 1.
GRPO replaces a learned critic with group-relative statistics on one prompt. Answers that beat the group mean get $A_i = +1$; misses get $A_i = -1$. If every sample scored the same, every advantage would be 0.

The update resembles a PPO-clipped objective with group-relative advantage and a KL penalty. DeepSeek-R1 writes a sequence-level sketch.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 DeepSeekMath applies the clipped surrogate per generated token, averages inside each sequence, then averages across the group.[7]Reference 7DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Modelshttps://arxiv.org/abs/2402.03300 Keep the sequence-level form for intuition, then treat token-level ratios as the implementation contract:

LGRPO=−1G∑i=1G[min⁡(ρiAi,  clip(ρi,1−ϵ,1+ϵ)Ai)−βDKL(πθ∥πref)]\begin{aligned} \mathcal{L}_{\text{GRPO}} = -\frac{1}{G} \sum_{i=1}^{G} \Big[ &\min\left(\rho_i A_i,\; \text{clip}(\rho_i, 1-\epsilon, 1+\epsilon) A_i\right) \\ &- \beta D_{\text{KL}}(\pi_\theta \|\pi_{\text{ref}}) \Big] \end{aligned}LGRPO​=−G1​i=1∑G​[​min(ρi​Ai​,clip(ρi​,1−ϵ,1+ϵ)Ai​)−βDKL​(πθ​∥πref​)]​

Here ρi=πθ(oi∣q)πold(oi∣q)\rho_i = \frac{\pi_\theta(o_i|q)}{\pi_{\text{old}}(o_i|q)}ρi​=πold​(oi​∣q)πθ​(oi​∣q)​ is a sequence-level policy-ratio shorthand, AiA_iAi​ is the normalized group advantage, ϵ\epsilonϵ is the clipping threshold, and β\betaβ controls the drift penalty toward the reference policy.

Implementation contract: during rollout, store old-policy token log-probs. At train time, recompute new-policy token log-probs, form per-token ratios, share the same group advantage AiA_iAi​ across tokens of that sample under outcome supervision, and mask padding. DAPO later argued that averaging loss first by sequence (sample-level) underweights long traces and proposed token-level loss, plus a higher policy-ratio clip on the upper bound to slow entropy collapse.[9]Reference 9DAPO: An Open-Source LLM Reinforcement Learning System at Scalehttps://arxiv.org/abs/2503.14476 Reimplementing GRPO from the sequence-level sketch alone will mis-state gradient scale and clipping.

The Kullback-Leibler (KL) term penalizes drift from a reference policy. It can constrain movement toward a verifier exploit. It can't prove that the verifier represents the intended behavior.

If every sample in the group gets the same reward, the standard deviation is 0 and vanilla GRPO gets no learning signal from that group. That's why prompt difficulty, group size, and reward shaping matter. DeepSeekMath reported G=64G = 64G=64 for its math RL run.[7]Reference 7DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Modelshttps://arxiv.org/abs/2402.03300 DeepSeek-R1's Figure 2 samples 16 responses per AIME question to stabilize evaluation averages. That isn't a published training group size GGG.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 DAPO later used 16 training rollouts per prompt and dynamic sampling: drop all-pass and all-fail groups and keep sampling until the batch has mixed outcomes.[9]Reference 9DAPO: An Open-Source LLM Reinforcement Learning System at Scalehttps://arxiv.org/abs/2503.14476

Common mistake: Saying that three equal rewards out of four collapse the GRPO signal. They don't: the one different outcome creates reward variance. Signal disappears when every sampled output gets the same reward, such as all failures on a prompt that's too hard or all passes on a prompt that's too easy.

This diagnostic identifies which prompt groups supply comparative signal before an update. The mixed group is usable even though three out of four answers fail. The all-fail and all-pass groups carry no relative ranking information.

reward-spread-diagnostic.py
1def population_std(values: list[float]) -> float: 2 mean = sum(values) / len(values) 3 variance = sum((value - mean) ** 2 for value in values) / len(values) 4 return variance ** 0.5 5 6groups = { 7 "mixed": [0.0, 0.0, 0.0, 1.0], 8 "all_fail": [0.0, 0.0, 0.0, 0.0], 9 "all_pass": [1.0, 1.0, 1.0, 1.0], 10} 11 12for name, rewards in groups.items(): 13 std = population_std(rewards) 14 informative = std > 0.0 15 print(f"{name}: std={std:.3f}, informative={informative}")
Reward spread diagnostic
1mixed: std=0.433, informative=True 2all_fail: std=0.000, informative=False 3all_pass: std=0.000, informative=False

The next snippet is a scalar sketch of the GRPO math: each sampled trajectory is one log-probability, which is enough to test group-normalized advantage, PPO-style clipping, and the KL estimator published with GRPO, exp⁡(log⁡πref−log⁡πθ)−(log⁡πref−log⁡πθ)−1\exp(\log \pi_{\text{ref}} - \log \pi_\theta) - (\log \pi_{\text{ref}} - \log \pi_\theta) - 1exp(logπref​−logπθ​)−(logπref​−logπθ​)−1.[7]Reference 7DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Modelshttps://arxiv.org/abs/2402.03300 A production trainer applies the objective at token level and stores old-policy log probabilities during rollout. Use population std (divide by GGG). PyTorch's default std divides by G−1G-1G−1 and will shrink ∣Ai∣|A_i|∣Ai​∣ on small groups unless you set it to unbiased/population mode.

Before the optimizer step, predict its sign. A positive advantage should increase a sampled trajectory's log-probability; a negative advantage should decrease it; an all-equal group should do neither. The scalar lab checks those three cases.

At initialization every ratio is 1, the clip is inactive, and the KL term is 0, so one SGD step on the mean clipped surrogate moves each log-probability by ηAi/G\eta A_i / GηAi​/G.

the-grpo-solution.py
1import math 2 3def group_advantages(rewards: list[float]) -> list[float]: 4 mean = sum(rewards) / len(rewards) 5 std = (sum((reward - mean) ** 2 for reward in rewards) / len(rewards)) ** 0.5 6 if std == 0.0: 7 return [0.0] * len(rewards) 8 return [(reward - mean) / std for reward in rewards] 9 10def clipped_surrogate(ratio: float, advantage: float, epsilon: float = 0.2) -> float: 11 clipped = min(max(ratio, 1.0 - epsilon), 1.0 + epsilon) 12 return min(ratio * advantage, clipped * advantage) 13 14def kl_unbiased(log_pi: float, log_ref: float) -> float: 15 log_ratio_ref = log_ref - log_pi 16 return math.exp(log_ratio_ref) - log_ratio_ref - 1.0 17 18rewards = [1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0] 19advantages = group_advantages(rewards) 20advantages_match = advantages == [1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0] 21 22log_probs = [0.0] * 8 23old_log_probs = [0.0] * 8 24reference_log_probs = [0.0] * 8 25epsilon = 0.2 26beta = 0.01 27lr = 0.1 28group_size = len(rewards) 29 30policy_term = -sum( 31 clipped_surrogate(math.exp(new - old), advantage, epsilon) 32 for new, old, advantage in zip(log_probs, old_log_probs, advantages, strict=True) 33) / group_size 34kl_term = sum( 35 kl_unbiased(new, ref) 36 for new, ref in zip(log_probs, reference_log_probs, strict=True) 37) / group_size 38loss = policy_term + beta * kl_term 39 40updated = [log_prob + lr * advantage / group_size for log_prob, advantage in zip(log_probs, advantages, strict=True)] 41step_direction_ok = updated[0] > 0 and updated[1] < 0 42 43print("advantages:", [round(value, 1) for value in advantages]) 44print("updated log probs:", [round(value, 3) for value in updated]) 45print(f"loss={loss:.6f}") 46print(f"advantages_match={advantages_match}") 47print(f"step_direction_ok={step_direction_ok}")
Output
1advantages: [1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0] 2updated log probs: [0.013, -0.013, -0.013, 0.013, -0.013, 0.013, -0.013, 0.013] 3loss=0.000000 4advantages_match=True 5step_direction_ok=True

The batch loss is 0 at this initialization because the four +1+1+1 and four −1-1−1 advantages cancel in the mean. The update still moves: each trajectory's log-probability changes by ηAi/G\eta A_i / GηAi​/G. GRPO is an optimizer, not a synonym for RLVR. Tülu 3 trained its RLVR stage with PPO. DeepSeekMath introduced GRPO as a PPO variant, and DeepSeek-R1 used GRPO in its reasoning stages.[1]Reference 1Tülu 3: Pushing Frontiers in Open Language Model Post-Traininghttps://arxiv.org/abs/2411.15124[7]Reference 7DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Modelshttps://arxiv.org/abs/2402.03300[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 Both optimizers can consume rule-based verifier rewards.

FeaturePPO-style policy optimizationGRPO
BaselinePredicted by a separate critic modelMean reward of the sampled group
Additional value-model costTrains a critic/value modelAvoids a separate critic
Main estimation riskCritic must predict returnsGroups with equal rewards give no relative signal
Compatible reward signalsLearned or rule-based rewardLearned or rule-based reward, including binary checks

Self-check: In the worked table above, what would happen to the advantages if all 8 samples got the same reward? Why does that make prompt difficulty and group size important in practice?

GRPO often fits RLVR for three engineering reasons. There's no critic to hold in GPU memory. The group mean is local to the current prompt, so you skip training a value head to predict returns from partial reasoning traces. Binary {0,1}\{0,1\}{0,1} rewards are easy to read: when a group contains both passes and failures, passes get positive advantage and failures negative. If all candidates pass or all fail, advantages are zero, so prompt selection and exploration still have to produce mixed outcomes often enough to learn.

DeepSeek-R1 training pipeline

RLVR success depends on the pipeline as well as the algorithm. DeepSeek-R1 used a multi-stage process that alternates supervised fine-tuning and reinforcement learning to improve checked reasoning, readability, and broader assistant behavior.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

On AIME 2024, DeepSeek-R1-Zero's reported pass@1 rose from 15.6% to 77.9% during rule-based RL from DeepSeek-V3-Base. Figure 1 also reports 86.7% with consistency over 16 samples.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 Those numbers are the empirical stake for the pipeline below. They aren't a promise that every base model and verifier will move the same way.

Diagram showing Base model, Stage 1: cold-start SFT readable reasoning, Stage 2: reasoning RL GRPO + rule-based rewards, and Rule-based rewards accuracy + format + language consistency.
Base model, Stage 1: cold-start SFT readable reasoning, Stage 2: reasoning RL GRPO + rule-based rewards, and Rule-based rewards accuracy + format + language consistency.

Caption: DeepSeek-R1's reported pipeline starts with readable cold-start behavior, then applies GRPO with rule-based rewards on reasoning tasks, including a language-consistency reward. Later stages collect filtered traces into SFT data, mix in broader instruction data, and combine reasoning rewards with general-behavior reward models.

Stage 1: cold start (not mandatory, often useful)

DeepSeek-R1-Zero showed that DeepSeek-V3-Base could improve on reported reasoning evaluations through rule-based RL without a preliminary SFT phase.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 That result doesn't mean every base model or verifier will train usefully from zero-reward-heavy rollouts.

DeepSeek still added cold-start data for DeepSeek-R1 because R1-Zero had poor readability and mixed languages. The paper describes collecting thousands of long-CoT examples, filtering for a readable response pattern, and using them to initialize the model before RL.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 In other projects, cold start also helps when the base model's initial pass rate is so low that almost every rollout gets zero reward.

Stage 2: reasoning RL (GRPO)

This stage trains on math, code, and logic prompts using GRPO with rule-based rewards. In DeepSeek-R1-Zero, those rewards were accuracy plus format. In DeepSeek-R1, the first RL stage also added a language-consistency reward (the share of target-language words in the chain of thought) to reduce mixed-language traces, with the paper reporting a slight performance trade-off in its ablation.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

For rule-graded prompts, a response that fails the checked outcome doesn't receive the accuracy reward no matter how persuasive its text is. That still leaves coverage risk: a pass can reflect a shortcut if the verifier or evaluation set fails to test it.

Stage 3: rejection sampling and SFT

Once the RL policy is producing higher-scoring traces, they can become new demonstrations. DeepSeek-R1 used rejection sampling, retaining checked-correct responses for rule-gradable data and using DeepSeek-V3 judgments for some expanded reasoning data.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

That stage produced about 600k reasoning samples plus about 200k non-reasoning samples, for roughly 800k total.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 This turns exploratory RL behavior into a stable supervised dataset and helps recover capabilities that pure reasoning RL doesn't optimize for, such as writing quality and everyday instruction following.

Stage 4: final RL

Pure reasoning RL can produce a model that's strong on benchmarks but rough around the edges. In the final stage, DeepSeek runs RL again, this time on a broader mix of scenarios.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

This uses a mix of:

  1. Rule-based rewards to maintain strong reasoning capabilities.
  2. Reward models (RLHF) for helpfulness and harmlessness in general conversation.

This final stage is intended to combine reasoning performance with broader helpfulness and harmlessness objectives. Those outcomes still have to be measured rather than assumed.

Observed reasoning patterns

Outcome-checked RL doesn't label each reasoning step. In DeepSeek-R1-Zero, the authors report longer responses and visible patterns such as verification, reflection, and exploration of alternatives during training.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 Treat those as observed output behaviors, not proof of an internal reasoning mechanism.

Self-verification patterns

An output may pause and check its work.

"Wait, let me double-check that calculation. 14×1214 \times 1214×12 is 168168168, not 148148148. I made a mistake."

DeepSeek-R1-Zero wasn't trained from step-level labels saying "write let me check here." Its paper reports a sharp increase in the use of "wait" during reflection later in training.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 The cautious interpretation is that RL changed the distribution of generated traces and that some reflective-looking traces co-occurred with improved checked outcomes. An outcome-only verifier doesn't establish why those traces improved.

Backtracking patterns

An output may abandon one approach and try another.

"Counting slots as 14+1214 + 1214+12 seems wrong. Let me multiply instead."

This can look search-like on the surface, but the training loop is still autoregressive generation plus reward-weighted updates, not an explicit tree-search controller. A verifier credits the final checked outcome. It doesn't separately establish that the pivot was necessary.

Extended thought

In DeepSeek-R1-Zero, average response length jumped sharply during training alongside reported accuracy gains.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 This connects RLVR to test-time compute because trained policies may emit longer traces on reasoning tasks. Longer traces aren't automatically better. Their value has to be measured against correctness, latency, and token cost.

A useful self-check: suppose a model trained with outcome rewards starts saying "Wait, let me double-check that" before finalizing answers. What can you conclude from the output pattern, and what would require separate evaluation? The reward confirms correct final answers, not the necessity or faithfulness of the written reflection.

Research caution: It remains open how much RLVR creates new problem-solving behavior versus eliciting behavior already likely under the base model. Shao et al. report that on Qwen2.5-Math-7B, MATH-500 rose 21.4 points with random rewards and 13.8 points with format-only rewards, versus 29.1 points with ground-truth rewards. Comparable spurious rewards gave little benefit or harmed Llama3 and OLMo2 variants.[10]Reference 10Spurious Rewards: Rethinking Training Signals in RLVRhttps://arxiv.org/abs/2506.10947 They connect this result to GRPO clipping and model-specific high-prior behaviors. Practical takeaway: compare against weak or spurious-reward baselines and validate across model families and held-out tasks. Track pass@1 and pass@k. A rising training reward with flat held-out pass@k is usually hacking, memorization, or probability mass shifting among traces the base model could already sample.

Reward hacking and failure modes

Any time you optimize a metric, a policy can exploit gaps in that metric. RLVR is no exception. If the verifier checks only final answers, a memorized answer, leaked target, or weak parser can receive reward without demonstrating general solution ability. DeepSeek-R1 explicitly identifies reliable reward construction as a limitation once tasks can't be graded by dependable rules.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948

Don't train against a verifier before adversarially testing it. Any malformed output or shortcut that earns reward can be reinforced by the optimization loop.

Format gaming

A format-heavy reward can favor output wrappers over correctness. If the verifier gives substantial credit for \boxed{...} before checking the value, it can reinforce neatly formatted wrong answers. A parser that accepts any matching line also risks rewarding output that contains several contradictory answers.

High format compliance with low task accuracy means the reward function prizes formatting before correctness. Make correctness dominant and fail closed on wrong or ambiguous contents, even if the wrapper is present.

This example compares a broken format-first reward with a correctness-gated version. A wrong boxed 148 should never beat an unboxed 168 just because it's easy to parse.

format-reward-trap.py
1import re 2 3def boxed_value(response: str) -> int | None: 4 matches = re.findall(r"\\boxed\{(\d+)\}", response) 5 return int(matches[0]) if len(matches) == 1 else None 6 7def broken_reward(response: str, expected: int) -> float: 8 value = boxed_value(response) 9 return 0.7 if value is not None else (0.3 if str(expected) in response else 0.0) 10 11def gated_reward(response: str, expected: int) -> float: 12 value = boxed_value(response) 13 return 1.0 if value == expected else 0.0 14 15wrong_boxed = r"The answer is \boxed{148}." 16right_plain = "The answer is 168." 17 18print(f"broken_prefers_wrong={broken_reward(wrong_boxed, 168) > broken_reward(right_plain, 168)}") 19print(f"gated_wrong_boxed={gated_reward(wrong_boxed, 168)}")
Format reward trap
1broken_prefers_wrong=True 2gated_wrong_boxed=0.0

Shortcut exploitation

If a training set has shortcuts (for example, one multiple-choice position is correct much more often), optimizing checked training reward can favor that shortcut. A code verifier that treats execution errors as passing outcomes creates an even more direct loophole.

Mitigation strategies

To prevent policies from exploiting the verifier, several defensive practices help during training:

  • Explicit verifier contracts: use isolated execution and fail closed on any parsing error. Symbolic checking belongs here when the answer isn't a plain integer.
  • Difficulty calibration: include prompts where rollouts produce both passing and failing outputs often enough for group-relative learning. All-zero groups contribute no comparative advantage. DAPO-style dynamic sampling filters those groups out of the update batch.[9]Reference 9DAPO: An Open-Source LLM Reinforcement Learning System at Scalehttps://arxiv.org/abs/2503.14476
  • Held-out tests: evaluate on independent problems and, when possible, an independently implemented checker so a parser shortcut isn't mistaken for generalization.
  • Length controls: cap rollout length or add carefully tuned penalties so the model doesn't learn to think forever without improving correctness. DAPO adds a soft overlong punishment near the generation cap rather than a hard truncate-and-fail that can punish otherwise valid traces.[9]Reference 9DAPO: An Open-Source LLM Reinforcement Learning System at Scalehttps://arxiv.org/abs/2503.14476
Side-by-side rewards for the same four 168-job rollouts: a scoped fail-closed verifier scores only a single boxed 168 as 1.0, while a weak verifier pays format, word match, and timeouts, so the policy can learn shortcuts.
The policy learns whatever you score. On the same four rollouts, a scoped 168-checker fails closed. A weak checker pays wrappers, guesses, and hangs.

When RLVR breaks

Set an evidence gate before training. Pause if training reward rises while held-out pass@k, format validity, or broad instruction metrics fall. Inspect verifier coverage, leakage, and reward components before adding steps or widening the task mix.

Forcing a checker onto a subjective task

A reward function that secretly depends on taste, safety judgment, or fuzzy grader text is forcing an objective RL method onto a subjective task. Ask whether a deterministic checker, theorem prover, unit test suite, database constraint, or schema validator can grade the output. If not, use RLHF, DPO, Reinforcement Learning from AI Feedback (RLAIF), or decompose the task into smaller verifiable checks.

Treating cold-start SFT as always required or never useful

DeepSeek-R1-Zero improved reported reasoning-task results from DeepSeek-V3-Base without a preliminary SFT phase.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 DeepSeek-R1 still used cold-start SFT because readability and language consistency mattered. Measure the base model's initial pass rate and output quality. If almost every rollout gets zero reward or the traces are unreadable, cold-start data may make RL more tractable.

Celebrating format accuracy

A verifier that rewards \boxed{} too strongly can teach box-writing instead of problem-solving. Keep correctness dominant, run adversarial parser tests, and track real task accuracy separately from format compliance.

Ignoring general capability drift

A model trained heavily on math or code RLVR can become better at those tasks while getting worse at normal instruction following. Use KL anchoring, mix in general instruction data during later SFT stages, and run broad evaluations such as writing, safety, and everyday chat alongside math or code metrics.

This release gate catches a reasoning gain that comes with an unacceptable instruction-following regression. The numbers are illustrative. Each team should define thresholds before training.

capability-regression-gate.py
1baseline = {"checked_reasoning": 0.61, "instruction_following": 0.92, "false_refusal": 0.04} 2candidate = {"checked_reasoning": 0.74, "instruction_following": 0.81, "false_refusal": 0.13} 3 4violations = [] 5if candidate["checked_reasoning"] <= baseline["checked_reasoning"]: 6 violations.append("no reasoning gain") 7if candidate["instruction_following"] < baseline["instruction_following"] - 0.03: 8 violations.append("instruction following regressed") 9if candidate["false_refusal"] > baseline["false_refusal"] + 0.02: 10 violations.append("false refusals increased") 11 12print(f"reasoning_gain={candidate['checked_reasoning'] - baseline['checked_reasoning']:+.0%}") 13print(f"ship={not violations}") 14print(violations)
Capability gate output
1reasoning_gain=+13% 2ship=False 3['instruction following regressed', 'false refusals increased']

Treating RLVR and distillation as rivals

RLVR can improve checked outcomes for a teacher. Distillation transfers sampled teacher behavior into a smaller model. Decide which bottleneck you have: if the teacher fails verifiable evaluations, train against better checks; if a capable teacher is too expensive to serve, consider distillation.

A tiny verifier lab

To understand RLVR, build a verifier yourself. You don't need a GPU cluster or a billion-parameter model. A Python script and a small set of arithmetic problems are enough to see the mechanics.

Treat a verifier edit like a model edit. Freeze held-out prompts, replay malformed and adversarial outputs, compare failure categories, and resume RL only after checker behavior is stable.

Checkpoint: Before building the verifier, state the exact contract: require one answer field, extract one number, compare with tolerance, and fail closed on missing, duplicated, or malformed fields. If that contract feels vague, re-read the math verifier example above.

Exercise: write a verifier that takes a model's raw text output and returns 1.0 if the answer is correct and 0.0 otherwise. Use the following prompt and ground-truth pairs:

PromptGround truth
"A GPU batch runner has 14 workers with 12 slots each. How many concurrent jobs fit?"168
"A scheduler runs 8 jobs per wave. How many waves are needed for 96 jobs?"12
"A request budget is 47.50 GPU-seconds with a 6% overhead. What's the total?"50.35

Step 1: Implement extract_answer(text: str) -> str | None that accepts exactly one \boxed{...} answer field. Reject missing or duplicated fields rather than guessing which number the model intended as final.

Step 2: Implement verify(prompt: str, response: str, ground_truth: float) -> float that extracts the predicted answer, compares it to the ground truth with a small tolerance (e.g., abs(predicted - expected) < 1e-3), and returns 1.0 or 0.0.

Step 3: Test your verifier against these three model outputs for the first prompt:

  1. "There are 14 workers and 12 slots each. 14 × 12 = 168. The answer is 168\boxed{168}168​."
  2. "The total is 148\boxed{148}148​."
  3. "It might be 168\boxed{168}168​ or 148\boxed{148}148​."

Expected results: output 1 should return 1.0. Outputs 2 and 3 should return 0.0. The third response contains the correct value, but its final answer is ambiguous.

Start from this minimal solution:

a-tiny-verifier-lab.py
1import re 2 3def extract_answer(text: str) -> str | None: 4 boxed = re.findall(r"\\boxed\{(-?\d+(?:\.\d+)?)\}", text) 5 return boxed[0] if len(boxed) == 1 else None 6 7def verify(prompt: str, response: str, ground_truth: float) -> float: 8 answer = extract_answer(response) 9 if answer is None: 10 return 0.0 11 try: 12 predicted = float(answer) 13 except ValueError: 14 return 0.0 15 return 1.0 if abs(predicted - ground_truth) < 1e-3 else 0.0 16 17prompt = "A GPU batch runner has 14 workers with 12 slots each. How many concurrent jobs fit?" 18correct_score = verify(prompt, r"There are 14 workers and 12 slots each. 14 * 12 = 168. The answer is \boxed{168}.", 168) 19wrong_score = verify(prompt, r"The total is \boxed{148}.", 168) 20ambiguous_score = verify(prompt, r"It might be \boxed{168} or \boxed{148}.", 168) 21 22print(correct_score) 23print(wrong_score) 24print(ambiguous_score) 25print(f"correct_passes={correct_score == 1.0}") 26print(f"wrong_rejected={wrong_score == 0.0}") 27print(f"ambiguous_rejected={ambiguous_score == 0.0}")
Output
11.0 20.0 30.0 4correct_passes=True 5wrong_rejected=True 6ambiguous_rejected=True

Step 4 (optional): add a format reward. Give +0.2 for using \boxed{} correctly, and +0.8 for a correct answer inside the box. What behavior does this mixed reward encourage? Does the model still get a positive reward if the box is present but the answer is wrong? For a strict production verifier, decide whether that partial credit is worth the gaming risk or whether correctness should gate every positive reward.

DeepSeek-R1-Zero combined accuracy rewards with format rewards targeting a parseable response structure.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 Mixed rewards require careful testing so formatting doesn't dominate correctness.

RLVR and distillation

RLVR and distillation aren't mutually exclusive. DeepSeek-R1 used RL in its teacher pipeline, then fine-tuned smaller dense models on the same 800k generated training samples.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 The systems distinction is clean: RLVR optimizes a policy against checks, while distillation trains a student from teacher outputs.

AspectRLVRDistillation
Training signalOnline reward from a verifierOffline supervision from teacher outputs
What it optimizesChecked success under a specified contractImitation of teacher behavior
Compute profileOnline sampling, verification, and RL updatesSupervised training over collected traces
DependencyNeeds a reliable verifierNeeds a useful teacher and clean trace data
Best useImprove checked outcomes for selected tasksTransfer teacher behavior into smaller models
Main failure modeReward hacking or sparse-credit collapseStudent inherits teacher blind spots and data coverage limits

DeepSeek-R1 makes this trade-off concrete. Distilling into Qwen2.5-32B outperformed a large-scale RL run on Qwen-32B-Base (DeepSeek-R1-Zero-Qwen-32B) on the paper's reasoning benchmarks.[2]Reference 2DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learninghttps://arxiv.org/abs/2501.12948 That's evidence for testing distillation when a strong teacher exists, not a universal ranking of the two methods.

RLVR still matters because distillation doesn't optimize the student online against a verifier. If the teacher's checked outcomes are insufficient, improving that policy against well-tested verifiers is a different operation from transferring its sampled outputs.

Complete the lesson

Mastery Check

Answer every question, then check your score. Score 75% or higher to mark this lesson complete.

1.When is RL with verifiable rewards a better fit than subjective preference optimization?

Correct answer: When task correctness can be checked by an executable or otherwise exact verifier with a clear pass condition.

RLVR is strongest when reward can be tied to an objective check such as tests, symbolic equivalence, or a proof condition. Subjective behavior still needs preference or human-oriented evaluation.

2.A math answer gives a valid final number with an invalid explanation, while another gives a valid proof and number. An outcome-only verifier labels both 1. What is the risk?

Correct answer: The verifier rewards lucky or unsupported reasoning, so the reward contract should separately validate reasoning when it matters.

Outcome checks are precise about the final result but blind to how it was obtained. If reasoning quality or trust matters, add appropriate checks or a separate gate instead of assuming a correct answer proves the path.

3.A generated solution cannot be parsed, times out, or triggers an ambiguous verifier exception. What reward policy is safest?

Correct answer: Fail closed with reward 0 and record the failure type for debugging and verifier coverage.

A verifier that rewards malformed or timed-out outputs creates an exploitable path. Fail-closed behavior protects the objective, while failure categories show whether parser, timeout, or verifier logic needs repair.

4.How does GRPO derive its training signal for a prompt?

Correct answer: It samples a group, normalizes rewards relative to that group, and needs nonzero reward variance to create advantages.

GRPO is group-relative online RL without a learned critic in the stated setup. If every sample receives the same reward, normalization produces zero advantages and no group learning signal.

5.A base model's verifier reward is nearly zero because it emits unreadable code. What can a cold-start stage provide?

Correct answer: A small supervised or distilled warm start that makes outputs parseable enough for verifier feedback to become informative.

Cold starts are optional but useful when exploration never reaches the verifier's valid region. They improve format or basic capability without replacing hidden-test evaluation or later verification.

6.Why must a verifier hold out hidden tests or cases?

Correct answer: To prevent a policy from overfitting the exposed checks while appearing correct on the verifier it can observe.

Visible tests can become a target for memorization or reward hacking. Hidden cases estimate transfer to the intended task rather than merely compliance with the public checker.

7.A code reward combines parse success, unit tests, and style. Which ordering is safest?

Correct answer: Gate downstream style or explanation rewards on parse and correctness checks, so formatting cannot compensate for invalid behavior.

A polished invalid program should not beat a correct one because style points dominate. Gated reward composition makes correctness a prerequisite and keeps auxiliary signals from masking failure.

8.RLVR improves hidden-test reasoning but lowers instruction-following and safety metrics. What release decision follows?

Correct answer: Block or revise the run because capability gains do not waive instruction and safety regression gates.

RLVR targets a checkable capability, but the resulting policy still has a product contract. Regression gates protect other required behaviors and prevent a narrow reward improvement from shipping a worse assistant.

9.Why is teacher-to-student distillation a separate intervention from RLVR?

Correct answer: Distillation transfers teacher distributions or traces through a supervised objective, while RLVR updates a policy from verifier feedback.

The signal source and training loop differ. Distillation teaches from a teacher's outputs or probabilities, while RLVR reinforces sampled behavior according to an executable correctness check.

9 questions remaining.

Next Step
Continue to Knowledge Distillation for LLMs

RLVR can raise a teacher's checked pass rate when a verifier exists. Distillation asks how to copy useful teacher behavior into a smaller model you can actually serve, without running that RL loop on the student.

PreviousConstitutional AI & Red Teaming
Share this article
XFacebookLinkedInBlueskyRedditHacker NewsEmail
References

Tülu 3: Pushing Frontiers in Open Language Model Post-Training

Lambert, N., et al. · 2024 · arXiv preprint

https://arxiv.org/abs/2411.15124

DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning

DeepSeek-AI · 2025

https://arxiv.org/abs/2501.12948

Training Language Models to Follow Instructions with Human Feedback (InstructGPT).

Ouyang, L., et al. · 2022 · NeurIPS 2022

https://arxiv.org/abs/2203.02155

Direct Preference Optimization: Your Language Model is Secretly a Reward Model.

Rafailov, R., et al. · 2023

https://arxiv.org/abs/2305.18290

Training Verifiers to Solve Math Word Problems (GSM8K).

Cobbe, K., et al. · 2021

https://arxiv.org/abs/2110.14168

Let's Verify Step by Step.

Lightman, H., et al. · 2023 · ICLR

https://arxiv.org/abs/2305.20050

DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models

Shao, Z., et al. · 2024

https://arxiv.org/abs/2402.03300

Proximal Policy Optimization Algorithms.

Schulman, J., et al. · 2017

https://arxiv.org/abs/1707.06347

DAPO: An Open-Source LLM Reinforcement Learning System at Scale

Yu, Q., et al. · 2025 · arXiv

https://arxiv.org/abs/2503.14476

Spurious Rewards: Rethinking Training Signals in RLVR

Shao, R., et al. · 2025

https://arxiv.org/abs/2506.10947

Discussion

Questions and insights from fellow learners.

Discussion loads when you reach this section.