中文 | English
- 此项目旨在从0开始,仅用1.3块钱成本 + 1小时!即可训练出67M参数的超小多模态视觉语言模型MiniMind-V。
-
MiniMind-V最小版本体积仅为 GPT3 的约
$\frac{1}{2600}$ ,力求做到个人GPU也可快速推理甚至训练。 - MiniMind-V是MiniMind纯语言模型的视觉能力额外拓展。
- 项目同时包含了VLM大模型的极简结构、数据集清洗、预训练(Pretrain)、监督微调(SFT)等全过程代码。
- 这不仅是一个开源VLM模型的最小实现,也是入门视觉语言模型的简明教程。
- 希望此项目能为所有人提供一个抛砖引玉的示例,一起感受创造的乐趣!推动更广泛AI社区的进步!
为防止误解,“1小时” 基于NVIDIA 3090硬件设备(单卡)测试
1 epoch,“1.3块钱” 指GPU服务器租用成本。
“用乐高拼出一架飞机,远比坐在头等舱里飞行更让人兴奋!” 构建VLM范式的多模态大模型是否真的如想象中那样复杂?它的代码实现到底如何? 训练过程究竟难不难?那么现在,探索它们的答案,一起感受创造的乐趣吧!
Tip
(截至2026-02-15)MiniMind-V 系列已完成了以下型号模型训练,最小仅需67M (0.067B),即可具备识图和对话的能力!
| 模型 (大小) | 推理占用 | release |
|---|---|---|
| minimind-3v-moe (201M-A67M) | 1.0 GB | 2026.04.01 |
| minimind-3v (67M) | 0.5 GB | 2026.04.01 |
| MiniMind2-V (104M) | 1.1 GB | 2025.02.20 |
| MiniMind2-Small-V (26M) | 0.6 GB | 2025.02.20 |
| minimind-v-v1-small (27M) | 0.6 GB | 2024.10.04 |
| minimind-v-v1 (109M) | 1.1 GB | 2024.10.04 |
2026-04-01
- 新增 minimind-3v (67M) 和 minimind-3v-moe (201M-A67M) 模型
- 统一使用768+8架构,支持dense和moe两种模式
- 视觉编码器从CLIP切换为SigLIP2(siglip2-base-p16-ve)
- 投影模块从QFormer改为MLP Projection + reshape压缩
- 数据集格式更新为parquet,混合数据源、更新tokenizer,图像占位符改为
<|image_pad|>、新增WebUI:支持动态扫描模型目录、下拉菜单切换模型 - 模型代码重构,LLM/VLM统一适配Transformers格式
- 训练脚本支持DDP多卡、bfloat16混合精度、torch.compile加速
2025-10-24
- bug修复:模型权重不对应
- 适配「minimind-1024更新」
- 代码重构:训练和评估脚本规范化
- 新增完整的断点续训支持
2025-04-27
- 兼容性更新
- 适配「minimind仓库新特性」
- 规范化部分代码
More...
2025-02-20
- MiniMind2-V伴随MiniMind2同步更新
- 大幅减少所有冗余代码,规范代码格式
- 大幅精简模型冗余结构
- 更新数据集格式,拓展新的SFT数据集
- 比前代VLM更优秀的效果!
2024-10-05
- MiniMind-V如期而至,首次开源
分享本人的软硬件配置(仅供参考)
- CPU: Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz
- RAM: 128 GB
- GPU: NVIDIA GeForce RTX 3090(24GB) * 8
- Ubuntu==20.04
- CUDA==12.2
- Python==3.10.16
- requirements.txt
# 克隆代码仓库
git clone --depth 1 https://github.com/jingyaogong/minimind-v# 下载siglip2模型到 ./model 目录下
git clone https://huggingface.co/jingyaogong/siglip2-base-p16-ve
# 或
git clone https://modelscope.cn/models/gongjy/siglip2-base-p16-ve# 下载minimind语言模型权重到 ./out 目录下(作为训练VLM的基座语言模型)
# HuggingFace
https://huggingface.co/jingyaogong/minimind-3v-pytorch/blob/main/llm_768.pth
# 国内源
https://modelscope.cn/models/gongjy/minimind-3v-pytorch/resolve/master/llm_768.pthpip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simplegit clone https://huggingface.co/jingyaogong/minimind-3v# load_from='model': 加载原生PyTorch权重, load_from='其他路径': 加载transformers格式
python eval_vlm.py --load_from model --weight sft_vlm
# 或使用transformers格式模型
python eval_vlm.py --load_from minimind-3v# ⚠️ 须先将 transformers 格式模型文件夹复制到 ./scripts/ 目录下(例如:cp -r minimind-3v ./scripts/minimind-3v),web_demo_vlm 脚本会自动扫描该目录下包含权重文件的子文件夹,如不存在则报错
cd scripts && python web_demo_vlm.pypip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple注:提前测试Torch是否可用cuda
import torch
print(torch.cuda.is_available())如果不可用,请自行去torch_stable 下载whl文件安装。参考链接
从下文提供的数据集链接
下载所需内容并放到./dataset下。
注:数据集须知
【注1】之前需解压50万零碎的图像文件可能非常慢。2025-12-27起,数据集格式统一为Parquet,图文一体化存储,体积更小,无需解压,加载更快。
【注2】Parquet是列式存储格式,支持高效压缩和快速读取。如果你对它感到陌生,可以预览数据内容,在dataset/目录下执行python lm_dataset.py可视化前5条图文对
Pretrain数据:
wget https://hf-mirror.com/datasets/jingyaogong/minimind-v_dataset/resolve/main/pretrain_i2t.parquetSFT数据:
wget https://hf-mirror.com/datasets/jingyaogong/minimind-v_dataset/resolve/main/sft_i2t.parquet建议预留~2GB空间存放数据集,若无多余空间存放pretrain数据,可尝试跳过pretrain训练步骤直接进行sft训练。
3.1 预训练(学图像描述)
# 基础训练命令(从LLM权重开始,仅训练vision_proj)
python train_pretrain_vlm.py --epochs 4 --from_weight llm执行预训练,得到
pretrain_vlm_*.pth作为预训练的输出权重(其中*为模型的dimension,默认为768)
3.2 监督微调(学看图对话方式)
# 基础训练命令(从预训练权重开始,全参数微调)
python train_sft_vlm.py --epochs 2 --from_weight pretrain_vlm执行监督微调,得到
sft_vlm_*.pth作为指令微调的输出权重
注:训练须知
训练特性:
- 支持断点续训:添加
--from_resume 1参数可从上次中断处继续训练 - 支持GPU数量变化:续训时GPU数量改变会自动转换step
- 原子性保存:使用临时文件+替换机制,防止保存过程中断导致权重损坏
- 每次保存同时生成
out/**.pth(模型权重)和checkpoints/**_resume.pth(训练状态)文件
# 训练中断后,使用相同命令并添加 --from_resume 1
python train_sft_vlm.py --epochs 4 --from_resume 1参数说明:
--from_weight: 基础权重名称(llm, pretrain_vlm, none等)--save_weight: 保存权重的前缀名--from_resume: 是否续训(0=从头开始,1=从检查点继续)--freeze_llm: 是否冻结LLM参数(仅pretrain使用)- 更多可直接参考代码
确保需要测试的模型*.pth文件位于./out/目录下。
也可以直接去此处下载使用我训练的*.pth文件。
# 测试SFT模型(默认)
python eval_vlm.py --weight sft_vlm
# 测试Pretrain模型
python eval_vlm.py --weight pretrain_vlmTip
训练脚本均为Pytorch原生框架,均支持多卡加速,假设你的设备有N (N>1) 张显卡:
单机N卡启动训练方式 (DDP, 支持多机多卡集群)
torchrun --nproc_per_node N train_xxx.py注:其它须知
deepspeed --master_port 29500 --num_gpus=N train_xxx.py可根据需要开启wandb记录训练过程
# 需要登录: wandb login
torchrun --nproc_per_node N train_xxx.py --use_wandb
# and
python train_xxx.py --use_wandb通过添加--use_wandb参数,可以记录训练过程,训练完成后,可以在wandb网站上查看训练过程。通过修改wandb_project
和wandb_run_name参数,可以指定项目名称和运行名称。
【注】:25年6月后,国内网络环境无法直连WandB,MiniMind项目默认转为使用SwanLab作为训练可视化工具(完全兼容WandB API),即import wandb改为import swanlab as wandb即可,其他均无需改动。
MiniMind-V (VLM)的基座语言模型MiniMind (LLM)来自孪生项目minimind, 具体的模型结构、训练细节、原理、测试效果等均可移步minimind项目查阅。 此处为减少冗余,省略讨论LLM的相关部分,默认您已对MiniMind (LLM)的细节有基本的了解。
即使您不太了解LLM的细节,也可参考“快速开始”流程训练一个MiniMind-V, 这并不受到影响,仓库致力于最低成本的开箱即用!
MiniMind-V的结构仅增加Visual Encoder和特征投影两个子模块,增加模态混合分支,以支持多种模态信息的输入:

【重要】一些有趣的思考
此处不妨展开想一想两个问题:
- 什么叫做Large Language Model (LLM)?
- 什么叫做多模态模型?
这篇文章完美吻合本人的想法: 大语言模型(LLM)名字虽然带有语言二字,但它们其实与语言关系不大,这只是历史问题,更确切的名字应该是自回归 Transformer 或者其他。LLM 更多是一种统计建模的通用技术,它们主要通过自回归 Transformer 来模拟 token 流,而这些 token 可以代表文本、图片、音频、动作选择、甚至是分子等任何东西。 因此,只要能将问题转化为模拟一系列离散 token 的流程,理论上都可以应用 LLM 来解决。 实际上,随着大型语言模型技术栈的日益成熟,我们可能会看到越来越多的问题被纳入这种建模范式。也就是说,问题固定在使用 LLM 进行『下一个 token 的预测』,只是每个领域中 token 的用途和含义有所不同。
ZJU-LiXi老师同样谈及过类似观点(原话大意如下):
文本、视频、语音、动作等在人类看来属于「多模态」信号,但所谓的「模态」其实只是人类在信息存储方式上的一种分类概念。
就像.txt和.png文件,虽然在视觉呈现和高级表现形式上有所不同,但它们本质上并没有根本区别。
之所以出现「多模态」这个概念,仅仅是因为人类在不同的感知层面上对这些信号的分类需求。
然而,对于机器来说,无论信号来自何种「模态」,最终它们都只是以一串二进制的「单模态」数字序列来呈现。
机器并不会区分这些信号的模态来源,而只是处理和分析这些序列背后所承载的信息内容。
个人认为Generative Pretrained Transformer (GPT) 比 Large Language Model (LLM)更为贴切, 因此本人表达上更习惯用"GPT"去代表LLM/VLM/类GPT架构的系列模型,而非为了蹭OpenAI的热度。
至此,我们可以用一句话总结GPT的所作所为:
GPT模型根据现有token预测输出下一个下下一个下下下一个token ...,直到模型输出结束符;此处的"token"其实并不需要一定是文本!
> 对于LLM模型,如果需要理解"图片",我们只要把"图片"作为对一种特殊的从来没见过的"外国语言",通过"外语词典"翻译后即可作为特殊的语言输入LLM
> 对于LLM模型,如果需要理解"音频",我们只要把"音频"作为对一种特殊的从来没见过的"外国语言",通过"外语词典"翻译后即可作为特殊的语言输入LLM
> ...
为了得到MiniMind-V,我们只需要完成这2件事即可:
- 借助擅长翻译图片的 "外语词典" ,把图片从 "外国语言" 翻译为模型便于理解的 "LLM语言"
- 训练微调LLM,使其和 "外语词典" 度过磨合期,从而更好的理解图片
"外语词典" 称之为Visual Encoder模型。 和LlaVA、Qwen-VL等视觉语言模型类似,MiniMind-V当前选用开源SigLIP2系列模型作为Visual Encoder。 具体使用siglip2-base-p16-ve, 一种基于 ViT-B/16 架构的Visual Encoder用于描述图像文本信息。 当前使用的 SigLIP2 NaFlex 视觉编码器会根据预处理结果生成最多256个patch token作为encoder编码层的输入, 最终产生1×768维的嵌入向量用于和文本对计算误差。 我们并不需要最终嵌入表示,因此只取encoder层的输出,也就是VIT核心主干的输出特征即可。 它拿到前一层256×768大小的特征,通过reshape将每4个相邻token拼接为1个(256×768 → 64×3072),再经过2层MLP(Linear→GELU→Linear)投影到LLM的隐藏维度,最终作为64个visual token输入MiniMind-V。 与LLM的结合在获取图像encoder特征后,一方面需要把视觉特征对齐到LLM的文本token维度, 另一方面,要将图像特征映射到与文本embedding相同的空间,即文本token和原生的视觉token需要磨合并不能直接地一视同仁, 可以称之为跨模态的特征对齐。
LlaVA-1使用简单的线性变换完成对齐,LlaVA-1.5升级为2层MLP,MiniMind-V采用与LlaVA-1.5相同的MLP Projection方案,并结合reshape进行token压缩。
MiniMind-V的主要结构已介绍完毕。
下面,我们简单讨论MiniMind-V的外部输入输出的变化。
VLM的输入依然是一段文本,其中包含特殊的<image>占位符。
在计算文本嵌入后,可以将图像编码器生成的向量投影到该占位符对应的嵌入部分,替换掉原先的占位符embedding。
例如:
<image>\n这个图像中有什么内容?
在minimind-v中,使用64个<|image_pad|>组成的占位符代替图像(SigLIP2输出的256个patch特征经reshape+MLP压缩为64个token),因此minimind-v的prompt为:
<|image_pad|><|image_pad|>...<|image_pad|>(×64)\n这个图片描述的是什么内容?
计算完embedding和projection,用视觉特征替换掉对应占位符的embedding后,整个计算过程到输出则和LLM部分没有差异。
至此,MiniMind-V的所有细节呈现完毕,VLM模型子类继承自MiniMind,仅做最小变更而产生,核心算法改动< 50行,迁移难度极低,和LlaVA等模型具体实现存在区别,但思路一致。
原始来源:
- Chinese-LLaVA-Vision:包含约57万张预训练图像,来自CC-3M和COCO 2014
- llava-en-zh-300k:包含300k条指令微调数据和15万张图像
- LLaVA-SFT-665K:包含665k条指令微调数据
其中部分为中文数据,部分为英文数据。问答内容经过翻译,对中文支持更友好,进一步经过整理并resize(pretrain分辨率128×128,sft分辨率160×160)。
(pretrain_i2t.parquet) 预训练数据集格式:
列名: conversations (json string), image_bytes (binary), image_names (string)
conversations 示例:
[
{"role": "user", "content": "提供给定图像的简要描述。\n<image>"},
{"role": "assistant", "content": "橄榄油是自由使用的健康成分。"}
]
image_bytes: <图像二进制数据>
(sft_i2t.parquet) 单图指令微调数据集格式:
列名: conversations (json string), image_bytes (binary), image_names (string)
conversations 示例:
[
{"role": "user", "content": "闹钟的位置对睡眠质量有什么影响?<image>"},
{"role": "assistant", "content": "把数字闹钟放在床头柜..."}
]
image_bytes: <图像二进制数据>
注:sft_i2t.parquet 共约 58 万条数据,其中约 23.6 万条为含图对话(i2t),约 34.6 万条为纯文本对话(t2t),后者用于保持模型的基础语言能力。
数据集下载地址:(ModelScope | HuggingFace)
训练分为两个阶段,均冻结Visual Encoder梯度,仅训练Projection和LLM部分。 训练基于LLM预训练权重初始化,支持DDP多卡训练、混合精度(bfloat16)、torch.compile加速和swanlab日志记录。
train_pretrain_vlm
预训练阶段从约113万条图文描述数据中学习图片的通用知识(如鹿是鹿,狗是狗)。 此阶段采用较高学习率(1e-4),最大序列长度360,冻结LLM主体参数,仅设置Projection和LLM的第0层可学习, 目的是让模型快速建立视觉特征到语言空间的基础映射,同时避免破坏LLM已有的语言能力。
train_sft_vlm
指令微调阶段从约58万条数据中学习真实问答格式,其中约23.6万条为图文多轮对话,约34.6万条为纯文本对话(用于保持LLM基础能力)。 此阶段采用较低学习率(1e-5~1e-6),最大序列长度768,解冻Projection和LLM全部参数进行全量微调, 使模型学会根据图片内容进行多轮对话,并通过混入的纯文本数据缓解灾难性遗忘。
训练时间和Loss走势(仅供参考)
Pretrain [768+8] (dense & moe)

| 模型格式 | ModelScope | HuggingFace |
|---|---|---|
原生PyTorch (*.pth) |
minimind-3v-pytorch | minimind-3v-pytorch |
| Transformers 格式 | minimind-v collection | minimind-v collection |
注:Transformers版本均为单图指令微调后的
MiniMind-V模型
两个模型均能识别图像主体(飞机、蛋糕、汽车、海滩等),但普遍存在重复表述和幻觉细节。受限于模型和数据规模,整体处于"能看懂大意、细节不准"的阶段。
视觉信号对于LLM视作一种特殊的外语,因此"学习外语"的能力高低,很大程度上取决于LLM的能力。LLM性能越强,对应的VLM越强,此时效果增益会很明显。
> 可引入动态分辨率和Tile-based编码(如LLaVA-NeXT),突破固定分辨率限制。
> Visual Encoder可升级为更强的视觉编码器,获取更细粒度的图像特征。
> 拓展多图理解、视频理解和视觉定位(Visual Grounding)能力。
> ...
Tip
如果您觉得 MiniMind-V对您有所帮助,可以在 GitHub 上加一个⭐
水平有限难免存在未知的纰漏,欢迎所有人在Issues交流指正或提交PR改进项目
您的支持就是持续改进项目的动力,谢谢!
🤝贡献者
@xinyanghuang7: 多图vlm分支 | 仓库截至此版本提供
参考链接 & 感谢以下优秀的论文或项目
- 排名不分任何先后顺序
- LlaVA
- LlaVA-VL
- Chinese-LLaVA-Vision-Instructions
如果您觉得 MiniMind-V 对您的研究或工作有所帮助,请引用:
@misc{minimind-v,
title = {MiniMind-V: Train a Tiny VLM from Scratch},
author = {Jingyao Gong},
year = {2024},
url = {https://github.com/jingyaogong/minimind-v},
note = {GitHub repository, accessed 2026}
}本仓库遵循 Apache-2.0 License 开源协议。














