ARTICLE DETAIL

资讯详情

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

PersonaPlex 全双工语音对话实战:在 vLLM-Omni 上以 80ms Lockstep 原生运行 NVIDIA PersonaPlex-7B

PersonaPlex 全双工语音对话实战:在 vLLM-Omni 上以 80ms Lockstep 原生运行 NVIDIA PersonaPlex-7B PersonaPlex 全双工语音对话实战在 vLLM-Omni 上以 80ms Lockstep 原生运行 NVIDIA PersonaPlex-7B【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni本指南以 recipes/NVIDIA/PersonaPlex.md 为核心骨架结合 vLLM-Omni 仓库中的部署配置、模型实现与测试代码展开。导读PersonaPlexnvidia/personaplex-7b-v1是 NVIDIA 开源的 Moshi 微调模型属于纯 lockstep并行帧联合形态的全双工语音对话模型——它一边听一边说无需客户端提交语音片段、也没有外部轮次信号。本指南讲解如何通过 vLLM-Omni 统一 duplex 服务栈/v1/duplex与/v1/realtime?duplex1在单卡 GPU 上将其运行为实时语音 Agent并设置每会话的 persona角色文本与 voice零样本音色克隆。读完本文你将掌握 PersonaPlex 的 Moshi 架构原理Mimi 编解码器 Helium temporal transformer depformer、部署配置的每个字段、启动与验证命令以及基于extra_body的会话级 voice/persona 注入方式。PersonaPlex 是什么根据 recipes/NVIDIA/PersonaPlex.md 的 Summary项目说明VendorNVIDIA模型nvidia/personaplex-7b-v1gated 仓库Moshi 微调任务全双工语音到语音S2S24 kHz 麦克风音频进Agent 语音 内心独白文本出以 80 ms lockstep 节奏工作模式通过统一 duplex 栈进行 Live duplex WebSocket 服务/v1/duplex与/v1/realtime?duplex1维护者linyueqian该配方适合在单 GPU上把 PersonaPlex 跑成实时语音 Agent。关键点是整条链路moshi-freetemporal transformer、depformer、流式 Mimi codec 全部是 vLLM-Omni 原生模块Mimi 运行在transformers.MimiModel之上不安装任何 vendored fork。解码采用贪心greedy策略在作为验收门槛的 golden replays 上逐帧匹配参考实现。从源码结构看PersonaPlex 是 vLLM-Omni 全双工服务栈上的第一个 Moshi 级纯 lockstep模型它通过标准插件接缝duplex_serving_adapter/duplex_runtime_extension位于其 pipeline.py接入通用/v1/duplex处理器模型专属代码包位于 vllm_omni/model_executor/models/personaplex/duplex/。何时使用本配方你需要一个无需轮次切换的实时语音 Agent模型持续监听用户可随时打断barge-in 是模型原生行为因为它始终在听用户。你需要每会话独立设置人设与音色persona 以角色文本注入文本流voice 以参考音频/embedding 做零样本克隆。你需要与参考实现逐帧对齐的确定性输出贪心解码在 parity gate 上对照参考实现逐帧验证见下。与 MiniCPM-o / JoyVL duplex 的区别lockstep 形态MiniCPM-o 4.5JoyVLPersonaPlex本文节奏Cadence1 s chunk groups~1 fps frames80 ms lockstep12.5 Hz轮次控制学习的⟨listen⟩/⟨speak⟩/silence//response无纯 lockstep每步行为变长 token group文本决策1 个用户帧进 → 1 个 Agent 帧 1 个文本 token 出Barge-in在 chunk 边界不适用原生模型始终听到用户会话状态chunk-group KV每 tick HTTP持久 ring KV 流式 Mimi 状态在统一栈上这种纯 lockstep 形态完全通过 capability payload 表达supports_client_commitfalse、supports_external_turn_signalfalse、supports_barge_infalsePersonaPlex 部署上的每个会话都是原生 duplexis_enabled()无条件返回True基于轮次的模型如 MiniCPM-o 4.5不受影响。这些 capability 在 serving_adapter.py 的capabilities()中逐一声明例如implementation_levelmodel_native_duplex、chunk_period_ms80、session_admission_modeengine_managed、input_modes[append_audio_chunk]。架构Moshi RQ-Transformer全原生实现Mimi codec24 kHz 采样率、12.5 Hz 帧率、每帧 1920 个采样、8 个激活 codebookcardinality 2048。流式 encode/decode 基于transformers.MimiModel并加载 PersonaPlex 参考 checkpoint 权重。这些常数在 config.py 中定义为SAMPLE_RATE 24000、FRAME_RATE 12.5、FRAME_SIZE 1920供整个包统一引用。Temporal transformerHelium backbone4096-d / 32 层 / 32 头。滑动窗口 3000 帧约 4 分钟的滚动上下文存放在 ring KV cache 中逐槽位回收per-slot recycle。实时形态的实现在 personaplex_temporal.py无引擎上下文的固定容量 ring KV、静态形状因此整个 step 可被 CUDA-graph 捕获语义逐算子镜像 Moshi 流式 transformerfp32 RMSNorm alpha 权重、融合 in-proj 注意力、绝对位置处的交错 RoPE、SiLU gating MLP 等使贪心解码可与参考输出逐帧对比。Depformer1024-d / 6 层 / 16 头。每帧在 16 个 codebook 上自回归其中 8 个是 vocoded 的 Agent 音频每帧重置reset each frame。帧 token 布局每个 80 ms tick 输出一个 17 行的 token 列[B, 17, 1]row 0内心独白文本inner-monologue textrows 1–8Agent 音频 codebookrows 9–16用户音频 codebook。该契约在 policy.py 中明确定义同时包含关键 token 常数SILENCE_TOKENSAgent 静音提示、SINE_TOKENS用户侧正弦占位、AUDIO_INITIAL_TOKEN 2048codec cardinality、TEXT_INITIAL_TOKEN 32000文本词表大小、AUDIO_SILENCE_FRAME_CNT 612.5 Hz 下 0.5 秒。Persona Voice 注入Persona 和 voice 在会话开启时通过同一个 lockstep step 注入一次voice 克隆用参考音频的 Mimi codes 强制 Agent 音频流voice 提示可为voices.tgz内置名称NATF*/NATM*自然音色VARF*/VARM*多样化音色或你自己的.pt/.wav路径persona以system ... systemtoken 强制文本流见 policy.py 的wrap_with_system_tags。首次 append 时stage0.py 的prepare_append会组装 voice embeddings从voices/目录或voices.tgz中按名称提取、静音帧与 persona token 的 prefill embedding并据此计算personaplex_prefill_slotsvoice embeddings 行数 2 × 静音帧数 persona token 数供调度器预留 prompt 槽位。硬件与环境配方在 GPUHopper 级上验证通过。服务路径为纯 PyTorch eager 原生模块因此其他显存足够的 CUDA GPU 也预期可用。1x 141 GB Hopper 级 GPUH20 级已验证OSLinuxPython3.10CI 覆盖 3.11 / 3.12vLLM-Omni当前main需要export HF_TOKEN...且该 token 有权访问 gated 仓库nvidia/personaplex-7b-v1需在模型页面接受许可协议首次运行会自动从模型仓库下载model.safetensors、tokenizer_spm_32k_3.model、voices.tgz以及 Mimi 参考 checkpointkyutai/mimi由transformers拉取用于 codec 模块图。部署配置详解personaplex.yamlpersonaplex.yaml 将 PersonaPlex 以talker → code2wavMimi两阶段、共享内存分块流式的形式部署复用了 Qwen3-TTS 的分阶段部署布局未写的字段回落到 stage_config.py 的StageDeployConfig默认值pipeline: personaplex session_mode: duplex duplex_session: max_sessions: 2session_mode: duplex启用引擎自有的全双工控制面duplex_session.max_sessions: 2会话并发上限超过限制的连接会被拒绝直到有空闲槽位释放。async_chunk: true connectors: connector_of_shared_memory: name: SharedMemoryConnector extra: shm_threshold_bytes: 65536 codec_streaming: true connector_get_sleep_s: 0.01 connector_get_max_wait_first_chunk: 3000 connector_get_max_wait: 300 codec_chunk_frames: 5 # Mimi 12.5 Hz80 ms/帧每 chunk 流式数帧 codec_left_context_frames: 10 initial_codec_chunk_frames: 1 # 只提前发出第一个音频 chunk随后回到 codec_chunk_framesStage 0talker- stage_id: 0 max_num_seqs: 10 gpu_memory_utilization: 0.4 trust_remote_code: true skip_tokenizer_init: true enable_prefix_caching: false # prompt ID 是占位符语义在 request 级 embedding 中 async_scheduling: true max_num_batched_tokens: 512 # 小的批量 token 数优化 async-chunk 首 chunk 延迟非正确性 max_model_len: 3000 # 与 temporal 的 sliding_window 3000 帧保持一致 devices: 0 output_connectors: to_stage_1: connector_of_shared_memory default_sampling_params: temperature: 0.0 top_k: 1 max_tokens: 3000 seed: 42 repetition_penalty: 1.0Stage 1code2wav- stage_id: 1 max_num_seqs: 10 gpu_memory_utilization: 0.3 enforce_eager: true # Mimi 外部解码器含 host-to-device 拷贝无法被 cudagraph 捕获 trust_remote_code: true skip_tokenizer_init: true enable_prefix_caching: false async_scheduling: true max_num_batched_tokens: 65536 # codec prefill 长度为 num_codebooks * num_frames留足余量 max_model_len: 65536 devices: 0 input_connectors: from_stage_0: connector_of_shared_memory default_sampling_params: temperature: 0.0 top_p: 1.0 top_k: -1 max_tokens: 65536 seed: 42 repetition_penalty: 1.0关键取舍配置文件注释与 personaplex_temporal.py 共同印证Stage 0 默认跑 cudagraphStage 1Mimi为 eager因为外部解码器执行无法捕获的 host-to-device 拷贝贪心 talker 解码Helium temporal 与 Moshi 在 cos 0.999 内一致非 bit-exact混沌采样会放大该数值差异导致发散因此默认temperature: 0.0, top_k: 1只有 temporal 达到 bit-exact 后才建议调高温度enable_prefix_caching: falsevoice/persona/audio 语义位于 request 特定 embedding 中token-ID 前缀缓存失效。启动服务与端点HF_TOKEN... CUDA_VISIBLE_DEVICES0 python -m vllm_omni.entrypoints.cli.main serve \ /path/to/personaplex-7b-v1 \ --omni \ --deploy-config vllm_omni/deploy/personaplex.yaml启动后暴露两个 WebSocket 端点WS /v1/duplex—— 原生 duplex 会话方言session.create/input_audio_buffer.append/response.output_audio.delta…WS /v1/realtime?duplex1—— 同一会话投影到 OpenAI Realtime 事件词汇表客户端 API 与线上协议见 docs/serving/realtime_duplex_api.md。Voice 与 persona 通过每会话的extra_body设置。会话配置的校验逻辑位于 serving_adapter.pyprepare_runtime_config会校验extra_body中不得包含服务端私有的 runtime 配置键personaplex_prefill_slots、personaplex_model_path等命中即抛ServingRuntimeConfigError从config.voice解析 voice默认NATF2.pt且必须是内置.pt基名不允许路径穿越从config.instructions解析 persona默认DEFAULT_PERSONAYou are a wise and friendly teacher...会话创建后 persona/voice 不可更改runtime_config_for_update通过reject_changed_runtime_value拒绝变更错误码persona_update_unsupported/voice_update_unsupported。客户端侧可使用 vllm_omni/clients/personaplex.py 的create_duplex_session_config(voiceNATF2.pt, persona)预设它设置 24 kHzpcm_f32le输入 / 24 kHzpcm16输出并把内置.ptvoice prompt 与 persona作为instructions装进会话。帧 payload 必须满足format pcm_f32le、sample_rate_hz 24000、恰好 1920 个采样base64 编码否则 append 被拒绝见 runtime_extension.py 的_validated_frame_payload与 stage0.py 的_decode_pcm。验证从无 GPU 契约测试到 GPU e2eGPU-free 契约测试覆盖 stage0 runtime 与统一 serving adapter无需 GPUpytest tests/model_executor/models/personaplex/duplex/ -q对应测试文件位于 tests/model_executor/models/personaplex/duplex/test_stage0_runtime.py、test_unified_runtime.py另有test_streaming_code2wav.py覆盖流式 code2wav。GPU e2e用节奏化 24 kHz PCM 走/v1/realtime?duplex1调度路径验证两个并发会话、溢出准入overflow admission、槽位回收slot recycling与非静音输出python tests/e2e/online_serving/personaplex_realtime_duplex.py \ --model /path/to/personaplex-7b-v1 \ --input-wav /path/to/speech.wav \ --output-dir /tmp/personaplex-realtime-duplex该驱动位于 tests/e2e/online_serving/personaplex_realtime_duplex.py它以裸 WebSocket 直接讲线上协议便于捕获准入限制等握手错误用EventCollector收集事件并断言。线上部署的完整步骤见 examples/online_serving/personaplex/README.md。贪心解码与 Parity 约束配方明确只暴露贪心解码temperature/top-k 旋钮有意不暴露贪心正是 parity gate 对照参考实现的锚点而采样会放大亚 bit 数值漂移直至发散。在引擎侧runtime_extension.py 的configure_sampling_params强制 Stage 0 为temperature0.0, top_k1, max_tokens1每 tick 一个 token与部署配置一致personaplex_temporal.py 逐算子镜像参考实现fp32 RMSNorm、绝对位置 RoPE、相对位置因果 mask保证贪心解码与参考逐帧可对比。运维要点与注意事项Realtime 预算80 ms/帧。在本硬件级别H20 级实测四路并发会话的 eager per-tick 延迟约 70–74 ms即四路对话均保持实时单会话余量充足。会话并发由部署配置的duplex_session.max_sessions控制超出限制的连接被拒绝直到有槽位释放。回收槽位对相同输入与全新引擎是 bit-exact 的ring KV 的start_offset掩码 均匀 tick 写入保证了这一点见 personaplex_temporal.py 的_RingKV。Voice 提示可用voices.tgz内置名称NATF*/NATM*自然、VARF*/VARM*多样化或自定义.pt/.wav路径。网络敏感客户端尽量贴近服务器运行。80 ms 节奏对网络抖动敏感高延迟链路上即使引擎很快播放也可能卡顿localhost 上则流畅。滑动窗口3000 帧约 4 分钟。ring KV 超出后回收超长会话以滚动上下文继续运行。Barge-in 语义统一端点声明supports_barge_infalse——重叠语音是模型原生行为但破坏性的输出中断与模型状态回退rewind未针对 PersonaPlex 验证。早期独立的 Moshi-web 兼容服务浏览器客户端于/、二进制 WS 协议于/api/chat、raw-PCM/v1/audio/duplex仅为 demo 用途已被移除请统一使用上述两个端点。参考资源在线服务示例与运行手册examples/online_serving/personaplex/README.md、recipes/NVIDIA/PersonaPlex.mdDuplex 服务包vllm_omni/model_executor/models/personaplex/duplex/serving_adapter.py、runtime_extension.py、policy.py、stage0.py、config.py原生模型模块temporal / depformer / 流式 Mimi / code2wavvllm_omni/model_executor/models/personaplex/两阶段管线声明talker → code2wavpipeline.py部署配置vllm_omni/deploy/personaplex.yamlRealtime Duplex API 线上协议docs/serving/realtime_duplex_api.md契约测试tests/model_executor/models/personaplex/duplex/、GPU e2etests/e2e/online_serving/personaplex_realtime_duplex.py【免费下载链接】vllm-omniA framework for efficient model inference with omni-modality models项目地址: https://gitcode.com/GitHub_Trending/vl/vllm-omni创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表