Install the SDK
Install the Together Python SDK, version 3.0.0 or later:Run a minimal loop
This loop trains a low-rank adapter (LoRA) for Qwen3.8 27B on one sample for one step, then saves the adapter as an inference checkpoint. The model resource it creates bills per GPU-minute from when it’s ready until the loop exits:Train on a batch
This loop trains on eight of yoursamples per step, for NUM_STEPS steps. You pass the learning rate on every optim_step, so it can follow a schedule, such as this loop’s linear decay:
result.loss is a sum over the batch’s trained tokens, not a mean. Divide it by the number of trained tokens for a per-token loss that stays comparable as the batch’s token count changes.
To train with group relative policy optimization (GRPO), build GRPO samples and pass a policy-gradient loss. GrpoLossParams sets the clip band and the beta weight of a Kullback-Leibler (KL) penalty:
Sample from the generator
Pass all your prompts tosample_batch in one call, and set num_samples to request a group of completions for each prompt. In this example, prompts holds each prompt’s token IDs:
tokens and logprobs.
Sampling can run at the same time as other sampling and trainer operations, but a synchronous weights_sync waits for in-flight sampling to finish.
One SamplingParams applies to every prompt in a sample_batch call. The API reference lists its fields and defaults. Two fields need care:
stop: For models without stop-string support, omitstopand truncate completions in your code. A request with an unsupported stop string fails as invalid input.seed: Leave it unset. It’s unsupported and causes an internal error when the generator uses multiple inference engines.
Compute log-probabilities for fixed text
Callsession.generator.compute_logprobs(prompt) for one prompt, or compute_logprobs_batch(prompts) for several. If the trainer has stepped since the last sync, call weights_sync first, so the log-probabilities come from the updated weights. Entry 0 of the result is a 0 placeholder, because the first token has no preceding context. sample with prompt_logprobs=True returns the same placeholder.
Session operations
Every operation targets a session. Calls onsession.trainer run on the model resource’s trainer. Calls on session.generator run on its generator replicas, which exist only on a resource created with num_generator_replicas above 0.
The API reference lists every operation’s fields and defaults.
weights_sync takes a weight_sync_type, which defaults to WEIGHT_SYNC_TYPE_SYNCHRONOUS and also accepts the deferred modes used for async training.
Each call submits an operation, then waits until the operation finishes or the call’s timeout runs out. When an operation fails on the resource, the SDK raises an operation error.
Call operations asynchronously
Every call has an_async variant, such as forward_backward_async, sample_batch_async, or ModelResourcesClient.create_async. Use the _async variants in async code. The synchronous calls block the calling thread, so they raise RuntimeError when called from code that’s already running an event loop, such as an async application.
Jupyter notebooks are the exception: a synchronous call works in a notebook cell but blocks the cell until it returns. The _async variants work in notebooks too.
The _async variants also let independent work overlap. For example, one session can sample while another trains, or you can train several adapters at once.
Next steps
For complete loops, see the cookbook’s notebooks and direct preference optimization (DPO) loop, which build samples with the cookbook’s helpers.SFT notebook
Supervised fine-tuning (SFT) on the No Robots dataset, step by step.
GRPO notebook
GRPO on GSM8K math problems, step by step.
DPO training loop
DPO on chosen and rejected pairs, built on a custom loss function.
Samples and loss masks
Line up a sample’s arrays and mask a chat prompt.
Custom loss functions
Train toward an objective you compute in PyTorch, such as DPO.
Model resources
Choose GPUs, attach to a running resource, and stop it.