Train with Slime
Slime manages training and serves the policy through its inference workers. FOCUS decides which partial solutions to continue and turns the resulting tree into actor advantages and critic targets.
This tutorial connects the MATH harness to Slime’s Megatron training backend. Each edge continues the same solution for up to 256 tokens. The integration returns actor segments to Slime and saves critic targets for a value-model training loop.
Slime owns the training loop and calls FOCUS through hooks named on its command line. focus.integrations.slime provides those hooks. You supply the same task function used in Train with Tinker: collector_for(policy, problem), which builds a collector for one problem.
Before you begin
Section titled “Before you begin”Use a Slime Megatron environment; step 7 gives a complete launch for Qwen3-4B-Instruct-2507 on two H100 GPUs. Reuse math_training.py from Train with Tinker, step 1: the search, the starting critic, and collector_for are the same for both trainers. Step 7 installs FOCUS and the answer verifier in the worker environment.
1. Write the hook module
Section titled “1. Write the hook module”The Slime hook module defines the generation and evaluation hooks and the directory for critic records:
make_generate() builds Slime’s custom generate function and make_evaluate() its evaluation function, both from collector_for. profile="token_chunk" resolves the served model’s tokenizer for use without tools. Segments in the shared make_agent() reads each reply as an exact 256-token segment.
JsonlDirectory writes each prompt’s critic records to a separate JSONL file, preventing concurrent workers from interleaving lines. Each rollout worker reads the directory from FOCUS_CRITIC_OUTPUT when it imports this module at startup.
2. What happens when Slime calls generate
Section titled “2. What happens when Slime calls generate”For each prompt, the hook:
- Builds a
SlimePolicyfor the model behind Slime’s SGLang router. The router address andhf_checkpointcome from Slime’sargs. Loading the tokenizer once per checkpoint keeps FOCUS’s prompt rendering matched to the served model. - Wraps Slime’s sample as a
Problem. Slime’s--input-keyand--label-keyfill itspromptandlabel; the sample’s index becomes itsid. - Calls
collector_for(policy, problem)and collects one tree with that fresh collector. The environment is built per prompt, so concurrent problems keep their own reference answers. The reference solution is used only for grading. - Sends the critic records to the critic sink and returns the actor records as Slime samples.
DirectBranchTd computes segment TD advantages, while the shared tree values provide direct-branch backup targets for the critic. A collection with failed expansions or critic predictions raises an error unless you pass allow_partial=True. The hook uses each collector once inside async with, following the ownership settings in collector_for. Slime owns the HTTP client used by the policy.
3. How actor segments become Slime samples
Section titled “3. How actor segments become Slime samples”focus.integrations.slime.to_sample() converts each actor record. It keeps:
| Field | Meaning |
|---|---|
tokens | Full conditioning prefix followed by the generated segment |
response_length | Number of tokens from the first generated token to the end |
loss_mask | Response-aligned mask selecting generated tokens |
rollout_log_probs | The segment’s recorded generation probabilities |
reward | The prepared FOCUS actor advantage |
rollout_id | The identity shared by all segments collected for this prompt |
The conditioning prefix stays outside the response loss. Conditioning tokens that arrive inside the response, such as tool results in a tool-using task, stay in the response with loss mask zero. All sibling segments keep the source sample’s rollout_id, so Slime groups them as one rollout during batch scheduling. The conversion follows Slime’s Sample fields.
Here reward carries the prepared actor weight: positive values reinforce the segment and negative values discourage it. MathEnv supplied the correctness outcomes used to compute that weight.
4. Use the advantage and loss hooks
Section titled “4. Use the advantage and loss hooks”Three hooks in focus.integrations.slime carry these weights through Slime’s training pipeline. Name them directly on the command line in step 7:
preserve_advantages()passes the prepared weights through reward post-processing unchanged.advantages()repeats each segment’s weight over its response positions, using tensors aligned with the recorded log probabilities. It overrides the estimator Slime’s argument parser selected and refuses advantage normalization.sum_policy_tokens()sums the masked token losses. Slime’s trainer applies its rollout-batch reduction across prompts.
The policy loss combines the clipped learner-to-behavior probability ratio with the segment’s fixed advantage, as in the paper. Prompt tokens remain masked. Retain the behavior probabilities after the model updates: they describe the policy that collected the segment.
Slime performs the optimizer step and synchronizes the actor weights to its inference workers. Start the next FOCUS collection round after that synchronization, with a fixed actor snapshot for the duration of collection.
5. Evaluate with a separate function
Section titled “5. Evaluate with a separate function”For each Slime evaluation dataset, set custom_generate_function_path to train_slime.evaluate. That hook runs one unbranched solution through the collector’s agent and returns its outcome reward, 0 or 1 here, rather than a signed advantage. It uses the same 256-token segments and 4,096-token horizon.
The evaluation sample uses the last recorded generation’s input and output tokens. It does not rebuild a chat conversation from the segments: that could insert turn markers or remove thinking, breaking alignment with the recorded log probabilities.
6. Publish the critic for the next collection round
Section titled “6. Publish the critic for the next collection round”collector_for begins with Critic.constant(0.5). To use a learned critic, return make_collector(policy, problem.label, critic=critic) from it, as in the Tinker tutorial.
Each exported critic record contains a checkpoint context and its backup target . Train the value model to predict that target, rendering contexts the same way as collection. The Tinker tutorial’s critic section explains the regression objective shared by both integrations.
Slime updates the actor using these hooks. Your value-model trainer consumes the exported critic records and publishes the next critic snapshot. Keep that critic fixed during collection, then refresh it before the next round.
7. Assemble the files and launch Slime
Section titled “7. Assemble the files and launch Slime”This launch uses Qwen3-4B-Instruct-2507 on one Linux node with two 80 GB H100 GPUs. Training and generation take turns on the same GPUs. Use the Slime environment from its setup guide, with Slime at revision 18868a79b0b083a093798a94ed0f8cb4f71b9c14 and Megatron-LM at /root/Megatron-LM.
Run the commands below in Bash inside that environment. They use /root/slime for Slime, /root/FOCUS for your FOCUS checkout, and the persistent /data mount for inputs and outputs. Save these files in /data/focus-hooks/. Open them in your editor to follow the examples and adjust the configuration:
- math_quickstart.py: environment, parser, and exact-prefix policy.
- math_training.py: the search and the collector for one problem.
- train_slime.py: the generate and evaluation hooks.
- prepare_math.py: data selection and JSONL output.
- slime_runtime.yaml: the worker environment.
- launch_slime.sh: the complete training command.
Install dependencies and download the model
Section titled “Install dependencies and download the model”Install the tutorial dependencies and download the model:
Prepare a small training set
Section titled “Prepare a small training set”The supplied prepare_math.py lives beside math_quickstart.py. It selects 64 problems from the MATH algebra training split and saves their original problem and solution fields as JSONL.
The selection has two checks: the answer verifier must be able to parse the reference answer, and the prompt must fit within 4,096 tokens. With the 8,192-token context configured below, that leaves 4,096 tokens for the generated solution. Use the served model’s tokenizer and the same system instruction as MathEnv’s agent:
Problem selection and JSONL writing
The script’s main() loads the tokenizer and dataset, then calls write_dataset(). It accepts the model and output paths as command-line arguments:
Command-line entry point
Run it from the same Bash session:
The script prints the number of saved problems and their file path. If it cannot find enough usable problems, it reports an error before writing the file.
Convert the model weights
Section titled “Convert the model weights”Convert the Hugging Face weights once into Slime’s distributed training checkpoint. The model configuration supplies Qwen’s layer dimensions and rotary-position settings:
Launch three training rounds
Section titled “Launch three training rounds”Open slime_runtime.yaml in /data/focus-hooks/. Ray reads this file to give the driver and rollout workers the Python import paths, critic-output directory, and CUDA setting they need:
Use absolute paths in this file. If you chose different directories above, update them here too; YAML does not expand the shell variables. Ray accepts this file through --runtime-env.
Review launch_slime.sh before running it. It contains the full Megatron and SGLang configuration, including the four FOCUS hooks. Edit its options for your experiment; the supplied settings use two H100 GPUs and three training rounds.
Complete training command: launch_slime.sh
Start Ray on this dedicated node, then run the script from the same Bash session so the exported model and data paths remain available:
Each round collects four problem trees and makes one optimizer update. --global-batch-size 4 counts the four rollout identities; all segments from each tree share that identity. Tensor parallelism splits the model across two GPUs, leaving one data-parallel replica. Dynamic batching packs the variable number of segments into training microbatches. --colocate enables Slime’s offload/onload cycle so the learner and inference engine share those GPUs.
The four custom-function options connect the hooks from steps 1 and 4. --n-samples-per-prompt 1 lets FOCUS control continuations within each tree. FOCUS takes its sampling settings from the agent and any per-phase override; the callback’s sampling_params argument does not override them.
Segments(CHUNK_TOKENS) in the shared make_agent() caps each request at 256 tokens. Change CHUNK_TOKENS to choose another limit. The execution service validates each response against the effective request settings; the token-segment parser extracts the tokens and finish reason. The custom advantage hook supplies FOCUS’s prepared values, overriding the estimator selected by Slime’s argument parser.
The harness formats the prompt, so the command leaves --apply-chat-template unset. It also leaves advantage normalization, per-token batch normalization, auxiliary KL loss, and dynamic reward filtering disabled to preserve the prepared actor weights.
After the command returns, learner checkpoints are in $FOCUS_RUN/checkpoints and critic records are in the directory set by FOCUS_CRITIC_OUTPUT in slime_runtime.yaml. Stop the Ray instance started above when you finish:
For another experiment, choose a new FOCUS_RUN directory and update FOCUS_CRITIC_OUTPUT in slime_runtime.yaml to match. To resume a saved training run, edit launch_slime.sh to add --load "$FOCUS_RUN/checkpoints" and raise --num-rollout to the desired total number of rounds.
The launch follows Slime’s Qwen recipe and customization interfaces. The hook contracts and launch arguments have been checked against that revision; the two-GPU training run has not been executed here.
Keep a distributed round consistent
Section titled “Keep a distributed round consistent”Slime owns the learner checkpoint and inference-worker lifecycle. Use its training checkpoint configuration to save and restore model and optimizer state. Resume from a completed round, publish those weights to the inference workers, and begin the next FOCUS collection round with the matching critic. Store exported critic files with that round’s identifier.
A FOCUS rollout checkpoint holds one agent’s context, environment, workspace, and remaining allowance. The BrowseComp-Plus walkthrough shows how to fork an in-memory compaction checkpoint. Persisting a training job requires storage for those states as well. The job must also track pending prompts, the tree scheduler, and accepted training batches. Save that information at the job level so a restart does not apply the same training batch twice.
Let Slime own distributed execution
Section titled “Let Slime own distributed execution”Slime runs the rollout workers and routes generation through SGLang. Each worker constructs its FOCUS collector locally and calls SlimePolicy directly. FOCUS manages task state, branching, and learning signals; Slime owns worker placement, model serving, and weight synchronization.
Keep the actor and critic fixed while a tree is being collected. Finish the active collections before replacing weights on a shared inference endpoint. FOCUS records the probabilities returned with each generation; the trainer tracks which optimizer step produced the batch.
Within one worker, collectors can share ExecutionServices(pool=AdmissionPool(capacity=8)) to limit simultaneous generation and critic requests. In collector_for, pass Execution(services=services) to the agent and build the collector with own=False. Close the shared services after all collections finish. This limit applies only to that process; Slime controls capacity across workers.