GRPOTrainer trains a model with Group Relative Policy Optimization: for each prompt it samples a group of completions, scores each one with your reward functions, and moves the model toward the completions that scored above the group average.
For code tasks, a good reward is “does the code pass the tests?”. That means running code the model just wrote, often thousands of times per training run. This page builds a reward function that runs each completion in its own Superserve sandbox, so untrusted code never runs on your training machine.
Setup
How it works
TRL calls a reward function once per batch with the completions and every extra column of the dataset as keyword arguments. The reward function on this page:- Extracts the code from the first fenced Python code block in each completion.
- Appends a line that prints the result of the problem’s test expression as JSON.
- Runs the program in a new sandbox with no internet access, then kills the sandbox. A thread pool scores several completions at the same time.
- Returns
1.0if the program exits with status 0 and its last line of output matches the expected result, and0.0otherwise.
Add the reward function
Save this file ascode_reward.py. The highlighted lines are the Superserve calls: create a sandbox, write the program, run it, and kill the sandbox.
code_reward.py
deny_out=["0.0.0.0/0"], so generated code cannot download packages or send data out. timeout -s KILL 10 stops code that never ends, such as an infinite loop, after 10 seconds. If your training process crashes before kill() runs, the sandbox auto-pauses after timeout_seconds, and auto_delete_seconds=0 deletes it at once. See Networking and Lifecycle.
The expected result stays on your training machine and never goes into the sandbox. Code that exits early, or reads its own file, cannot print a passing result without computing it.
If a sandbox call fails with a rate-limit, server, timeout, or network error, score returns None instead of 0.0. Other errors, such as an invalid API key, still raise and stop training. TRL 1.6 and later leave a completion with no score out of the policy update, so a temporary outage does not teach the model that correct code is wrong.
Train with GRPO
Save this file astrain.py, next to code_reward.py. TRL passes the test and expected columns of the dataset to code_reward as arguments with the same names, one entry for each completion.
train.py
rewards/code_reward/mean. The model learns only from groups where some completions pass and others fail. When every completion in a group gets the same reward, reward_std is 0 and that group contributes no gradient. Add harder problems, or more num_generations, if most steps show this.
On a machine without a GPU, add
use_cpu=True to GRPOConfig. A 0.5B model trains on CPU, but slowly.Good to know
- Concurrency: each completion uses one sandbox for a few seconds.
MAX_SANDBOXEScaps how many run at the same time. Keep it within your team’s concurrent sandbox limit; limits depend on your team’s plan. - Dependencies: the default sandbox has Python 3 and the standard library. If your tests import packages such as
numpy, build a template with them and passfrom_template=toSandbox.create. - Partial credit: when the test expression is a list, as in the
is_primeproblem, return the fraction of items that match the expected list instead of1.0or0.0. - Other languages: change the run command, for example to
node /tmp/solution.js, and use a template that has the runtime.
Resources
GRPO Trainer
Read how GRPOTrainer samples completions and uses rewards.
Custom reward functions
Review the arguments TRL passes to a reward function.