[BUG] KTO with mrope models (Qwen3.5 family) crashes at step 0: "Multimodal data was passed ... but mm_token_type_ids is missing"
Author: haqishenCreated Sep 5, 2026Updated Sep 5, 2026
Reminder
- I have read the above rules and searched the existing issues.
System Info
llamafactory版本:最新main(data/collator.py/train/kto/trainer.py相关代码与当前main完全一致,已核对)- 平台:Linux x86_64
- Python:3.11
- PyTorch:2.10 / 2.11 均复现
- Transformers:5.5.0 与 5.10.1 均复现(引入
mm_token_type_ids强校验的版本起) - GPU:单卡 / 多卡(torchrun)均复现
Reproduction
对任意 mrope 架构模型(例如 Qwen3.5 系列,纯文本 checkpoint 也一样)跑 KTO,第 0 步 forward 即崩溃。SFT 和 DPO 同配置正常。
最小配置:
model_name_or_path: Qwen/Qwen3.5-0.8B
stage: kto
finetuning_type: lora
template: qwen3_5
dataset: kto_en_demo
cutoff_len: 1024
报错堆栈:
File "llamafactory/train/kto/trainer.py", line 190, in forward
logits = model(**model_inputs, return_dict=True, use_cache=False).logits.to(torch.float32)
File "transformers/models/qwen3_5/modeling_qwen3_5.py", line 1589, in forward
position_ids = self.compute_3d_position_ids(
File "transformers/models/qwen3_5/modeling_qwen3_5.py", line 1502, in compute_3d_position_ids
raise ValueError(
ValueError: Multimodal data was passed (via `image_grid_thw` or `video_grid_thw`) but `mm_token_type_ids` is missing. Please pass `mm_token_type_ids` to the model so that multimodal RoPE (M-RoPE) can be computed correctly. `mm_token_type_ids` is returned by the processor alongside `input_ids`.
根因分析
三个环节叠加:
MultiModalDataCollatorForSeq2Seq.__call__对纯文本 batch 注入 dummy image(zero3/FSDP 防挂死的 workaround),因此image_grid_thw在每个 batch 里都存在。collator 同时通过get_rope_index预计算了position_ids/rope_deltas并放进 features。CustomKTOTrainer.forward()用显式白名单构造model_inputs:转发了image_grid_thw,但不转发 collator 已算好的position_ids/rope_deltas(kl_前缀侧更是从未从 kl batch 里带出这两个 key ——KTODataCollatorWithPadding只拷贝kl_input_ids/kl_attention_mask/kl_labels等)。- transformers 的
modeling_qwen3_5.forward看到position_ids=None且image_grid_thw非 None,走compute_3d_position_ids自行重算——该路径要求mm_token_type_ids,而没有任何一方提供 → raise。
SFT 不受影响(标准 Trainer 全量透传 collator 输出,position_ids 到达 forward);DPO 不受影响(concatenated_forward 用 model(**batch))。只有 KTO 的白名单丢 key。
修复建议
两处都需要(只补 trainer 一侧时 kl_ forward 仍崩,已实测):
KTODataCollatorWithPadding.__call__:把 kl batch 的position_ids/rope_deltas以kl_position_ids/kl_rope_deltas带出。- KTO trainer
forward():白名单增加{prefix}position_ids/{prefix}rope_deltas的透传。position_ids一旦到达 forward,模型完全跳过 3D 位置重算路径,mm_token_type_ids不再被需要。仅在 key 存在时转发,非 mrope 模型零影响。
已在 Qwen/Qwen3.5-0.8B LoRA KTO(单卡、真实偏好数据)上验证:修复前第 0 步崩溃,修复后完整训练收敛。PR 随后提交。
Source: hiyouga/LlamaFactory