MiniCPM-o 4.5: Towards Real-Time Full-Duplex Omni-Modal Interaction

Paper: arXiv:2604.27393 Code: OpenBMB/MiniCPM-o Code reference: main @ 3ec4cb0e (2026-05-19); HF model repo openbmb/MiniCPM-o-4_5 @ 4382fcae (2026-05-19)

1. Motivation (研究动机)

MiniCPM-o 4.5 关注的不是「再给 MLLM 加一种输入模态」这么窄的问题,而是把多模态模型从离线、轮流、被动的问答接口推进到实时、连续、全双工的交互接口。论文的判断是:当图像、视频、音频、文本输入和语音输出都已经能被模型覆盖之后,主要瓶颈不再只是 modality coverage 或单次推理 latency,而是交互范式本身。传统 MLLM 通常先收集用户输入,再完成理解,再生成文本或语音回复;这会把 perception 和 response 切成交替阶段,模型说话时不能持续吸收新环境信息,也很难在环境变化时立刻修改输出。

Figure 1 解读:这张图把 AI 交互范式从 text-only、multimodal understanding、omni live streaming 一直推到 full-duplex interaction。MiniCPM-o 4.5 的位置不是单纯增加 audio/video 输入,而是把「看、听、说」放进同一条实时互动时间轴:模型需要在说话期间继续接收视觉与音频流,并允许输出由正在变化的上下文驱动。

现有方法的第一个具体问题是 blocked I/O:输入和输出不能同时流动。以视频通话或车载助手为例,用户讲话、环境画面和模型语音反馈本来是并行发生的;如果模型必须等用户停顿、等一段视频结束、再开始说话,它生成的内容就天然滞后。第二个问题是 passive response:多数模型只在明确 prompt 之后反应,而不是持续观察环境后主动提醒。论文给出的目标能力包括 continuous scene description、proactive reminding、实时纠正正在说出的描述等,这些都要求模型能够在没有新的显式 user trigger 时根据环境变化决定是否开口。

Figure 2 解读:图中对比了 turn-based interaction 与 full-duplex streaming。左侧范式里,模型先等输入结束,再生成完整输出,因此信息流被阶段边界阻塞;右侧范式里,env-visual、env-audio 和 out-stream 同时推进,模型在每个时间窗口吸收最新输入并决定继续听还是说。这正是本文把「实时交互」定义为时间对齐问题的原因。

这个问题值得研究,因为它直接决定 MLLM 是否能从「多模态工具」变成「环境中的交互式 agent」。如果模型只能在回合边界更新状态,那么它可以做离线视频理解、语音转文本、TTS 或图像问答,却很难做长时间陪伴、实时教学、驾驶/机器人场景中的提醒、会议中的插话和纠错。MiniCPM-o 4.5 的工程目标也很明确:在 9B 参数规模下,把视觉、语音理解、语音生成和全双工交互放在同一个端侧可部署系统里,并在 INT4/llama.cpp-omni 设置下把 RAM 控制到约 11GB,避免把 full-duplex 只留给巨大云端模型。

2. Idea (核心思想)

核心洞见是:全双工 omni-modal interaction 可以被建模为共享时间轴上的多路 token stream 对齐问题,而不是一个「先听完再回答」的序列到序列问题。MiniCPM-o 4.5 用 Omni-Flow 将 env-visual、env-audio 和 out-stream 切成细粒度时间窗口,在每个窗口内先接收新到达的感知 token,再生成控制/文本/语音相关输出 token,从而把 perception-response coupling 变成 LLM backbone 可以处理的统一 serialization。

关键创新有三层。第一层是 end-to-end omni-modal architecture:SigLIP2-style vision encoder、Whisper-medium audio encoder、Qwen3-8B backbone、轻量 speech token decoder 与 streaming flow-matching Token2Wav 模块通过 hidden state/token 接口连接。第二层是 Omni-Flow:把并行的输入/输出流用 time-division multiplexing 变成时间局部的信息组,显式表示 [listen] / speak control、边界和 chunk。第三层是 Time-Aligned Interleaving (TAIL):不让文本大幅领先语音播放,而是按累计播放进度调节每个 chunk 生成多少文本和 speech tokens,让用户听到的语音尽量对应当前环境。

与 Qwen3-Omni 或 Mini-Omni 类方法相比,本文的根本区别在于它把「是否说、说什么、何时说出来」都纳入同一条实时 timeline。常见 streaming speech generation 要么先产生较长 text lead 再合成语音,要么用固定 text/speech token ratio 交替,这两者都可能造成 spoken content 对应过旧上下文。MiniCPM-o 4.5 的 TAIL 和 Omni-Flow 则把「语音播放时间」本身当作模型输出结构的一部分;因此它牺牲了一部分离线生成的自由度,换取说话期间持续听看和主动开口的能力。

3. Method (方法)

3.1 Overall framework:端到端 omni-modal 架构

Figure 3 解读:图中从左到右展示了 MiniCPM-o 4.5 的输入、核心 LLM 和输出链路。视觉输入通过 visual encoder/resampler 转成视觉 token;音频输入通过 Whisper encoder 和 projector 转成音频 token;Qwen3-8B backbone 在统一序列中做理解、控制和文本生成;speech token decoder 读取 backbone hidden states 后生成 S3 speech tokens,最后由 streaming flow-matching decoder 转成 waveform。图底部的 timeline 是方法的关键:这些 token 不是离线拼接,而是按毫秒级时间轴对齐。

视觉编码。 论文采用 LLaVA-UHD 式 image partitioning 支持任意纵横比高分辨率图像,并用 resampler 提高压缩率。在 full-duplex streaming 模式下,最大分辨率为 ;其他模式下可到 。每个 image slice 先由 0.4B SigLIP ViT 编成 1024 个 token,再由 resampler 压缩到 64 个 token,达到 visual token compression。这个设计的动机是很实用的:全双工流式模式下每秒都会持续塞入视觉与音频信息,如果视觉 token 太多,LLM 的时间窗口会被感知 token 挤满,留给控制和语言生成的预算就不足。

音频编码。 音频侧使用 Whisper Medium encoder(约 0.3B)以 chunk-based streaming 方式编码输入,原始输出约为每秒 50 个 feature tokens;随后使用 two-layer MLP projector 进行 temporal compression,变成每秒 10 个 audio tokens 供 LLM backbone 消费。released code 的 HF config.json 中也能看到 audio_pool_step=5stream_input=truemodeling_minicpmo.pyget_audio_embedding_streaming 维护 audio_past_key_values,在 streaming 场景中复用历史 KV cache,并在 mel 序列接近 audio encoder 最大长度时 reset。

LLM backbone 与输出。 backbone 是 Qwen3-8B,论文附录给出的架构为 36 layers、hidden dimension 4096、32 attention heads、8 KV heads、FFN dimension 12288、vocabulary size 151748、max context length 40960。这个 backbone 同时承担 omni-modal understanding、listen/speak control 和 text generation。

语音输出不是直接由 LLM 生成 waveform,而是先进入约 0.3B 的 Llama-style speech token decoder:对每个 text token,将 LLM hidden state 经 MLP reshaping 后与 speech decoder state 结合,生成 S3 discrete speech tokens;最后 streaming flow-matching decoder 根据 multimodal system prompt 中的 reference audio 把 speech tokens 转成 waveform。

这解释了为什么系统能支持 configurable voice、voice cloning 和 role play:参考音频不是事后滤镜,而是 waveform synthesis 的条件。

3.2 Omni-Flow:共享时间轴上的统一 serialization

Omni-Flow 的形式化对象是三条时间对齐流:环境视觉流、环境音频流、输出流。令时间窗口长度为 ,第 个窗口覆盖 。在该窗口内,视觉输入编码为 ,音频输入编码为 ,输出更新表示为 ;如果模型不应输出内容, 只包含特殊 token \texttt{[listen]}。于是一个交互片段可以抽象为: 实际送入 LLM 时,Omni-Flow 使用 time-division multiplexing 思想把并行 stream 序列化为按时间排列的 group。每个 group 先放新到达的 perception tokens,再放 output/control tokens,这保证了 至少条件于同一窗口内最新的 ,而不是只条件于上一回合结束前的旧状态。直觉上,这相当于把「边听边说」拆成很多很短的 micro-turn:单个窗口仍是自回归 token prediction,但窗口足够短时,宏观行为就近似全双工。

Omni-Flow 的 ablation 说明这种 serialization 不是随意选择。论文比较了 chunk size、boundary explicitness 和 control formulation。最佳设置是 1.0s chunk、显式边界、Listen-Speak (LS) 控制,在 AdvBench/AlpacaEval/IFEval/SDQA/MMLU 上分别为 0.98/3.56/0.29/0.36/0.65。改成 Listen-Text (LT) 时 AlpacaEval 最高为 3.60,但 IFEval 和 MMLU 降到 0.24 和 0.56;去掉显式边界时 IFEval/SDQA/MMLU 进一步降到 0.22/0.28/0.45。把 chunk 缩到 0.2s 或 0.1s 会让控制更频繁,但模型每个窗口可用信息和生成预算太少,MMLU 分别降到 0.45 和 0.32。论文据此选择 1.0s 作为稳定性与响应性的折中。

3.3 Time-Aligned Interleaving (TAIL):让语音不要落后于环境

Figure 4 解读:图中 (a) 表示先生成较长 text lead 再合成语音,内容质量可能好但播放滞后;(b) 表示固定 text-speech ratio 的交替生成,能流式输出但假设文本 token 与语音时长几乎固定;(c) 是本文的 TAIL,它按 chunk 的时间边界自适应决定本 chunk 生成多少文本/语音,使播放进度追随当前环境。

TAIL 解决的是 text generation time 与 speech playback time 的 mismatch。如果第 秒窗口内生成的一段文本实际要读 秒,语音就会越来越落后;当环境中出现新事件时,用户听到的仍是旧文本。这在 full-duplex 场景中比普通 TTS 更严重,因为模型说话期间仍在接收新视觉/音频流。TAIL 的监督来自全双工训练数据中每个 text token 的 start/end time:start time 落在 的 text tokens 及其 speech tokens 被分配到第 个 Omni-Flow chunk。这样模型学到的不是固定比例,而是 history-dependent interleaving:若前面已经积累播放延迟,本 chunk 可以少生成文本,让语音追上。

TAIL 还引入 bounded look-ahead。语音合成有时需要少量未来文本上下文,例如英文冠词 “the” 的发音取决于后续词。TAIL 因此将 chunk 末尾少数 text tokens 对应的 speech tokens 延迟到 chunk ,给 pronunciation/prosody 留出局部上下文,但避免 text stream 大幅领先 playback。实验中,固定文本 interleaving 在 SeedTTS 上 ZH CER=0.86、EN WER=2.38 最好;动态 TAIL 的 ZH CER=1.04、EN WER=3.93,略损失离线识别精度,但 EN SIM-o=65.1 最高,并保留 full-duplex 时间对齐能力。这个结果说明 TAIL 不是单纯追求 TTS benchmark,而是在 speech quality 和 interaction freshness 之间取平衡。

3.4 训练流程与目标

训练分四阶段。第一阶段是 speech pretraining:从 Whisper encoder 和 MiniCPM-V 4.5 checkpoint 初始化,随机初始化 audio projector、LLM-to-speech projector 和 speech decoder;为保护视觉/语言能力,冻结 pretrained components,仅训练新增 speech-related modules,使 Whisper features 对齐到 LLM hidden space,并让 speech decoder 学会从 LLM hidden states 预测 speech tokens。第二阶段是 joint pretraining:解冻全部参数,在 vision-language、speech、omni-modal 数据混合上训练。论文特别指出不同 modality combinations 会分配给不同 data-parallel ranks,以保证每个训练 step 的数据比例稳定。

第三阶段是 joint supervised fine-tuning:先做大规模 instruction tuning 覆盖广泛能力,再用高质量人工标注样本做行为精修。为了在推理时支持质量/效率折中,omni-modal data 会随机最大 frame resolution 到 0.2—0.4 megapixels,并从 1—5 FPS 均匀采样 frame rate。第四阶段是 RL:先用 GRPO 提升 reasoning 与 instruction following,奖励包括 answer accuracy、format reward、general reward model;accuracy reward 混合 rule-based verification 和 judge model。随后用 RLAIF-V 降低视觉场景幻觉,并观察到 image-text hallucination mitigation 能迁移到 omni-modal full-duplex streaming。

RL 中的平滑长度奖励是本文少数明确公式之一。对同一 prompt 的候选回复,设 表示正确性, 为第 个回复长度, 为同组最短/最长长度,则: 这里 避免短但错误的回答拿到正奖励, 在长度差很小时下调奖励强度。作者还在前 480 个 RL steps 不加入 length reward,避免训练早期过早压缩 reasoning path。length reward ablation 显示:Kimi K1.5-style 奖励在 thinking mode 中让长度减少 50.7%,但 benchmark average 从 73.5 降到 73.0;本文 smooth reward 长度减少 35.3%,average 反而到 74.3。也就是说,它不是简单惩罚长答案,而是只减少冗余推理。

Figure 5 解读:这张训练曲线展示了 length reward 的副作用差异。Kimi K1.5-style 的长度惩罚更激进,会在后期拖慢甚至伤害 training accuracy;smooth length reward 的曲线更接近 no length reward,同时获得明显长度缩短。这支持论文对 中平滑因子和 warmup 的设计。

3.5 Released code 对应关系与伪代码

论文主仓库 OpenBMB/MiniCPM-o 提供 README、demo、评测/微调入口和 MiniCPM-o 4.5 的代码链接;实际 AutoModel.from_pretrained("openbmb/MiniCPM-o-4_5", trust_remote_code=True) 使用的模型实现位于 HuggingFace model repo。下面伪代码基于 GitHub main@3ec4cb0e 与 HF 4382fcae,重点反映 released inference implementation;训练 launch scripts 和训练数据配比没有在该 GitHub/HF snapshot 中开源,因此训练超参不从 README 默认运行参数中推断。

伪代码 1:streaming audio embedding 注入。 对应 MiniCPMO.get_audio_embedding_streamingget_omni_embedding

def inject_streaming_audio_embeddings(model, data, token_embeddings):
    wav = data.get("audio_features", [])
    if len(wav) == 0:
        return token_embeddings
 
    # Whisper encoder runs chunk by chunk and reuses cached KV.
    audio_out = model.apm(
        wav,
        past_key_values=model.audio_past_key_values,
        output_hidden_states=True,
        attention_mask=build_streaming_audio_mask(wav),
    )
    model.audio_past_key_values = audio_out.past_key_values
    audio_states = audio_out.hidden_states[model.audio_encoder_layer]
    audio_embeds = model.audio_projection_layer(audio_states)
    audio_embeds = model.audio_avg_pooler(audio_embeds.transpose(1, 2)).transpose(1, 2)
 
    # Replace placeholder positions in the LLM input sequence.
    for b, bounds in enumerate(data["audio_bounds"]):
        cursor = 0
        flat_audio = torch.cat(split_by_lengths(audio_embeds[b], data["audio_feature_lens"][b]), dim=0)
        for start, end in bounds:
            n = end - start
            token_embeddings[b, start:end] = flat_audio[cursor:cursor + n]
            cursor += n
    return token_embeddings

伪代码 2:Omni-Flow full-duplex streaming loop。 对应 README 中 model.as_duplex()MiniCPMODuplex.preparestreaming_prefillstreaming_generate

def duplex_omni_loop(model, video_chunks, audio_chunks, ref_audio, system_prompt):
    duplex = model.as_duplex(chunk_ms=1000, max_new_speak_tokens_per_chunk=20)
    duplex.prepare(prefix_system_prompt=system_prompt, ref_audio=ref_audio)
    outputs = []
 
    for frames_t, audio_t in zip(video_chunks, audio_chunks):
        # Once per second: feed current perceptual chunk into the decoder state.
        prefill_log = duplex.streaming_prefill(
            audio_waveform=audio_t,
            frame_list=frames_t,
            max_slice_nums=1,
            batch_vision_feed=True,
        )
 
        # Then decide listen/speak and optionally synthesize a speech chunk.
        step = duplex.streaming_generate(max_new_speak_tokens_per_chunk=20)
        if step["is_listen"]:
            outputs.append(torch.zeros_like(step["audio_waveform"]))
        else:
            outputs.append(step["audio_waveform"])
    return torch.cat(outputs), duplex.get_generated_text()

伪代码 3:TAIL / interleaved speech token generation。 对应 MiniCPMTTS.interleaved_generategenerate_chunk;注意 released code 中 interleaved_generate 不把 make_streaming_chunk_mask_inference 作为参数传给 generate_chunk,后者的实际签名不含 attention_mask

def interleaved_tts_generate(tts, text_hidden_chunks, speaker_embedding, eos_token):
    past_key_values = None
    generated_tokens = []
    eos_token = torch.as_tensor(eos_token, device=text_hidden_chunks[0].device)
 
    for idx, hidden_k in enumerate(text_hidden_chunks):
        # Real code receives a list of per-chunk conditions. Each condition already
        # represents text hidden states plus the audio-BOS context for the TTS decoder.
        condition = hidden_k.to(text_hidden_chunks[0].device)
 
        # sliding_recompute path: concatenate a few recent conditions and their
        # generated audio-token embeddings, then restart KV for this local window.
        if tts.attention_type == "sliding_recompute" and should_recompute(idx):
            recomputed = []
            for j in recent_chunk_indices(idx, tts.window_size, tts.recomputed_chunks):
                recomputed.append(text_hidden_chunks[j])
                recomputed.append(tts.emb_code[0](generated_tokens[j][:, :, 0]))
            recomputed.append(condition)
            condition = torch.cat(recomputed, dim=1)
            past_key_values = None
 
        new_tokens, past_key_values = tts.generate_chunk(
            inputs_embeds=condition,
            temperature=tts.temperature,
            repetition_penalty=tts.repetition_penalty,
            eos_token=eos_token,
            max_new_token=500,
            past_key_values=past_key_values,
            force_no_stop=False,
        )
        generated_tokens.append(new_tokens)
    return torch.cat(generated_tokens, dim=1)

make_streaming_chunk_mask_inference 仍是 released code 中的 streaming attention 辅助函数:它根据 tts_text_scopetts_text_mask 和 audio chunk size 构造 4D causal mask,使 [Ptts] 与后续 audio tokens 只能看到允许的 text prefix;但它不是 interleaved_generate -> generate_chunk 调用链中的显式参数。

伪代码 4:smooth length reward。 对应 paper §Training 公式;released repo 未包含训练 launch/config:

def smooth_length_reward(correct: torch.Tensor, lengths: torch.Tensor, tau: float):
    l_min = lengths.min()
    l_max = lengths.max()
    denom = torch.clamp(l_max - l_min, min=1.0)
    scale = torch.minimum(torch.tensor(1.0, device=lengths.device), denom / tau)
    s = (0.5 - (lengths - l_min) / denom) * scale
    return torch.where(correct.bool(), s, torch.minimum(torch.zeros_like(s), s))

论文公式与 released code 实现差异:本次没有发现 inference code 与论文架构描述直接矛盾;更重要的 gap 是训练侧并未开源完整 launch script、数据混合配置和 GRPO/RLAIF-V 实现。因此笔记中的训练阶段、length reward 和数据配比来自 paper source,架构/推理实现来自 HF remote code;不把 README 的 demo 参数当作训练配置。

Code reference: GitHub main @ 3ec4cb0e (2026-05-19); HF openbmb/MiniCPM-o-4_5 @ 4382fcae (2026-05-19) — pseudocode and mapping based on these snapshots

Paper ConceptSource FileKey Class/Function
MiniCPM-o 4.5 usage / code entryREADME.mdAutoModel.from_pretrained(..., init_vision=True, init_audio=True, init_tts=True), model.as_duplex()
Model config / architecture flagsconfiguration_minicpmo.py, config.jsonMiniCPMOConfig, MiniCPMTTSConfig, init_vision, init_audio, init_tts, audio_pool_step=5
Unified omni modelmodeling_minicpmo.pyMiniCPMO.__init__, get_vision_embedding, get_audio_embedding_streaming, get_omni_embedding
Full-duplex session wrappermodeling_minicpmo.pyMiniCPMODuplex.from_existing_model, prepare, streaming_prefill, streaming_generate
Streaming speech token decoder / TAIL-related inferencemodeling_minicpmo.pyMiniCPMTTS.generate_chunk, interleaved_generate, make_streaming_chunk_mask_inference
Vision slicing and audio preprocessingprocessing_minicpmo.py, modeling_navit_siglip.pyMiniCPMVImageProcessor, StreamingMelProcessorExact, MiniCPMOProcessor, SiglipVisionEmbeddings

4. Experimental Setup (实验设置)

数据。 训练数据分为三大类。Speech data 包括从多源收集并经 VAD、ASR、speaker/music separation 等流水线处理的「millions of hours」无标注自然语音,以及由文本 LLM 生成后经专业 voice actors 录制的 spoken dialog data;论文没有公开精确小时数和样本数。Vision-language data 继承并扩展 MiniCPM-V 4.5 数据体系,包括 CapsFusion 生成的高质量 caption、relevance-aware masking 的 document/OCR 数据、真实用户交互查询、reward-model filtering 后的详细 CoT-style responses、dense video captioning data 和 MiniCPM 4.1 post-training text-only instruction data。Omni-modal full-duplex data 包括大规模 web audio-video 数据和少量高质量 full-duplex task data;每个样本包含 visual input、audio input、output text、output speech,并给每条信息加 time index。论文同样没有披露该部分的精确规模。

模型与训练配置。 基座来自 MiniCPM-V 4.5 pretraining checkpoint;音频侧初始化 Whisper encoder;LLM backbone 为 Qwen3-8B;视觉 encoder 为 SigLIP ViT;TTS/Token2Wav 使用 CosyVoice2/Step-Audio2 风格组件。附录架构表给出的关键参数包括:visual encoder 417.8M、hidden 1152、27 layers、16 heads、patch size ;visual resampler 88.9M、64 query tokens、embedding dimension 4096;

audio encoder 307.2M、hidden 1024、24 layers、80 mel bins;audio projector 21.0M、1024→4096→4096 two-layer MLP;Qwen3-8B backbone 8189.2M、36 layers、hidden 4096、32 heads、8 KV heads、max context length 40960;speech token decoder hidden 768、20 layers、12 heads、speech codebook size 6562、speech token frame rate 25/s。

训练过程包括 speech pretraining、joint pretraining、joint SFT、GRPO/RLAIF-V;论文未公开 GPU type/count、batch size、learning rate 或总 steps。

评测基准。 Vision-language 评测覆盖五类:STEM/general(OpenCompass、MMBench、MathVista、MMVet、MMMU、MMStar、AI2D、MMT-Bench、MM-IFEval)、document/OCR(OCRBench、TextVQA、DocVQA、OmniDocBench)、hallucination(HallusionBench、MMHal)、multi-image(Mantis-Eval、MUIRBench、MMSI-Bench)和 video(Video-MME、LVBench、MLVU、LongVideoBench、MotionBench)。

Speech understanding 使用 VoiceBench AlpacaEval、Speech TriviaQA/Web Questions/CMMU;speech generation 使用 SeedTTS Test-ZH/EN、LongTTS、Expresso、ESD,其中 CER/WER 越低越好,SIM-o 越高越好。Text capability 与 Qwen3-8B-Instruct 比较 IFEval-PLS、BBH、CMMLU、MMLU、HumanEval、MBPP、Math500、GSM8K。

Omni-modal / streaming 评测包括 Daily-Omni、WorldSense、Video-Holmes、JointAVBench、AVUT-Human、FutureOmni、Video-MME-Short with audio,以及 vision-only full-duplex LiveSports-3K-CC。

推理设置。 vLLM 效率表在单张 NVIDIA RTX 4090 上比较 MiniCPM-o 4.5 与 Qwen3-Omni-30B-A3B;first-token latency 用 64-frame visual inputs 测量,throughput/memory 用 text-only tasks 测量。full-duplex streaming 部署进一步比较 PyTorch 与 llama.cpp-omni,在 RTX 4090 和 DGX Spark 上报告 real-time factor (RTF) 与 memory。RTF 越低越好;RTF<1 意味着生成速度快于实时播放。

5. Experimental Results (实验结果)

Figure 6 解读:雷达图汇总了 MiniCPM-o 4.5 在视觉语言、语音、omni-modal 与效率维度上的相对位置。它强调的是 9B 模型在多项能力上的平衡:不是每个单项都绝对第一,但在端侧可部署规模下同时具备视觉理解、语音生成和全双工 live streaming。

Vision-language instruct mode。 MiniCPM-o 4.5 在 OpenCompass 上得 77.6,略低于 Gemini 2.5 Flash 的 78.5,但高于 Qwen3-Omni-30B-A3B 的 75.7;在 MMBench EN/CN v1.1 分别为 87.6/87.2,是表中最高;MathVista 为 80.1,也是最高。Document/OCR 方面,TextVQA 83.8 接近 Qwen3-Omni 的 84.1,DocVQA 94.7 接近 95.4;OmniDocBench 越低越好,EN/CN 分别为 0.109/0.162,是表中最好。HallusionBench 63.2 最高,MMHal-Hallrate 24.3 只略高于 Gemini 2.5 Flash 的 23.9。Multi-image 中 Mantis-Eval 79.7、MMSI-Bench 16.6 最高;video 中 Video-MME 70.4、LVBench 50.9、MLVU 76.5、LongVideoBench 66.0,说明它保留了 MiniCPM 家族强视觉能力,但在长视频单项上并非全面领先。

Vision-language thinking mode。 thinking mode 中,MiniCPM-o 4.5 的 OpenCompass 为 78.2,低于 Gemini/GPT-5 但高于 MiniCPM-V 4.5 thinking 的 77.3;MMBench EN 为 89.0 最高,MMBench CN 为 87.6,接近 Qwen3-Omni 的 87.7;MathVista 81.0 低于 Gemini 2.5 Flash 的 81.9 和 MiniCPM-V 4.5 的 81.4。OCRBench 879 是表中最高,TextVQA 79.8、DocVQA 92.3 则低于 Qwen3-Omni/MiniCPM-V 4.5 的部分数值。这个模式的结论是:thinking 能提升部分 general/OCR 表现,但 omni-modal post-training 仍会在部分纯视觉 benchmark 上产生取舍。

Speech understanding 与 speech generation。 Audio understanding 表中,MiniCPM-o 4.5 在 VoiceBench AlpacaEval 上为 4.81,高于 Qwen3-Omni 的 4.74 和 MiniCPM-o 2.6 的 4.46;Speech TriviaQA 为 75.5,显著高于 62.9/41.9;Speech Web Questions 为 70.2,低于 Qwen3-Omni 的 74.9;Speech CMMU 为 59.2,低于 MiniCPM-o 2.6 的 67.0。Speech generation 表中,MiniCPM-o 4.5 在 SeedTTS Test-ZH CER=0.86、SeedTTS Test-EN WER=2.38、LongTTS EN WER=3.37、Expresso=29.8、ESD=82.1 上领先;SIM-o 上为 ZH 74.5、EN 64.9,略低于 CosyVoice2 的 74.8/65.2。与 Qwen3-Omni 相比,它在 SeedTTS EN WER(2.38 vs 3.39)和 LongTTS ZH CER(6.58 vs 18.99)差距明显。

Text capability 与 omni-modal benchmark。 与 Qwen3-8B-Instruct 相比,MiniCPM-o 4.5 的 text benchmark average 为 82.1,高于 Qwen3-8B-Instruct 的 81.6;IFEval-PLS 84.7、BBH 81.1、CMMLU 79.6、MBPP 76.7、GSM8K 94.5 更高,MMLU 77.0、Math500 77.0 低于 Qwen3 的 81.7/84.0。这说明 omni-modal training 没有整体摧毁文本能力,但数学/知识 benchmark 存在保留不完全。Omni-modal simplex benchmark 上,Daily-Omni 80.2 高于 Gemini 2.5 Flash 79.3 和 Qwen3-Omni 70.7;WorldSense 55.7 高于 52.6/54.0;Video-Holmes 64.3 高于 51.3/50.4;JointAVBench 60.0、AVUT-Human 78.6 最高;FutureOmni 56.1 低于 Qwen3-Omni 62.1;Video-MME-Short with audio 84.7 略低于 Gemini 85.5。

Full-duplex 与 ablation。 Vision-only full-duplex benchmark LiveSports-3K-CC 上,MiniCPM-o 4.5 为 54.4,高于 StreamingVLM 的 45.6 和另一个 8B baseline 的 41.5。Omni-Flow 设计 ablation 表明:1.0s/Explicit/LS 在 AdvBench=0.98、IFEval=0.29、SDQA=0.36、MMLU=0.65 上最好;LT 控制虽让 AlpacaEval 到 3.60,但综合稳定性较差;0.2s 和 0.1s chunk 的 AlpacaEval 只有 1.22 和 2.40,MMLU 只有 0.45 和 0.32,说明过短 chunk 会伤害语义决策。Speech generation mode ablation 显示 no interleave 的 ZH CER=1.44、EN WER=2.70;fixed text interleaving 为 0.86/2.38 最好;dynamic TAIL 为 1.04/3.93,但 EN SIM-o=65.1 最好,并满足全双工时间对齐目标。

推理效率。 vLLM on RTX 4090 中,Qwen3-Omni-30B-A3B BF16 OOM,而 MiniCPM-o 4.5 BF16 达到 154.3 tokens/s、first-token latency 0.59s、memory 19GB。INT4 下,Qwen3-Omni 为 147.8 tokens/s、0.98s、20GB;MiniCPM-o 4.5 为 212.3 tokens/s、0.58s、11GB,吞吐更高且内存近乎减半。full-duplex streaming 的框架比较中,PyTorch BF16 在 RTX 4090 OOM,在 DGX Spark RTF=2.43、memory 26GB;PyTorch INT4 在 RTX 4090/DGX Spark RTF=1.26/1.27、memory 14GB;llama.cpp-omni FP16 为 0.27/0.46、19GB;llama.cpp-omni INT4 为 0.21/0.20、11GB。这个结果支撑了论文「小于 12GB RAM 可端侧部署」的主张。

局限。 作者承认 MiniCPM-o 4.5 仍是 full-duplex omni-modal interaction 的早期探索。第一,长时间、动态真实流中的 foundation capability 与 robustness 仍需验证。第二,omni streaming mode 的语音生成偶尔会出现误读和中英混杂。第三,web demo 在网络不稳时可能高延迟或丢失输出片段,本地 llama.cpp-omni 更适合平滑实时体验。第四,proactive behavior 仍比较简单,未来需要更强的 context-aware planning 和 self-initiated assistance。整体看,本文的价值不在于每个 benchmark 都第一,而在于给出了一个可运行的时间对齐范式:在 9B 规模下把多模态理解、语音生成、主动提醒和全双工 streaming 统一到同一个模型与部署栈中。