Mind Lab Toolkit (MinT)
CustomizeConcepts

Rendering

Rendering 把一组 message 转换成 model 能消费的 token 序列。它和 HuggingFace 的 chat template 类似,但 MinT 的 renderer 覆盖完整训练生命周期:监督学习、强化学习和部署。Renderer 处于两层之间 —— 上层是结构化的对话数据,底层是 model 实际看到的 token。

Concept

Renderer 在两类数据之间转换:结构化的 message 字典(带 user / assistant / system 等 role)和扁平的 token 序列。SFT 阶段用 build_supervised_example() 把 prompt token(不计入 loss)和 completion token(model 学习的部分)分开。RL 和采样阶段用 build_generation_prompt() 构造 prompt,再用 parse_response() 把 model 采样出来的 token 解码回 message。

Renderer 是按 model 家族区分的:Qwen3、Llama 3、DeepSeek V3 等各自有自己的特殊 token 和格式约定。MinT 自带主要家族的 renderer,每一个都会返回正确的 chat template:

Messages(list of dict)--> Renderer --> Token IDs(list of int)
                                         + loss masks(用于 SFT)
                                         + stop tokens(用于采样)

Pattern

下面是渲染一段对话的标准写法:

import mint
from mint import types

# 初始化 renderer 和 tokenizer
service_client = mint.ServiceClient()
training_client = service_client.create_lora_training_client(
    base_model="Qwen/Qwen3-0.6B",
    rank=16,
)
tokenizer = training_client.get_tokenizer()
renderer = mint.renderers.get_renderer("qwen3", tokenizer)

# 构造对话
messages = [
    {"role": "system", "content": "简洁回答;每条回复最多一句话"},
    {"role": "user", "content": "最长寿的啮齿动物是什么?"},
    {"role": "assistant", "content": "裸鼹鼠,可以活超过 30 年。"},
    {"role": "user", "content": "它们为什么活得这么长?"},
    {
        "role": "assistant",
        "content": "它们进化出了多种保护机制,包括能抑制癌症的特殊透明质酸、稳定性极高的蛋白质,以及高效的 DNA 修复系统。",
    },
]

# SFT:得到 token 和 loss weights
model_input, weights = renderer.build_supervised_example(messages)

# 采样:构造一个让 model 续写的 prompt
prompt = renderer.build_generation_prompt(messages[:-1])  # 不包括最后一条 assistant 消息
stop_sequences = renderer.get_stop_sequences()  # 采样何时停止

# 把采样到的 token 解码回 message
sampled_tokens = [45, 7741, 34651, 31410]  # 实际场景里是 model.sample 的输出
message, success = renderer.parse_response(sampled_tokens)

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

API Surface

方法用途返回
build_supervised_example(messages, train_on_what)把 message 转成 SFT 用的 token + loss weights(ModelInput, weights_array)
build_generation_prompt(messages)把 message 转成 model 续写用的 promptModelInput
get_stop_sequences()表示生成结束的 tokenlist[int | str]
parse_response(tokens)把采样到的 token 还原成 message(dict, bool),bool 是成功标志

Renderer 列表(用 get_renderer(name, tokenizer) 取)

  • "qwen3" — Qwen3(默认启用 thinking)
  • "qwen3_disable_thinking" — Qwen3(关闭 thinking)
  • "llama3" — Llama 3
  • "deepseekv3" — DeepSeek V3(non-thinking)
  • "deepseekv3_thinking" — DeepSeek V3(thinking 模式)
  • "nemotron3" — NVIDIA Nemotron 3
  • "kimi_k2" — Kimi K2

Vision renderer(用于 Qwen3-VL 这类 VLM):

from mint.image_processing_utils import get_image_processor

image_processor = get_image_processor("Qwen/Qwen3-VL-235B-A22B-Instruct")
renderer = mint.renderers.get_renderer("qwen3_vl_instruct", tokenizer, image_processor=image_processor)

Caveats & Pitfalls

  • Renderer 选错家族:调 get_renderer() 时务必传对应 model 家族的名字。把 llama3 renderer 用在 Qwen3 的 token 上,会拼出错误的特殊 token。
  • Vision 编码:VL model 同时需要 tokenizer image processor。缺 image processor 会让视觉输入的 shape 对不上。
  • Loss 掩码build_supervised_example() 默认只在最后一条 assistant 消息上算 loss。要在所有 assistant 回合上训练,传 train_on_what=TrainOnWhat.ALL_ASSISTANT_MESSAGES
  • Stop tokenget_stop_sequences() 返回的 token ID 是 model 家族特定的。采样时务必传给 SamplingParams(stop=...)
  • 自定义格式:清单里没有的 model 家族,训练前用 register_renderer() 注册自己的 renderer。不注册的话会悄悄用错特殊 token,不报错也不正确。

本页目录