Mind Lab Toolkit (MinT)
CustomizeSFT

SFT Hyperparameters

这个 recipe 会在 MinT 上跑真实的 supervised fine-tuning sweep。它用同一个小的 arithmetic chat 数据集训练多组超参数,然后比较最终 training loss。

关键点:这个 recipe 不再手写 Datum。它使用 recipe.supervised.conversation_to_datum() 和高层的 recipe.supervised.train.main(config) 训练循环。

Use Case

  • Instruction tuning:训练 model 按任务指令工作。
  • Domain adaptation:在领域内 Q&A 或 chat 样本上微调。
  • 小规模 grid search:在大训练前先比较 learning rate 和 LoRA rank。
  • Recipe debugging:确认 MinT API key、renderer、tokenizer、SFT 训练循环可以一起跑通。

Sweep 什么

默认情况下,recipes/sft_hyperparameters.py 会跑:

learning_rate:  [1e-5, 5e-5]
lora_rank:      [8, 16]
max_steps:      每组配置 2 step
configs:        2 x 2 = 4

可以用环境变量覆盖:

MINT_SFT_STEPS=1 \
MINT_SFT_LRS=1e-5,5e-5 \
MINT_LORA_RANKS=8,16 \
python recipes/sft_hyperparameters.py

核心模式

recipe 先创建一个内存里的 supervised dataset:

class ArithmeticSFTDataset(recipe.supervised.types.SupervisedDataset):
    def __init__(self, conversations, model_name, renderer_name, batch_size, max_length):
        tokenizer = get_tokenizer(model_name)
        renderer = recipe.renderers.get_renderer(renderer_name, tokenizer)
        self.datums = [
            recipe.supervised.conversation_to_datum(
                conversation,
                renderer,
                max_length=max_length,
            )
            for conversation in conversations
        ]
        self.batch_size = batch_size

    def __len__(self):
        return max(1, (len(self.datums) + self.batch_size - 1) // self.batch_size)

    def get_batch(self, index):
        start = (index * self.batch_size) % len(self.datums)
        return self.datums[start : start + self.batch_size]

然后每个 grid item 调用标准 SFT trainer:

config = recipe.supervised.train.Config(
    log_path="/tmp/mint-sft-sweep-lr1e-5-rank8",
    model_name="Qwen/Qwen3-0.6B",
    renderer_name="qwen3",
    dataset_builder=ArithmeticSFTDatasetBuilder(...),
    learning_rate=1e-5,
    lora_rank=8,
    max_steps=2,
    save_every=999,
    eval_every=999,
    infrequent_eval_every=999,
    ttl_seconds=3600,
)

await recipe.supervised.train.main(config=config)

完整源码:https://github.com/MindLab-Research/mint-quickstart/blob/main/recipes/sft_hyperparameters.py

运行

export MINT_API_KEY=sk-your-api-key
python recipes/sft_hyperparameters.py

输出最后会有类似这样的表:

=== Grid Search Summary ===
LR           Rank     Steps    Final train NLL    Log path
------------------------------------------------------------------------------------------
1e-05        8        2        10.4975            /tmp/mint-sft-sweep-...-1em05-rank8
1e-05        16       2        10.4919            /tmp/mint-sft-sweep-...-1em05-rank16
5e-05        8        2        10.1574            /tmp/mint-sft-sweep-...-5em05-rank8
5e-05        16       2        9.4928             /tmp/mint-sft-sweep-...-5em05-rank16

Verified Run

已在 MinT 上验证:Qwen/Qwen3-0.6B,8 条生成的 arithmetic conversations,每组配置 2 steps:

Learning rateLoRA rankStepsFinal train NLL
1e-58210.4975
1e-516210.4919
5e-58210.1574
5e-51629.4928

这些数字来自很小的 smoke dataset。它们用于验证 API 和代码形状,不代表模型质量。真正调参时,请使用你的真实数据集、更多训练 steps,并比较 validation metrics。

为什么这个形状有效

chat messages


conversation_to_datum()
    │  应用 renderer + assistant-token loss mask

SupervisedDataset.get_batch()


recipe.supervised.train.main(config)
    │  创建 LoRA TrainingClient,执行 forward/backward + optimizer steps

metrics.jsonl + final checkpoint

这样 tokenization 和 loss masking 会和 MinT 使用的 renderer 对齐。它也使用了更大的 supervised recipes 使用的同一个高层训练循环,所以这个 sweep 验证的是用户会复制的真实路径。

本页目录