
vLLM-Omni 部署 MiniCPM-o 4.5 在线服务多模态全双工与流式语音实战指南【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni本篇技术指南以 examples/online_serving/minicpmo/README.md 为主线系统讲解在 vLLM-Omni 中在线部署 OpenBMB MiniCPM-o 4.5 的完整流程从三阶段部署配置、/v1/chat/completions多模态请求到原生全双工full-duplexRealtime 会话、Gradio 演示与 Omni-DuplexEval 评测。读完本文你将掌握如何用一条命令启动 Thinker/Talker/Code2Wav 三阶段服务、用 curl / Python 客户端 / WebSocket 三种方式与之交互并理解各部署布局的内存预算与上下文开销计算。MiniCPM-o 4.5 在线服务概览MiniCPM-o 4.5 是 OpenBMB 的 omni 多模态模型输入支持文本、图像、音频与视频输出为文本以及可选的 24 kHz 语音。vLLM-Omni 将其拆分为三个独立推理阶段stageStage 0Thinker多模态 thinker负责理解用户输入并生成文本与编解码 tokenStage 1Talker基于 MiniCPMTTS 的流式编解码语言模型codec LM将 token 流转换为音频编解码单元Stage 2Code2Wav批量式的 codec-to-waveform 生成阶段负责把编解码单元合成为 24 kHz 单声道 PCM 波形。三个阶段由SharedMemoryConnector通过共享内存衔接详见各部署 YAML 中的connectors段。在线服务的示例代码位于 examples/online_serving/minicpmo/目录内包含 curl 脚本、OpenAI 兼容 Python 客户端、Gradio 演示、Realtime 全双工 CLI 演示以及浏览器端 WebSocket 客户端。关于原生全双工运行时的架构、生命周期不变量与能力边界可阅读 docs/design/fullduplex.mdDuplexClientAPI 与/v1/realtime?duplex1的完整线上协议见 docs/serving/realtime_duplex_api.md。环境安装安装 vLLM-Omni 并带上 MiniCPM-o talker 依赖pip install stepaudio2-minicpmominicpmoextra 会安装stepaudio2-minicpmo及其音频依赖包括librosaGradio 演示中的参考音频重采样即依赖它。启动后端服务部署配置通过--omni自动加载。默认的 vllm_omni/deploy/minicpmo_4_5.yaml 将三个阶段全部放在逻辑设备 0 上内存预算分别为 55%、15%、18%为 HiFi-GAN vocoder 的 cuDNN workspace 等运行时内核预留了余量该配置每个阶段最多接受 4 条序列并将 Talker 上下文限制在 4096 token。追求吞吐时vllm_omni/deploy/minicpmo_4_5_2gpu.yaml 将 Thinker 独占 GPU 090% 内存Talker55%与 Code2Wav35%共享 GPU 1每个阶段同样最多 4 条并发序列。部署配置GPU 数说明minicpmo_4_5.yaml默认1内存受限的兼容性布局。minicpmo_4_5_2gpu.yaml2推荐的连续批处理布局Talker 与 Code2Wav 共享 GPU 1。minicpmo_4_5_3gpu.yaml3每个阶段一张 GPU。minicpmo_4_5_8x4090.yaml8完整的 8x4090 布局。所有配置都设置了session_mode: duplex因此原生全双工与/v1/chat/completions由同一进程提供。默认单 GPU 启动vllm serve openbmb/MiniCPM-o-4_5 \ --omni \ --deploy-config vllm_omni/deploy/minicpmo_4_5.yaml \ --trust-remote-code \ --host 0.0.0.0 --port 8099如需使用本地 ModelScope 检查点将openbmb/MiniCPM-o-4_5替换为检查点路径即可。要使用原生全双工在同一台服务器上连接/v1/realtime?duplex1。从部署 YAML 理解默认配置以 minicpmo_4_5.yaml 为例其关键字段如下duplex_session.max_sessions: 4与 Stage 0/1 的max_num_seqs对齐窗口越小并发对话轮流时首个数据包的生成越会被串行化。Stage 0gpu_memory_utilization: 0.55、max_num_batched_tokens: 16384、interleave_mm_strings: trueMiniCPM 交错图像/音频的 Daily-Omni 数据包需要、media_io_kwargs.video为fps: 1, num_frames: 128、limit_mm_per_prompt中image: 64 / audio: 64 / video: 1采样参数为temperature 0.0 / top_p 1.0 / top_k -1 / max_tokens 2048 / seed 42 / repetition_penalty 1.0注释说明 1.0 用于 MCQ 精度1.1 可能对短 A–D 答案引入偏差。Stage 1Talkergpu_memory_utilization: 0.15、max_model_len: 4096对应tts_config.max_position_embeddings。Talker 是单一词表的编解码 LM采样参数直接作用于 vLLM 的 Samplertemperature 0.8 / top_p 0.85 / top_k 25 / repetition_penalty 1.05 / min_tokens 50 / max_tokens 4096。其中repetition_penalty由 Talker 在 16 帧窗口上重打分min_tokens对应上游的min_new_token。Stage 2Code2Wavgpu_memory_utilization: 0.18、enforce_eager: true、enable_chunked_prefill: false、max_model_len: 65536。Connectorconnector_get_sleep_s: 0.01、connector_get_max_wait_first_chunk: 3000、connector_get_max_wait: 300、codec_chunk_frames: 25、codec_left_context_frames: 3并开启enable_hift_graph、enable_cfm_graphcfm_max_graphs: 32、cfm_graph_bucket_frames: 16。HiFT 捕获桶由codec_chunk_frames与codec_left_context_frames推导。platforms.npuNPU 平台上 Stage 0/1 使用PIECEWISE的 CUDA 图模式Stage 2 保持外部 eager仅通过code2wav_enable_npu_graph: true捕获精确形状的 CFM DiT 估计器内核。8x4090 布局 的注释进一步解释了显存约束Stage 0 采用 4 路张量并行GPU 0-385% 内存Thinker 权重在 4090 上每卡约 17.5 GBStage 1 在 GPU 4、Stage 2 在 GPU 5均 90%。由于上游config.json宣称max_position_embeddings40960为 H20 141GB 调优在 24 GB 的 4090 上 40k token 的 KV cache 请求会在服务首个请求前 OOM因此该配置将max_model_len固定在 4096——这是经验验证的安全上限。逐阶段参数覆盖不需要手写整个 YAML 时可通过--stage-overrides覆盖任意阶段的参数vllm serve openbmb/MiniCPM-o-4_5 --omni --trust-remote-code --port 8099 \ --stage-overrides {0: {gpu_memory_utilization: 0.55}}发送多模态请求cd examples/online_serving/minicpmocurl 方式仓库自带的 run_curl_multimodal_generation.sh 支持四种查询类型text、use_audio、use_image、use_video与可选 modalities 参数bash run_curl_multimodal_generation.sh text bash run_curl_multimodal_generation.sh use_image bash run_curl_multimodal_generation.sh use_audio [text]脚本内部构造的请求体要点来自源码第 104-143 行sampling_params_listThinker 与 Talker 的采样参数分别传入注释说明这些是可选项默认值位于vllm_omni/deploy/minicpmo_4_5.yaml。modalitiesJSON 列表或nullnull表示服务端默认的 textaudio。chat_template_kwargs.use_tts_template请求根级显式传入curl 不会展开嵌套的extra_body当 modalities 为纯文本时自动置为false跳过|tts_bos|触发词。messages系统提示为 You are MiniCPM-o, a helpful multimodal assistant that can understand images, audio and video, and respond in text and speech.。脚本还内置了三个公共演示资源 URLmary_had_lamb.ogg、cherry_blossom.jpg、sample_demo_1.mp4并用jq只打印首个 choice 的文本音频是 base64 WAV过大不宜打印同时统计携带音频的 choice 数量。Python 客户端openai_chat_completion_client_for_multimodal_generation.py 是共享多模态客户端助手的薄封装内置 MiniCPM 专属默认值端口 8099、系统提示、chat_template_kwargs.use_tts_templatepython openai_chat_completion_client_for_multimodal_generation.py \ --query-type use_image \ --port 8099 \ --host localhost # 纯文本更快无 |tts_bos| python openai_chat_completion_client_for_multimodal_generation.py \ --query-type text \ --modalities text \ --prompt Briefly introduce yourself.客户端支持--model、--video-path、--image-path、--audio-path、--prompt、--modalities如text或text,audio、--num-concurrent-requests并发请求可搭配--prompts逗号分隔列表等参数。其内部逻辑源码第 48-147 行当modalities未指定时默认启用 TTS音频输出从choice.message.audio.data中 base64 解码后写入 WAV 文件--stream模式下逐 chunk 打印文本增量并保存音频块。流式文本 音频加--streampython openai_chat_completion_client_for_multimodal_generation.py \ --query-type text \ --prompt Briefly introduce yourself. \ --port 8099 \ --stream客户端会边接收边打印文本增量并将流式音频块保存为 WAV 文件。共享的辅助模块也直接可用只需自行传入 MiniCPM 默认参数python ../openai_chat_completion_client_for_multimodal_generation.py \ --model openbmb/MiniCPM-o-4_5 \ --query-type text \ --port 8099值得注意的架构变化语音输出不再依赖通用服务层中的 MiniCPM 专属默认值chat_template_kwargs.use_tts_templatetrue仍作为显式支持的模型选项保留见客户端源码第 84-86 行。启动 Gradio 演示bash examples/online_serving/minicpmo/run_gradio_demo.sh # 或直接运行 Python 入口 python examples/online_serving/minicpmo/gradio_demo.py \ --minicpmo45-api-base http://localhost:8099/v1 \ --minicpmo45-model openbmb/MiniCPM-o-4_5 \ --port 7862浏览器打开http://host:7862。从 gradio_demo.py 的源码可以看到几个实现细节默认参考音频为模型路径下的assets/HT_ref_audio.wav加载后会重采样为 16 kHz 单声道并截断到最多 8 秒3-10 秒是推荐范围避免长参考音频浪费 token开启语音输出时系统消息会携带参考音频构成 audio_assistant 提示中文前缀模仿音频样本的音色并生成新的内容要求模型以面壁小钢炮身份用高自然度方式聊天界面支持文本/图像/音频/视频输入TTS 开关、max tokens 与 temperature 滑杆音频输出直接内嵌在 UI 中播放。Daily-Omni 精度评测要点Daily-Omni 要求回答以 A–D 单个字母开头。评测时必须在--extra-body中显式设置chat_template_kwargs.enable_thinkingfalse——通用评测 CLI 不会注入 MiniCPM 专属默认值。若保留推理reasoning模式think中的思考文本可能耗尽 256 token 的答案预算导致首字母提取把推理文本也计为得分。建立文本基准时发送--extra_body {modalities:[text],chat_template_kwargs:{enable_thinking:false}}请求音频还会额外评测 Talker 与 Code2Wav并改变 assistant 模板因此与纯文本评测不是同一口径的精度对比。运行 Realtime 全双工 CLI 演示服务启动后通过 Realtime WebSocket 端点流式传输一个 WAVpython examples/online_serving/minicpmo/realtime_duplex_demo.py \ --url ws://localhost:8099/v1/realtime?duplex1 \ --model openbmb/MiniCPM-o-4_5 \ --input-wav /path/to/input_16k_mono_pcm16.wav \ --ref-audio /path/to/MiniCPM-o-Demo/assets/ref_audio/ref_minicpm_signature.wav \ --output-dir /tmp/minicpmo_realtime_duplex_demo输入 WAV 必须是 16 kHz 单声道 PCM16--ref-audio是 MiniCPM-o 全双工助手音色的必需参考音频缺少时会话会被拒绝错误为ref_audio_required。演示结束会在输出目录生成output.pcm、output.wav、events.jsonl与result.json其中result.json记录 TTFT、TTFP首个音频包延迟、RTF、文本/转写增量数、模型决策speak/listen等指标。该脚本基于 vllm_omni/clients/duplex.py 的DuplexClient与EventCollector实现。视频输入与帧堆叠--stack-frames视频输入使用同一个会话PyAV 按--video-fps默认 1.0解复用 JPEG 帧vLLM 的load_audio提取 16 kHz 单声道 WAV除非--input-wav覆盖音轨。帧保持原始采集尺寸--frame-max-side 0由服务端process_image在scale_resolution448下归一化。--stack-frames N用于提高视觉刷新率机制与官方 duplex 一致每个 1 秒单元额外采样其内部的N-1个子帧将它们拼贴为一张合成图与该单元的基础帧一起发送。音频节奏不变一个单元永远是 1 秒无论N多大线上始终每个单元携带 2 张图因为子帧共享一张合成图。官方在高刷新率模式下使用 5python examples/online_serving/minicpmo/realtime_duplex_demo.py \ --url ws://localhost:8099/v1/realtime?duplex1 \ --model openbmb/MiniCPM-o-4_5 \ --input-video /path/to/clip.mp4 \ --stack-frames 5 \ --ref-audio /path/to/MiniCPM-o-Demo/assets/ref_audio/ref_minicpm_signature.wav \ --output-dir /tmp/minicpmo_realtime_duplex_video_demoStage 0 处理堆叠单元的方式与官方 HD 模式一致max_slice_nums[2, 1]基础帧保留自己的 66-token 块加上get_sliced_grid按其尺寸在scale_resolution448切出的 patches合成图额外增加一个块。线上协议仍拒绝调用方传入max_slice_nums因此切片是 Stage 0 的决定而非客户端的。上下文成本预算帧堆叠会显著消耗上下文一个 960x540 帧每单元 66 个视觉 token堆叠的一对则是 264 个再加上单元音频Stage 0 提示词在堆叠模式下每秒增长 277 token而单帧模式为 79。以该模型自带的 40960-token 上下文计算一段 264 秒的 960x540 片段堆叠模式约 2.5 分钟触顶非堆叠约 8.5 分钟实测数据来自仓库文档。由于全双工会话尚不能淘汰旧单元多分钟通话请保持默认的--stack-frames 1堆叠会话若超出上下文将以 context-length 错误结束。打开实验性浏览器客户端浏览器 UI 会托管页面并将同源 Realtime WebSocket 代理到后端python -m examples.online_serving.minicpmo.realtime_web \ --port 7862 \ --ws-backend ws://127.0.0.1:8099 \ --ref-audio /path/to/MiniCPM-o-Demo/assets/ref_audio/ref_minicpm_signature.wav打开http://host:7862/。使用反向代理时访问映射到 7862 端口的 URL浏览器会根据该 URL 相对推导其 WebSocket 端点静态资源与 worklet 代码位于 examples/online_serving/minicpmo/realtime_web/app/。如果页面代理只提供 HTTP 而不转发 WebSocket 升级可将浏览器指向单独暴露的 Realtime 端点python -m examples.online_serving.minicpmo.realtime_web \ --port 7862 \ --ws-backend ws://127.0.0.1:8099 \ --public-realtime-url wss://public.example/v1/realtime验证软打断barge-in行为软打断 E2E 驱动默认使用--validation-mode model-policy对任意输入音频检查生命周期与流式不变量。更强的response-required模式属于诊断用途它要求一段专门构造的双响应 WAV、其--input-sha256以及--expect-second-response-substring值。仓库同时提供了 barge_in_serve.sh 用于一键启动带软打断验证的推理服务。运行 Omni-DuplexEval 评测Omni-DuplexEval 的生成阶段使用 vLLM-Omni 原生的 MiniCPM-o 全双工端点评估阶段使用同一个 vLLM-Omni 环境服务的独立 OpenAI 兼容多模态 judge。该流程验证的是 vLLM-Omni duplex 客户端与本地 judge 的集成并不复现论文原始的 MiniCPM-o 推理实现。先启动 duplex 生成服务器vllm serve openbmb/MiniCPM-o-4_5 --omni --trust-remote-code \ --deploy-config vllm_omni/deploy/minicpmo_4_5.yaml \ --served-model-name openbmb/MiniCPM-o-4_5 \ --host 0.0.0.0 --port 8099再启动一个独立的多模态 judge。--allowed-local-media-path必须包含通过--judge-video-mode video_url传入的本地视频vllm serve Qwen/Qwen2.5-VL-7B-Instruct \ --served-model-name Qwen/Qwen2.5-VL-7B-Instruct \ --allowed-local-media-path /data/omni-duplex-eval \ --host 0.0.0.0 --port 8000生成、评估与汇总vllm bench omni-duplex-eval --omni generate \ --url ws://127.0.0.1:8099/v1/realtime?duplex1 \ --model openbmb/MiniCPM-o-4_5 \ --ref-audio /data/ref.wav \ --dataset Hothan/Omni-DuplexEval \ --concurrency 2 \ --response-root /data/omni-duplex-eval/responses vllm bench omni-duplex-eval --omni evaluate \ --dataset Hothan/Omni-DuplexEval \ --response-root /data/omni-duplex-eval/responses \ --score-root /data/omni-duplex-eval/scores \ --judge-base-url http://127.0.0.1:8000 \ --judge-model Qwen/Qwen2.5-VL-7B-Instruct \ --judge-video-mode video_url \ --eval-workers 4 vllm bench omni-duplex-eval --omni summarize \ --score-root /data/omni-duplex-eval/scores数据集名称如RTD_OCR、PR_correction是 Hugging Face 的 split 而非数据集配置用--split传入其中一个或省略以运行全部九个 split--limit 1适合做冒烟测试。Realtime 生成记录clockmedia以--pace as-fast-as-possible生成的产物记录clockinvalid评估默认拒绝除非显式指定--allow-invalid-clock。流水线实现要点Stage 1 执行请求级的 AR 连续批处理Stage 2 持有请求级的 Flow/HiFT 缓存并按精确形状兼容的块进行批处理。参考音频随第一个 codec chunk 一起传输Stage 2 拥有其临时 prompt WAV并在请求结束时驱逐 prompt 特征。编解码采样读取检查点tts_config默认确定性种子 42Stage 1 YAML 的采样参数只作用于暴露给 vLLM 的二进制 continue/stop token。StageRequestStats.batch_size是请求作用域的不反映调度器的执行批次。Stage 0 与 Stage 1 使用 vLLM CUDA Graph 捕获Stage 2 保持 eager直到专用的精确形状图包装器接管静态 I/O 缓冲并在捕获之外复制请求缓存状态。三阶段共置可最小化硬件需求但会使它们的 CUDA 上下文在同一张 GPU 上争抢吞吐优先时应使用 8x4090 布局或自定义多 GPU 部署配置。输出音频以 base64 WAV 编码在message.audio.data中24 kHz 单声道。相关示例与延伸阅读离线推理对应示例examples/offline_inference/minicpmo/官方配方含硬件支持、加载配置与最佳实践recipes/OpenBMB/MiniCPM-o-4_5.md全双工运行时架构docs/design/fullduplex.mdRealtime Duplex API 与DuplexClient客户端文档docs/serving/realtime_duplex_api.md【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考