跳到主要内容

MiniCPM-V 4.6

MiniCPM-V 多模态系列

把模型接入自己的服务:vLLM 与 SGLang 面向高吞吐的 GPU 服务,llama.cpp 与 Ollama 面向本地与端侧运行,Gradio 与 iOS 则是开箱即用的演示应用。按硬件与场景选择其一,本页给出各自的安装、启动与调用步骤。

MiniCPM-V 4.6 提供 两个独立的 checkpoint,各框架均通过切换模型路径使用:

方案适用场景要点
vLLM高吞吐 GPU 服务官方 main 已支持(PR #43213),无需 fork
SGLang高吞吐 GPU 服务官方 main 已支持(PR #24998),无需 fork
llama.cpp本地 CPU / Metalrelease b9049 起支持,转换不再需要 surgery 脚本
Ollama本地快速体验官方 v0.30 起内置支持,ollama run openbmb/minicpm-v4.6
GradioWeb 演示(图像 / 视频对话)服务端 + 客户端两部分
iOS端侧 App(含 Android / HarmonyOS)基于 llama.cpp submodule 编译
共同前提

MiniCPM-V 4.6 注册为 MiniCPMV4_6ForConditionalGeneration,需 transformers >= 5.7.0。与 MiniCPM-V 4.5 通过 enable_thinking 切换模式不同,MiniCPM-V 4.6 按需部署对应 checkpoint;vLLM 的 stop_token_ids 改为 [248044, 248046](MiniCPM-V 4.5 是 [1, 151645])。

vLLM​

1. 环境准备​

1.1 安装 vLLM​

MiniCPM-V 4.6 自 PR #43213(2026-05-22 merged)起在官方 vLLM main 分支上完整可用。无需使用 fork,直接从官方仓库安装即可,确保检出的 commit ≥ 该 PR 的 merge 时间:

Bash
# 新建干净的 conda 环境
conda create -n vllm-v46 python=3.10 -y
conda activate vllm-v46

# 从官方 main 源码安装(需要 CUDA 工具链;HEAD 需包含 #43213)
git clone https://github.com/vllm-project/vllm.git
cd vllm
MAX_JOBS=6 VLLM_USE_PRECOMPILED=1 pip install --editable . -v

[!TIP] 等到 vLLM 发布包含 #43213 的正式 release 之后,可直接 pip install -U vllm 升级,无需源码安装。请关注 vLLM Releases。

进行视频推理时,需要安装相应的视频模块:

Bash
pip install vllm[video]

vLLM 要求 transformers>=5.7.0,MiniCPM-V 4.6 在 transformers 中以独立架构 MiniCPMV4_6ForConditionalGeneration 形式合并。

校验安装:

Bash
python -c "import vllm, transformers; print('vllm', vllm.__version__, '| transformers', transformers.__version__)"

2. API 服务部署​

2.1 启动 API 服务​

Bash
vllm serve <模型路径> \
--dtype auto \
--max-model-len 8192 \
--api-key token-abc123 \
--gpu_memory_utilization 0.9 \
--trust-remote-code \
--max-num-batched-tokens 8192

参数说明:

  • <模型路径>:MiniCPM-V-4.6 的本地路径,或 HuggingFace ID openbmb/MiniCPM-V-4.6 / openbmb/MiniCPM-V-4.6-Thinking
  • --api-key:API 访问密钥
  • --max-model-len:最大上下文长度。MiniCPM-V 4.6 backbone 最长支持 256K,部署时按需设置即可
  • --gpu_memory_utilization:GPU 显存使用率

2.2 图片推理​

Python
from openai import OpenAI
import base64

openai_api_key = "token-abc123" # 需与启动服务时设置的密钥保持一致
openai_api_base = "http://localhost:8000/v1"

client = OpenAI(api_key=openai_api_key, base_url=openai_api_base)

with open('./assets/airplane.jpeg', 'rb') as file:
image = "data:image/jpeg;base64," + base64.b64encode(file.read()).decode('utf-8')

chat_response = client.chat.completions.create(
model="<模型路径>",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "请描述这张图片"},
{"type": "image_url", "image_url": {"url": image}},
],
}],
extra_body={
# v4.6 使用 Qwen3.5 词表,stop_token_ids 与 v4.5 不同
"stop_token_ids": [248044, 248046]
}
)

print("Chat response:", chat_response)
print("Chat response content:", chat_response.choices[0].message.content)

2.3 视频推理​

Python
from openai import OpenAI
import base64

openai_api_key = "token-abc123"
openai_api_base = "http://localhost:8000/v1"

client = OpenAI(api_key=openai_api_key, base_url=openai_api_base)

with open('./videos/video.mp4', 'rb') as video_file:
video_base64 = base64.b64encode(video_file.read()).decode('utf-8')

chat_response = client.chat.completions.create(
model="<模型路径>",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": [
{"type": "text", "text": "请描述这个视频"},
{"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video_base64}"}},
],
},
],
extra_body={"stop_token_ids": [248044, 248046]}
)

print(chat_response.choices[0].message.content)

MiniCPM-V 4.6 的视频通路非常简单:图像处理器逐帧调用,单视频帧切片预算由 mm_processor_kwargs / video_processor.max_slice_nums 控制,无需 enhanced_opencv 等特殊后端。

调整单视频帧切片数量:

Python
extra_body = {
"stop_token_ids": [248044, 248046],
"mm_processor_kwargs": {"max_slice_nums": 2},
}

2.4 思考模式​

如果部署的是 openbmb/MiniCPM-V-4.6-Thinking 模型,chat template 会默认在 assistant 起始位置插入 <think> 块;模型先输出推理过程,再以 </think> 分隔后给出回答。可通过 chat_template_kwargs 跳过:

Python
extra_body = {
"stop_token_ids": [248044, 248046],
# 在 Thinking 模型上跳过开头的 <think> 块
"chat_template_kwargs": {"enable_thinking": False},
}

Instruct 模型不会输出 <think> 块,按业务需求选择对应 checkpoint 即可,不再像 MiniCPM-V 4.5 那样需要在请求里切换模式。

2.5 多轮对话​

启动参数配置​

进行多图 / 多视频对话时,需在启动时调大 --limit-mm-per-prompt:

Bash
# 视频多轮对话(最多 3 个视频)
vllm serve <模型路径> --dtype auto --max-model-len 16384 --api-key token-abc123 \
--gpu_memory_utilization 0.9 --trust-remote-code \
--limit-mm-per-prompt '{"video": 3}'
Bash
# 图片和视频混合输入
vllm serve <模型路径> --dtype auto --max-model-len 16384 --api-key token-abc123 \
--gpu_memory_utilization 0.9 --trust-remote-code \
--limit-mm-per-prompt '{"image": 5, "video": 2}'
多轮对话示例代码​
Python
from openai import OpenAI
import base64
import mimetypes
import os

openai_api_key = "token-abc123"
openai_api_base = "http://localhost:8000/v1"

client = OpenAI(api_key=openai_api_key, base_url=openai_api_base)

messages = [{"role": "system", "content": "You are a helpful assistant."}]

def file_to_base64(file_path):
with open(file_path, 'rb') as f:
return base64.b64encode(f.read()).decode('utf-8')

def get_mime_type(file_path):
mime, _ = mimetypes.guess_type(file_path)
return mime or 'application/octet-stream'

def build_file_content(file_path):
mime_type = get_mime_type(file_path)
base64_data = file_to_base64(file_path)
url = f"data:{mime_type};base64,{base64_data}"
if mime_type.startswith("image/"):
return {"type": "image_url", "image_url": {"url": url}}
elif mime_type.startswith("video/"):
return {"type": "video_url", "video_url": {"url": url}}
else:
print(f"不支持的文件类型: {mime_type}")
return None

while True:
user_text = input("请输入问题(输入 'exit' 退出):")
if user_text.strip().lower() == "exit":
break

content = [{"type": "text", "text": user_text}]

upload_file = input("是否上传文件?(y/n): ").strip().lower() == 'y'
if upload_file:
file_path = input("请输入文件路径: ").strip()
if os.path.exists(file_path):
file_content = build_file_content(file_path)
if file_content:
content.append(file_content)
else:
print("文件路径不存在,跳过文件上传。")

messages.append({"role": "user", "content": content})

chat_response = client.chat.completions.create(
model="<模型路径>",
messages=messages,
extra_body={"stop_token_ids": [248044, 248046]},
)

ai_message = chat_response.choices[0].message
print("MiniCPM-V 4.6:", ai_message.content)

messages.append({"role": "assistant", "content": ai_message.content})

3. 离线推理​

Python
from transformers import AutoProcessor
from PIL import Image
from vllm import LLM, SamplingParams

MODEL_NAME = "<模型路径>"
# 或直接使用 HuggingFace ID:
# MODEL_NAME = "openbmb/MiniCPM-V-4.6"

image = Image.open("./assets/airplane.jpeg").convert("RGB")
processor = AutoProcessor.from_pretrained(MODEL_NAME)

llm = LLM(
model=MODEL_NAME,
max_model_len=8192,
trust_remote_code=True,
disable_mm_preprocessor_cache=True,
limit_mm_per_prompt={"image": 5},
)

messages = [{
"role": "user",
"content": [
{"type": "image"},
{"type": "text", "text": "请描述这张图片的内容"},
],
}]

prompt = processor.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)

inputs = {
"prompt": prompt,
"multi_modal_data": {
"image": image,
# 多图推理:
# "image": [image1, image2]
},
}

sampling_params = SamplingParams(
stop_token_ids=[248044, 248046],
temperature=0.7,
top_p=0.8,
max_tokens=1024,
)

outputs = llm.generate(inputs, sampling_params=sampling_params)
print(outputs[0].outputs[0].text)

注意事项​

  1. 模型路径:将示例中的 <模型路径> 替换为本地路径,或 openbmb/MiniCPM-V-4.6 / openbmb/MiniCPM-V-4.6-Thinking。
  2. 停止符:MiniCPM-V 4.6 采用 Qwen3.5 词表,正确的 stop_token_ids 为 [248044, 248046](MiniCPM-V 4.5 用的是 [1, 151645])。
  3. API 密钥:客户端密钥需与 vllm serve 启动时一致。
  4. 显存配置:根据硬件调整 --gpu_memory_utilization / --max-model-len / --max-num-batched-tokens。MiniCPM-V 4.6 backbone 最长支持 256K,但通常无需开满。
  5. 多模态限制:多图 / 多视频对话时设置合适的 --limit-mm-per-prompt。

SGLang​

[!NOTE] MiniCPM-V 4.6 自 PR #24998(2026-05-12 merged)起在官方 SGLang main 分支上完整可用。无需使用 fork,直接从官方仓库安装即可,确保检出的 commit ≥ 该 PR 的 merge 时间。

MiniCPM-V 4.6 在 transformers>=5.7.0 中以独立架构 MiniCPMV4_6ForConditionalGeneration 注册,SGLang 的适配也基于这一布局。

MiniCPM-V 4.6 提供两个 checkpoint:

1. SGLang 安装​

从官方 main 源码安装​

包含 #24998 的正式 release 出来前,推荐从官方 main 安装(请关注 SGLang Releases;正式版发布后可直接 pip install -U "sglang[all]"):

Bash
git clone https://github.com/sgl-project/sglang.git
cd sglang

pip install --upgrade pip
pip install -e "python[all]"

上述命令会自动安装 transformers>=5.7.0,而它会牵入一个较新版本的 PyTorch(截至撰写时 ≥ 2.6)。安装 FlashInfer 之前先确认实际 torch / CUDA 版本,避免下一步装错 wheel 把 torch 又降回去:

Bash
python -c "import torch, transformers; print('torch', torch.__version__, '| cuda', torch.version.cuda, '| transformers', transformers.__version__)"

FlashInfer 依赖(可选,建议安装)​

[!IMPORTANT] FlashInfer 的 wheel 是按 (torch 版本, CUDA 版本) 组合发布的,必须 选与刚才验证出来的 torch + CUDA 完全匹配的 index。不要直接复制 cu121/torch2.4 这种老链接——那会偷偷把 torch 降级并破坏前面装好 的 SGLang / transformers 环境。

FlashInfer 总索引:<https://flashinfer.ai/whl/&gt;。挑跟你环境匹配的目录,例如:

你的 torch / CUDAIndex URL
torch 2.6 + CUDA 12.4<https://flashinfer.ai/whl/cu124/torch2.6/>
torch 2.6 + CUDA 12.6<https://flashinfer.ai/whl/cu126/torch2.6/>
torch 2.7 + CUDA 12.8<https://flashinfer.ai/whl/cu128/torch2.7/>

然后任选一种安装:

Bash
# 方法 1:从对应索引 pip 安装(国内访问可能慢)
pip install flashinfer-python -i <上表选的 index URL>

# 方法 2:手动下载匹配的 whl 安装
# 1) 浏览器打开索引 URL,选一份匹配你 Python 版本(cp310/cp311/…)
# 与平台(linux_x86_64 / win_amd64)的 whl
# 2) pip install <下载的 whl 文件>

其它(Docker 镜像、纯 CPU 退路等)参见 SGLang 官方安装文档。

2. 启动推理服务​

默认情况下,会从 Hugging Face Hub 下载模型文件:

Bash
python -m sglang.launch_server --model-path openbmb/MiniCPM-V-4.6 --port 30000 --trust-remote-code --dtype bfloat16

也可以在 --model-path 后指定本地路径:

Bash
python -m sglang.launch_server --model-path /your/local/MiniCPM-V-4.6 --port 30000 --trust-remote-code --dtype bfloat16

部署 Thinking 模型只需替换 model id:

Bash
python -m sglang.launch_server --model-path openbmb/MiniCPM-V-4.6-Thinking --port 30000 --trust-remote-code --dtype bfloat16

3. 调用服务接口​

  • bash / curl:

    Bash
    curl -s http://localhost:30000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
    "model": "MiniCPM-V-4.6",
    "messages": [
    {
    "role": "user",
    "content": [
    {"type": "text", "text": "What is in this image?"},
    {
    "type": "image_url",
    "image_url": {
    "url": "https://github.com/OpenSQZ/MiniCPM-V-CookBook/blob/main/inference/assets/airplane.jpeg?raw=true"
    }
    }
    ]
    }
    ],
    "max_tokens": 300,
    "top_k": -1
    }'
  • Python(OpenAI 客户端)调用:

    Python
    from openai import OpenAI

    client = OpenAI(base_url="http://localhost:30000/v1", api_key="None")

    response = client.chat.completions.create(
    model="MiniCPM-V-4.6",
    messages=[
    {
    "role": "user",
    "content": [
    {"type": "text", "text": "请描述这张图片"},
    {
    "type": "image_url",
    "image_url": {
    "url": "https://github.com/OpenSQZ/MiniCPM-V-CookBook/blob/main/inference/assets/airplane.jpeg?raw=true",
    },
    },
    ],
    }
    ],
    max_tokens=300,
    extra_body={"top_k": -1, "stop_token_ids": [248044, 248046]},
    )

    print(response.choices[0].message.content)

如 image_url 无法访问,可替换为本地图片路径或 base64 data URL。

MiniCPM-V 4.6 使用 Qwen3.5 词表 —— 若发现模型在回答后继续生成,请显式传入 stop_token_ids=[248044, 248046]。

更多调用方法可参考 SGLang 使用文档。

llama.cpp​

[!NOTE] MiniCPM-V 4.6 已合并到官方 llama.cpp(PR #22529),从 release b9049 开始包含。

与 MiniCPM-V 4.5 相比,MiniCPM-V 4.6 重做了视觉塔(resampler 被替换为新的 merger 结构,提升 ViT 推理效率),并且 GGUF 转换合并到了标准的 convert_hf_to_gguf.py 流程中 —— 不再需要专用的 surgery 脚本。

1. 编译安装 llama.cpp​

克隆 llama.cpp 代码仓库(需要 release b9049 及之后的提交):

Bash
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp

使用 CMake 构建(详见构建文档):

CPU / Metal:

Bash
cmake -B build
cmake --build build --config Release

CUDA:

Bash
cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release

2. 获取 GGUF 权重​

方法一:下载官方 GGUF 文件​

从仓库中下载语言模型文件(如 MiniCPM-V-4.6-Q4_K_M.gguf)与视觉模型文件(mmproj-MiniCPM-V-4.6-F16.gguf):

Thinking 版本在以下仓库单独发布:

方法二:从 PyTorch 模型转换​

下载 PyTorch 模型:

用 llama.cpp 仓库自带的标准脚本 convert_hf_to_gguf.py 直接转换:

Bash
# 1) 将语言模型 + 视觉 merger 转为 GGUF
python ./convert_hf_to_gguf.py /path/to/MiniCPM-V-4.6 \
--outfile /path/to/MiniCPM-V-4.6/MiniCPM-V-4.6-F16.gguf \
--outtype f16

# 2) 转换视觉 projector(mmproj)
python ./convert_hf_to_gguf.py /path/to/MiniCPM-V-4.6 \
--mmproj \
--outfile /path/to/MiniCPM-V-4.6/mmproj-MiniCPM-V-4.6-F16.gguf

convert_hf_to_gguf.py 会从 config.json 自动识别 MiniCPMV4_6ForConditionalGeneration,同时输出 LM 与视觉塔。

MiniCPM-V 4.6 不再需要 legacy-models/minicpmv-surgery.py + minicpmv-convert-image-encoder-to-gguf.py 这套两步流程。如果您在跟随旧的 MiniCPM-V 4.5 文档,请忽略这些脚本。

3. 模型推理​

[!IMPORTANT] 新版 llama.cpp(PR #20606 之后)的 --reasoning 默认值为 auto,会从 chat template 自动启用 thinking。MiniCPM-V 4.6 Instruct 模型本身不输出 <think> 块,但其模板默认会开启 thinking,导致 Instruct 推理输出异常。请在所有 Instruct 推理命令中显式加 --reasoning off 关闭。 Thinking 模型则保留默认或显式 --reasoning on。

Bash
cd build/bin/

# F16 版本
./llama-mtmd-cli \
-m /path/to/MiniCPM-V-4.6/MiniCPM-V-4.6-F16.gguf \
--mmproj /path/to/MiniCPM-V-4.6/mmproj-MiniCPM-V-4.6-F16.gguf \
-c 8192 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--reasoning off \
--image xx.jpg -p "请描述这张图片"

# INT4 量化版本
./llama-mtmd-cli \
-m /path/to/MiniCPM-V-4.6/MiniCPM-V-4.6-Q4_K_M.gguf \
--mmproj /path/to/MiniCPM-V-4.6/mmproj-MiniCPM-V-4.6-F16.gguf \
-c 8192 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--reasoning off \
--image xx.jpg -p "请描述这张图片"

# 交互模式
./llama-mtmd-cli \
-m /path/to/MiniCPM-V-4.6/MiniCPM-V-4.6-Q4_K_M.gguf \
--mmproj /path/to/MiniCPM-V-4.6/mmproj-MiniCPM-V-4.6-F16.gguf \
-c 8192 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--reasoning off \
--image xx.jpg -i

部署 Thinking 模型时,可通过 --jinja + --reasoning-budget 控制思考预算(--reasoning 默认 auto,对 Thinking 模型会自动开启):

Bash
# Thinking 模型 - 不限制思考输出
./llama-mtmd-cli \
-m /path/to/MiniCPM-V-4.6-Thinking/MiniCPM-V-4.6-Thinking-Q4_K_M.gguf \
--mmproj /path/to/MiniCPM-V-4.6-Thinking/mmproj-MiniCPM-V-4.6-Thinking-F16.gguf \
-c 8192 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--image xx.jpg --jinja --reasoning-budget -1 -p "图中有什么?"

# Thinking 模型 - 跳过开头的 <think> 块(直接出答案)
./llama-mtmd-cli \
-m /path/to/MiniCPM-V-4.6-Thinking/MiniCPM-V-4.6-Thinking-Q4_K_M.gguf \
--mmproj /path/to/MiniCPM-V-4.6-Thinking/mmproj-MiniCPM-V-4.6-Thinking-F16.gguf \
-c 8192 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 \
--image xx.jpg --jinja --reasoning-budget 0 -p "图中有什么?"

Instruct 模型本身不会生成 <think> 块,因此 --reasoning-budget 在它上面是无效的。

命令行参数说明:

参数含义
-m, --model语言模型路径
--mmproj视觉模型路径
--image输入图片路径
-p, --prompt提示词
-c, --ctx-size输入上下文最大长度
-rea, --reasoning [on|off|auto]是否启用思考;默认 auto,会从 chat template 推断。Instruct 模型必须显式 off,Thinking 模型可保留默认或显式 on
--reasoning-budget最大思考输出 token 数(-1 无限制,0 立即结束);仅在 Thinking 模型有效
--jinja使用模型自带的 Jinja chat template(新版 llama.cpp 默认已启用)

Ollama​

[!NOTE] Ollama 自 v0.30 起官方支持 MiniCPM-V 4.6。请确保 Ollama 版本 不低于 0.30,旧版本不包含该模型支持,会加载失败。

1. 安装 Ollama​

确认版本不低于 0.30:

Bash
ollama --version

2. 快速使用​

从 Ollama registry 拉取并运行 OpenBMB 官方模型(<https://ollama.com/openbmb/minicpm-v4.6&gt;):

Bash
ollama run openbmb/minicpm-v4.6
# 或 Thinking 版本
ollama run openbmb/minicpm-v4.6-thinking

命令行​

用空格分隔输入问题和图片路径:

Plain Text
这张图片描述了什么? xx.jpg

API​

Python
import base64, requests

with open(image_path, 'rb') as image_file:
# 将图片文件转换为 base64 编码
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
data = {
"model": "openbmb/minicpm-v4.6",
"prompt": query,
"stream": False,
"images": [encoded_string], # 列表可以放多张图,每张图用上面的方式转化为 base64
}
url = "http://localhost:11434/api/generate"
response = requests.post(url, json=data)

3. 自定义方式​

如果需要加载本地 GGUF(例如自定义量化版本),请按下面的步骤操作。

获取 GGUF 模型​

(Thinking 版本:openbmb/MiniCPM-V-4.6-Thinking-gguf)

创建 ModelFile​

Bash
vim minicpmv4.6.Modelfile

ModelFile 的内容如下:

Plain Text
FROM ./MiniCPM-V-4.6/MiniCPM-V-4.6-Q4_K_M.gguf
FROM ./MiniCPM-V-4.6/mmproj-MiniCPM-V-4.6-F16.gguf

TEMPLATE """{{- if .Messages }}{{- range $i, $_ := .Messages }}{{- $last := eq (len (slice $.Messages $i)) 1 -}}<|im_start|>{{ .Role }}{{ .Content }}{{- if $last }}{{- if (ne .Role "assistant") }}<|im_end|><|im_start|>assistant{{ end }}{{- else }}<|im_end|>{{ end }}{{- end }}{{- else }}{{- if .System }}<|im_start|>system{{ .System }}<|im_end|>{{ end }}{{ if .Prompt }}<|im_start|>user{{ .Prompt }}<|im_end|>{{ end }}<|im_start|>assistant{{ end }}{{ .Response }}{{ if .Response }}<|im_end|>{{ end }}"""

SYSTEM """You are a helpful assistant."""

PARAMETER top_p 0.8
PARAMETER num_ctx 8192
PARAMETER stop ["<|im_start|>", "<|im_end|>"]
PARAMETER temperature 0.7

参数说明:

first FROMsecond FROMnum_ctx
语言模型 GGUF 路径视觉 projector GGUF 路径最大上下文长度

创建 Ollama 模型实例​

Bash
ollama create minicpm-v4.6 -f minicpmv4.6.Modelfile

另起一个命令行窗口,运行 Ollama 模型实例​

Bash
ollama run minicpm-v4.6

输入问题和图片路径,以空格分隔​

Plain Text
这张图片描述了什么? xx.jpg

Gradio​

MiniCPM-V 4.6 的单进程 Gradio 演示。一个进程可以同时加载 instruct 和 thinking 两个检查点;通过界面上的"思考模式"开关即可实时切换当前使用的模型(并在 chat template 中切换 enable_thinking)。

与 MiniCPM-V 4.5 演示(使用 FastAPI server + Gradio client 分离架构以及 model.chat(...) 自定义 API)不同,MiniCPM-V 4.6 使用标准的 HuggingFace transformers API:

Python
from transformers import AutoProcessor, MiniCPMV4_6ForConditionalGeneration

processor = AutoProcessor.from_pretrained(path)
model = MiniCPMV4_6ForConditionalGeneration.from_pretrained(path, dtype=torch.bfloat16)

inputs = processor.apply_chat_template(messages, add_generation_prompt=True,
tokenize=True, return_dict=True,
return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=..., do_sample=...)
text = processor.decode(out[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True)

流式输出通过 transformers.TextIteratorStreamer 在后台线程中实现,使 Gradio 界面能逐 token 输出。

目录结构​

Plain Text
gradio/v46/
├── app.py # 单进程 Gradio 应用(加载 1 或 2 个检查点)
├── start.sh # tmux 启动器(双模型 / instruct / thinking 模式,负载均衡注册)
├── requirements.txt
└── README.md

模型​

模型路径
instruct./minicpm-v-4_6-0420-rlaif-instruct
thinking./minicpm-v-4_6-0420-rlaif-thinking

注意:两个模型的 config.json 均已添加 image_token_id: 248056(即 <|image_pad|> 特殊 token 的 id)——缺少此项会导致模型在 get_placeholder_mask 中抛出 AttributeError: 'bool' object has no attribute 'sum'。

环境配置​

从 omni 克隆一个专用的 v46 conda 环境:

Bash
conda create --clone omni -n v46 --offline
conda activate v46

PYTHONNOUSERSITE=1 pip install -e ./new-model-addition-MiniCPM-V-4.6 --no-deps
PYTHONNOUSERSITE=1 pip install -U "huggingface_hub>=1.0" "tokenizers>=0.22.0,<=0.23.0" "regex>=2025.10.22" "mistral_common>=1.11.0"

需要设置 PYTHONNOUSERSITE=1,因为该服务器上的包会覆盖 conda 环境中的 transformers 和 huggingface_hub,导致版本不兼容。

还需要对环境中的 src/transformers/models/minicpmv4_6/configuration_minicpmv4_6.py 进行一个小补丁:

Python
# 修改前:
merge_kernel_size: list[int] = [2, 2]
# 修改后:
from dataclasses import field
merge_kernel_size: list[int] = field(default_factory=lambda: [2, 2])

(Python 3.10+ 的 @dataclass 不允许使用可变列表作为默认值。)

思考模式切换原理​

Plain Text
┌─────────────────────────────────────────────┐
│ 单个 app.py 进程(同一个 CUDA 设备) │
│ │
│ MODELS = { │
│ "instruct": <MiniCPMV4_6…instruct> │
│ "thinking": <MiniCPMV4_6…thinking> │
│ } │
└─────────────────────────────────────────────┘

开关关闭 → variant="instruct", enable_thinking=False
开关开启 → variant="thinking", enable_thinking=True

切换开关时,对话历史会自动清除并显示提示 Switched to 'thinking' model, history cleared.。清除历史是因为两个检查点的输出风格不同(<think>…</think> vs 直接回答),混合在同一对话中会在后续轮次中干扰模型。

显存占用:每个检查点在 bfloat16 下约 16 GB,因此双模型进程需要约 32 GB。推荐在 80 GB 的 A100/H100 上运行。显存较小的显卡可以使用 --variant instruct 或 --variant thinking 只加载一个检查点。

启动方式​

A. 快速启动 — 单 GPU 上运行一个双模型实例​

Bash
cd ./MiniCPM-o-demo-web/gradio/v46

# 在 GPU 7 上运行双模型,端口 8890,不使用负载均衡
bash start.sh -n 1 --gpu-start 7 --port-base 8890 --no-lb

访问 http://<host>:8890,通过"思考模式"开关切换检查点。

B. 生产部署 — 多个双模型实例 + 负载均衡​

架构:

Plain Text
┌──────────────────────────────────────────┐
用户 ─────▶ │ load_balancer :8121 (ip_hash + SSE) │
└──┬───────────────┬──────────────┬────────┘
│ │ │
▼ ▼ ▼
127.0.0.1:8890 127.0.0.1:8891 127.0.0.1:8892 ← v4.6 app.py(双模型)
(GPU 7) (GPU 6) (GPU 5)
│ │ │
└─── 每个进程同时持有 instruct + thinking ───

由于每个后端都提供两种变体,因此只需一个负载均衡池,ip_hash 会话粘性确保每个用户始终访问同一个后端(保持开关状态一致)。

1) 启动负载均衡器​
Bash
cd ../load_balancer
python load_balancer.py --port 8121 --strategy ip_hash
2) 启动 Gradio 实例(自动注册到负载均衡器)​
Bash
cd ../v46

# 在 GPU 7,6,5,4 上启动 4 个双模型实例 → 负载均衡器 :8121
bash start.sh -n 4 \
--gpu-start 7 --port-base 8890 \
--lb-host 127.0.0.1 --lb-port 8121

用户访问:http://<host>:8121。

3) 状态查看 / 停止​
Bash
bash start.sh --status
bash start.sh --stop # 同时从负载均衡器注销

C. 单变体集群(降低每个进程的显存占用)​

如果显卡无法容纳约 32 GB,可以分别部署两种变体。此模式下"思考模式"开关仅切换 enable_thinking(无法切换模型,因为只加载了一个),需要两个负载均衡端口以避免用户误访问另一个模型。

Bash
bash start.sh -n 4 --variant instruct --gpu-start 7 --port-base 8890 --lb-port 8121
bash start.sh -n 4 --variant thinking --gpu-start 3 --port-base 8900 --lb-port 8122

D. 手动运行 app.py(不使用 tmux 和负载均衡)​

Bash
conda activate v46

# 双模型(开关切换模型)
PYTHONNOUSERSITE=1 CUDA_VISIBLE_DEVICES=7 python app.py \
--instruct_path=minicpm-v-4_6-0420-rlaif-instruct \
--thinking_path=minicpm-v-4_6-0420-rlaif-thinking \
--port=8890

# 单模型
PYTHONNOUSERSITE=1 CUDA_VISIBLE_DEVICES=7 python app.py \
--instruct_path=minicpm-v-4_6-0420-rlaif-instruct \
--port=8890

多机部署​

与 MiniCPM-V 4.5 相同。在主节点上运行负载均衡器,然后在每台工作节点上:

Bash
bash start.sh -n K --lb-host <主节点IP> --lb-port 8121 --local-ip <本机IP>

界面功能​

  • 上传:每轮可上传单张或多张图片,或一个视频。不支持同时上传图片和视频(后端强制检查)。
  • 解码方式:Beam Search(确定性,num_beams=1)或采样。
  • 思考模式:加载双模型时切换活跃的检查点;仅加载单模型时切换 enable_thinking。切换时会清除对话历史以避免混合不同输出风格。
  • 流式输出:通过 TextIteratorStreamer 逐 token 更新。Beam Search 会自动禁用流式输出。
  • 参数滑块:max_new_tokens、temperature、top_p、top_k。
  • 操作按钮:重新生成 / 清除历史 / 停止。
  • <think>…</think> 段落以蓝色卡片形式渲染在回答上方,便于实时查看模型的推理过程。

与 MiniCPM-V 4.5 演示的主要区别​

方面MiniCPM-V 4.5MiniCPM-V 4.6
架构FastAPI server + Gradio client + LB单进程 Gradio 应用(可选负载均衡)
每进程模型数11 或 2(双模型 instruct+thinking)
模型加载AutoModel.from_pretrained(trust_remote_code=True)MiniCPMV4_6ForConditionalGeneration.from_pretrained(...)
推理调用model.chat(msgs, tokenizer, processor, ...)model.generate(**processor.apply_chat_template(...))
视频编码客户端预提取帧 → base64 逐帧 POSTProcessor 从本地路径内部提取帧
流式输出自定义 chat(stream=True) → SSE over HTTPTextIteratorStreamer 线程 → Gradio 直接 yield
思考模式enable_thinking 传给 model.chatenable_thinking 传给 apply_chat_template + 模型切换

iOS​

官方仓库: OpenBMB/MiniCPM-V-Apps

README:English · 简体中文 README_zh

同一仓库内含 iOS、Android、HarmonyOS NEXT 三端 demo,共享仓库根目录的 llama.cpp git submodule(分支 Support-iOS-Demo)。本文侧重 iOS;安卓与鸿蒙的编译说明请直接看 upstream README。

预编译安装包(TestFlight / APK / HAP):DOWNLOAD.md / DOWNLOAD_zh.md。下面内容为从源码自行构建时使用。


1. 克隆仓库与子模块​

Bash
git clone https://github.com/OpenBMB/MiniCPM-V-Apps.git
cd MiniCPM-V-Apps
git submodule update --init --recursive

2. 打开 Xcode 工程​

说明:在真机(iPhone / iPad)上部署、调试通常需要有效的 Apple Developer 帐号。

安装 Xcode:

  • 从 App Store 安装 Xcode

  • 安装命令行工具:

    Bash
    xcode-select --install
  • 同意许可协议:

    Bash
    sudo xcodebuild -license

使用 Xcode 打开 MiniCPM-V-demo/MiniCPM-V-demo.xcodeproj,等待 Xcode 自动下载所需依赖;在顶部选好运行目标设备,点击 Run(三角形)。

说明:若出现 thirdparty/llama.xcframework 相关报错,按第 3 节手动构建框架。


3. 手动构建 llama.xcframework​

在仓库根目录(并已拉取 submodule)执行:

Bash
cd llama.cpp
./build-xcframework.sh
cp -r ./build-apple/llama.xcframework ../MiniCPM-V-demo/thirdparty

4. App 所用 GGUF 模型​

当前 Demo 对齐 MiniCPM-V 2.6 / 4.0 / 4.6。每个版本都需要分别从官方 GGUF 仓下载 语言模型 GGUF + 视觉投影器 mmproj-model-f16.gguf(视觉塔保留 f16 精度,避免感知质量损失)。

推荐设备内存与总下载体量(详见 upstream README_zh 硬件说明):

模型LLM 参数量推荐量化总下载量推荐设备内存
MiniCPM-V 2.68BQ4_K_M~5.4 GB≥ 8 GB
MiniCPM-V 4.04.1BQ4_K_M~2.9 GB≥ 6 GB
MiniCPM-V 4.61.3BQ4_K_M~1.6 GB≥ 6 GB

三端 demo 默认上下文为 4K token,KV cache 占用近似随上下文线性增长,临界设备上可适当下调。

MiniCPM-V 2.6 — 官方 GGUF​

下载语言模型文件(如 ggml-model-Q4_0.gguf)与视觉模型文件 mmproj-model-f16.gguf。

MiniCPM-V 4.0 — 官方 GGUF​

下载语言模型文件(如 ggml-model-Q4_K_M.gguf)与视觉模型文件 mmproj-model-f16.gguf。

MiniCPM-V 4.6 — 官方 GGUF​

下载语言模型文件(如 MiniCPM-V-4_6-Q4_K_M.gguf)与视觉模型文件 mmproj-model-f16.gguf。


5. 从 PyTorch 自行转换 GGUF(可选)​

Cookbook 中的转换流程见:

请在 MiniCPM-V-Apps 仓库根目录下的 llama.cpp 子模块内执行各文档中的命令。