llama.cpp 多模态实战:MiniCPM-V 2.6 的模型转换、量化与推理全流程
MiniCPM-V 2.6 是 openbmb 推出的轻量级视觉语言模型,llama.cpp 通过其多模态子项目(libmtmd + llama-mtmd-cli)完整支持了该模型的本地推理。本文以仓库中 docs/multimodal/minicpmv2.6.md 的操作指南为主体,逐步讲清"PyTorch 权重 → GGUF → 量化 → 图像推理"的完整链路,并结合 tools/mtmd/legacy-models 下的转换脚本源码与 tools/mtmd/mtmd-cli.cpp 的实现,补充每个步骤背后的参数含义与底层原理,读完即可在自己的机器上跑通 MiniCPM-V 2.6 的看图问答。
一、整体流程:为什么要拆成"模型 + mmproj"两个文件
llama.cpp 的多模态支持被设计为一个独立子项目,其核心思想(见 tools/mtmd/README.md)是:图像先由一个独立的多模态投影器(multimodal projector,即 mmproj 文件)编码为 embedding,再喂给语言模型。这样做的目的是把各视觉模型差异很大的预处理与投影逻辑隔离在核心 libllama 之外。
因此运行 MiniCPM-V 2.6 需要准备两个 GGUF 文件:
- 语言模型文件(
ggml-model-*.gguf)——由标准convert_hf_to_gguf.py产出; - 投影器文件(
mmproj-model-f16.gguf)——由 MiniCPM-V 专用脚本产出,内部同时封装了 SigLIP 视觉编码器(ViT)与 resampler 投影器。
由于 MiniCPM-V 2.6 属于仓库所称的"旧架构"(legacy)模型,convert_hf_to_gguf.py --mmproj 通吃式转换尚不适用它,需要用 tools/mtmd/legacy-models 下的专用脚本(该目录的定位见 tools/mtmd/README.md 中的说明)。tools/mtmd/README.md 也把 docs/multimodal/minicpmv2.6.md 列为官方支持的旧模型指南之一。
整个流水线的产物关系如下:
MiniCPM-V-2_6/ ← HF 下载的 PyTorch 原始模型
├── minicpmv.projector ← 步骤1: surgery 脚本抽取 resampler 权重
├── minicpmv.clip ← 步骤1: surgery 脚本抽取 vpm(ViT) 权重
├── model/ ← 步骤1: 剥离出的纯 LLM 部分
│ └── ggml-model-f16.gguf ← 步骤3: convert_hf_to_gguf.py 产出
├── mmproj-model-f16.gguf ← 步骤2: 图像编码器转 GGUF 产出
└── ggml-model-Q4_K_M.gguf ← 步骤4: llama-quantize 产出
二、准备模型与构建 llama.cpp
2.1 下载 PyTorch 模型
从 Hugging Face 的 openbmb/MiniCPM-V-2_6 仓库下载完整 PyTorch 权重到 MiniCPM-V-2_6 文件夹(-m ../MiniCPM-V-2_6 均以此为基准路径,可按实际位置调整)。
2.2 编译 llama.cpp
克隆仓库后用 CMake 构建(原文档标注其 README 核对时间为 20250206,若用法有出入以官方构建文档为准):
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build
cmake --build build --config Release
构建产物在 build/bin/ 下,后续会用到其中两个二进制:llama-quantize(量化)与 llama-mtmd-cli(多模态推理入口)。llama-mtmd-cli 的用法横幅明确声明了必填参数与 GPU 卸载开关(见 tools/mtmd/mtmd-cli.cpp):
-m and --mmproj are required
-hf user/repo can replace both -m and --mmproj in most cases
to disable using GPU for mmproj model, add --no-mmproj-offload
也就是说:-m 与 --mmproj 缺一不可;mmproj 默认会卸载到 GPU,显存紧张时可加 --no-mmproj-offload 让视觉编码器留在 CPU。
三、模型转换四步
3.1 第一步:surgery 脚本"解剖"原始权重
python ./tools/mtmd/legacy-models/minicpmv-surgery.py -m ../MiniCPM-V-2_6
这一步是 MiniCPM-V 系列转换的特殊之处:HF 上的 MiniCPM-V 权重是"视觉编码器 + resampler + LLM 揉在一起"的单体 checkpoint,不能直接喂给 convert_hf_to_gguf.py。tools/mtmd/legacy-models/minicpmv-surgery.py 读取源码可以看到它做了三件事:
- 抽取投影器权重:筛选所有以
resampler开头的张量,存为minicpmv.projector。若模型 config 中存在scale_emb,resampler.proj会先除以scale_emb做归一(minicpmv-surgery.py 的 L19-L20),这保证了后续 GGUF 推理与 PyTorch 前向数值一致; - 抽取视觉编码器权重:筛选以
vpm开头的张量(MiniCPM-V 中 ViT 模块的前缀),去掉前缀后存为minicpmv.clip(L23-L26); - 剥离出纯 LLM:改写
model.llm.config.auto_map后把 LLM 部分与 tokenizer 保存到{模型目录}/model子目录(L33-L43),使其变成一个可被convert_hf_to_gguf.py识别的常规 LLaMA 风格模型。
脚本结尾也会打印提示:接下来可以把 model/ 转成常规 GGUF,并用 minicpmv.projector 准备 mmproj 文件。
3.2 第二步:图像编码器转 mmproj GGUF
python ./tools/mtmd/legacy-models/minicpmv-convert-image-encoder-to-gguf.py \
-m ../MiniCPM-V-2_6 \
--minicpmv-projector ../MiniCPM-V-2_6/minicpmv.projector \
--output-dir ../MiniCPM-V-2_6/ \
--minicpmv_version 3
脚本参数中值得展开的有两处:
--minicpmv-projector:指定上一步产出的minicpmv.projector路径。一旦给出该参数,脚本就把输出文件的中间名设为mmproj-,并写入clip.has_minicpmv_projector = true、clip.projector_type = "resampler"、clip.minicpmv_version三个 GGUF 元数据(见 minicpmv-convert-image-encoder-to-gguf.py 的 L663-L691)。这正是运行时libmtmd区分"这是 MiniCPM-V 的 resampler 型图像编码器"的依据;--minicpmv_version 3:版本号按模型区分——MiniCPM-V-2 用 1、MiniCPM-V-2.5 用 2、MiniCPM-V-2.6 用 3、MiniCPM-o-2.6 用 4、MiniCPM-V 4.0 用 5、MiniCPM-o-4.0 用 6(脚本 help 原文,同文件 L504)。版本 3 对应 SigLIP 视觉编码器:源码中minicpmv_version == 3时构造的是SiglipVisionTransformer(L629-L631),且当找不到config.json时的兜底参数为emb_dim=3584、27 个视觉块(L601-L603)。如果找得到config.json,脚本会优先从其中读取hidden_size、vision_config等真实配置(L570-L589),兜底值仅用于缺 config 的场景。
产物为 {模型目录}/mmproj-model-f16.gguf(默认 f16,可用 --use-f32 改为 f32)。
3.3 第三步:LLM 部分转 GGUF
python ./convert_hf_to_gguf.py ../MiniCPM-V-2_6/model
surgery 之后 model/ 已是"常规 LLM"目录,标准转换脚本 convert_hf_to_gguf.py 即可工作,产出 ../MiniCPM-V-2_6/model/ggml-model-f16.gguf。
3.4 第四步:量化出 int4 版本
# quantize int4 version
./build/bin/llama-quantize ../MiniCPM-V-2_6/model/ggml-model-f16.gguf \
../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf Q4_K_M
Q4_K_M 是 llama.cpp 常用的 4-bit k-quant 档位,体积约为 f16 的 1/4,适合显存/内存有限的主机;对精度要求高时可直接用 f16 版本推理(第四节的单轮示例用的就是 f16 模型)。
四、推理:llama-mtmd-cli 的两种运行方式
libmtmd 时代,各模型专用的 CLI(如早期的 minicpmv-cli)已被统一的 llama-mtmd-cli 取代(演进过程见 tools/mtmd/README.md 的时间线部分)。MiniCPM-V 2.6 的推理命令如下。
4.1 单轮问答模式(Linux / Mac)
./build/bin/llama-mtmd-cli \
-m ../MiniCPM-V-2_6/model/ggml-model-f16.gguf \
--mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf \
-c 4096 \
--temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--image xx.jpg \
-p "What is in the image?"
参数说明:
| 参数 | 含义 |
|---|---|
-m |
语言模型 GGUF,必填 |
--mmproj |
图像编码器/投影器 GGUF,必填;缺失时 CLI 会直接报错(mtmd-cli.cpp 的 L401-L404) |
-c 4096 |
上下文长度 |
--temp / --top-p / --top-k |
采样温度、核采样、top-k 截断,取值即文档推荐的 MiniCPM-V 2.6 生成配置 |
--repeat-penalty 1.05 |
轻微重复惩罚 |
--image |
输入图像路径 |
-p |
单轮提示词,给出后执行一次生成 |
4.2 会话模式
./build/bin/llama-mtmd-cli \
-m ../MiniCPM-V-2_6/model/ggml-model-Q4_K_M.gguf \
--mmproj ../MiniCPM-V-2_6/mmproj-model-f16.gguf
不带 -p 时进入交互式会话,可多轮对话并随时粘贴图像路径。此例使用量化后的 Q4_K_M 模型,说明量化版同样支持完整推理流程。
4.3 图像在推理中如何被消费(源码视角)
从 tools/mtmd/models/minicpmv.cpp 的构图代码看,MiniCPM-V 系列的 mmproj 前向包含两个阶段:
- ViT 阶段:图像 patch 过
build_vit(学习式位置嵌入position_embeddings通过positions索引选取),得到 patch 级视觉特征; - resampler 阶段:这实际上是一台小型 Transformer——
mm_model_query提供可学习查询向量,ViT 特征经mm_model_kv_proj投影为 K/V,K 上叠加按 2D patch 坐标构造的正弦位置嵌入(omega/pos_h/pos_w,对应 HF 侧 resampler 的实现),做多头注意力(d_head = 128,缩放因子1/sqrt(128))后经mm_model_ln_post归一化、mm_model_proj投影,输出固定数量的视觉 embedding(minicpmv.cpp 的 L38-L111)。
这些 embedding 替代 prompt 中占位 token 的位置一起进入语言模型,这正是"图像能回答 'What is in the image?'" 的底层机制。
五、注意事项与适用前提
- 版本对齐:
--minicpmv_version必须与实际模型版本严格对应(2.6 传 3),传错会导致加载错误的 ViT 配置。脚本 help 中的完整对照表(1→MiniCPM-V-2,2→2.5,3→2.6,4→o-2.6,5→V 4.0,6→o-4.0)可直接当速查表使用; - mmproj 与模型必须配套:
mmproj-model-f16.gguf由同一份原始权重导出,跨版本混用无保证; - GPU 卸载:
mmproj默认走 GPU,可用--no-mmproj-offload关闭(用法横幅见 mtmd-cli.cpp); - 环境前提:surgery 与编码器转换脚本依赖 Python 环境中的
transformers、torch等库(脚本头部直接import torch并调用AutoModel.from_pretrained,且对远程代码使用trust_remote_code=True); - 预量化模型:若不想自己转换,openbmb 在 HF 上提供
MiniCPM-V-2_6-gguf预转换产物;更完整的预量化多模态模型列表可参考 docs/multimodal.md; - 同系列对照阅读:MiniCPM-V 2.5(docs/multimodal/minicpmv2.5.md)与 MiniCPM-V 4.0(docs/multimodal/minicpmv4.0.md)的转换流程类似但版本号与视觉编码器不同,MiniCPM-V 4.6 等新架构已可走
convert_hf_to_gguf.py --mmproj直转(见 tools/mtmd/README.md)。
至此,从 PyTorch 权重到 Q4_K_M 量化模型、从 surgery 解剖到 resampler 构图,MiniCPM-V 2.6 在 llama.cpp 中的完整生命周期都已覆盖。按第三节四步转换、第四节命令推理,即可在 Linux 或 Mac 上完成图像问答。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00