Skip to main content
TRL is Hugging Face’s library for post-training language models. Its 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

TRL needs Python 3.11 or later and installs PyTorch and Transformers. See API keys to create a Superserve API key.

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:
  1. Extracts the code from the first fenced Python code block in each completion.
  2. Appends a line that prints the result of the problem’s test expression as JSON.
  3. 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.
  4. Returns 1.0 if the program exits with status 0 and its last line of output matches the expected result, and 0.0 otherwise.

Add the reward function

Save this file as code_reward.py. The highlighted lines are the Superserve calls: create a sandbox, write the program, run it, and kill the sandbox.
code_reward.py
Each sandbox blocks all outbound traffic with 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 as train.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
Run it:
TRL logs the reward for each step as 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_SANDBOXES caps 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 pass from_template= to Sandbox.create.
  • Partial credit: when the test expression is a list, as in the is_prime problem, return the fraction of items that match the expected list instead of 1.0 or 0.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.