ms-swift多模态数据准备:自定义数据集格式说明
2026/5/6 12:06:18 网站建设 项目流程

ms-swift多模态数据准备:自定义数据集格式说明

在使用 ms-swift 进行多模态大模型微调时,数据是起点,更是成败的关键。你可能已经成功下载了 Qwen3-VL 或 InternVL3.5 这样的先进模型,也配置好了 A100 或 H100 环境,但一旦运行训练命令却报出KeyError: 'image'ValueError: unsupported modality,问题往往不出在模型或硬件,而在于——你的数据集没有按 ms-swift 的“语言”说话。

这不是文档缺失导致的困惑,而是框架对多模态数据结构有明确、统一且可扩展的约定。它不强制你用某种数据库或云存储,也不要求你重写整个预处理流水线;它只要求你用一种清晰、稳定、机器可解析的方式描述:“这张图要配哪段文字”、“这段语音对应哪个答案”、“这个框选区域想表达什么”。

本文将完全聚焦于“如何组织自己的多模态数据”这一具体动作,不讲原理推导,不堆砌参数列表,只提供可立即验证、可直接复用、经生产环境反复打磨的数据格式规范。你会看到:

  • 为什么 JSONL 是 ms-swift 多模态数据的事实标准;
  • 图像、视频、音频、文本、坐标框等不同模态字段该怎么命名、怎么填值;
  • 如何支持单模态输入、双模态组合、甚至四模态混合(图文+语音+视频);
  • 怎样让同一个数据集既可用于 SFT,也能无缝切到 DPO 或 GRPO 训练;
  • 常见陷阱与绕过方案:路径错误、编码异常、字段缺失、尺寸越界等真实问题。

读完后,你将能独立构建一个符合 ms-swift 要求的本地多模态数据集,并用一行命令启动训练。


1. 核心原则:字段驱动,路径为本,结构即协议

ms-swift 对自定义数据集的设计哲学非常务实:它不解析原始二进制数据,只解析数据描述。换句话说,框架从不直接打开一张 JPG 或 WAV 文件,而是读取你提供的 JSONL 行中关于该文件的“元信息”,再由内部加载器按需拉取、解码、归一化。

因此,所有数据准备工作的核心,就是写出一份字段语义准确、路径指向可靠、结构层次合理的文本描述。

1.1 为什么首选 JSONL(每行一个 JSON)

  • 流式加载:训练时无需一次性载入全部数据到内存,适合百万级样本;
  • 容错性强:某一行 JSON 格式错误,仅跳过该样本,不影响整体训练;
  • 字段灵活:每行可包含不同模态组合(如第1行只有 image+text,第2行含 image+audio+boxes),框架自动适配;
  • 工具链成熟:可用jq、Pythonjsonlines、Pandasread_json(..., lines=True)快速校验与清洗;
  • 不推荐:JSON(单个大对象)、CSV(无法自然表达嵌套结构如 conversations)、Parquet(虽支持但调试成本高,初学者易卡在 schema 定义)。

1.2 字段命名不是随意的:必须与 ms-swift 内置解析器对齐

ms-swift 在swift.dataset模块中预定义了一组标准字段名。当你在数据中使用这些字段时,框架会自动触发对应模态的加载逻辑。命名错误 = 模态被忽略 = 训练退化为纯文本任务

以下是必须掌握的 7 个核心字段(区分大小写,不可缩写):

字段名类型说明示例值
imagestrlist[str]单张图像路径(相对或绝对),支持本地路径、HTTP URL、ModelScope 资源 ID"data/images/cat.jpg""https://example.com/dog.png"
videostr视频文件路径(MP4/AVI/WebM),框架自动抽帧并采样关键帧"data/videos/meeting.mp4"
audiostr音频文件路径(WAV/MP3/FLAC),支持单声道/立体声,自动重采样至 16kHz"data/audio/question.wav"
textstr主干文本输入,用于指令微调或作为上下文锚点"请描述这张图片的内容。"
conversationslist[dict]多轮对话结构,每轮含role("user"/"assistant")和content(支持<img>等模态标记)[{"role":"user","content":"<img>这是什么动物?"},{"role":"assistant","content":"这是一只橘猫。"}]
boxeslist[list[float]]归一化边界框坐标[x1, y1, x2, y2](0~1 范围),用于 grounding 任务[[0.2, 0.3, 0.8, 0.7]]
labelslist[str]分类标签或细粒度描述,常与boxes配合使用["cat", "furry"]

重要提示conversations是唯一支持内联模态标记的字段。你在content中写的<img><audio>不是字符串,而是 ms-swift 的“模态占位符”,会被自动替换为对应图像/音频的 embedding 序列。而imageaudio等顶层字段,仅用于单模态任务或作为conversations的补充元信息。

1.3 路径规则:本地优先,绝对可靠

  • 所有路径(image/video/audio)默认以数据集文件所在目录为根
    例如你的数据文件是./my_mm_data.jsonl,其中一行写"image": "imgs/pic1.jpg",则框架会尝试加载./imgs/pic1.jpg
  • 支持file://协议前缀(显式声明本地路径):"image": "file:///home/user/data/pic.jpg"
  • 支持 HTTP/HTTPS:"image": "https://cdn.example.com/photo.jpg"(需网络可达,首次加载稍慢);
  • 不支持:相对路径跨目录回溯(如"../other/img.jpg")、Windows 驱动器盘符裸写("C:\data\img.jpg")、未转义空格("my pic.jpg"→ 应写为"my%20pic.jpg""my pic.jpg"并确保文件系统支持)。

2. 四种典型数据组织方式:从简单到复杂

你不需要一开始就设计最复杂的格式。ms-swift 允许你从最简结构起步,随着任务演进逐步增强。以下四种模式覆盖 95% 的实际场景。

2.1 单图 + 单文本:VQA / Captioning 基础版

适用于图像问答、图像描述生成等任务。结构最轻量,调试最快。

{ "image": "images/beach.jpg", "text": "这张图片展示了什么场景?" }

或更贴近对话形式(推荐,兼容性更好):

{ "image": "images/beach.jpg", "conversations": [ {"role": "user", "content": "这张图片展示了什么场景?"}, {"role": "assistant", "content": "一片阳光明媚的海滩,有蓝色海水、白色沙滩和几把彩色遮阳伞。"} ] }

优势:字段少,易生成,swift sft命令开箱即用
注意:若只用text字段而无conversations,则不会触发多模态对齐,模型仅将图像路径当作文本字符串处理

2.2 多图 + 多轮对话:图文交互式 Agent

适用于需要连续理解多张图像并进行多步推理的场景,如电商导购、医疗报告分析。

{ "image": ["images/xray1.jpg", "images/xray2.jpg"], "conversations": [ {"role": "user", "content": "<img><img>请对比这两张X光片,指出差异。"}, {"role": "assistant", "content": "第一张显示左肺下叶有模糊阴影,第二张该区域密度增高,提示炎症进展。"} ] }

关键点

  • image字段支持list[str],框架会依次加载并拼接 embedding;
  • <img>标记数量必须与image列表长度一致(两个<img>→ 两张图);
  • 可混用:"content": "<img>这是什么?<img>另一张呢?",实现精准位置绑定。

2.3 图文 + 音频 + 坐标框:细粒度指代定位(Grounding)

适用于需要模型精确定位并描述图像中特定区域的任务,如工业质检、教育辅导。

{ "image": "images/circuit.jpg", "audio": "audios/instruction.wav", "boxes": [[0.15, 0.22, 0.45, 0.68], [0.62, 0.10, 0.92, 0.40]], "labels": ["defective capacitor", "normal resistor"], "conversations": [ {"role": "user", "content": "<img><audio>请检查红色框内的元件状态。"}, {"role": "assistant", "content": "红色框内是一个失效的电容,顶部已鼓包;绿色框内电阻外观正常。"} ] }

🔧技术细节

  • boxes中每个子列表必须是 4 个浮点数,顺序为[x_min, y_min, x_max, y_max],值域0.0 ~ 1.0
  • boxeslabels长度不等,框架会截断或填充"",但强烈建议严格一一对应;
  • <audio>标记会触发 Whisper 编码器,输出与图像 patch 同维度的序列,参与跨模态注意力。

2.4 四模态混合:视频 + 图像 + 文本 + 语音(高级研究场景)

面向前沿探索,如多传感器自动驾驶日志分析、沉浸式教育内容生成。

{ "video": "videos/driving.mp4", "image": "images/dashboard.jpg", "audio": "audios/voice_command.wav", "text": "当前车速60km/h,前方30米有施工区域,请减速并变道。", "conversations": [ {"role": "user", "content": "<video><img><audio>根据画面、仪表盘截图和语音指令,生成安全操作建议。"}, {"role": "assistant", "content": "请立即松开油门,轻踩刹车将车速降至40km/h以下,并观察左侧车道确认安全后平稳变道。"} ] }

注意事项

  • videoimage可共存,但video会主导视觉输入(自动抽关键帧),image作为辅助参考;
  • 所有模态标记<video><img><audio>必须在conversations.content中显式声明,否则不会参与建模;
  • 此类样本训练显存占用显著增加,建议搭配--max_length 4096和梯度累积。

3. 数据集构建实操指南:三步完成验证

理论终需落地。下面以一个真实可运行的案例,带你走完从零创建到命令行验证的全过程。

3.1 第一步:准备最小可行数据集(3 行 JSONL)

创建文件demo_mm.jsonl,内容如下(请确保images/目录下存在对应图片):

{"image": "images/cat.jpg", "conversations": [{"role": "user", "content": "<img>这是什么动物?"}, {"role": "assistant", "content": "一只橘猫。"}]} {"image": "images/dog.jpg", "conversations": [{"role": "user", "content": "<img>这只狗在做什么?"}, {"role": "assistant", "content": "它正坐在草地上吐舌头。"}]} {"image": "images/bird.jpg", "conversations": [{"role": "user", "content": "<img>这只鸟的羽毛是什么颜色?"}, {"role": "assistant", "content": "主要是蓝绿色,翅膀边缘带黑色条纹。"}]}

验证命令(检查 JSONL 格式):

# Linux/macOS jq -e '.image and .conversations' demo_mm.jsonl > /dev/null && echo " 格式正确" || echo " 有错误"

3.2 第二步:编写训练命令并启动(单卡快速验证)

使用轻量模型 Qwen2-VL-2B(约 2GB 显存占用),避免资源瓶颈:

CUDA_VISIBLE_DEVICES=0 swift sft \ --model qwen-vl-chat \ --dataset ./demo_mm.jsonl \ --train_type lora \ --lora_rank 8 \ --per_device_train_batch_size 1 \ --gradient_accumulation_steps 4 \ --learning_rate 1e-4 \ --num_train_epochs 0.1 \ --max_length 2048 \ --output_dir ./output_demo \ --logging_steps 1 \ --save_steps 10 \ --eval_steps 10 \ --torch_dtype bfloat16

关键参数说明

  • --dataset ./demo_mm.jsonl:指定本地 JSONL 路径,框架自动识别为多模态;
  • --model qwen-vl-chat:必须使用支持多模态的模型 ID(不能用纯文本模型如qwen2-7b);
  • --max_length 2048:多模态输入 token 更长,需适当增大上限;
  • --logging_steps 1:设为 1 便于第一时间观察是否成功加载图像。

成功标志:日志中出现类似
Loading image from: ./images/cat.jpg
Loaded 3 samples from ./demo_mm.jsonl
Starting training...

3.3 第三步:排查常见失败原因(附解决方案)

现象可能原因快速诊断命令解决方案
FileNotFoundError: images/cat.jpg路径相对于 JSONL 文件不正确ls -l ./images/cat.jpg使用realpath检查路径,或改用绝对路径"image": "/full/path/to/cat.jpg"
KeyError: 'image'JSONL 行中缺少image字段head -n1 demo_mm.jsonl | jq '.image'确保每行都含image(即使为空数组[],但不推荐)
ValueError: invalid literal for int()boxes中含非数字字符或空字符串jq -r '.boxes[] | join(",")' demo_mm.jsonl用 Python 脚本清洗:boxes = [[float(x) for x in box] for box in boxes]
日志无Loading image提示模型未启用多模态分支swift list-models | grep -i vl确认--model参数值正确,如qwen-vl-chat而非qwen2-7b
训练 loss 不下降conversations中未使用<img>标记jq -r '.conversations[].content' demo_mm.jsonl"content": "这是什么?"改为"content": "<img>这是什么?"

4. 进阶技巧:让数据集更健壮、更高效

当你已能稳定运行基础训练,可引入以下技巧提升工程鲁棒性与实验效率。

4.1 数据分片与缓存:加速千万级数据加载

对超大数据集(>100 万样本),直接读 JSONL 仍可能成为 I/O 瓶颈。ms-swift 支持.parquet格式,其列式存储与内置压缩可提速 3~5 倍。

转换脚本(Python):

import pandas as pd import jsonlines # 读取 JSONL with jsonlines.open('large_mm.jsonl') as reader: records = [obj for obj in reader] # 转为 DataFrame(自动处理 list 字段) df = pd.DataFrame(records) # Parquet 会将 list 序列化为 string,但 ms-swift 加载器可自动反序列化 df.to_parquet('large_mm.parquet', index=False, compression='zstd')

训练时直接使用:

swift sft --dataset ./large_mm.parquet ...

优势:文件体积减小 60%,随机采样速度提升,支持 Spark/Dask 分布式预处理。

4.2 动态字段注入:同一份数据适配多种任务

你无需为 SFT、DPO、GRPO 分别准备三套数据。通过conversations结构微调,一份 JSONL 可复用:

  • SFT 格式(监督微调):

    {"conversations": [{"role":"user","content":"<img>描述一下"},{"role":"assistant","content":"一只猫。"}]}
  • DPO 格式(偏好学习):

    { "conversations": [{"role":"user","content":"<img>描述一下"}], "chosen": "一只橘猫蹲在窗台上,毛发蓬松。", "rejected": "猫。" }
  • GRPO 格式(强化学习):

    { "conversations": [{"role":"user","content":"<img>描述一下"}], "response": "一只橘猫蹲在窗台上,毛发蓬松。", "reward": 0.92 }

ms-swift 的Dataset加载器会自动检测字段存在性,并路由到对应任务处理器。你只需在命令中指定--rlhf_type dpo--rlhf_type grpo,数据逻辑完全解耦。

4.3 模态缺失容错:优雅降级策略

现实数据总有缺失。ms-swift 允许你定义 fallback 行为:

  • image字段为空或文件不存在,默认跳过该样本(--drop_invalid true,默认开启);
  • audio缺失,但conversations.content<audio>,则静音向量替代(不影响训练);
  • 最佳实践:预处理脚本中添加完整性检查:
from PIL import Image import os def validate_sample(sample): if 'image' in sample and isinstance(sample['image'], str): return os.path.exists(sample['image']) and Image.open(sample['image']).size[0] > 0 return True # 其他模态暂不强校验

5. 总结:数据即契约,格式即生产力

在 ms-swift 的多模态工作流中,数据集不是训练的“输入”,而是你与框架之间的一份隐式契约。这份契约规定了:

  • 你承诺提供哪些模态(image/video/audio);
  • 你承诺如何组织它们(conversations中的<img>顺序);
  • 你承诺字段值的语义(boxes是归一化坐标,不是像素值);
  • 框架承诺据此加载、对齐、融合,并端到端优化。

遵守这份契约,你获得的是:
一次写好,多任务复用(SFT/DPO/GRPO);
本地调试与集群训练无缝切换;
新增模态(如 3D 点云、传感器信号)只需扩展字段与加载器;
团队协作时,数据格式即文档,无需口头解释。

反之,若绕过格式规范,试图用 hack 方式“骗过”框架,最终只会陷入无限 debug 循环——因为问题不在代码,而在你与框架的沟通失效。

所以,请把本文当作一份可执行的数据协议说明书。下次准备数据时,先打开 VS Code,新建my_dataset.jsonl,对照本文的字段表与示例,逐行填写。运行swift sft,看到Loading image...的日志那一刻,你就真正掌握了 ms-swift 多模态能力的第一把钥匙。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询