Requirements
- A cookbook checkout. To set one up, see the RL quickstart.
- A dataset where each row has a prompt and a target to score completions against, either on Hugging Face or in a form you can load into the same shape.
Write a reward function
A reward function takes the model’s decoded completion and the row’s target, and returns a float:- Returns values in
[0, 1]: This keeps advantages on a predictable scale. - Varies across completions: A reward that scores most completions the same leaves GRPO nothing to learn from. A group where every completion scores the same has zero-variance advantages and is skipped. Before training, score a sample of the base model’s outputs and check that the scores spread.
- Is deterministic: The same prediction and target always score the same.
- Is fast: It runs at least
batch_size * group_sizetimes per step, and more often with dynamic sampling or validation, or when it doubles as the metric. The cookbook scores single-turn completions one at a time, so a reward that waits on an API call, a model, or a subprocess adds that wait to every step. To score with something slow, such as a judge model, write a one-turn environment instead, because the cookbook runs every episode’s asyncstepconcurrently.
Built-in datasets
The cookbook registers four datasets, each paired with a reward. To train on one, pass its name asdataset on GRPOConfig. Their entries in post_training_cookbook/datasets/registry.py also serve as working examples of the fields described in Register a dataset and reward.
Register a dataset and reward
The cookbook’s dataset registry maps each dataset name to how its rows become prompts, what its target is, and how its completions are scored. The steps below register a dataset of Python coding problems, where each row has aprompt and an expected_output.
1
Write the reward function
Add your reward function to The cookbook scores every completion twice, once with
post_training_cookbook/datasets/rewards.py. This example runs the generated code and compares its standard output with the expected output:compute_reward and once with compute_metric, which falls back to the reward when you don’t set one. The lru_cache decorator returns the cached score for the second call, so each completion’s code runs only once.2
Register the dataset
Add a
DatasetConfig entry to post_training_cookbook/datasets/registry.py:To train on data that isn’t on Hugging Face, save it as a JSON Lines file named
train.jsonl, one row per line, in a folder of its own. Then set hf_name to the folder’s path, such as "./my_problems", hf_config to None, and hf_split to "train". The cookbook loads the folder with the Hugging Face datasets library, which reads train.jsonl into the train split. A relative path resolves from the directory you run the recipe in.3
Test the reward
Run the reward on hand-written completions before you train on it:Then add the same cases to
tests/datasets/test_rewards.py and run uv run pytest tests/datasets. Include one edge case per failure mode: an empty completion, a very long completion, output in an unexpected format, and, for this reward, a timeout.4
Create and run the recipe
Create A code solution takes more tokens than a math answer, so this recipe sets
recipes/grpo/code_output.py:max_sample_tokens higher than the GSM8K recipe does, and temperature=0.8 gives the completions in each group more room to diverge. Run it with uv run python recipes/grpo/code_output.py.Reward shapes
Binary:1.0 for correct, 0.0 for wrong, like exact_match_reward above. Use it for tasks with a single checkable answer, such as math and factual questions.
Tiered: Partial credit at several levels. Use it when partial progress deserves credit, such as in multi-step problems or in puzzles where getting the format right is a large part of the task.
compute_reward drives the advantages. compute_metric is what validation reports as val/accuracy.
Design guidance
- Reward the format you want: If you want
\boxed{}answers, give partial credit for the format even when the content is wrong. The model has to learn to emit the format before it can get the content right. - Penalize degenerate outputs: Return
0.0for empty responses, repetition, or outputs that don’t attempt the task. - Guard against reward hacking: Watch
val/accuracyalongside training reward. If training reward rises while validation accuracy falls, or validation response length creeps up, the model has found a way to score well on your reward without solving the task. - Sandbox code execution: A reward that executes model output, like the code example above, needs a timeout and should run isolated from your machine, for example in a container or a code sandbox.
- Don’t rely on the main thread: Rewards can run off the main thread, for example when a sweep trains each arm in its own thread. Timeouts built on
signal.alarmfail there, so use a subprocess timeout like the one in the code example.
Check a baseline before training
To see how a model performs on your task before you spend GPU time training it, run one of the cookbook’srecipes/serverless_eval/ scripts. Each script scores a hosted chat model on a dataset’s validation split, without a training session or model resource:
gsm8k, deepmath, game24, and the multi-turn tool-use environment. To score your own registered dataset, copy a script and change its dataset. Each run writes its episodes to runs/serverless_eval_<label>_<model>_<timestamp>/episodes.json.
To score Qwen3.8 27B before training, deploy Qwen/Qwen3.8-27B-FP8 on dedicated model inference. The scripts take no arguments, so edit the script’s model to the endpoint string. The same flow works for a model you trained. For an adapter attached to a multi-LoRA deployment, use the adapter’s model string, such as your-project-slug/my-sweep:ml_abc123. Then run the script with TOGETHER_BASE_URL set to the dedicated inference host:
eval/length_capped metric in the output, which reports the fraction of episodes the endpoint cut off at max_tokens. If it’s high, the score measures truncation rather than ability, so raise max_tokens, especially for models with thinking on.
Multi-turn rewards
In a multi-turn environment, the reward comes from the environment’sstep result instead of a (prediction, target) function. It’s assigned per episode, not per completion. For details, see Multi-turn environments.
Next steps
Reinforcement learning with GRPO
The settings that shape how your reward turns into updates.
Multi-turn environments
Reward whole episodes of tool use instead of single completions.
Monitoring
The metrics that show whether your reward is giving the model a signal.
RL quickstart
Run the GSM8K recipe your dataset will slot into.