Skip to main content
Continue from the quickstart with a chat dataset: prepare batches, train a LoRA adapter, save resumable state, and sample from the trained checkpoint. This example uses the same GLM-5.3-Flash model and explicitly selects serverless Loops, so it bills for tokens and fails if serverless can’t accept the run. The example dataset is pirate-ultrachat-10k, chat-format conversations that teach the model pirate dialect. The Jobs quickstart uses the same dataset. Use the Python project and BASETEN_API_KEY from the quickstart. For a model or configuration that needs dedicated capacity, see Dedicated Loops.

Turn a dataset into training data

Each training example becomes a Datum: input tokens plus loss targets that mask the prompt and supervise the answer, with the same label shift the quickstart uses. For chat data, render the conversation with the tokenizer’s chat template and treat the final assistant message as the answer. Install the dataset library in your project:
Save the following code as train_dataset.py:
train_dataset.py
The script reads 64 conversations and skips ones without a final assistant answer or whose tokenized input exceeds the sequence limit. Keep this small slice for a first run; choose training data and a held-out evaluation before scaling up.

Run the training loop

Each iteration is the quickstart’s round trip over a batch: one forward_backward() on a list of Datum, one optim_step(). Append:
train_dataset.py

Save a resumable checkpoint

As in the quickstart, save both types of checkpoint: save_state() preserves training and optimizer state, while save_weights_for_sampler() publishes the adapter for sampling and deployment. Append:
train_dataset.py
To resume later, provision a training client and call load_state_with_optimizer() with the saved state.path.

Sample from the checkpoint

Create a sampling client from the returned sampler checkpoint, then generate a completion without creating an inference deployment. The serverless client stays pinned to that checkpoint; publish again and create a new client to sample later weights. Append:
train_dataset.py
Run the complete script:
Check that it finishes without an error and prints the run ID, number of prepared examples, loss for each batch, both returned checkpoint paths, and a completion. Trainer state paths use weights/; sampler paths use sampler_weights/. Keep the returned paths rather than constructing them, because checkpoint names can include a unique suffix. A completion checks that sampling works. A small training slice doesn’t establish a change in dialect, and batch losses need not fall at every step. To measure whether training helped, compare the checkpoint with the base model on a held-out evaluation.

Shut down the run

Closing the SDK clients releases local connections and stops the training client’s keepalive. An idle serverless run incurs no token charges. To end the run and its paired sampler explicitly, use the printed run ID. With the Baseten CLI installed, end the run:
  1. Deactivate the run, and confirm when prompted:
  2. Check that the run’s status.name is INACTIVE:
Saved checkpoints remain available. See Deactivate a run for the REST API option.

Next steps

  • Deploy a checkpoint: Serve the returned sampler checkpoint as an inference endpoint.
  • Hyperparameters: Apply a learning-rate schedule to this training loop.
  • Loss functions: Swap cross_entropy for importance_sampling, ppo, and other objectives when you move past SFT.