Skip to main content
Every cookbook on this site links back to these building blocks instead of a repository file. Copy what you need — none of it depends on a provider SDK, only the standard library.

Datum helpers

A “datum” is one Whitney training example: right-shifted input/target tokens plus whatever loss-specific tensors your loss_function needs. The completion’s last token only ever appears as a target, never as an input, so input and target_tokens are one token shorter than prompt_tokens + completion_tokens.
See JSON primitives for the wire shape these produce.

Advantage helpers

Building a forward payload

The build_loss contract

Most RL loops in the cookbooks are a single callable plugged into the same loop skeleton below:
  • sample — the raw sampler result: {"sequences": [{"tokens", "logprobs", "stop_reason"}, ...], ...}.
  • cycle — the zero-based cycle index.
  • request — your original sample request object, needed for request["prompt"]["token_ids"] (the sampler result alone carries no prompt tokens).
  • ctx — a context object bundling a live client, run_id, sampler_id, and provider, so your callable can issue further ordered operations before returning its payload — e.g. an extra logprobs call for a reference-policy KL term, or another sample call for dynamic resampling. ctx.client.sampler_operation(ctx.run_id, ctx.sampler_id, kind, payload) is the same method the loop itself uses for sample. Any such call still advances the run’s ordered seq_id — it is a real, billed Whitney operation, not a side channel.
Check ctx.provider against the provider loss support table before using a provider-specific loss name.

Ordered RL loop skeleton

On failure or interruption: cancel the run, poll until terminal, then close the session. See SFT for the equivalent single-pass loop without sampling, and Distillation for the two-run variant where a frozen teacher run answers logprobs instead of training.

Provider loss support

GET /v1/training/capabilities does not return a loss-function list — it cannot, because Whitney forwards loss_function straight through to the provider. The table below is a caller-side hint that saves a wasted allocation, not a live capability; call require_advertised_loss before you build a payload with a provider-specific loss name. Scalar loss_config keys Modal actually validates, per loss (an empty row means that loss accepts no loss_config keys at all): On Tinker Cloud, the equivalent clip range is set per-token on the datum itself (rl_datum(..., clip_low=, clip_high=)), not through loss_config.

Requiring an advertised loss