TrainingClient drives the managed path against one model slug; lower-level methods
expose the gradient-accumulation and custom-loss steps underneath it. For the end-to-end loop (forking a
model, rolling out a taskset in groups, feeding rewards back) see training agents.
Training paths
Each path accumulates gradients differently, then applies them with the sameoptim_step. All operate on
a TrainingClient except the last.
Gradients accumulate across
forward_backward / forward_backward_custom / backward calls until an
optim_step (or step, which calls both) applies them, checkpoints, and promotes the new weights.
Objects
TrainingClient
ATrainingClient drives managed training for one model: it accumulates gradients from rewarded
trajectories and advances the weights behind the model’s gateway slug in place. Inputs are Runs (sent
inline) or trace_id strings (resolved server-side); the two can be mixed.
Methods
Advantages are group-relative (GRPO-style) when
group_size is set, normalized within contiguous
groups of that size; None treats the whole batch as one group. The loss_fn selects the
policy-gradient objective applied on top, defaulting to importance_sampling (not GRPO itself). The
batch must divide evenly into groups - forward_backward rejects a partial final group before spending
a forward pass. num_substeps splits the batch for gradient accumulation.
Inputs
A training input is a recorded trajectory by id, or an inline one:str | Run | TrajectoryPayload, mixed freely. A Run is converted automatically -
inline TrajectoryPayload when it carries token-level samples (local rollout), else its trace_id
(remote rollout). Build a TrajectoryPayload yourself when the tokens didn’t come from a Run at all -
e.g. an opponent move sampled inside the environment during self-play, trained with its own reward.
A sample’s prompt is
prompt_token_ids for a flat text prompt, or prompt_chunks (serialized text +
image chunks) for a multimodal one, where prompt_token_ids is empty. output_logprobs are per output
token under the sampling policy.
Token capture
The token ids and logprobs a sample needs come from the gateway.completion_kwargs carries the flag,
and it lives only on OpenAIChatConfig, so token capture runs through OpenAIChatAgent (the agent
create_agent selects for gateway models routed over Chat
Completions). Setting extra_body={"return_token_ids": True} is enough: that agent sets logprobs=True
automatically and writes a Sample onto each turn, which a Run converts to a TrajectoryPayload for
training.
logprobs for you:
Built-in losses
loss_fn is an open string validated against the model’s provider; discover the set with
await trainer.available_losses(). BuiltinLoss lists the common Tinker names (each is a str):
loss_fn_config forwards provider-specific hyperparameters to the loss (e.g. {"epsilon": 0.2} for
the ppo clip). The supported keys are provider-defined and not every loss accepts config, so prefer
the defaults (None) unless a provider documents a key.
Custom losses
forward_backward_custom runs the current-policy forward pass server-side, hands you per-token tensors,
runs your loss locally (torch autograd), and ships the per-token gradients back. Requires torch
(pip install 'hud[train]').
optim_step applies them, so a custom-loss step is not
complete until that call promotes the new weights.
logprobs[i] are the current policy for datum i as differentiable leaves. Everything else is constant
on the matching DatumTensors:
Under the hood
forward returns a ForwardResult (forward_id + data: list[DatumTensors]);
backward(forward_id, weights) applies weights[d][t] = -dC/dlogprobs.
Results
hud models CLI
For the end-to-end loop see training agents; for the
Job and Run the trainer consumes see
types, and for where rollouts run see runtimes.