Mind Lab Toolkit (MinT)
Use MinT

SFT (Supervised Fine-Tuning)

SFT (supervised fine-tuning) applies to labeled prompt → response data. On MinT it runs the standard training loop with loss_fn='cross_entropy', and the training target is a LoRA low-rank adapter.

Building a Datum

Prompt tokens get a loss weight of 0 and do not contribute to the gradient; completion tokens get a weight of 1.0. The whole thing goes through a teacher-forcing shift: input is all_tokens[:-1], target is all_tokens[1:], and weights are all_weights[1:].

def process_sft_example(prompt_text, completion_text, tokenizer):
    prompt_ids     = tokenizer.encode(prompt_text, add_special_tokens=True)
    completion_ids = tokenizer.encode(f" {completion_text}", add_special_tokens=False)
    completion_ids.append(tokenizer.eos_token_id)

    all_tokens  = prompt_ids + completion_ids
    all_weights = [0.0] * len(prompt_ids) + [1.0] * len(completion_ids)

    return types.Datum(
        model_input=types.ModelInput.from_ints(tokens=all_tokens[:-1]),
        loss_fn_inputs={
            "target_tokens": all_tokens[1:],
            "weights":       all_weights[1:],
        },
    )

For chat-style data, we recommend using apply_chat_template(..., add_generation_prompt=True) for the prompt part.

mint.recipe provides a Renderer that automatically handles the chat template, loss masking, and the teacher-forcing shift:

from mint import recipe

renderer = recipe.renderers.get_renderer(
    recipe.get_recommended_renderer_name("Qwen/Qwen3-0.6B"), tokenizer
)
messages = [
    {"role": "user",      "content": "..."},
    {"role": "assistant", "content": "..."},
]
model_input, weights = renderer.build_supervised_example(messages)
datum = recipe.datum_from_model_input_weights(model_input, weights, max_length=2048)

For multi-turn conversations, by default loss is computed only on the last assistant message; to compute it on every assistant message, pass train_on_what=TrainOnWhat.ALL_ASSISTANT_MESSAGES.

Parameters

ParameterTypeDefaultMeaning
base_modelstr"Qwen/Qwen3-0.6B"Base model ID
rankint16LoRA rank; higher means more expressive but more memory, typically 8–64
train_mlpboolTrueTrain the MLP layers
train_attnboolTrueTrain the attention layers
train_unembedboolTrueTrain the unembedding (output) layer
loss_fnstr"cross_entropy"SFT always uses cross_entropy; no other option
learning_ratefloat5e-5Adam learning rate; instruction tuning is typically 1e-5 to 1e-4
weight_decayfloat0.0L2 regularization; LoRA is typically 0.0–0.01

Tinker compatibility notes

  • Do not call zero_grad_async(); the MinT server zeroes gradients automatically.
  • loss_fn goes to forward_backward(...), not to AdamParams.
  • save_weights_for_sampler(...) and save_weights_and_get_sampling_client(...) are equivalent for serializing LoRA weights.

Which algorithm to choose

SFT fits "labeled prompt → response." For preference-pair data, see DPO; for scenarios with reward / verifier / environment feedback, see RL (GRPO); for the two-stage pipeline, see the SFT + RL combined Recipe.

On this page