vLLM-Omni 教程源码、PR 与证据索引
本文为 架构、Runtime、阶段内执行、Connectors 和 Diffusion Runtime 提供共同研究坐标。阅读代码时先固定版本、配置和执行分支,再使用文中的类名与调用关系。
1.固定版本与证据约定
| 项目 | 本组教程采用的坐标 |
|---|---|
| 仓库 | vllm-project/vllm-omni |
| 当前实现提交 | 5ca23106fd6a0f500deea818bc2b7089306a210f |
| 核对日期 | 2026-10-05 |
| 主请求模型 | Qwen/Qwen3-Omni-30B-A3B-Instruct |
| 主请求部署 | vllm_omni/deploy/qwen3_omni_moe.yaml,普通 turn、CUDA、默认 V1 runner |
| 主请求形态 | 文本输入,modalities=["text", "audio"];非 streaming HTTP,内部 async chunk |
| Diffusion 请求 | Qwen/Qwen-Image,Images API,step execution,容量 1、1024×1024、50 步、seed 42 |
| 研究方式 | 固定源码、配置、官方请求示例、回归测试与 PR review 走读 |
| 本次未进行的验证 | 模型权重加载、GPU 生成、GPU profiler、并发服务压测与 PR benchmark 复测 |
固定 vLLM-Omni 提交,不等于固定了一次完整的可执行实验环境。仓库引用上游 vllm 的接口,本教程以被检查的 Omni 调用点解释其用途;没有把本机包环境当作该提交对应的受验证安装环境。若实际运行,还需记录 vLLM、PyTorch、Transformers、CUDA/驱动、硬件、模型/tokenizer revision、启动参数及环境变量。教程给出的模型名称也不代替 checkpoint revision 或权重哈希。
文中四类陈述有不同证据强度:
| 陈述形式 | 可支持的结论 | 不自动支持的结论 |
|---|---|---|
| 固定源码/配置中的实现 | 该版本、该分支如何组织对象和操作 | 任意平台与配置均可运行 |
| 测试代码的断言与构造 | 测试针对什么契约、能暴露哪种错误 | 本次环境已经跑过测试 |
| PR 作者或 reviewer 报告 | 对方记录的版本、负载与环境中的结果 | 本文独立复现或更广负载的普遍结论 |
| 教学推演与测试建议 | 已知条件下的预期关系、应验证的假设 | 实际日志、真实随机 Tensor 或已完成实验 |
2.当前源码入口:按要回答的问题阅读
2.1 架构、配置与模型拓扑
| 要回答的问题 | 源码入口 | 阅读重点 |
|---|---|---|
| stage 有哪些类型,拓扑与部署怎样区分? | config/stage_config.py |
StageExecutionType、StagePipelineConfig、PipelineConfig、DeployConfig 与合并/校验 |
| Qwen3-Omni 真实有几个 stage? | models/qwen3_omni/pipeline.py |
三个 stage、input_sources、两类 final output、输入适配器 |
| stage 怎样放到 GPU? | deploy/qwen3_omni_moe.yaml |
stage 0 与 stage 1/2 放置,SHM、chunk 参数和平台覆盖 |
| 框架总体试图解决什么? | docs/design/architecture_overview.md |
职责定位;具体当前行为再回源码核查 |
2.2 请求编排与生命周期
| 要回答的问题 | 源码入口 | 阅读重点 |
|---|---|---|
| API 如何选择输出并提交? | entrypoints/openai/serving_chat.py |
generate 调用、输出模态、stream/full response |
| 入口如何等待和终止请求? | entrypoints/async_omni.py、async_omni_base.py |
结果分发、request state、输出过滤、abort fallback |
| 引擎如何向编排提交? | engine/async_omni_engine.py |
输入处理、消息和队列 |
| 谁推进下游、汇合最终结果? | engine/orchestrator.py |
请求状态、下游预提交、ready、终态和清理 |
| 谁管理阶段实例? | engine/stage_runtime.py、stage_pool.py |
启动、实例选择、亲和、取消与退出 |
2.3 阶段内执行
| 要回答的问题 | 源码入口 | 阅读重点 |
|---|---|---|
| 上游输入怎样参与 AR 调度? | core/sched/omni_ar_scheduler.py |
输入等待、上游 scheduler 调用、调度输出包装 |
| 多模态输入与中间状态怎样交给模型? | worker/gpu_model_runner.py |
_preprocess、请求 token spans、中间 buffer、_model_forward |
| 执行与采样怎样衔接? | worker/gpu_ar_model_runner.py |
execute_model、sample_tokens、按请求输出 |
| 非 AR 生成怎样包装结果? | worker/gpu_generation_model_runner.py |
媒体结果、host copy 与完成条件 |
| Talker 实际消费和产生什么? | models/qwen3_omni/qwen3_omni.py |
preprocess、code predictor、make_omni_output |
| MRv2 怎样处理 Graph 辅助输出? | worker_v2/omni_model_runner.py |
能力声明、flatten/reconstruct、capture/replay |
2.4 跨阶段交接与 Diffusion
| 要回答的问题 | 源码入口 | 阅读重点 |
|---|---|---|
| Qwen3-Omni 如何转换下游输入? | stage_input_processors/qwen3_omni.py |
Thinker 条件、Talker codec、chunk 与左上下文 |
| chunk 怎么排队和清理? | transfer_adapter/chunk_transfer_adapter.py |
请求注册、send/receive、终态、清理顺序 |
| SHM 传输资源由谁持有? | connectors/shm_connector.py |
put/get、pending key、lock/SHM 回收 |
| diffusion 步调度由谁推进? | diffusion/sched/step_scheduler.py |
等待/运行请求、步级调度与生命周期 |
| 步状态和当前 batch 如何形成? | diffusion/worker/diffusion_model_runner.py、input_batch.py |
state cache、准备、执行、scatter 和结束 |
| Qwen-Image 如何落实四步协议? | diffusion/models/qwen_image/pipeline_qwen_image.py |
prepare、denoise、scheduler 更新、decode |
| Images API 如何解释参数? | entrypoints/openai/protocol/images.py、api_server.py |
size/n 与内部参数映射、提交及响应编码 |
这些表是源码入口索引,不替代各篇已经缩小范围的函数链接。可以先从可观察异常对应的边界进入,再沿生产者/消费者向两侧追踪;无需从整个仓库的启动代码开始逐行阅读。
3.真实 PR 案例与冻结坐标
以下五个 PR 在核对时均已合并。选择依据是问题是否具体、代码是否呈现清楚的机制、测试是否覆盖相关边界,以及 review 是否提供可解释的修正;不依据 PR 大小或性能数字是否好看。
| PR | 用于解释什么 | 正文位置 | 合并日期(UTC) |
|---|---|---|---|
| #7006:Route synthetic aborts through final stage | 终态的路由身份也是正确性契约 | Runtime Level 5 | 2026-09-16 |
| #8184:Extend the shared multi-stage execution framework for mixed V1/MRv2 pipelines | stage 级执行选择、辅助输出与 live 请求信息 | 阶段内执行 Level 4–5 | 2026-09-29 |
| #7544:Fix Qwen3-TTS word timestamps with async chunking | 混合 chunk/full-output 的输入完整性契约 | Connectors Level 4 | 2026-09-16 |
| #8082:Reclaim aborted chunk SHM and consumed connector state | 取消、in-flight put、ID 复用与清理顺序 | Connectors Level 5 | 2026-09-24 |
| #5810:Support diffusion continuous batching | packing 隔离、backend 能力与负向性能结果 | Diffusion Level 4–5 | 2026-08-24 |
历史源码固定于最终 PR head;合并提交单独列出,避免将 PR head 与 merge SHA 混用:
| PR | 阅读使用的 head | 合并提交 |
|---|---|---|
| #7006 | cd6960e6eaa70e620411d6d76a3f32f69fcfde3a |
c97b5fc741ea44acaed37efe520ef8600d1c2abf |
| #8184 | e4689f3a8ad7754f1cb442a018a7f693530614e2 |
001f8a80b9d92e5378912f25a4d3ae619d510ce0 |
| #7544 | 216ba3636648dca9b61fb69a5cba9ede50c88c05 |
c32aaeb2da49235689f1aa0cb4c4cc116616601e |
| #8082 | 546e4e4f27aec4b66d9c083cf6b76059475b8242 |
d486bf097a8d2b31c30a105785c1de21f256a263 |
| #5810 | d8dfe6bd1d2a21f8061b9035890b73274f64733e |
d150a4fde77d15d466102323a4048b0a8631d74c |
3.1 阅读 PR 时保持三个时间点
先辨认原问题对应的旧实现,再读取最终修复,最后核对教程基线中的后续演变。PR 的初始描述可能没有及时包含 rebase 或 review 后的补丁;测试数字也可能来自不同代码时点。
例如 #7006 的最终修复位于 async_omni_base.py,早期叙述可能笼统称作 AsyncOmni;初始测试报告和 rebase 后报告也不同。#8082 解释一个明确的回收修复,但当前 connector 又有新的资源管理和唤醒机制,不能把现有文件中的所有功能都归因到这一 PR。
3.2 各案例能证明什么
| 案例 | 可学习的验证方法 | 结论边界 |
|---|---|---|
| #7006 | 跨过真正发生过滤的生成器/消费者,断言收到一个正确身份的终态 | 两 stage 最小回归与多 final 模型的触发条件不能混同 |
| #8184 | 检查模型 hook 使用当前 batch;改变输入后 replay,观察主/辅助 Tensor;验证 D2H 完成 | 功能契约测试不等于任意混合 runner 或端到端速度已验证 |
| #7544 | 检查完整波形累计、客户端仅发新尾部、对齐阶段不提前执行 | 内部 chunking、HTTP streaming、WebSocket 能力分别核对 |
| #8082 | 用 Events 建立 put/abort/复用顺序,检查精确 SHM key 和 terminal 处理 | 特定资源回收测试不等于所有内存泄漏或长期 RSS 已验证 |
| #5810 | 让输出依赖 document/timestep,覆盖提前退出;再核对真实 backend 与实测负载 | 正确合批不保证更快,负向结果也不能推广到全部 diffusion |
4.复现入口与测试导航
真正运行前应按固定仓库的安装说明、模型 recipe 与硬件配置准备环境;以下提供的是定位入口,不是本次实测记录。命令以 vLLM-Omni 源码 checkout 根目录 为工作目录,不以本笔记目录为工作目录。
| 目的 | 仓库入口 |
|---|---|
| Qwen3-Omni 模型与部署准备 | recipes/Qwen/Qwen3-Omni.md |
| 主例的合法公开请求 | examples/online_serving/qwen3_omni/run_curl_multimodal_generation.sh |
| Qwen-Image step 配置说明 | docs/user_guide/diffusion/execution_modes.md |
| Images API 客户端参数映射 | examples/online_serving/text_to_image/openai_chat_client.py |
| 合成 abort 回归 | #7006 的入口测试 |
| MRv2 输出契约与 CUDA 输出测试 | test_shared_stage_contracts.py、test_shared_stage_cuda.py |
| 取消/发送交错与 SHM 回收 | #8082 的 transfer-adapter 测试 |
| H3 packing 与混合步数 | #5810 的 step-execution 测试 |
若将教程中的“应考虑覆盖”转为实际测试,先确认它是否已在当前仓库存在,再选择保留触发条件的最小输入。文中的候选验证矩阵不等同于每一个组合都已有实现或已经通过。
5.更新教程时怎样避免版本混用
更新源码基线时,至少重新检查五个边界:模型 pipeline.py 与部署配置是否匹配;输入 processor/adapter 是否改变;请求状态与终态字段是否迁移;runner 的有效范围与输出契约是否调整;connector 和 diffusion backend 的能力门控是否变化。
设计文档能帮助找到问题,但其 draft、current-plus-in-flight 等标记必须保留语义。文档中的候选不变量或在研框架调整,不能自动写成当前行为。对主例尤其要核对实际 stage 数量、当前 runner 默认值和公开 API 的请求格式。
本组遵循仓库已有 SGLang 架构概览、Execution Runtime 和 NCCL/MoE EP 的教学组织:先职责,再对象,随后让对象沿一次调用运转,最后解释机制及验证。相似的教学 Level 不代表两个框架具有相同对象关系。