Use the Loops Python SDK to create a LoRA training run, save a checkpoint, and list that checkpoint from Python and HTTP. The base model throughout isDocumentation Index
Fetch the complete documentation index at: https://docs.baseten.co/llms.txt
Use this file to discover all available pages before exploring further.
Qwen/Qwen3.5-2B, one of the supported base models.
Prerequisites
- Baseten account: Sign up for Baseten if you don’t have one.
- Baseten workspace with Loops enabled: Loops is in early access. Fill out the signup form to request access for your workspace.
-
API key with org access to Loops: Generate a workspace API key and export it:
-
Python 3.13+ and uv: The quickstart uses
uvto install the Loops client and run the training script.
Install
The main client package isbaseten-loops on PyPI. The Tinker compatibility shim ships as the [tinker] extra (distributed as baseten-loops-tinker) and re-exports the public API under the tinker namespace, so existing import tinker scripts run unchanged.
uv add writes the dependency into a project’s pyproject.toml, so create a project first if you don’t already have one:
loops-quickstart project, install baseten-loops, and make the tinker namespace available.
Verify the install:
Provision a trainer
A Loops session pairs a trainer server (forward, backward, and optimizer steps) with a sampling server (generates from current weights). Constructing aServiceClient and calling create_lora_training_client provisions both in one shot and returns a TrainingClient you can drive directly. The call blocks until the trainer is ready, which can take several minutes for a fresh base model.
Start train_loops.py with the provision step:
Run a training round trip
The smallest complete round trip is one forward pass, one backward pass, one optimizer step, and one weight save. The block below mirrors the canonical SFT example: it tokenizes a prompt-and-answer pair, masks the prompt positions from the loss, runs the round trip, and saves a named checkpoint. Append totrain_loops.py:
forward_backward is the first training operation you submit after provisioning. Because create_lora_training_client waits for trainer readiness, this call starts after the trainer can accept work. save_state publishes the trainer-side weights under the name you pass and returns a bt://loops:<run_id>/weights/<name> URI. The paired sampler picks up the new weights asynchronously through the weight-sync runtime.
List checkpoints
Everysave_state call creates a checkpoint. The TrainingClient is already bound to your trainer, so listing is one line. Append to train_loops.py:
run_id your script printed when provisioning:
id and checkpoint name:
id value as the checkpoint_id argument: training_client.get_checkpoint_archive_url(checkpoint_id). From a separate Python session where training_client isn’t in scope, construct tinker.ServiceClient() and call service_client.get_checkpoint_archive_url(checkpoint_id) instead.
Skip the cold start on re-runs
Your first run provisioned a trainer and sampler. The second run doesn’t have to. Grab thesession_id your script printed (session_id=7qrp4v3 in the example output above), point the next run at it, and Loops reuses the same trainer and sampler:
reuse_from_session_id in the body of POST /v1/loops/runs or POST /v1/loops/samplers.
Reuse is best-effort. If the prior trainer is stopped, failed, or unhealthy, Loops provisions a fresh one and your script still runs.
Next steps
To turn any of these checkpoints into an inference endpoint, runtruss loops checkpoints deploy --run-id <run_id> and pick a checkpoint interactively, or pass --checkpoint-ids to deploy specific ones. See the checkpoints deploy CLI reference for the full option set.
Read Loops concepts to understand the paired-process model before you build longer training workflows: how sessions own trainer and sampling servers, how weight sync works, and how checkpoints land as unzipped folders of paginated presigned URLs rather than single archives.
If you’re migrating from Tinker, the Tinker compatibility page documents what carries over exactly (forward, backward, optim step, sampling, data types) and what behaves differently (checkpoint layout, authentication, cluster routing). The import tinker path used here already covers most cookbook recipes; that page names the three places where behavior has changed.
When you’re ready to call the HTTP API directly (for scripting deployments, fetching checkpoint files programmatically, or integrating Loops into a CI pipeline), the Loops API overview covers each route’s path, request body, response shape, and authentication scope in one place.
To generate from a checkpoint instead of publishing it only, swap save_state for save_weights_and_get_sampling_client, which publishes weights and returns a SamplingClient pinned to the new version.