



| iPhone iPhone 17 Pro Max | Android Redmi K70 | HarmonyOS HUAWEI nova 14 |
![]() | ![]() | ![]() |
pip install "transformers[torch]>=5.7.0" torchvision torchcodecNote on CUDA compatibility:torchcodec(used for video decoding) may have compatibility issues with certain CUDA versions. For example,torch>=2.11bundles CUDA 13.1 by default, while environments with CUDA 12.x may encounter errors such asRuntimeError: Could not load libtorchcodec. Two workarounds:
- Replace
torchcodecwithPyAV— supports both image and video inference without CUDA version constraints:pip install "transformers[torch]>=5.7.0" torchvision av- Pin the CUDA version when installing torch to match your environment (e.g. CUDA 12.8):
pip install "transformers>=5.7.0" torchvision torchcodec --index-url https://download.pytorch.org/whl/cu128
1from transformers import AutoModelForImageTextToText, AutoProcessor
2
3model_id = "openbmb/MiniCPM-V-4.6"
4
5processor = AutoProcessor.from_pretrained(model_id)
6model = AutoModelForImageTextToText.from_pretrained(
7 model_id, torch_dtype="auto", device_map="auto"
8)
9
10# Flash Attention 2 is recommended for better acceleration and memory saving,
11# especially in multi-image and video scenarios.
12# model = AutoModelForImageTextToText.from_pretrained(
13# model_id,
14# torch_dtype=torch.bfloat16,
15# attn_implementation="flash_attention_2",
16# device_map="auto",
17# )1messages = [
2 {
3 "role": "user",
4 "content": [
5 {"type": "image", "url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/refract.png"},
6 {"type": "text", "text": "What causes this phenomenon?"},
7 ],
8 }
9]
10
11downsample_mode = "16x" # Using `downsample_mode="4x"` for Finer Detail
12
13inputs = processor.apply_chat_template(
14 messages, tokenize=True, add_generation_prompt=True,
15 return_dict=True, return_tensors="pt",
16 downsample_mode=downsample_mode,
17 max_slice_nums=36,
18).to(model.device)
19
20generated_ids = model.generate(**inputs, downsample_mode=downsample_mode, max_new_tokens=512)
21generated_ids_trimmed = [
22 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
23]
24output_text = processor.batch_decode(
25 generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
26)
27print(output_text[0])1messages = [
2 {
3 "role": "user",
4 "content": [
5 {"type": "video", "url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/football.mp4"},
6 {"type": "text", "text": "Describe this video in detail. Follow the timeline and focus on on-screen text, interface changes, main actions, and scene changes."},
7 ],
8 }
9]
10
11downsample_mode = "16x" # Using `downsample_mode="4x"` for Finer Detail
12
13inputs = processor.apply_chat_template(
14 messages, tokenize=True, add_generation_prompt=True,
15 return_dict=True, return_tensors="pt",
16 downsample_mode=downsample_mode,
17 max_num_frames=128,
18 stack_frames=1,
19 max_slice_nums=1,
20 use_image_id=False,
21).to(model.device)
22
23generated_ids = model.generate(**inputs, downsample_mode=downsample_mode, max_new_tokens=2048)
24generated_ids_trimmed = [
25 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
26]
27output_text = processor.batch_decode(
28 generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
29)
30print(output_text[0])apply_chat_template:| Parameter | Default | Applies to | Description |
|---|---|---|---|
downsample_mode | "16x" | Image & Video | Visual token downsampling. "16x" merges tokens for efficiency; "4x" keeps 4× more tokens for finer detail. Must also be passed to generate(). |
max_slice_nums | 9 | Image & Video | Maximum number of slices when splitting a high-resolution image. Higher values preserve more detail for large images. Recommended: 36 for image, 1 for video. |
max_num_frames | 128 | Video only | The max_num_frames parameter dynamically controls the temporal context length and prevents VRAM overflow: Short Videos (duration ≤ max_num_frames sec): The processor defaults to 1 FPS, capturing second-by-second details without hitting the upper limit. Long Videos (duration > max_num_frames sec): The processor automatically switches to uniform sampling, selecting exactly max_num_frames evenly spaced across the entire timeline. |
stack_frames | 1 | Video only | Total sample points per second. 1 = main frame only (no stacking). N (N>1) = 1 main frame + N−1 sub-frames per second; the sub-frames are composited into a grid image and interleaved with main frames. Recommended setting is 1 for short videos, and 3 or 5 for long videos. |
use_image_id | True | Image & Video | Whether to prepend <image_id>N</image_id> tags before each image/frame placeholder. Set True for image, False for video. |
Note:downsample_modemust be passed to bothapply_chat_template(for correct placeholder count) andgenerate(for the vision encoder). All other parameters only need to be passed toapply_chat_template.
transformers serve pip install "transformers[serving]>=5.7.0"transformers serve openbmb/MiniCPM-V-4.6 --port 8000 --host 0.0.0.0 --continuous-batching1curl -s http://localhost:8000/v1/chat/completions \
2 -H 'Content-Type: application/json' \
3 -d '{
4 "model": "openbmb/MiniCPM-V-4.6",
5 "messages": [{
6 "role": "user",
7 "content": [
8 {"type": "image_url", "image_url": {"url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/refract.png"}},
9 {"type": "text", "text": "What causes this phenomenon?"}
10 ]
11 }]
12 }'1curl -s http://localhost:8000/v1/chat/completions -H 'Content-Type: application/json' -d '{
2 "model": "openbmb/MiniCPM-V-4.6",
3 "messages": [{"role": "user", "content": [
4 {"type": "text", "text": "the weather of Beijing"}
5 ]}],
6 "tools": [{
7 "type": "function",
8 "function": {
9 "name": "get_weather",
10 "description": "Get the current weather for a given location",
11 "parameters": {
12 "type": "object",
13 "properties": {
14 "location": {"type": "string", "description": "City name"}
15 },
16 "required": ["location"]
17 }
18 }
19 }]
20}'{
"id": "f4f09c7d-8045-4cb1-ade9-07aa5dee637d",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "I need to check the current weather for Beijing, so I will call the get_weather function.\n\n<tool_call>\n<function=get_weather>\n<parameter=location>\nBeijing\n</parameter>\n</function>\n</tool_call>",
"role": "assistant"
}
}
],
"created": 1778748859,
"model": "openbmb/MiniCPM-V-4.6@main",
"object": "chat.completion",
"usage": {
"completion_tokens": 47,
"prompt_tokens": 283,
"total_tokens": 330
}
}\n as string literals instead of actual newlines. To render the text correctly, especially in UI layers, you can use the following utility function. This function carefully replaces literal \n with real newlines while protecting scenarios where \n has specific semantic meaning.1import re
2
3_PATTERN = re.compile(
4 r'(```[\s\S]*?```' # fenced code blocks
5 r'|`[^`]+`' # inline code
6 r'|\$\$[\s\S]*?\$\$' # display math
7 r'|\$[^$]+\$' # inline math
8 r'|\\\([\s\S]*?\\\)' # \(...\)
9 r'|\\\[[\s\S]*?\\\]' # \[...\]
10 r')'
11 r'|(?<!\\)(?:\\r\\n|\\[nr])'
12)
13
14def normalize_response_text(text: str) -> str:
15 """
16 Lightweight post-processing: Converts literal '\\n' to actual newlines,
17 while protecting code blocks, inline code, and LaTeX commands.
18 """
19 if not isinstance(text, str) or "\\" not in text:
20 return text
21 return _PATTERN.sub(lambda m: m.group(1) or '\n', text)1vllm serve openbmb/MiniCPM-V-4.6 \
2 --port 8000 \
3 --enable-auto-tool-choice \
4 --tool-call-parser qwen3_coder \
5 --default-chat-template-kwargs '{"enable_thinking": false}'Note:--enable-auto-tool-choiceand--tool-call-parser qwen3_coderenable tool/function calling support. If you don't need tool use, you can omit these flags and simply runvllm serve openbmb/MiniCPM-V-4.6.
1curl -s http://localhost:8000/v1/chat/completions -H 'Content-Type: application/json' -d '{
2 "model": "openbmb/MiniCPM-V-4.6",
3 "messages": [{"role": "user", "content": [
4 {"type": "image_url", "image_url": {"url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/refract.png"}},
5 {"type": "text", "text": "What causes this phenomenon?"}
6 ]}]
7}'1curl -s http://localhost:8000/v1/chat/completions -H 'Content-Type: application/json' -d '{
2 "model": "openbmb/MiniCPM-V-4.6",
3 "messages": [{"role": "user", "content": [
4 {"type": "text", "text": "北京的天气"}
5 ]}],
6 "tools": [{
7 "type": "function",
8 "function": {
9 "name": "get_weather",
10 "description": "Get the current weather for a given location",
11 "parameters": {
12 "type": "object",
13 "properties": {
14 "location": {"type": "string", "description": "City name"}
15 },
16 "required": ["location"]
17 }
18 }
19 }]
20}'python -m sglang.launch_server --model openbmb/MiniCPM-V-4.6 --port 300001curl -s http://localhost:30000/v1/chat/completions -H 'Content-Type: application/json' -d '{
2 "model": "openbmb/MiniCPM-V-4.6",
3 "messages": [{"role": "user", "content": [
4 {"type": "image_url", "image_url": {"url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/refract.png"}},
5 {"type": "text", "text": "What causes this phenomenon?"}
6 ]}]
7}'llama-server -m MiniCPM-V-4.6-Q4_K_M.gguf --port 80801curl -s http://localhost:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{
2 "model": "MiniCPM-V-4.6",
3 "messages": [{"role": "user", "content": [
4 {"type": "image_url", "image_url": {"url": "https://huggingface.co/datasets/openbmb/DemoCase/resolve/main/refract.png"}},
5 {"type": "text", "text": "What causes this phenomenon?"}
6 ]}]
7}'ollama run minicpm-v-4.6llamafactory-cli train examples/train_lora/minicpmv4_6_lora_sft.yamlswift sft --model_type minicpm-v-4_6 --dataset <your-dataset>1@proceedings{yu2025minicpmv45cookingefficient,
2 title={MiniCPM-V 4.5: Cooking Efficient MLLMs via Architecture, Data, and Training Recipe},
3 author={Tianyu Yu and Zefan Wang and Chongyi Wang and Fuwei Huang and Wenshuo Ma and Zhihui He and Tianchi Cai and Weize Chen and Yuxiang Huang and Yuanqian Zhao and others},
4 year={2025},
5 url={https://arxiv.org/abs/2509.18154},
6}
7
8@article{yao2024minicpm,
9 title={MiniCPM-V: A GPT-4V Level MLLM on Your Phone},
10 author={Yao, Yuan and Yu, Tianyu and Zhang, Ao and Wang, Chongyi and Cui, Junbo and Zhu, Hongji and Cai, Tianchi and Li, Haoyu and Zhao, Weilin and He, Zhihui and others},
11 journal={arXiv preprint arXiv:2408.01800},
12 year={2024}
13}