Chapter 08

多模态:Qwen2-VL / InternVL / MiniCPM-V

📌 commit b58b1bdms-swift 在多模态上比 LLaMA-Factory 强

ms-swift 多模态支持是它的招牌:覆盖 50+ VLM / 音频模型,且数据格式统一。本章把多模态训练流程过一遍。

8.1支持的多模态模型

类别模型
视觉 LLM (VLM) Qwen2-VL / Qwen2.5-VL, InternVL2 / InternVL3, MiniCPM-V-2.5/2.6, LLaVA-1.5/1.6/NeXT, Llama-3.2-Vision, Pixtral, Gemma3-vision, Idefics2/3, DeepSeek-VL2, GLM4V, Yi-VL, Phi-3-vision
音频 LLM Qwen2-Audio, Llama3.1-Whisper, MiniCPM-Audio
OCR / 文档 Qwen2-VL OCR mode, GOT-OCR2
多模态 R1 Qwen2.5-VL + GRPO(推理增强)

8.2统一数据格式

所有 VLM 训练都用 messages + 引用图片/音频文件:

{"messages": [
  {"role": "user", "content": "<image>描述这张图"},
  {"role": "assistant", "content": "图中有一只猫..."}
 ],
 "images": ["./imgs/cat.jpg"]
}

{"messages": [
  {"role": "user", "content": "<audio>这段话说了什么?"},
  {"role": "assistant", "content": "..."}
 ],
 "audios": ["./audios/clip.wav"]
}

<image> 占位符的数量必须等于 images 列表长度。ms-swift 自动按模型 template 替换成正确的 image token。

8.3典型 SFT:Qwen2-VL-7B + LoRA

swift sft \
    --model Qwen/Qwen2-VL-7B-Instruct \
    --dataset AI-ModelScope/llava-instruct-mix-vsft \
    --train_type lora \
    --num_train_epochs 1 \
    --per_device_train_batch_size 1 --gradient_accumulation_steps 16 \
    --learning_rate 1e-4 \
    --max_length 4096 \
    --torch_dtype bfloat16 \
    --target_modules all-linear \
    --freeze_vit true \                   # ★ 冻结 ViT 节省显存
    --freeze_aligner true                 # ★ 冻结对齐 MLP(可选)

关键开关:

字段作用
--freeze_vit冻结视觉 encoder(推荐 true,省 30% 显存)
--freeze_llm冻结 LLM 部分(罕见)
--freeze_aligner冻结 vision-LLM 对齐 MLP
--vit_lr给 ViT 单独 lr(默认 = lr)
--aligner_lr给 aligner 单独 lr

8.4多图 / 视频

多图:

{"messages": [{"role":"user","content":"<image><image>这两张图区别?"}, ...],
 "images": ["./a.jpg", "./b.jpg"]}

视频(自动抽帧):

{"messages": [{"role":"user","content":"<video>视频里发生了什么"}, ...],
 "videos": ["./clip.mp4"]}

视频抽帧由模型 template 内部处理,通常 8-32 帧。可以传 --video_max_pixels 控制分辨率。

8.5多模态 GRPO(R1 风格视觉推理)

swift rlhf \
    --rlhf_type grpo \
    --model Qwen/Qwen2.5-VL-7B-Instruct \
    --dataset AI-ModelScope/clevr_cogen_a_train \
    --train_type lora \
    --num_generations 8 \
    --max_completion_length 1024 \
    --reward_funcs accuracy format \
    --use_vllm true \
    --vllm_gpu_memory_utilization 0.3 \
    --beta 0.04

这是 2025 年很火的"视觉 R1"配方:让 VLM 学会 <think>...</think><answer>...</answer> 推理。

8.6显存预算

Qwen2-VL-7B、LoRA、freeze_vit=True、单卡:

序列长度显存
2K + 1 张图~18 GB
4K + 4 张图~26 GB
8K + 8 张图~38 GB
视频 16 帧 + 2K text~32 GB

8.7常见踩坑

现象处理
图片找不到jsonl 里写绝对路径;或设 --media_dir
OOM--freeze_vit true;降图片分辨率 --max_pixels 1024*1024
训完只会输出文字、不"看"图检查 vision token 是否生效;用 swift infer --stream true 看注意力
视频抽帧慢用 decord / pyav 后端;预处理时持久化抽帧结果

8.8VLM 60+ 族实际覆盖

v4 之后 ms-swift 支持的 VLM 族在 swift/model/constant.pyMLLMModelType 类下。按"图像 / 视频 / 音频 / 全模态"分类:

类别代表模型
图像 VLM Qwen2-VL / Qwen2.5-VL / Qwen3-VL / InternVL3 / InternVL3.5 / GLM4.5-V / MiniCPM-V-4 / Ovis2.5 / LLaVA-Next / LLaVA-OneVision / DeepSeek-VL2 / DeepSeek-OCR / Llama4-VL / Gemma3-VL / MiniMax-M2-VL / mPLUG-OWL3 / CogVLM2
视频 VLM Qwen2.5-VL(原生视频)/ MiniCPM-V(多帧)/ InternVL3(视频)
音频 LLM Qwen-Audio / Qwen2-Audio / MiniCPM-o / Qwen3-Omni
全模态(Omni)Qwen2.5-Omni / Qwen3-Omni / MiniCPM-o
OCR 专用 DeepSeek-OCR / KeyeOCR / HunyuanOCR
Reranker VLM Qwen3-VL-Reranker

8.9Template 多模态 token 占位

VLM 训练用的 template 跟纯 LLM 不同,会处理 <image> / <video> / <audio> 三种占位符。看 swift/template/templates/vl/ 目录组织:

文件注册的 template关键能力
qwen_vl.py qwen_vl / qwen2_vl / qwen3_vl 视觉 token 嵌入;视频抽帧后多 <image>
internvl.py internvl3 / internvl3_5 image patch 切分(动态分辨率)
minicpm_v.py minicpmv 系列 多 patch 视觉编码
llava.py llava-next / llava-onevision 多图 + 视频统一
deepseek_vl2.py deepseek_vl2 / deepseek_ocr OCR 专用 special token
qwen_omni.py qwen2_5_omni / qwen3_omni image + audio + video 一体
cogvlm.py cogvlm2 双向视觉

8.10视觉 token 数控制(--max_pixels 实际怎么算)

训练 VLM 时显存最敏感的字段是 --max_pixels。Qwen2-VL 系列规则(来自 template/vision_utils.py):

8.11多模态 packing(2025 新)

2025-06 之后 ms-swift 引入多模态 packing,README 声称训练吞吐 +100%。原理:

启用:swift sft --packing true --use_flash_attn true。新人首次跑 VLM 强烈建议开。

8.12Grounding(bbox / 关键点)

VLM 训练除了"看图说话"还可以训"指物"。swift/template/grounding.py(3.1 KB)支持把 bounding box 归一到 [0, 1000] 或原始像素坐标。数据 schema 示例:

{
  "messages": [
    {"role": "user", "content": "<image>找到图中的红色汽车"},
    {"role": "assistant", "content": "<ref>红色汽车</ref><box>(123,456),(789,012)</box>"}
  ],
  "images": ["/path/img.jpg"]
}

训完模型能输出含 <box> 标签的位置;推理时 swift 自动解析回像素坐标。

8.13这章你需要带走的