
vLLM-Omni Qwen3-Omni 离线推理实战同步多模态推理与 async_chunk 阶段级并发【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni本文基于仓库示例 examples/offline_inference/qwen3_omni 与其文档 Qwen3-Omni: Offline inference讲解如何在 vLLM-Omni 中对 Qwen3-Omni 执行离线offline推理从同步入口Omni的单条/批量多模态推理、输出模态控制、本地媒体文件接入到基于AsyncOmni的 async_chunk 阶段级并发Thinker 未结束前 Talker、Code2Wav 已提前启动的配置与运行方法并对照部署 YAML 与入口源码说明各参数背后的实际行为。1. 示例目录结构与两个入口离线示例位于examples/offline_inference/qwen3_omni包含两套入口脚本与配套 shell文件说明end2end.py同步入口基于 Omni 类end2end_async_chunk.py异步入口基于 AsyncOmni启用 async_chunk 阶段级并发run_single_prompt.sh单条 prompt音频输入run_multiple_prompts.sh批量 promptpy_generator 模式run_single_prompt_tp.sh显存不足时的单条 prompt 变体run_single_prompt_async_chunk.shasync_chunk 单条 promptrun_multiple_prompts_async_chunk.shasync_chunk 批量 并发控制text_prompts_10.txt10 条纯文本 QA 提示词两个入口的默认模型均为Qwen/Qwen3-Omni-30B-A3B-Instruct见 end2end.py 的 --model 定义。文档同时建议使用--deploy-config做部署级覆盖如各 stage 的显存分配其 YAML 结构可参考仓库内的 stage configs 文档。从源码结构看两条路径的核心差异在入口类Omni 的generate()带两个重载omni.py#L58-L101py_generatorTrue时返回 Python 生成器边生成边消费py_generatorFalse默认时一次性返回list[OmniRequestOutput]。AsyncOmni 的generate()是异步生成器async_omni.py#L104支持async for逐块消费并允许用asyncio.Semaphore控制请求级并发。另外Omni.generate 内部会把非 diffusion 的 LLM stage 采样参数强制为FINAL_ONLY输出除非显式指定DELTA这解释了为什么同步入口适合整请求落盘的离线场景。2. 同步推理单条与批量 prompt2.1 单条 prompt进入示例目录后运行cd examples/offline_inference/qwen3_omni bash run_single_prompt.sh该脚本run_single_prompt.sh实际执行python end2end.py --output-wav output_audio \ --query-type use_audio即加载一段默认音频资产未提供--audio-path时使用内置的mary_had_lamb音频见 get_audio_query把文本回答与 24 kHz WAV 分别写入output_audio目录。文档提示如果显存不足可改为 Thinker 阶段张量并行tensor parallel的变体bash run_single_prompt_tp.sh该脚本额外传入--stage-init-timeout 300run_single_prompt_tp.sh脚本注释说明该超时用于避免两个 vLLM stage 同时在同一张卡上初始化。需要注意脚本中另有一处注释end2end.py#L34-L36提醒默认的max_num_seqs/max_model_len在低端 GPU 上可能 OOM未特别配置时相关设置仅在单卡 L4 上验证过——显存紧张时应结合--deploy-config调整各 stage 的gpu_memory_utilization等参数。2.2 批量 prompt 与 py_generator 模式cd examples/offline_inference/qwen3_omni bash run_multiple_prompts.sh脚本内容run_multiple_prompts.shpython end2end.py --output-wav output_audio \ --query-type text \ --txt-prompts text_prompts_10.txt \ --py-generator关键点在于--py-generator文档说明处理大批量数据时应使用 py_generator 模式此时Omni.generate()返回一个 Python 生成器对象调用方可在生成过程中逐步消费每条请求的输出而不必等全部请求完成后再取结果。text_prompts_10.txt 是仓库自带的 10 条简单 QA 提示词如 What is the capital of France?用于演示--txt-prompts的每行一条 prompt格式注意--txt-prompts仅在--query-type text时有效代码中有断言见 end2end.py#L344-L349。2.3 提示词格式与分 stage 采样参数end2end.py 中每个 query 构造函数都返回一个QueryResultprompt 多模态数据 limit_mm_per_promptprompt 使用 Qwen 对话模板拼接system / user / assistant三段默认 system 为 Qwen 官方多模态人设end2end.py#L38-L59。多模态数据通过multi_modal_data字典挂载音频(np.float32 信号, 采样率)元组采样率默认 16000图像经convert_image_mode(pil_image, RGB)转换后的 PIL Image视频video_to_ndarrays(video_path, num_frames16)抽帧后的 ndarray 序列帧数默认 16。采样参数按 stage 逐一给出end2end.py#L302-L340Stage关键参数说明Thinkerstage 0temperature0.9, top_p0.9, top_k-1, max_tokens1200, repetition_penalty1.05文本理解/生成Talkerstage 1temperature0.9, top_k50, max_tokens4096, detokenizeFalse, stop_token_ids[2150]代码预测器在 Qwen3-Omni 中已并入 Talker2150 为TALKER_CODEC_EOS_TOKEN_IDCode2Wavstage 2temperature0.0, top_p1.0, max_tokens4096*16, detokenizeTrue, repetition_penalty1.1音频解码贪心解码代码随后用omni.num_stages截断参数列表all_sampling_params[:num_stages]即采样参数个数需匹配已配置的 stage 数——如果你用 deploy YAML 只部署了 Thinker后面的 Talker/Code2Wav 参数会被自动丢弃。3. 输出模态控制与本地媒体文件3.1 模态控制--modalities为逗号分隔字符串会写入每个 prompt 的modalities字段end2end.py#L351-L354控制只产出部分模态。例如只要文本、跳过音频生成python end2end.py --output-wav output_audio \ --query-type use_audio \ --modalities text3.2 使用本地媒体文件end2end.py支持通过命令行参数直接传入本地音频、视频、图像未提供路径时回退到内置默认资产# 本地视频 python end2end.py --query-type use_video --video-path /path/to/video.mp4 # 本地图像 python end2end.py --query-type use_image --image-path /path/to/image.jpg # 本地音频 python end2end.py --query-type use_audio --audio-path /path/to/audio.wav # 多模态混合 python end2end.py --query-type mixed_modalities \ --video-path /path/to/video.mp4 \ --image-path /path/to/image.jpg \ --audio-path /path/to/audio.wav文档列出的 query 类型及语义use_video视频输入use_image图像输入use_audio音频输入text纯文本multi_audios多段音频输入mixed_modalities视频 图像 音频组合需要说明的是end2end.py 的 query_map 中实际注册的键为text、use_audio、use_image、use_video、use_multi_audios、use_mixed_modalities此外还支持use_audio_in_video视频帧 同视频音轨并通过mm_processor_kwargs.use_audio_in_videoTrue让处理器对齐音视频见 end2end.py#L229-L251。--query-type的 choices 由 query_map 键生成请以--help输出为准。其他常用参数均见 parse_args--num-frames默认 16、--sampling-rate默认 16000、--num-prompts默认 1用于把同一 query 复制 N 条、--dtype默认 auto、--stage-init-timeout默认 300s、--enable-profiler与--profiler-stages按 stage 启停性能剖析。4. 部署配置qwen3_omni_moe.yaml 解析async_chunk 示例默认加载 vllm_omni/deploy/qwen3_omni_moe.yaml当从仓库内运行时由 _default_deploy_config_path 自动解析该路径在其他位置安装运行时应显式传--deploy-config。该文件头部注释标明verified on 2x H100stage 0 on cuda:0stages 12 on cuda:1是硬件匹配的直接依据。配置核心内容async_chunk: true connectors: connector_of_shared_memory: name: SharedMemoryConnector extra: initial_codec_chunk_frames: 4 codec_chunk_frames: 25 codec_left_context_frames: 25 stages: - stage_id: 0 # Thinker max_num_batched_tokens: 32768 max_num_seqs: 64 gpu_memory_utilization: 0.9 moe_backend: triton devices: 0 - stage_id: 1 # Talker max_num_batched_tokens: 32768 gpu_memory_utilization: 0.6 devices: 1 input_connectors: from_stage_0: connector_of_shared_memory - stage_id: 2 # Code2Wav max_num_batched_tokens: 65536 gpu_memory_utilization: 0.1 enable_chunked_prefill: false async_scheduling: false devices: 1 input_connectors: from_stage_1: connector_of_shared_memory要点顶层async_chunk: true是启用阶段级并发的开关文档说明可以基于该 YAML 做 overlay 覆盖。要关闭时复制 YAML 并置async_chunk: false或用--deploy-config传入覆盖该字段的 YAML。每个 stage 未写字段时回落到 StageDeployConfig 默认值注释见 qwen3_omni_moe.yaml#L1-L14 与 stage_config.py每个 stage 还带有default_sampling_params这正是 async 入口在sampling_params_listNone时所使用的默认参数来源。connectors定义SharedMemoryConnectorcodec 分块参数为 25 帧左侧上下文 25 帧、初始块 4 帧对应文档中chunk 数据经 in-worker 连接器在 stage worker 之间直接流动的机制。platforms段按平台做差异覆盖CUDA 上给 Thinker 开启custom_ops: [rotary_embedding]注释说明与上游 #6090 的音频输出变化有关MUSA 上对 BF16 音频 stage 清空quantization_configNPU 上 Thinker 用tensor_parallel_size: 2且 cudagraph 为 PIECEWISEROCm 上 Code2Wav 强制enforce_eager: trueMIOpen 的conv_transpose1d不可被图捕获XPU 上 Thinker 用 4 卡张量并行。完整内容见 qwen3_omni_moe.yaml#L73-L139。5. async_chunk 离线模式阶段级并发5.1 语义与前提async_chunk 的目标是真正的阶段级并发下游 stageTalker、Code2Wav在上游 stageThinker结束之前就开始处理。文档列出两个前提一份带async_chunk: true的部署 YAML如基于 vllm_omni/deploy/qwen3_omni_moe.yaml 的 overlay与配置匹配的硬件默认 3-stage 配置为 2x H100。实现上end2end_async_chunk.py 使用AsyncOmni而非同步Omni异步编排器接收 stage-0 的中间输出并提前触发下游 stage而 chunk 数据经 in-worker 的OmniChunkTransferAdapter/ connector 在 stage worker 之间直接流动不经过编排器。脚本细节印证了这一机制通过 AsyncOmni.from_cli_args(args, model...) 创建实例from_cli_args定义在 omni_base.py#L141只转发显式传入的 CLI 参数避免 argparse 默认值悄悄覆盖 deploy YAML 中的配置sampling_params_list传None直接使用流水线/部署配置解析出的默认采样参数且.generate会自动把输出种类设为delta契合多模态流式场景脚本开头设置VLLM_WORKER_MULTIPROC_METHODspawnend2end_async_chunk.py#L33worker 以 spawn 方式拉起。5.2 运行命令单条 promptcd examples/offline_inference/qwen3_omni bash run_single_prompt_async_chunk.sh脚本固定使用--query-type use_audio并注入--deploy-config ${REPO_ROOT}/vllm_omni/deploy/qwen3_omni_moe.yaml、--output-dir output_audio_async_chunk其余参数透传可追加--query-type text --modalities text或自定义--deploy-config见 run_single_prompt_async_chunk.sh。多条 prompt 与并发控制bash run_multiple_prompts_async_chunk.sh --max-in-flight 4--max-in-flight默认 1内部用asyncio.Semaphoreasyncio.gather控制请求级并发end2end_async_chunk.py#L400-L423——注意这是请求级并发上限每个请求内部仍享有 async_chunk 的阶段级并发。仅文本输出跳过音频生成python end2end_async_chunk.py --query-type text --modalities text自定义部署配置python end2end_async_chunk.py \ --query-type use_audio \ --deploy-config /path/to/your_async_chunk.yaml文档特别提示对于非 async_chunk 工作流同步版end2end.py基于Omni仍是推荐入口只有当你需要阶段级并发语义时才使用 async_chunk 示例。5.3 指标输出与长音频落盘run_single_request 对每个请求做了完整的时延打点stage-0 首个输出时间、首个音频块时间TTFA, time-to-first-audio、端到端时延、音频时长与 chunk 数批量运行结束还会汇总成功率、总音频时长与实时率Real-time factor见 end2end_async_chunk.py#L426-L445。两个针对长音频/高并发的实用开关--stream-audio-to-disk将音频块通过sf.SoundFile增量写入 WAV而不是在内存中累积适用于超长音频或较高的--max-in-flight--request-timeout-s/--batch-timeout-s单请求超时超时取消并记为错误与整批全局超时超时后AsyncOmni.shutdown()仍由 finally 块保证执行。6. 输出结果解析同步入口对每个final_output_type分别落盘end2end.py#L369-L419text写{request_id}.txt包含 Prompt 与模型文本输出audio写output_{request_id}.wav采样率固定 24000 Hz若音频以 chunk 列表到达async_chunk 路径先torch.cat拼接再转 numpy 写入必要时展平为一维。async 入口的文件命名规则相同output_{request_id}.wav/{request_id}.txt输出目录默认为output_audio_async_chunk--output-dir可改。同步脚本使用--output-wav指定目录该参数在 parse_args 中标注为 Deprecated推荐--output-dir但两个脚本仍在使用它脚本对目录的优先级为--output-dir优先、回退--output-wav。7. 适用前提小结硬件默认部署 qwen3_omni_moe.yaml 在 2x H100 上验证显存更紧张时参考平台段覆盖如 NPU 的 TP2、XPU 的 TP4或自行通过--deploy-config调整 stage 的gpu_memory_utilization。入口选择常规批量/单条离线推理用end2end.pyOmni只有需要下游 stage 抢跑上游的语义时才用end2end_async_chunk.pyAsyncOmni。批量数据同步路径加--py-generator以生成器方式流式消费异步路径用--max-in-flight控制并发并用--stream-audio-to-disk控制内存。部署覆盖一切 stage 级参数内存、并行、连接器、平台差异都建议走--deploy-configYAML而不是改动示例脚本。【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考