跳到主要内容

MiniCPM-o 4.5

MiniCPM-o 全模态系列

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

方案适用场景要点
vLLM高吞吐 GPU 服务官方 v0.16.0 起支持(PR #33431),可直接 pip 安装
SGLang高吞吐 GPU 服务需源码安装
llama.cpp本地 CPU / Metal需先转 GGUF
Ollama本地快速体验需使用 OpenBMB 分支
FastAPI 全模态流式实时音视频流式对话全双工演示,含前后端
GradioWeb 演示(图片 / 视频对话)服务端 + 客户端两部分

vLLM​

1. 环境准备​

1.1 安装 vLLM​

[!NOTE] MiniCPM-o 4.5 的支持已经合入 vLLM 官方仓库(PR #33431),并从 vLLM v0.16.0 起正式发布。

现在可以直接通过 PyPI 安装官方 vLLM,无需再从 tc-mb/vllm 的 Support-MiniCPM-o-4.5 分支编译(代码合入官方后,该分支已删除)。

Bash
# 创建干净的 conda 环境
conda create -n vllm-o45 python=3.10
conda activate vllm-o45

# 从 PyPI 安装 vLLM(>= 0.16.0)
pip install "vllm>=0.16.0"

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

Bash
pip install vllm[video]

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

Bash
pip install vllm[audio]

1.2 从源码安装 vLLM(可选)​

如果您希望使用 main 分支的最新特性,也可以从官方源码安装 vLLM:

Bash
# 创建干净的 conda 环境
conda create -n vllm-o45 python=3.10
conda activate vllm-o45

# 克隆官方 vLLM 仓库
git clone https://github.com/vllm-project/vllm.git
cd vllm

# 使用预编译选项加速构建
MAX_JOBS=6 VLLM_USE_PRECOMPILED=1 pip install --editable . -v --progress-bar=on

# 安装视频和音频模块
pip install vllm[video]
pip install vllm[audio]

安装完成后可以使用以下命令验证:

Bash
python -c "import vllm; print(vllm.__version__)"

2. API 服务部署​

2.1 启动 API 服务​

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

参数说明:

  • <模型路径>:指定 MiniCPM-o 4.5 模型的本地路径
  • --api-key:设置 API 访问密钥
  • --max-model-len:设置最大模型长度
  • --gpu_memory_utilization:GPU 内存使用率

2.2 图片推理​

Python
from openai import OpenAI
import base64

# API 配置
openai_api_key = "token-abc123" # API 密钥需与启动服务时设置的密钥保持一致
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="<模型路径>", # 指定模型路径或 HuggingFace ID
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "请描述这张图片"},
{
"type": "image_url",
"image_url": {
"url": image, # 支持网络图片 URL
},
},
],
}],
extra_body={
"stop_token_ids": [151643, 151645]
}
)

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

2.3 视频推理​

Python
from openai import OpenAI
import base64

# API 配置
openai_api_key = "token-abc123"
openai_api_base = "http://localhost:8000/v1"

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

# 读取视频文件并编码为 base64
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": [151643, 151645]
}
)

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

2.4 音频推理​

Python
from openai import OpenAI
import base64

# API 配置
openai_api_key = "token-abc123"
openai_api_base = "http://localhost:8000/v1"

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

# 读取音频文件并编码为 base64
with open('./audio/audio.wav', 'rb') as audio_file:
audio_base64 = base64.b64encode(audio_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": "audio_url",
"audio_url": {
"url": f"data:audio/wav;base64,{audio_base64}",
},
},
],
},
],
extra_body={
"stop_token_ids": [151643, 151645]
}
)

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

2.5 多轮对话​

启动参数配置​

进行视频多轮对话时,需要在 vLLM 启动时添加 --limit-mm-per-prompt 参数:

视频多轮对话配置(支持最多3个视频):

Bash
vllm serve <模型路径> --dtype auto --max-model-len 4096 --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 4096 --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

# API 配置
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):
"""将文件转换为 base64 编码"""
with open(file_path, 'rb') as f:
return base64.b64encode(f.read()).decode('utf-8')

def get_mime_type(file_path):
"""获取文件 MIME 类型"""
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}}
elif mime_type.startswith("audio/"):
return {"type": "audio_url", "audio_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": [151643, 151645]
}
)

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

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

3. 离线推理​

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

# 模型配置
MODEL_NAME = "<模型路径>"
# 可选择使用 HuggingFace 模型 ID
# MODEL_NAME = "openbmb/MiniCPM-o-4_5"

# 加载图片
image = Image.open("./assets/airplane.jpeg").convert("RGB")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)

# 初始化 LLM
llm = LLM(
model=MODEL_NAME,
max_model_len=2048,
trust_remote_code=True,
disable_mm_preprocessor_cache=True,
limit_mm_per_prompt={"image": 5}
)

# 构建消息
messages = [{
"role": "user",
"content": "(<image>./</image>)\n请描述这张图片的内容"
}]

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

# 单次推理
inputs = {
"prompt": prompt,
"multi_modal_data": {
"image": image
# 多图片推理需使用列表格式:
# "image": [image1, image2]
},
}

# 批量推理示例
# inputs = [{
# "prompt": prompt,
# "multi_modal_data": {
# "image": image
# },
# } for _ in range(2)]

# 设置停止标记
stop_tokens = ['<|im_end|>', '<|endoftext|>']
stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]

# 采样参数
sampling_params = SamplingParams(
stop_token_ids=stop_token_ids,
temperature=0.7,
top_p=0.7,
max_tokens=1024
)

# 生成结果
outputs = llm.generate(inputs, sampling_params=sampling_params)
print(outputs[0].outputs[0].text)

注意事项​

  1. 模型路径:需将所有示例中的 <模型路径> 替换为实际的 MiniCPM-o 4.5 模型路径
  2. API 密钥:确保启动服务时的 API 密钥与客户端代码中的密钥保持一致
  3. 文件路径:需根据实际情况调整图片、视频、音频文件的路径
  4. 内存配置:应根据 GPU 内存情况合理调整 --gpu_memory_utilization 参数
  5. 多模态限制:使用多轮对话时需设置合适的 --limit-mm-per-prompt 参数

SGLang​

1. SGLang安装​

SGLang源码安装​

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

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

flashinfer依赖安装​

方法1:pip 安装(网速可能不行)

Bash
pip install flashinfer -i https://flashinfer.ai/whl/cu121/torch2.4/

方法2: whl文件安装

  • 网页访问:https://flashinfer.ai/whl/cu121/torch2.4/flashinfer/

  • 找到适合自己服务器的版本并且下载whl文件:例如flashinfer-0.1.6+cu121torch2.4-cp310-cp310-linux_x86_64.whl

  • 使用pip install ***.whl进行安装,比如:

    Cpp
    pip install flashinfer-0.1.6+cu121torch2.4-cp310-cp310-linux_x86_64.whl

如果在安装过程中遇到问题,请随时查阅官方安装文档

2. sglang发起推理服务​

默认情况下,它将从 Hugging Face Hub 下载模型文件

Bash
python -m sglang.launch_server --model-path openbmb/MiniCPM-o-4_5 --port 30000

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

Bash
python -m sglang.launch_server --model-path your_model_path --port 30000 --trust-remote-code

3. 调用服务接口​

  • bash调用

    Python
    curl -s http://localhost:30000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
    "model": "MiniCPM-o-4.5",
    "messages": [
    {
    "role": "user",
    "content": [
    {
    "type": "text",
    "text": "What's 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
    }'
  • python调用

    Python
    from openai import OpenAI

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

    response = client.chat.completions.create(
    model="MiniCPM-o-4.5",
    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,
    )

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

    image_url如果不能访问,可以替换成本地图片 更多调用方法可以参考sglang使用文档

llama.cpp​

1. 编译安装 llama.cpp​

克隆 llama.cpp 代码仓库:

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

使用 CMake 构建 llama.cpp: https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md

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-o-4_5-Q4_K_M.gguf)与视觉模型文件(MiniCPM-o-4_5-vision-F16.gguf)

方法二: 从 Pytorch 模型转换​

下载 MiniCPM-o-4_5 PyTorch 模型到 "MiniCPM-o-4_5" 文件夹:

将 PyTorch 模型转换为 GGUF 格式:

Bash
bash ./tools/omni/convert/run_convert.sh

# 需要修改脚本中的路径:
MODEL_DIR="/path/to/MiniCPM-o-4_5" # 源模型
LLAMACPP_DIR="/path/to/llamacpp" # llamacpp 目录
OUTPUT_DIR="${CONVERT_DIR}/gguf" # 输出目录
PYTHON="/path/to/python" # Python 路径

3. 模型推理​

Bash
cd build/bin/

# 运行 f16 版本
./llama-mtmd-cli -m ../MiniCPM-o-4_5/model/Model-8.2B-F16.gguf --mmproj ../MiniCPM-o-4_5/MiniCPM-o-4_5-vision-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?"

# 运行 int4 量化版本
./llama-mtmd-cli -m ../MiniCPM-o-4_5/model/MiniCPM-o-4_5-Q4_K_M.gguf --mmproj ../MiniCPM-o-4_5/MiniCPM-o-4_5-vision-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?"

# 或以交互模式运行
./llama-mtmd-cli -m ../MiniCPM-o-4_5/model/MiniCPM-o-4_5-Q4_K_M.gguf --mmproj ../MiniCPM-o-4_5/MiniCPM-o-4_5-vision-F16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg -i

# 或以思考模式运行(思考输出的token无限制)
./llama-mtmd-cli -m ../MiniCPM-o-4_5/model/MiniCPM-o-4_5-Q4_K_M.gguf --mmproj ../MiniCPM-o-4_5/MiniCPM-o-4_5-vision-F16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg --jinja --reasoning-budget -1 -p "what is it?"

# 或以禁止思考模式运行
./llama-mtmd-cli -m ../MiniCPM-o-4_5/model/MiniCPM-o-4_5-Q4_K_M.gguf --mmproj ../MiniCPM-o-4_5/MiniCPM-o-4_5-vision-F16.gguf -c 4096 --temp 0.7 --top-p 0.8 --top-k 100 --repeat-penalty 1.05 --image xx.jpg --jinja --reasoning-budget 0 -p "what is it?"

命令行参数解析:

参数-m, --model--mmproj--image-p, --prompt-c, --ctx-size--reasoning-budget--jinja
含义语言模型路径视觉模型路径输入图片路径提示词输入上下文最大长度最大思考输出token数量使用jinja模板

Ollama​

1. 安装 Ollama​

本地构建运行 Ollama​

环境需求:

  • go version 1.22 or above
  • cmake version 3.24 or above
  • C/C++ Compiler e.g. Clang on macOS, TDM-GCC (Windows amd64) or llvm-mingw (Windows arm64), GCC/Clang on Linux.

获取 OpenBMB 官方 Ollama 分支:

Bash
git clone https://github.com/tc-mb/ollama.git
cd ollama
git checkout MiniCPM-V

在仓库根目录下编译并运行 Ollama:

Bash
go build .
./ollama serve

2. 快速使用​

Ollama 可以直接使用:

Bash
./ollama run openbmb/minicpm-o4.5

命令行​

用空格分割输入问题、图片路径

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

API​

Python
with open(image_path, 'rb') as image_file:
# 将图片文件转换为 base64 编码
encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
data = {
"model": "minicpm-o4.5",
"prompt": query,
"stream": False,
"images": [encoded_string]# 列表可以放多张图,每张图用上面的方式转化为base64的格式
}

# 设置请求 URL
url = "http://localhost:11434/api/generate"
response = requests.post(url, json=data)

return response

3. 自定义方式​

若上述方式无法运行,请参考以下教程。

获取 GGUF 模型​

创建 ModelFile​

编辑 ModelFile:

Bash
vim minicpmv4.5.Modelfile

ModelFile 的内容如下:

Plain Text
FROM ./MiniCPM-o-4_5/model/MiniCPM-o-4_5-Q4_K_M.gguf
FROM ./MiniCPM-o-4_5/mmproj-model-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 4096
PARAMETER stop ["<|im_start|>","<|im_end|>"]
PARAMETER temperature 0.7

参数说明:

first fromsecond fromnum_ctx
Your language GGUF model pathYour vision GGUF model pathMax Model length

创建 Ollama 模型实例:​

Bash
./ollama create minicpm-o4.5 -f minicpmv4.5.Modelfile

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

Bash
./ollama run minicpm-o4.5

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

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

FastAPI 全模态流式​

提供 Web 与端侧演示应用,帮助您快速体验和展示 MiniCPM-o / MiniCPM-V。

📖 English Version | 返回主页

移动端与鸿蒙 Demo(MiniCPM-V-Apps)​

在 iOS / Android / HarmonyOS NEXT 上通过 llama.cpp 做本地多模态推理,请使用官方仓库 OpenBMB/MiniCPM-V-Apps(三端共享根目录 llama.cpp submodule;完整说明见 README / README_zh;预编译包见 DOWNLOAD / DOWNLOAD_zh)。

Cookbook 中 iOS 快速入口:iOS demo。

Web Demo​

我们提供两种类型的 Web 演示应用,适用于不同的使用场景:

📖 图文演示​

最适合: 标准多模态交互、文档处理、图像分析

特点:

  • 基于文本和图像的交互
  • 支持文件上传的多轮对话
  • 适合研究、教育和基础多模态任务
  • 支持多种图像格式和文档解析

可用版本:

  • Gradio: 简洁易用的 Web 界面,支持快速部署
  • OpenWebUI: 高级 Web 界面,具有增强功能

🎤 全模态流式演示​

最适合: 实时语音对话、多模态流式处理、语音交互

特点:

  • 实时语音对话能力
  • 音视频流处理支持
  • 语音克隆和情感控制
  • 多模态同时处理
  • 流式交互 API 端点

使用场景​

全模态流式演示​

  • 语音助手: 支持语音交互的对话 AI
  • 流媒体应用: 多模态流式交互界面
  • 客户服务: 语音客服系统
  • 娱乐应用: 语音克隆和互动媒体

Gradio​

为 MiniCPM-o 4.5 提供 Web 界面演示服务,支持图片和视频的多模态对话。演示由两部分组成:服务端 和 客户端。

📖 English Version

主要特性​

  • 多模态输入:支持图片和视频
  • 流式输出:实时流式响应
  • 思考模式:显示模型的推理过程(<think> 标签)
  • 显存优化:仅加载视觉和语言模块,禁用音频/TTS以节省显存

部署步骤​

服务端​

Bash
cd server
conda create -n gradio-server python=3.10
conda activate gradio-server
pip install -r requirements.txt
python gradio_server.py

自定义参数:

Bash
# 指定服务端口、日志目录、模型路径和模型类型 (MiniCPM-o 4.5)
# 如果显存有限,可以使用 INT4 量化模型
python gradio_server.py --port=9999 --log_dir=logs_o45 --model_path=openbmb/MiniCPM-o-2_6 --model_type=minicpmo4_5

客户端​

Bash
cd client
conda create -n gradio-client python=3.10
conda activate gradio-client
pip install -r requirements.txt
python gradio_client_minicpmo4_5.py

自定义参数:

Bash
# 指定前端端口和后端服务地址 (MiniCPM-o 4.5)
python gradio_client_minicpmo4_5.py --port=8889 --server=http://localhost:9999/api

访问​

默认情况下,服务启动后,可以通过浏览器访问 http://localhost:8889 来使用 Web Demo。

UI 功能​

解码类型​

  • Sampling:默认模式,支持实时流式输出
  • Beam Search:输出质量更高但不支持流式输出

思考模式​

启用后可以看到模型的推理过程。思考内容会以视觉区分的方式显示在单独的区域。

流式模式​

启用后可以实时逐字符输出。仅在 Sampling 模式下可用。

demo

开发者精选

查看全部 →