ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

vLLM-Omni 全双工打断(Barge-in)实战:基于 `barge_in_client.py` 的语音对话流程深度解析

vLLM-Omni 全双工打断(Barge-in)实战:基于 `barge_in_client.py` 的语音对话流程深度解析 vLLM-Omni 全双工打断Barge-in实战基于barge_in_client.py的语音对话流程深度解析【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni本文基于仓库文档 examples/online_serving/barge_in_client_flow.md 编写。在真实的全双工语音对话中打断barge-in是衡量系统自然度的关键能力用户提问后助手已经开始回答但用户不等说完就再次开口。模型能否在被抢话时得体应对——要么果断掐断当前回答、要么把新问题排在轮次末尾——直接决定了对话体验。vLLM-Omni 仓库中的 barge_in_client.py 正是演示这一场景的可运行示例它既可以连接远端/v1/realtime?duplex1WebSocket 服务也可以借助--inline在进程内驱动DuplexOmni完整复现提问 → 中途被打断 → 模型处理重叠 → 回答追问的全过程并将每次回答的音频与状态落盘。读完本文你将掌握barge-in 场景的完整时序与两种运行方式、脚本全部命令行参数与输入输出约定、DuplexClient/InlineDuplexClient客户端 API 与模型会话预设preset的用法以及重叠策略overlap policy、播放确认playback ack等全双工底层机制在源码中的实现依据。场景概述一次日常对话式的中途打断barge_in_client.py演示的是一个高度贴近真实生活的对话模式问一个问题 → 回答中途被抢话 → 看模型如何应对。脚本对模型完全中立model-neutral它不依赖任何特定模型内部实现而是通过公开的客户端 API 驱动任意全双工duplex模型默认走网络路径通过vllm_omni.clients.duplex.DuplexClient连接ws://host/v1/realtime?duplex1或者使用--inline通过vllm_omni.clients.inline_duplex.InlineDuplexClient在进程内驱动vllm_omni.entrypoints.duplex_omni.DuplexOmni无需起服务端模型直接加载在当前进程。两种模式下对话内容完全一致。完整的高层流程如下精确的线上事件序列见 barge_in_client.py 的 docstring输出结果一目了然输出目录会明确显示走了哪条分支——被打断掐断的第一个回答保存为response_1_cancelled.wav完整讲完的保存为response_1_completed.wav而summary.json逐条记录了每次回答的状态、文本与时长。运行方式一连接远端全双工服务启动服务端以 MiniCPM-o 4.5 为例仓库提供了现成的服务端启动脚本 barge_in_serve.shMODEL${MODEL:-openbmb/MiniCPM-o-4_5} PORT${PORT:-8099} exec vllm-omni serve $MODEL \ --omni \ --deploy-config vllm_omni/deploy/minicpmo_4_5.yaml \ --trust-remote-code \ --host 0.0.0.0 --port $PORT要点拆解--omni启用 vLLM-Omni 的 omni 模式--deploy-config vllm_omni/deploy/minicpmo_4_5.yaml使用 MiniCPM-o 4.5 的三阶段部署配置Thinker / Talker / Code2Wav--trust-remote-codeMiniCPM-o 自带自定义 HF 代码pipeline必须信任远端代码才能解析该 deploy 配置声明了session_mode: duplex因此vllm-omni serve会把模型以DuplexOmni方式运行服务端仅挂载ws://host:8099/v1/realtime?duplex1别名/v1/duplex、POST /v1/chat/completions、/v1/models与/health其余基于轮次turn-based的 HTTP 路由speech、batch、embeddings、video 等在 duplex 模型上不提供服务。关于会话容量的关键事实vllm_omni/deploy/minicpmo_4_5.yaml中duplex_session.max_sessions: 4与 Stage 0/1 的max_num_seqs对齐每个请求在其整个生命周期内都占用一个准入名额因此该上限同时约束 WebSocket 会话与 HTTP 并发超出后请求以 HTTP 503 被拒绝WebSocket 侧对应resource_exhausted错误可重试。会话的其他运行时默认值包括空闲 TTL 300 秒、断线宽限disconnect grace30 秒、每个会话待处理输入上限 16 MiB。仓库还提供 2-GPU、3-GPU、8×4090 等多卡变体配置vllm_omni/deploy/minicpmo_4_5_2gpu.yaml 等可按硬件替换。运行客户端服务端就绪后执行也可直接cd examples/online_serving后运行python examples/online_serving/barge_in_client.py \ --url ws://127.0.0.1:8099/v1/realtime \ --model openbmb/MiniCPM-o-4_5 \ --ref-audio /path/to/reference_voice.wav \ --question-wav question_16k.wav \ --interrupt-wav follow_up_16k.wav \ --output-dir ./duplex_out脚本会依次完成握手GREET、流式上传问题音频并提交轮次ASK、等待模型开口、监听约 2 秒后在回答播放中流式上传打断音频并提交INTERRUPT、等待针对打断的新回答结束ANSWER AGAIN、回报播放进度并优雅关闭会话HANG UP。运行方式二--inline进程内模式免服务端不需要独立服务端时使用--inline让模型直接加载在当前进程内python barge_in_client.py --inline \ --model /path/to/MiniCPM-o-4_5 \ --ref-audio /path/to/reference_voice.wav \ --question-wav question_16k.wav \ --interrupt-wav follow_up_16k.wav--model此时传本地模型路径而非服务端模型名--deploy-config可选默认使用模型自带的 duplex 部署 profile该路径下脚本会惰性导入InlineDuplexClient与DuplexOmni在当前进程创建引擎并加载模型这正是 WebSocket 路径所不需要的重型依赖并以trust_remote_codeTrue解析带自定义 HF 代码的模型 pipeline。从源码实现看barge_in_client.py 的_make_client--inline构造的DuplexOmni(**omni_kwargs)被包装进InlineDuplexClient且客户端不持有引擎——脚本退出时会通过client.owned_omni.shutdown()关闭进程内引擎避免遗留 GPU 资源。由于内联客户端没有传输层它天然不具备重连、会话恢复、心跳与事件确认机制这是与 WebSocket 客户端的本质差异。命令行参数全览脚本通过argparse暴露以下参数默认值与含义均来自源码 barge_in_client.py 的main()参数默认值说明--urlws://127.0.0.1:8099/v1/realtimeWebSocket 服务地址--inline时忽略--modelopenbmb/MiniCPM-o-4_5服务端模型名或--inline时的本地模型路径--inline关闭进程内运行DuplexOmniInlineDuplexClient--deploy-configNone--inline使用的 deploy YAML默认取模型自带 profile--presetminicpmo_4_5会话预设可选minicpmo_4_5/personaplex/none--ref-audio无参考人声 WAVMiniCPM-o preset 必填缺失时会话以ref_audio_required被拒--question-wav必填问题音频mono 16 kHz PCM16--interrupt-wav必填在回答中途说出的追问音频mono 16 kHz PCM16--output-dir./duplex_out输出目录自动创建--chunk-ms依 presetappend 分块大小默认按 preset 对齐模型单元minicpmo_4_5为 100 mspersonaplex为 80 msnone为 100 ms--listen-s2.0开始打断前聆听的秒数--timeout-s120.0握手、等待事件等各阶段的超时上限输入音频格式约束--question-wav与--interrupt-wav必须是mono 16 kHz PCM16。脚本内部read_pcm16_wav会校验单声道与非压缩 PCM随后_convert_to_session_format依据会话协商的输入格式config.input_audio做转换当 preset 的会话采用不同采集格式如 PersonaPlex preset 为 24 kHz float32时音频会被重采样并转码后再流式上传。MiniCPM-o 的会话输入为 16 kHzpcm16、输出为 24 kHzpcm16。输出产物与判定逻辑脚本结束时会在--output-dir下生成三类产物每个回答一个 WAV命名规则为response_序号_status.wav其中status只有两种取值cancelled—— 该回答被 barge-in 掐断半途而废completed—— 该回答完整讲完。summary.json逐条记录每次回答的response_id、status、audio_s音频时长秒数、text累积的转写文本与wav文件名events.jsonl本次运行收到的全部服务端事件的原始 JSON 逐行落盘便于事后排查线上事件序列。判定逻辑在源码_fold_responses中脚本监听三类转写增量事件response.output_audio_transcript.delta、response.output_text.delta、response.text.delta累积文本response.done事件携带status若为cancelled则标记为 cancelled否则标记为 completed此外audio.cancelled事件会把仍在in_progress的回答强制标记为 cancelled。这与服务端response.done的status_details.reason如barge_in语义一致——见 docs/serving/realtime_duplex_api.md 的事件目录。脚本 stderr 最后会打印形如N responses (M interrupted); outputs in dir的汇总其中 M 即被打断cancelled的回答数可直接用于验证本次打断是否真的触发了 barge-in 分支。底层机制模型自主决定 vs VAD、重叠策略与播放确认barge_in_client.py演示的会话走的是model-native 通道不启用任何 VADturn_detection为 null模型自己决定何时聆听、何时开口。脚本提交问题轮次时调用await client.commit(create_responseFalse)即把听/说决策完全交给模型本身。在 model-native 通道中音频在 commit 之前就已经边流边喂给模型因此模型可能在没有任何 commit 的情况下就开始回答或发出聆听决策。当用户在回答中插入追问时决定权在服务端的重叠策略overlap policyMiniCPM-o 4.5 preset 的默认策略为overlap_policylisten_only见 vllm_omni/clients/minicpmo_4_5.py 的create_duplex_session_config服务端根据重叠语音的量级做出两类决策并以overlap.decision事件上报打断内容足够实质如重叠时长超过阈值→barge-in正在进行的回答被掐断response.done状态为cancelledstatus_details.reason为barge_in追问随后被回答只是短暂插话 → 推迟到轮次末尾再处理先讲完第一个回答再回应追问。以 MiniCPM-o 4.5 为例session.created返回的会话对象中可见重叠相关默认阈值overlap_short_ack_ms: 700、overlap_barge_in_ms: 1200、overlap_silence_rms: 0.003。能力协商capabilities中supports_barge_in: true表示该模型支持打断PersonaPlex 与 Nemotron VoiceChat 当前不支持见 docs/serving/realtime_duplex_api.md 的能力表。播放确认playback ack是保证打断后历史真实性的关键MiniCPM-o preset 的playback_commit_policyack_only意味着助手的回答只有被客户端确认播放到的部分才进入会话历史。脚本在 HANG UP 阶段调用acknowledge_collected_playback(client, collector)回报全部收集到的播放进度使历史与真实播放内容对齐。若客户端不回报服务端历史最多只会按commit_all_on_done的默认保守口径提交。这一设计正是打断后模型知道自己说到哪、没说什么的基础。客户端 API 与模型预设演示脚本建立在 vllm_omni/clients/duplex.py 之上这是一个仅依赖标准库、pybase64与websockets的客户端侧包服务端代码从不导入它。核心组成DuplexClient异步上下文管理器进入时连接并完成session.update握手、等待session.created退出时发送session.close并等待session.closed。支持ReconnectPolicy默认 5 次尝试、0.25–4 秒抖动退避与 30 秒心跳租约stream_pcm(pcm, chunk_ms...)将 PCM 切成chunk_ms毫秒的 append 并按实时节奏发送realtimeFalse则全速发送commit(create_responseFalse)把缓冲语音封装成用户条目并结束一个轮次轮次只能通过 commit 结束responses()把事件流按回答解复用为ResponseHandle含decision、transcript、played_ms、audio()、wait()等EventCollector累积事件用于断言与延迟统计timing_summary可报告首字/首音频延迟、音频节奏以及请求extra_body.return_stage_metricsTrue时的 Stage 0 token 指标ttft_ms/tpot_ms/itls_msack_playback(played_ms, ...)报告累计播放位置是ack_only策略下保持历史诚实的入口。会话形态由SessionConfig决定模型特有参数放在其extra_body中因此客户端保持模型中立每个模型各提供一个 presetPreset输入 / 输出音频设定内容vllm_omni.clients.minicpmo_4_5.create_duplex_session_config(ref_audio...)16 kHzpcm16/ 24 kHzpcm16force_listen_count0、overlap_policylisten_only、playback_commit_policyack_onlyref_audio为助手音色片段vllm_omni.clients.personaplex.create_duplex_session_config(voiceNATF2.pt, persona)24 kHzpcm_f32le/ 24 kHzpcm16内置.pt音色提示与以instructions传入的人设SessionConfig(...)16 kHzpcm16/ 24 kHzpcm16模型中立默认值自行传extra_body、turn_detection、overlap_policy、playback_commit_policy、instructions、voice、temperature关键词覆盖会替换 preset 中对应SessionConfig字段例如create_duplex_session_config(ref_audio..., temperature0.6)。ref_audio通过audio_data_url()编码为data:audio/wav;base64,...数据 URL 后随会话下发。与全双工运行时架构的关系barge_in_client.py只是全双工能力的前台示例其底层架构与完整线上协议分别记录在两份配套文档中运行时架构docs/design/fullduplex.md 描述 MiniCPM-o 4.5 全双工运行时DuplexOmni、会话运行器、重叠与播放确认的规范性契约线上协议与客户端 APIdocs/serving/realtime_duplex_api.md 完整规定了/v1/realtime?duplex1的线协议21 个客户端→服务端事件、42 个服务端→客户端事件、三类 OpenAI Realtime 兼容层级、每个事件的消息示例DuplexClient讲的正是这套契约InlineDuplexClient则把DuplexOmni包装在同样的DuplexClientAPI 之后实现同一份应用代码进程内或跨网络两用。写自己的全双工客户端时建议先跑通本文演示脚本、检查events.jsonl理解事件序列再对照 realtime_duplex_api.md 的事件目录逐类实现模型自主听说的会话关掉 VADturn_detection: null需要服务器 VAD 打断的会话则设置turn_detection.server_vad并配合overlap_policybarge_in_on_speech注意interrupt_responsefalse会被拒绝工具调用、摄像机帧、会话恢复等能力均以session.created返回的capabilities标志为准按标志分支而不是按模型名硬编码。【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表