tinker SDK runs on post-training after you change its import line and, if needed, its base model. The client replaces only the service calls, so your rendering, tokenization, and grading code runs unchanged, including the tinker_cookbook helpers it imports.
Requirements
- Python 3.11 or later.
- The Together Python SDK 2.41.0 or later, with the
tinkerextra. The extra installstinker0.23.1, the version the client builds on, so it replaces a newertinkeryou already have installed. - The
tinker-cookbookpackage, if your script importstinker_cookbook. TOGETHER_API_KEYexported in your shell.- A credit balance of at least $100, the minimum for creating a model resource.
Swap the import
Replace thetinker import with the Together client:
tinker.types resolves to the real Tinker types, so the prompts and Datum objects your code builds pass through unchanged.
Besides the import, the only value you might need to change is the base model. Tinker and Together host different catalogs, so pick an ID from Supported models.
When the script calls create_lora_training_client, the client provisions a model resource for the base model, waits until it’s ready, and opens a low-rank adapter (LoRA) session on it. The wait takes a few minutes for a small model, and longer when GPU capacity is scarce. The client waits up to an hour, then raises TimeoutError and stops the queued resource. To wait longer, create the resource with ModelResourcesClient.create(..., timeout=None) and train on it as an existing resource. Billing starts when the resource is ready. See Pricing.
Run the example scripts
The post-training cookbook ships three Tinker scripts indemos/tinker-migration/, each adapted from a tinker_cookbook recipe and already switched to the Together client. They import it the same way as the one-line swap above:
grpo_gsm8k.py: A minimal GRPO loop on GSM8K.grpo_gsm8k_async.py: The same loop, sampling each batch while the previous one trains.sft_no_robots.py: Supervised fine-tuning on No Robots.
The demos build their training data in Tinker’s format, with
tinker_cookbook helpers or by hand. When you write a loop on the cookbook or on the SDK directly, build samples with the cookbook’s build_cross_entropy_sample or build_policy_sample instead. Both take per-token rows and shift them to the target positions for you. See Data and samples.How Tinker calls map to post-training
As in Tinker, every call also has an
_async variant, except create_training_client_from_state and create_training_client_from_state_with_optimizer.
Behavior differences
Each of these differences affects how your results compare with a Tinker run, and some need a change to your script:- Sampling clients aren’t snapshots: Together samples from the most recently published weights. After a later
save_weights_and_get_sampling_clientcall, an earlier sampling client raisesRuntimeErrorinstead of serving the old policy. Create a new sampling client after each publish, or passallow_stale=Trueto keep a client that samples whatever weights are live. - Fractional weights apply to cross-entropy only: The policy-gradient loss functions accept only
0and1inweights. The client warns when it sees fractional values, and the server then fails the operation. To include or exclude tokens, usemask. forward_backwardreturns no per-datum outputs by default: Itsloss_fn_outputslist is empty unless you passreturn_loss_fn_outputs=True, an argument Tinker doesn’t accept. Scripts that read log-probabilities from it, such as thetinker_cookbookrecipesl_loop.py, need that argument or a separateforwardcall. The total loss is inmetrics["loss:sum"].- Stop sequences must be strings: Together’s sampler takes stop strings, so the client drops stop sequences given as token IDs and warns. Generation still stops at the model’s end-of-sequence token.
- Module selection is fixed:
train_mlpandtrain_attncan’t be turned off, so the client warns on non-default values and ignores them.seedandtrain_unembedpass through to the session’s LoRA config. - Checkpoint names are server-assigned: Training and inference checkpoints get a generated ID, whatever
nameyou pass. The client warns on thettl_seconds,overwrite, andretry_configarguments and ignores them. - Custom loss functions train only weighted positions:
forward_backward_customapplies your gradients only at positions whoseweightsare nonzero. A datum with noweightsgets all zeros, so it trains nothing. Passweightsof1on every position your loss reads. forwardreturns zeros at unweighted positions: Positions whoseweightsare0come back as0.0inloss_fn_outputs, not as their log-probabilities. To read every position, passweightsof1everywhere.- Text input only:
model_inputmust contain only encoded text chunks. Image chunks raiseValueError. - Loss inputs must be one-dimensional: A two-dimensional
loss_fn_inputstensor raisesValueError, so loss functions that need several target tokens per position, such as top-K distillation, aren’t supported. droneeds abeta: Passloss_fn_config={"beta": ...}. The loss function has no default.- LoRA rank and alpha: The maximum rank is 64 on Qwen models and 32 on every other model. The client never sends
lora_alpha, so every session uses Together’s default of64, whatever rank you pass. - Sampling arguments:
topk_prompt_logprobsabove20raisesValueError. - Checkpoints aren’t served by path: There’s no
tinker://path to pass to an OpenAI-compatible endpoint. To call a trained model, deploy its inference checkpoint first. See Deploy a checkpoint. - The project comes from your API key:
ServiceClientacceptsproject_idanduser_metadataand ignores them. Every call runs in the project that yourTOGETHER_API_KEYbelongs to. - Transport options are ignored:
ServiceClientaccepts Tinker’s HTTP options and ignores them. It warns onhttp_client,max_retries, andtimeout. Any other unknown argument raisesTypeError. - Some calls aren’t available:
create_rest_clientraisesTinkerErrorfrom thetinkerpackage, and passingweights_access_tokenraisesNotImplementedError. To catch the error, import it withfrom tinker import TinkerError, becausetogether.post_training.tinkerdoesn’t re-export it. The client doesn’t definecreate_sampling_client,get_tokenizer,get_info,get_base_model,get_telemetry,load_state,load_state_with_optimizer, orget_server_capabilities, so calls to them raiseAttributeError. Sampling clients don’t defineget_tokenizerorget_base_modeleither.ServiceClientalso has nocloseand isn’t a context manager, so close the training client instead, as in Clean up GPUs. To get a tokenizer, calltinker_cookbook.tokenizer_utils.get_tokenizer(base_model), as the example scripts do. To sample from a saved checkpoint instead ofcreate_sampling_client, see Sample a saved checkpoint.
Replace RestClient calls
create_rest_client isn’t available, so call the Together SDK for the run and checkpoint lookups that Tinker’s RestClient handles:
client is a together.Together client.
Clean up GPUs
Tinker’s training client has no teardown call, so the Together client registers its own cleanup, which stops the session and the model resource the client provisioned. The cleanup runs when the script exits normally, raises an uncaught exception, is interrupted withCtrl+C, or receives SIGTERM. Only SIGKILL and os._exit skip it, which leaves the resource billing until it stops on its own after an hour idle.
In a long-lived process such as a notebook, call training_client.close() to release the GPUs as soon as training ends, or use the training client as a context manager:
Train on an existing resource
To attach to a model resource that’s already running, pass its ID toServiceClient:
create_lora_training_client. The client opens its session on that resource. On exit, it stops the session but leaves the resource running.
model_resources_id is a Together-only argument, so a script that passes it no longer runs unchanged on Tinker.
Troubleshooting
- Creating the training client fails because the base model isn’t supported: The model ID isn’t in the post-training catalog. Pick one from Supported models.
- Sampling raises
RuntimeErrorabout a stale sampling client: The script reused a sampling client after publishing newer weights. Create a new one after eachsave_weights_and_get_sampling_clientcall, or passallow_stale=True. - Reward stays at zero: If the script’s renderer has thinking turned on, completions can use up
max_tokenson reasoning and never reach the answer. Raisemax_tokens, or use a renderer with thinking turned off. ServiceClientraisesTypeError: The script passes an argument the Together client doesn’t accept. Remove it.
Next steps
Concepts
How work splits between your code and Together AI GPUs, and the model resources, sessions, and checkpoints behind the Tinker calls.
Supported models
Pick a base model by training mode, context length, and GPU type.
Monitoring
Watch sessions and resources in the console.
Manage checkpoints
Download the weights or resume a run from a checkpoint.