Compare commits

...
Author SHA1 Message Date
Gao Han 5cf2681aeb Revert "[Perf][Qwen3-TTS] Fuse QKV and gate_up projections in code predictor …"
This reverts commit 6fdc4ca62d.
2026-08-04 22:25:12 +08:00
6fdc4ca62d [Perf][Qwen3-TTS] Fuse QKV and gate_up projections in code predictor (#4958)
Signed-off-by: sheenlin <sheenlin@tencent.com>
Co-authored-by: sheenlin <sheenlin@tencent.com>
Co-authored-by: yurain <yurain26@users.noreply.github.com>
2026-08-04 11:59:32 +00:00
Zeyu Huang | 黃澤宇andCopilot Autofix powered by AI b6728db486 [Frontend] Add ComfyUI support for r2v (MiniMax H3 as example) (#5756)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Signed-off-by: Zeyu Huang | 黃澤宇 <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-08-04 11:51:12 +00:00
Mu GuanLin b9a51592f0 [Model][Feat] MiniMax H3 online FP8 support (#5737)
Signed-off-by: mglyn <1203789601@qq.com>
2026-08-04 11:35:01 +00:00
ruirui(rein) yang 5215e03a91 [Refactor][1/N Scheduler]Remove duplicated AR/generation scheduler plumbing and establish explicit shared lifecycle contracts. (#5461)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-08-04 15:10:47 +08:00
Chenguang Zheng d5d47e9be1 [Doc] Document async Omni output materialization (#5610)
Signed-off-by: Chenguang ZHENG <645327136@qq.com>
2026-08-04 14:50:38 +08:00
Hongsheng Liu 30cba84222 [Doc] Update README and installation docs for v0.26.0 (#5715)
Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
2026-08-04 14:18:51 +08:00
WeiQing Chen 9f9f9f274a [Bugfix] Fix MiniMax H3 reference video URL (#5740)
Signed-off-by: David Chen <530634352@qq.com>
2026-08-04 14:15:26 +08:00
WeiQing Chen 900a7f0813 [Model] Add MiniMax H3 T2VA accuracy test (#5709)
Signed-off-by: david6666666 <530634352@qq.com>
2026-08-03 23:59:30 +08:00
Yukim1 7a2007cc17 [Refactor] Remove legacy --stage-configs-path from the serve CLI (#5647)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
2026-08-03 23:41:52 +08:00
WeiQing Chen 76de642c54 Update WeChat community QR code (#5701)
Signed-off-by: David Chen <530634352@qq.com>
2026-08-03 17:56:16 +08:00
ooooooye a4ea67a21b [Model] Add soundfile fallback for MiniMax H3 audio loading (#5699)
Signed-off-by: brandneway <gyuan4892@gmail.com>
2026-08-03 16:24:50 +08:00
zzh e0c2b9d73f Adapt HunyuanImage3.0 test for npu (#5436)
Signed-off-by: zzh <943967662@qq.com>
2026-08-03 06:31:50 +00:00
Isotr0py 24741961eb [Model] Add MiniMax H3 diffusion support (#5691) 2026-08-03 14:10:40 +08:00
wangyu 727f90958e [CI/Build] Split diffusion distributed nightly tests by L4 and H100 (#5695)
Signed-off-by: wangyu <410167048@qq.com>
2026-08-03 12:35:54 +08:00
ChoHee 67c54777bb [Bugfix] Reject /v1/completions for thinker+talker models when --trust-remote-code is unset (#5525)
Signed-off-by: ChoHee15 <cc5281@126.com>
2026-08-01 15:49:12 +00:00
Zhou TaichangandClaude Fable 5 2c4e9a945b [BugFix] Make pure-TP KV receive fallback all-or-nothing across ranks (#5636)
Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-01 15:43:48 +00:00
SYLARandlishunyang12 4b1547b4d8 [Bugfix] Fix Wan2.2 omitted guidance scale resolution (#5615)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Signed-off-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-08-01 15:17:33 +00:00
SYLARandlishunyang12 6e8c279a68 [Bugfix] Match image file metadata to output format (#5619)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-08-01 15:09:27 +00:00
SYLARandlishunyang12 6f98c807d2 [Bugfix] Restore BAGEL CFG KV transfers (#5620)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-08-01 15:06:05 +00:00
Librium 185e3d6df6 [Bugfix] Preserve channel-last video tensor layout (#5418)
Signed-off-by: pxljs <1621352782@qq.com>
2026-08-01 07:05:57 +00:00
amy-why-3459andCursor 67aa6c55a4 [Bugfix][MiniCPM-o] Align Daily-Omni bench with MiniCPM interleaved A… (#5625)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-31 22:41:00 -07:00
Shenglei Fu 9d67f8e02f [CI/Build] Let audio assertions pin the transcript language (#5646)
Signed-off-by: Shenglei Fu <sfu@confluent.io>
2026-07-31 21:44:28 -07:00
akshatvishu cd5daaea6a [BugFix][Metrics] Fix per-stage time and token stats in metrics API (#4974)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-08-01 03:54:17 +00:00
Harenome 安仁 Ranaivoarivony-Razanajato 8cb79308c6 diffusion: Fix silent override of explicit guidance_scale=0 (#4999)
Signed-off-by: Harenome Ranaivoarivony-Razanajato <harenome.razanajato1@huawei.com>
2026-08-01 03:19:21 +00:00
NATURE 0a03359224 [Bugfix][MiniCPM-o] Stabilize single-GPU audio generation (#5637)
Signed-off-by: natureofnature <wzliu@connect.hku.hk>
2026-08-01 03:01:06 +00:00
Weiming Liao fe02e8b81e [CI][NPU] Add MiniCPM-o 4.5 dependencies (#5660)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-08-01 02:57:12 +00:00
SYLAR 896f05e7e6 [Kernel] Add typed SAGE for TRTLLM_ATTN (#5509)
Signed-off-by: lishunyang12 <lishunyang12@163.com>
2026-07-31 23:11:39 +00:00
林鑫 d33c905d80 [Perf] Cache RoPE cos/sin tables in code predictor (#5503)
Signed-off-by: I-wave <2083236231@qq.com>
2026-07-31 22:03:18 +08:00
Nathan PriceandClaude Opus 5 4715570acc [Bugfix][Full Duplex] Make runtime_control payloads JSON serializable (#5613)
Signed-off-by: thecodewrangler <nathan@abridge.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 03:17:25 -07:00
wuli666 4956a41f12 [Bugfix] Default missing legacy stage input sources (#5498)
Signed-off-by: wuli666 <421774554@qq.com>
2026-07-31 03:00:14 -07:00
ruirui(rein) yang 2739f0776b [Bugfix][MiniCPM-o]Fix implicit deploy connector resolution for registered pipelines (#5533)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-07-31 02:38:26 -07:00
maithilijoshi20andmaithilijoshi20 2d8ef4754c [Bugfix] Restore Gradio demo dependency (#5632)
Signed-off-by: maithilijoshi20 <maithilijoshi2003@gmail.com>
Co-authored-by: maithilijoshi20 <maithilijoshi2003@gmail.com>
2026-07-31 02:24:45 -07:00
SYLARandlishunyang12 f8a8fbf72e [Bugfix][CI] Reuse servers across paired perf cases (#5624)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-31 08:23:17 +00:00
boatman 226cb4a38c [Bugfix][VoxCPM2] Fix Chunked Prefill Length Mismatch (#5416)
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
2026-07-31 05:44:53 +00:00
0a51a18570 [Bugfix] Leave MiniCPM-o vocoder memory headroom (#5621)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Signed-off-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-31 03:35:13 +00:00
SYLARandlishunyang12 499d930fe5 [Bugfix] Use MiniCPM-o speech template in long audio test (#5623)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-31 03:16:17 +00:00
273fc8eb1d [Tests] Further extend the tiny model testing framework and enable multiple models (#5353)
Signed-off-by: Nick Cao <ncao@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-31 07:47:26 +08:00
a951dd0cb4 [BugFix] Never dispatch diffusion with an incomplete CFG companion bundle (#5482)
Signed-off-by: tzhouam <tzhouam@gmail.com>
Co-authored-by: tzhouam <tzhouam@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 08:17:24 -07:00
akshatvishu 4563999ec0 [BugFix][Diffusion] Add CPU LAPACK fallback for FlowUniPC (#5329)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-30 15:09:48 +00:00
Weiming Liaoand汪志鹏 86d7864588 [Bugfix][Diffusion] Honor HF_HUB_OFFLINE in OmniDiffusionConfig (align with AR stage) (#5403)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
Signed-off-by: Weiming Liao <fayespica@outlook.com>
Co-authored-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-07-30 15:07:46 +00:00
Shenglei FuandClaude 3b0718f22e [Bugfix] Fix active_stream_window silently stalling audio generation (#5349) (#5373)
Signed-off-by: Shenglei Fu <sfu@confluent.io>
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-30 14:56:18 +00:00
Yuanheng Zhao ce3d8e4bac [Bufix] Ming-omni-tts-16.8B Skip rejected and unused weights loading (#5607)
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
2026-07-30 22:38:40 +08:00
Henry JandClaude Fable 5 81cd7964d4 [Bugfix] Qwen3-TTS full-payload: emit one placeholder frame on a degenerate take instead of an empty payload (#5472)
Signed-off-by: henryj <349043+henryj@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 14:27:39 +00:00
Sy03 09c6ad4204 [CI/Build][MiniCPM-o] Allow auto-response before input commit (#5567)
Signed-off-by: Sy03 <1370724210@qq.com>
2026-07-30 14:14:19 +00:00
Yash JainandClaude Fable 5 f7e87e7cfd [Bugfix][Diffusion] Apply MagCache residual once per skipped step (#5561)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 07:09:25 -07:00
evanchuenganddavid6666666 744c65b730 [Feature] Distributed layerwise offload with DP multi-concurrency + mmap weight… (#5397)
Signed-off-by: evanchueng <evanchueng@outlook.com>
Signed-off-by: david6666666 <530634352@qq.com>
Co-authored-by: david6666666 <530634352@qq.com>
2026-07-30 13:35:38 +00:00
Yukim1 b3f4fbf9e2 [Refactor] Migrate Step-Audio2 offline test to deploy config (#5319)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
2026-07-30 09:59:05 +00:00
Yukim1 1752e8ee5b [Refactor] Migrate Qwen3 Omni thinker-only deploy config (#5285)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
2026-07-30 09:57:33 +00:00
Alex Brooks 089bb88706 [Model] Remove Text Encoder Output Layer Hardcoding in Flux2 (#5589)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-07-30 09:55:42 +00:00
SYLARandlishunyang12 04b408ffd2 [Bugfix] Add Cosmos3-Edge preset (fix wrong Nano/Super defaults in T2V/I2V examples) (#5596)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-30 08:41:30 +00:00
TaffyOfficialandTaffyOfficial 0c88f8a0b6 [Refactor] Normalize diffusion request extra arguments in Chat serving (#5171)
Signed-off-by: TaffyOfficial <2324465096@qq.com>
Co-authored-by: TaffyOfficial <2324465096@qq.com>
2026-07-30 07:08:12 +00:00
wangyu 1d6c0816a4 [CI/Build] Fix nested group breaking nightly pipeline upload (#5572)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-30 11:43:08 +08:00
TJian d50ea9fccc [ROCm] [CI] Fix ROCm CI for v0.26.0 (#5528)
Signed-off-by: tjtanaa <tunjian.tan@embeddedllm.com>
2026-07-30 11:27:32 +08:00
Yash JainandClaude Fable 5 daec3a6a49 [Bugfix] Trim AR sampled logprob rows with new_token_ids on mid-step stop (#5564)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 03:00:53 +00:00
ruirui(rein) yangandGao Han 0461da345a [bugfix][MiniCPM-o]delete duplicate files (#5535)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-07-30 09:59:44 +08:00
aa5364f705 [refactor][MiniCPM-o] Consolidate MiniCPM-o 4.5 2-GPU deploy configs and E2E tests (#5458)
Signed-off-by: y_null <y_null@qq.com>
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-07-30 09:56:19 +08:00
Mu GuanLin 1b718f7b15 [Feat] [CI] [bugfix] Generalize LTX CFG parallelism to the complete guidance plan (#5547)
Signed-off-by: mglyn <1203789601@qq.com>
2026-07-29 17:40:40 +00:00
zzhanddengyunyang dba05c3517 Enable Diffusion Image models asynchronous output (#4981)
Signed-off-by: zzh <943967662@qq.com>
Co-authored-by: dengyunyang <584797741@qq.com>
2026-07-29 17:21:55 +00:00
whisper f2d9eb1630 [Bugfix][CI/Build] Avoid refetching HunyuanVideo I2V input during sim… (#5552)
Signed-off-by: whisper-la <131673492+whisper-la@users.noreply.github.com>
2026-07-29 09:49:07 -07:00
Weiming Liao fa0658eabb [Doc][NPU] Fix a missed version reference: 0.25.0 → v0.26.0 (#5538)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-07-29 23:53:20 +08:00
wangyu 7c17111ff5 [Refactor][CI] Reorganize test tree, and move slow e2e to weekly (#4951)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-29 23:53:03 +08:00
zzh 925347332f Add vae-patch-parallel-size and vae-use-tiling for HunyuanImage Benchmark (#5502)
Signed-off-by: zzh <943967662@qq.com>
2026-07-29 02:43:45 -07:00
R0CKSTAR 7be7e0d249 Support Python 3.10 runtime compatibility (#5366)
Signed-off-by: Xiaodong Ye <xiaodong.ye@mthreads.com>
2026-07-29 17:11:04 +08:00
Canlin Guo 18be2ba3df [Perf] Enable compile for MOSS-TTS-Local v1.5 talker and codec (#5530)
Signed-off-by: Canlin Guo <canlinguosdu@gmail.com>
2026-07-29 14:09:06 +08:00
BruceLoveDecimalandGao Han 1c6e731339 fix(diffusion): convert caller sampling params instead of discarding … (#4115)
Signed-off-by: BruceLoveDecimal <39156883+BruceLoveDecimal@users.noreply.github.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-07-29 13:24:51 +08:00
Zeyu Huang | 黃澤宇 b8e7b21188 [skip ci][Misc] remove stray md introduced in #4652 (#5473)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
2026-07-29 12:42:25 +08:00
Weiming Liao 39663d5287 [NPU] upgrade to v0.26.0 (#5490)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-07-29 11:21:04 +08:00
R0CKSTAR ab0da662c0 [Hardware] Enable CosyVoice3 on Moore Threads MUSA (#5164)
Signed-off-by: Xiaodong Ye <xiaodong.ye@mthreads.com>
2026-07-29 02:46:27 +00:00
Zhang Jian fa41fdf252 [recipe][NPU] add cosmos3-super recipe on 8xA3 (#5097)
Signed-off-by: Zhang Jian <jianmusings@gmail.com>
2026-07-29 08:29:33 +08:00
Joshna-MedisettyandChendi.Xue 7fa40681ff Xpu/vllm 0.26 fixes (#5476)
Signed-off-by: Joshna Medisetty <joshna.medisetty@intel.com>
Co-authored-by: Chendi.Xue <chendi.xue@intel.com>
2026-07-29 08:15:36 +08:00
iancarrasco-b10 23bb4395bb [Feature] Flush the speech WebSocket on input.done without closing it (#5517)
Signed-off-by: iancarrasco-b10 <ian.carrasco@baseten.co>
2026-07-28 23:46:19 +00:00
Sy03andHongsheng Liu 0feb92bdfa [Bugfix][Minicpm] Support full-duplex three-stage serving (#5380)
Signed-off-by: Sy03 <1370724210@qq.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-29 01:58:34 +08:00
张芷瑜(Zhang Zhiyu)andZhiyu0603 f6e59c329b [Bugfix] Return diffusion metrics from /v1/images/generations (#5278)
Signed-off-by: Zhiyu0603 <Zhiyu0603@users.noreply.github.com>
Co-authored-by: Zhiyu0603 <Zhiyu0603@users.noreply.github.com>
2026-07-28 16:38:37 +00:00
Inesh Reddy Chappidi c96fe54bd8 [Test] Add regression test for MiniCPM-o 4.5 audio-stream output kinds (#5356)
Signed-off-by: Inesh Reddy <ineshreddy249@gmail.com>
2026-07-28 16:27:51 +00:00
c2b55de5b9 [Test] Give the logprobs scheduler doubles the vLLM 0.26 contracts (#5483)
Signed-off-by: Gao Han <hgaoaf@connect.ust.hk>
Co-authored-by: tzhouam <tzhouam@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-07-28 15:25:57 +00:00
Canlin Guo 61324e65d7 [Refactor] Make MOSS-TTS-Local stream session dynamic batch (#5235)
Signed-off-by: gcanlin <canlinguosdu@gmail.com>
Signed-off-by: Canlin Guo <canlinguosdu@gmail.com>
2026-07-28 21:38:24 +08:00
Hongsheng Liu f775e80732 Revert "[BugFix] Fix 'GPUARWorker' attribute error" (#5507) 2026-07-28 21:00:49 +08:00
herotai214 c96f0bc773 [Perf][GLM-Image] Skip redundant hidden state D2H (#5346)
Signed-off-by: herotai214 <herotai214@gmail.com>
2026-07-28 20:34:35 +08:00
Ting FU f4640d9a2e [BugFix] Fix 'GPUARWorker' attribute error (#5478)
Signed-off-by: Semmer <semmer@live.cn>
2026-07-28 20:13:33 +08:00
Mu GuanLin 12d75cf63a [Feature] Add official LTX multimodal guidance and precision guard (#5148)
Signed-off-by: mglyn <1203789601@qq.com>
2026-07-28 10:44:25 +00:00
Zhou TaichangandClaude Opus 5 66a9b0c84f [Bugfix] Select the AR-Diffusion engine in the DreamZero CFG-parallel deploy config (#5439)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 17:14:26 +08:00
wangyu cee2e40c33 [CI] Skip known-failing tests and filter NPU ready TTS by npu mark (#5489) 2026-07-28 15:26:36 +08:00
5014fea4a0 [New Model] support nemotron Audex (#4976)
Signed-off-by: Yuekai Zhang <zhangyuekai@foxmail.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-28 03:58:22 +00:00
Weiming Liaoandwangyu f2c5152df0 [CI][NPU]: Add nightly performance test for NPU - qwen3-omni/wan2.2/qwen-image-edit-2511 (#5339)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
Co-authored-by: wangyu <53896905+yenuo26@users.noreply.github.com>
2026-07-28 11:44:30 +08:00
WeiandSamit d3e0171cd7 [bugfix] validate AR sampled-token logprob alignment (#5273)
Signed-off-by: hbhflw2000 <417911774@qq.com>
Signed-off-by: Samit <285365963@qq.com>
Co-authored-by: Samit <285365963@qq.com>
2026-07-28 10:34:19 +08:00
Joshna-Medisetty 807db6efd7 [Refactor] Migrate Voxtral TTS XPU stage config to --deploy-config (#5467)
Signed-off-by: Joshna Medisetty <joshna.medisetty@intel.com>
2026-07-28 07:35:35 +08:00
Yueqian LinandSy03 d4a5eaac90 [Bugfix][Realtime] Stop disconnected sessions from cycling through stages (#5388)
Signed-off-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
Co-authored-by: Sy03 <1370724210@qq.com>
2026-07-27 17:04:17 +00:00
Yueqian Lin 8f115164c2 [Bugfix][Connectors] Flush processor tail on terminal async-chunk sends (#5414)
Signed-off-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-27 16:04:08 +00:00
cbab1d4d8f [Rebase] Rebase to vllm 0.26.0 (#5443)
Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
Signed-off-by: tzhouam <tzhouam@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: tzhouam <tzhouam@gmail.com>
2026-07-27 23:35:49 +08:00
LHXuuuandYuanheng Zhao fb89ab43ea [Refactor][Ming-TTS] Move speaker extraction and caching to Stage-0 (#5351)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
Co-authored-by: Yuanheng Zhao <54058983+yuanheng-zhao@users.noreply.github.com>
2026-07-27 07:55:47 -07:00
SYLARandlishunyang12 7762d664d8 [Attention] Add trtllm diffusion attention backend with Skip-Softmax (#5283)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-27 22:48:11 +08:00
Wang fuyinandHongsheng Liu 4dd1b47f47 [Config] Read stage metadata from VllmOmniConfig (#5343)
Signed-off-by: Acerak01-fy <wfy2003324@163.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-27 22:44:06 +08:00
e108cbb510 [NPU][HunyuanImage3] Adapt diffusion FusedMoE for vLLM >= 0.24.0 (#5167)
Signed-off-by: betta18 <jiangmengyu1@huawei.com>
Signed-off-by: jiangmengyu18 <56633611+jiangmengyu18@users.noreply.github.com>
Co-authored-by: betta18 <jiangmengyu1@huawei.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-27 22:41:34 +08:00
ruirui(rein) yangandamy-why-3459 82172b112d [BugFix][MiniCPM-o] Restore audio output without async chunk (#5455)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-27 22:19:46 +08:00
汪志鹏 e9bc7fc06a [Refactor]: Mammothmoda2-dev use x_to_text.py in examples (#5454)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-27 14:11:49 +00:00
zzh 8001bb155d Fix missing sequence_parallel_size in deploy config output (#5449)
Signed-off-by: zzh <943967662@qq.com>
2026-07-27 02:15:08 -07:00
汪志鹏 88b7ca2ffa [Model] Support MammothModa2-Dev (#5411)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-27 17:01:54 +08:00
rein yang 5b230541c9 [Deploy] Reduce MiniCPM-o single-GPU startup memory (#5447)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-07-27 16:37:25 +08:00
Zhou TaichangandClaude Opus 4.8 776424f0de [Refactor][WIP] Add missing test for modelrunner (G1/N) (#5333)
Signed-off-by: Taichang Zhou <tzhouam@connect.ust.hk>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 16:24:47 +08:00
xsmcccandxsmccc d688aa82fc [Model] Optimize MiniCPM-o multimodal encoder memory (#5188)
Signed-off-by: xsmccc <247721718+xsmccc@users.noreply.github.com>
Co-authored-by: xsmccc <247721718+xsmccc@users.noreply.github.com>
2026-07-27 15:24:51 +08:00
WeiQing Chen 9b4ea13c80 docs: update WeChat QR code (#5430)
Signed-off-by: David Chen <530634352@qq.com>
2026-07-27 14:30:15 +08:00
Zeyu Huang | 黃澤宇 eaf90d8eff [Frontend] Add midway prompt update for streaming video generation (#4652)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
2026-07-27 14:07:43 +08:00
wjsuijlenh 1f01d05603 [Core] Session state manager for AR-diffusion world models (RFC #4480 Phase 0) (#4487)
Signed-off-by: Wijnand Suijlen <wijnand.suijlen@huawei.com>
2026-07-27 13:17:38 +08:00
Inesh Reddy Chappidi 9f3a73df17 test: make Qwen-Image diffusers-backend latency check fair and stable (#5108) (#5132)
Signed-off-by: Inesh Reddy <ineshreddy249@gmail.com>
2026-07-26 22:14:26 -07:00
Zheng Wengang b9b8282cf5 [BugFix] Couple audio+video mm-cache for use_audio_in_video (#5308)
Signed-off-by: ZhengWG <zwg0606@gmail.com>
2026-07-27 04:29:53 +00:00
Yash Jain 911ea0c586 [Bugfix][Frontend] Parse VLLM_USE_MODELSCOPE via vllm.envs (#5428)
Signed-off-by: Yash Jain <yashjainjain1704@gmail.com>
2026-07-27 04:19:22 +00:00
Wallbreazzz e28e389a76 feat(qwen3-tts): add codec_chunk_ramp for gradual chunk size warmup (#5152)
Signed-off-by: Wallbreazzz <110282866+Wallbreazzz@users.noreply.github.com>
2026-07-27 04:15:43 +00:00
zhumingjue138 138c6988ad [Bugfix] skip test case for #5437 (#5440)
Signed-off-by: zhumingjue <zhumingjue@huawei.com>
2026-07-27 11:47:59 +08:00
汪志鹏 ddc3c87547 [Refactor][Docs]: Remove stale BAGEL offline guide (#5429)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-27 09:46:11 +08:00
SYLARandlishunyang12 2bb618903a [Recipe] Add Cosmos3-Edge (#5313)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-26 09:25:00 +00:00
汪志鹏 ccdb2b51aa [Refactor]: Intrduce x_to_text.py in examples (#5384)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-07-26 16:33:17 +08:00
b6c4578dac [BugFix]Add MiniCPM-o 4.5 end-to-end test suite (offline, online serving) (#5237)
Signed-off-by: y_null <y_null@qq.com>
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-25 17:00:13 -07:00
boatman 76e4a78afc [Bugfix][Higgs-Audio-V3] Propagate Sampling Parameters to Sampler (#5406)
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
2026-07-25 15:25:35 +00:00
af2f84582b perf(qwen3-tts): cache decoder masks and compile pre-transformer (#5107)
Signed-off-by: Ziyang Zhang <hafuhafu@qq.com>
Co-authored-by: Sy03 <1370724210@qq.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-25 08:09:19 +00:00
wangyu 7afd3a0dcb [CI/Bugfix] Pin dev deps and downgrade mooncake for connector CI (#5389) (#5392) 2026-07-25 13:03:19 +08:00
Sy03 e043818abf [Bugfix][Frontend] Remove async-chunk guard from realtime API (#5383)
Signed-off-by: Sy03 <1370724210@qq.com>
2026-07-25 09:20:47 +08:00
akshatvishu d6240742f3 [BugFix][CI] Upgrade ROCm and CUDA docker base images to v0.25.0 (#5115)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-24 18:18:32 +00:00
wangyu ff0a76e31c [CI/Bugfix] Move CI editable APP_DIR to /opt/vllm-omni for k8s package discovery (#5364) (#5368)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-24 16:34:30 +00:00
TaffyOfficialandTaffyOfficial 93786c9cd3 [perf] Add configurable diffusion compile granularity (#4603)
Signed-off-by: TaffyOfficial <2324465096@qq.com>
Co-authored-by: TaffyOfficial <2324465096@qq.com>
2026-07-24 15:22:06 +00:00
84bbd57e4d [Feature] Add AllGather-KV sequence-parallel attention str… (#4968)
Signed-off-by: zhuhh97 <zhuhonghan@huawei.com>
Signed-off-by: dph97 <nenbaying@163.com>
Signed-off-by: zhuhh97 <zhh@unknown>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: dengyunyang <584797741@qq.com>
2026-07-24 14:45:26 +00:00
Yang_wdrs 8927ec057c [Refactor][1/N]diffusion/cache: cache-dit (#5226)
Signed-off-by: yangjianjuan <66548561+yangjianjuan@users.noreply.github.com>
2026-07-24 22:42:45 +08:00
wangyuandWeiming Liao a5d9d57adc [Refactor][CI] Unify skip-ci targeting and mirror_hardwares pipeline presets (#5254)
Signed-off-by: wangyu <410167048@qq.com>
Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
Signed-off-by: [Your Name] [Your Email]
Co-authored-by: Weiming Liao <fayespica@outlook.com>
2026-07-24 22:28:43 +08:00
akshatvishuandHongsheng Liu 536daea107 [BugFix] Fix Helios Cholesky positive-definite crashes and CPU LAPACK… (#4921)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-24 19:41:56 +08:00
Viacheslav Klimkov 784c27f493 [Bugfix][Core] Fix async streaming segment-stop accounting (#5183)
Signed-off-by: Viacheslav Klimkov <vklimkov@nvidia.com>
2026-07-24 19:31:47 +08:00
Canlin Guoandboatman c56d0da1bb [Perf] Refactor MOSS-TTS-Local v1.5 talker and local structure for CUDA Graph (#5197)
Signed-off-by: gcanlin <canlinguosdu@gmail.com>
Signed-off-by: Canlin Guo <canlinguosdu@gmail.com>
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>

Co-authored-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
2026-07-24 19:08:17 +08:00
rein yangandSy03 ad3a162eb8 [perf] Minicpm o4.5 optimization (#5228)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
Co-authored-by: Sy03 <1370724210@qq.com>
2026-07-24 17:20:39 +08:00
Diya Peng acf941da4d [Diffusion] Add VAE patch parallel support for FLUX.2-dev (#5292)
Signed-off-by: dpeng123 <diyapeng123@gmail.com>
2026-07-24 07:00:57 +00:00
wangyu 6eed6b9434 [CI/Test] Skip realtime async_chunk WebSocket case blocked by #3907 (#5363) (#5367)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-24 10:52:24 +08:00
汪志鹏 a61d5c0fd8 [Refector] Remove mammothmodal2-preview example (#5335)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-07-24 07:29:55 +08:00
Joshna-MedisettyandChendi.Xue 0fe5d73a63 [Bugfix][XPU] Fix free-memory abort and num_speculative_steps crash on XPU (#5330)
Signed-off-by: Joshna Medisetty <joshna.medisetty@intel.com>
Co-authored-by: Chendi.Xue <chendi.xue@intel.com>
2026-07-23 17:17:00 +00:00
ZacheryAU 4c23a3164b [Refactor] Split vllm_omni/entrypoints/cli/benchmark/serve.py (#5206) 2026-07-23 16:00:32 +00:00
ZacheryAU 778959797c [Refactor] Centralize metrics related helpers to metrics/ (#5168) 2026-07-23 15:55:05 +00:00
wangyu e9a06d5bdc [CI/Bugfix] Fix empty vllm_omni stub breaking stage CLI imports after Docker cache (#5338) (#5341)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-23 14:15:52 +00:00
wangyu f72b38184b [CI] move Krea-2 expansion to slow and skip failing README snippets (#5347)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-23 21:47:58 +08:00
05b794f29b [Full Duplex] Feat: Support Full-Duplex realtime runtime & add MiniCPM-o 4.5 demo (#3907)
Signed-off-by: Sy03 <1370724210@qq.com>
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: StormMelody <22371184@zju.edu.cn>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-23 16:45:18 +08:00
psv666 b55120c93b [Model][MiniCPM-o 4.5] Resolve Hugging Face model ID to local cache path in TTS (#5301)
Signed-off-by: psv666 <2693925048@qq.com>
2026-07-23 16:05:54 +08:00
Diya Peng b471a5cf23 [Diffusion] Add FLUX.2-dev CPU Offload (Layerwise) (#5256)
Signed-off-by: dpeng123 <diyapeng123@gmail.com>
2026-07-23 14:53:04 +08:00
Jack Chen 96235da468 Generalize AR-Diffusion KV session capabilities (#5271)
Signed-off-by: Jack47 <scsvip@gmail.com>
2026-07-23 12:37:32 +08:00
LHXuuu 00bdb5dcd7 [Perf][Ming-TTS] Cache speaker embeddings for uploaded reference audio (#5240)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
2026-07-23 11:22:51 +08:00
bjf-frzandHongsheng Liu be667a8067 [Refact] Refactor diffusion output streaming (#5166)
Signed-off-by: bjf-frz <frz123db@gmail.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-23 10:06:08 +08:00
7d5376f215 [CI/Perf] Optimize Docker Caching (#5133)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
Signed-off-by: Doug Smith <dougbtv@gmail.com>
Co-authored-by: dougbtv <dosmith@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-22 19:14:55 -06:00
Nick Cao f10320f53f [Tests] Config driven tiny model builder (#5090)
Signed-off-by: Nick Cao <ncao@redhat.com>
2026-07-22 17:11:53 +00:00
vOvandClaude Opus 4.8 cc1939120f [Bugfix] Skip non-positive scheduled token spans in omni stage runners (#5269)
Signed-off-by: cr-gao <gaochenrui@sjtu.edu.cn>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 16:01:45 +00:00
汪志鹏 f44649ffd0 [Refactor]: Remove sensenova examples (#5201)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-22 15:36:00 +00:00
Weiming Liao 8219c01b57 [Bugfix][NPU] Port OmniConnectorModelRunnerMixin to NPU runners to fix async_chunk=false full-payload hang (#5234) (#5290)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-07-22 13:53:04 +00:00
Ricardo Noriega 23d0ee5c0c [Bugfix] Return error for unsupported output modalities instead of empty choices (#4720)
Signed-off-by: Ricardo Noriega De Soto <rnoriega@redhat.com>
2026-07-22 11:00:01 +00:00
汪志鹏 fb4dd41d79 [Refactor]: Remove unnecessary config getattr (#5199)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-22 03:48:05 -07:00
68ee52f4e7 [Model] MiniCPM-o 4.5: optimize SigLIP position IDs (#5130)
Signed-off-by: 道路自信 <182356120+daoluzixin@users.noreply.github.com>
Co-authored-by: 道路自信 <182356120+daoluzixin@users.noreply.github.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-22 18:35:37 +08:00
rein yang 1984346bc7 [Refactor] [0/N] Scheduler clean dead code (#5312)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-07-22 17:59:44 +08:00
Yukim1 633ebbd8a4 [Refactor] Migrate Step-Audio2 online test to deploy config (#5309)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
2026-07-22 09:44:27 +00:00
wangyu 8fc9df4331 [CI][Bugfix] remove module-level skip_if_gated_repo_inaccessible in flux kontext e2e (#5250) (#5297)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-22 17:29:59 +08:00
Zeyu Huang | 黃澤宇andHongsheng Liu 9479720f81 [Refactor]: clean up diffusion model runner surface (#5218)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-22 17:07:36 +08:00
f43d761c26 [Refactor]: clean up diffusion worker interfaces (#5217)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-22 17:07:09 +08:00
Mu GuanLin 39e83e27f0 [Bug][CI] Pin the LTX FP8 quality gate to its established sigma schedule (#5302)
Signed-off-by: mglyn <1203789601@qq.com>
2026-07-22 14:36:32 +08:00
Yifan TianandDidan Deng 24eb4ab89c [Model] Add Cache-DiT support for FLUX.1-Kontext-dev (#4205)
Signed-off-by: yifan <Yifan.Tian@colorado.edu>
Signed-off-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
Co-authored-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
2026-07-22 14:06:12 +08:00
e39f4dddfb [Refactor]: clean up diffusion scheduler interfaces (#5216)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Signed-off-by: Zeyu Huang | 黃澤宇 <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 14:05:49 +08:00
Yuekai ZhangandClaude Fable 5 e2115fb642 [Bugfix][CI] Relax higgs_audio_v2 PCM streaming HNR threshold (fixes #5045) (#5232)
Signed-off-by: Yuekai Zhang <zhangyuekai@foxmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 11:26:00 +08:00
Alicia f18924c1ca [Refactor][Misc] Remove unused code in diffusion hooks/model_loader (#5270)
Signed-off-by: Alicia <115451386+congw729@users.noreply.github.com>
2026-07-22 09:45:17 +08:00
Bingyu (Spencer) Liu dcf8b07d39 [Core] Cleanup Omni connector runtime and transfer backends (#5096)
Signed-off-by: spencerr221 <liubingyu62@gmail.com>
2026-07-22 09:44:15 +08:00
Zeyu Huang | 黃澤宇 2cf5f57b3e [Refactor]: clean up diffusion executor lifecycle (#5215)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
2026-07-22 09:30:59 +08:00
ea34bde619 [Bugfix] MiniCPMo-4.5 bugfix (#5233)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
Co-authored-by: Guanzhe (Leo) Huang <116847811+leohuang257@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-22 09:23:03 +08:00
JaeandCursor ee33954dff [Model] Support Boogu/Boogu-Image-0.1-Base and Boogu/Boogu-Image-0.1-Edit (#4995)
Signed-off-by: zzehli <jaeli_ottawa@outlook.com>
Signed-off-by: jl <jaeli_ottawa@outlook.com>
Signed-off-by: Gao Han <hgaoaf@connect.ust.hk>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 18:58:56 +00:00
akshatvishu d34b91722f [BugFix][Diffusion] Preserve image payloads with reasoning metadata (#5238)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-22 00:49:18 +08:00
wangyu 9ca98009b2 [Bugfix][CI] Recognize local_model in check-test-ci-coverage hook (#5275)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-21 08:29:06 -07:00
wangyu 7b5b399210 [CI] skip test_audio_in_video_default_loader_sampling_regression (#5248) (#5280)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-21 21:47:55 +08:00
SYLARandlishunyang12 7924beef84 [Refactor] Migrate replica-DP Wan2.2 example to --deploy-config (#5267)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-21 12:28:31 +00:00
Alicia 0034eaa9c3 Update perf baseline base on 7/5-7/11 7 days avg. (#5231)
Signed-off-by: Alicia <115451386+congw729@users.noreply.github.com>
2026-07-21 12:26:22 +00:00
SYLARandlishunyang12 779466becb [Bugfix][Quant] Skip quack FP8 GEMM when scales are unpopulated (#5262)
Signed-off-by: lishunyang12 <lishunyang03@gmail.com>
Co-authored-by: lishunyang12 <lishunyang03@gmail.com>
2026-07-21 10:11:16 +00:00
wtz2333andhsliuustc0106 5a6a93dc5f [diffusion][model] Add LingBot Video dense and MoE support (#5035)
Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
Signed-off-by: wtz2333 <2955110911@qq.com>
Co-authored-by: hsliuustc0106 <liuhongsheng4@huawei.com>
2026-07-21 17:27:29 +08:00
bastefaniak 2f33df4678 [bugfix] Cosmos3 edge fix config use_k_norm_und_for_gen name (#5239)
Signed-off-by: Bartosz Stefaniak <bstefaniak@nvidia.com>
2026-07-21 07:56:31 +00:00
Hongshaorouandamy-why-3459 0576264dd1 [Bugfix] Fix MiniCPM-o 4.5 audio placeholder pool step (#5116)
Signed-off-by: a-kaa <siruhe666@gmail.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-21 15:44:05 +08:00
fatSheepandamy-why-3459 5d44868e91 [Hardware][Ascend] Keep HiFT vocoder on NPU (#5242)
Signed-off-by: fatSheep <tzh2005t@163.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-21 14:30:30 +08:00
mjZhaoElaineandClaude Opus 4.8 740bb31ff9 [Bug] Fix Ming feature extractor/processor registration crash under transformers >= 5.x (#5243)
Signed-off-by: Mengjie Zhao <zmj0129@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 17:49:08 +12:00
amy-why-3459andCursor 64bcdc2186 [Example][MiniCPM-o] Add offline/online MiniCPM-o 4.5 examples (#5222)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 11:37:15 +08:00
Juan Pablo ZuluagaandYueqian Lin dacb8e6f10 [Bugfix][Perf] mimo_audio: fix per-request speech-code routing under continuous batching (#5070)
Signed-off-by: JuanPZuluaga <juanz9312@gmail.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-20 17:22:45 +00:00
leo e24bddfb22 Fix Qwen3-Omni thinker fused MoE LoRA (#5191)
Signed-off-by: leo <yaoliu548926@gmail.com>
2026-07-20 08:52:21 -07:00
zhumingjue138 4d799997d3 [Bugfix] Fix issue 5205, add trust-remote-code (#5213)
Signed-off-by: zhumingjue <zhumingjue@huawei.com>
2026-07-20 15:20:53 +00:00
Yukim1 7d75095b84 [BugFix] Fix SoulX-Singer deploy pipeline registration (#5210)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
2026-07-20 14:34:42 +00:00
amy-why-3459 74f2742ac2 [Hardware][Ascend][Model] Add NPU support for MiniCPM-o 4.5 talker/vo… (#5117)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-20 21:45:28 +08:00
Mu GuanLin a06664a243 [Refactor] Unify the LTX-2 and LTX-2.3 pipeline runtime (#5147)
Signed-off-by: mglyn <1203789601@qq.com>
2026-07-20 20:02:30 +08:00
Diya Penganddiyapeng 6cd1ff7e64 [Quantization] Add FLUX.2-dev Mistral TE online FP8 support (#5136)
Signed-off-by: diyapeng <50388704+diyapeng@users.noreply.github.com>
Co-authored-by: diyapeng <50388704+diyapeng@users.noreply.github.com>
2026-07-20 16:16:31 +08:00
Shenglei Fu 7b2edd6650 [Bugfix][Qwen3-TTS] Mode-aware ref_audio artifact readiness (fixes #5049) (#5157) 2026-07-20 00:38:07 -07:00
boatmanandYueqian Lin 32dddfcef4 [Cleanup]Migrate model validation to adapters and clean up serving_speech.py (#4833)
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-19 23:03:32 -07:00
Wei 10d3a25916 [Feature] Support per-video audio masks for Qwen Omni (#4656)
Signed-off-by: hbhflw2000 <417911774@qq.com>
2026-07-20 11:39:59 +08:00
WeiQing Chen 98e0a49eb0 docs: update WeChat QR code (#5204)
Signed-off-by: David Chen <530634352@qq.com>
2026-07-20 11:00:58 +08:00
Lancer eef3bd5c4a [Feat] support CFG Parallel for FLUX kontext (#2281)
Signed-off-by: Lancer <maruixiang6688@gmail.com>
2026-07-20 10:05:05 +08:00
wangyu 0d8c632688 [Refactor][CI] Reorganize .buildkite directory by platform (#5119) 2026-07-19 15:06:54 +08:00
Alex Brooks c23dbfe111 [CI/Build] Add Precommit Hooks for Catching Missing PytestMarks (#4953)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-07-19 06:03:07 +00:00
Wang fuyin ffd4e1f97e [Bugfix] Fix stale pipeline resolver test call (#5193)
Signed-off-by: Acerak01-fy <wfy2003324@163.com>
2026-07-18 23:38:35 -06:00
Yuxiang LiangandChendi.Xue 109942465f Support Fish Speech TTS inference on XPU platform (#4856)
Signed-off-by: Liangyx2 <yuxiang.liang@intel.com>
Signed-off-by: Yuxiang Liang <yuxiang.liang@intel.com>
Signed-off-by: Yuxiang <yuxiang.liang@intel.com>
Co-authored-by: Chendi.Xue <chendi.xue@intel.com>
2026-07-18 19:52:44 +08:00
psv666andamy-why-3459 e9991a5907 [Doc] Fix Qwen3-Omni modality documentation examples (#5173)
Signed-off-by: psv666 <2693925048@qq.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-18 19:51:38 +08:00
4fbbdfd250 [Refactor] Migrate Legacy Stage Configs to the Pipeline Registry (#5031)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
Co-authored-by: zwhzzz0821 <zwhzzz0821@users.noreply.github.com>
Co-authored-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-18 09:34:33 +00:00
Yukim1andHongsheng Liu 793d3e9ab7 [Config] Return VllmOmniConfig from create_from_model (#4818)
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-18 09:21:07 +00:00
wangyu 907f932b72 [CI][Test] Tier diffusion offloader CI and reduce gpu_4_queue merge usage and fix #5182 (#5185)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-18 17:15:17 +08:00
Nick Cao 1f0ed96fcd [Bugfix] Fix broken FrameSimilarityFilter threshold test (#4786)
Signed-off-by: Nick Cao <ncao@redhat.com>
2026-07-18 13:52:07 +08:00
6853d7204d [Bugfix] Add single-80GB deploy config for MOSS-TTS (resolves #4643 OOM) (#4761)
Signed-off-by: Inesh Reddy <ineshreddy249@gmail.com>
Signed-off-by: Inesh Reddy Chappidi <ineshreddy249@gmail.com>
Co-authored-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-18 13:49:10 +08:00
bastefaniak d09f549e86 [bugfix] Use FlowMatchEulerDiscreteScheduler from diffusers 0.39.0 with correct RNG handling for upcoming Cosmos3 distilled models (#5176)
Signed-off-by: Bartosz Stefaniak <bstefaniak@nvidia.com>
2026-07-17 11:38:04 -07:00
Weiming Liaoandwangyu 7aa5c9a090 [CI][NPU]: Add nightly performance test for NPU - Qwen3-TTS on A3 (#5158)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
Co-authored-by: wangyu <53896905+yenuo26@users.noreply.github.com>
2026-07-17 17:32:48 +08:00
linzhenpl07 be517db18a examples: replica data-parallel recipe + benchmark for video DiT (#4707) (#5052)
Signed-off-by: linzhenpl07 <linzhenpl07@gmail.com>
2026-07-17 03:26:35 +00:00
bastefaniakandRoger Wang 07957e12f4 Fix FP8 Quack GEMM call when inference_mode() and torch.compile() is used. (#5153)
Signed-off-by: Bartosz Stefaniak <bstefaniak@nvidia.com>
Co-authored-by: Roger Wang <hey@rogerw.io>
2026-07-16 15:01:21 -07:00
Alex Steiner ae949d129f [Bugfix][Quantization] Remap ModelOpt NVFP4 scale tensors (#5087)
Signed-off-by: Alex Steiner <asteiner@nvidia.com>
2026-07-16 12:33:57 -07:00
bastefaniak 85f7a5b374 Add Cosmos3 Edge and Distilled checkpoints support (#5001)
Signed-off-by: Bartosz Stefaniak <bstefaniak@nvidia.com>
2026-07-16 09:39:40 -07:00
zzh 0a9a5c231e Fix hunyuan ci (#5143)
Signed-off-by: zzh <943967662@qq.com>
2026-07-16 14:49:13 +00:00
wangyu 2a49b2b217 [CI][Perf] Add JSON mark support and paired parametrize for L4 perf, so as to further support performance‑case selection for NPU‑CI. (#5084)
Signed-off-by: wangyu <410167048@qq.com>
Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
2026-07-16 14:45:00 +00:00
Canlin Guoandsunnyxyli 5c3900960b [Feature] Support MOSS-TTS-Local-v1.5 vocoder graph (#4929)
Signed-off-by: gcanlin <canlinguosdu@gmail.com>
Signed-off-by: sunnyxyli <1550693033@qq.com>
Co-authored-by: sunnyxyli <1550693033@qq.com>
2026-07-16 15:02:15 +08:00
Ricardo Noriega 68a992060b [Bugfix] Fix audio.format parameter silently ignored in chat completions (#4718)
Signed-off-by: Ricardo Noriega De Soto <rnoriega@redhat.com>
2026-07-16 00:17:02 -06:00
zhumingjue138 238fc0a609 [Bugfix] fix issue 5065 (#5118) 2026-07-15 19:39:44 -07:00
Shi Boao Bowieandbjf-frz a432b8a325 [Refactor][OutputProcessor 1/8]: clean up multimodal payload accumulation and move payload logic into MultimodalPayload & directory refactor (#4980)
Signed-off-by: Boao Shi <aoibosh@connect.hku.hk>
Signed-off-by: bjf-frz <frz123db@gmail.com>
Co-authored-by: bjf-frz <frz123db@gmail.com>
2026-07-15 15:50:19 +08:00
wangyu 795e4e0160 [CI] Add local job runner scripts for L2-L4 pytest execution (#4672)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-15 14:18:58 +08:00
f84f0e72fd [Bug Fix] Hunyuan image cfg bugfix (#4752)
Signed-off-by: zhuhh97 <zhuhonghan@huawei.com>
Signed-off-by: dph97 <nenbaying@163.com>
Co-authored-by: zhuhh97 <z00806815@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-15 13:08:15 +08:00
zyz111222andamy-why-3459 2d58070f60 [Hardware][Ascend][Model] Optimize Qwen3-TTS on 310P (#4841)
Signed-off-by: zouyizhou <zouyizhou@huawei.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-15 08:57:44 +08:00
wkutak a7b6a174bc Fix loading of ModelOpt FP8 checkpoints for Cosmos3 (#5076)
Signed-off-by: Wojciech Kutak <wkutak@nvidia.com>
2026-07-14 17:33:27 -07:00
wuli666andwuli666 6603450d71 [Bugfix][Quantization] Initialize component quantization base state (#5103)
Signed-off-by: wuli666 <djjpro975@gmail.com>
Co-authored-by: wuli666 <djjpro975@gmail.com>
2026-07-14 12:06:55 +00:00
bjf-frz b14ff23041 [PERF][CI]Add Cosmos3 diffusion perf config (#5010)
Signed-off-by: bjf-frz <frz123db@gmail.com>
2026-07-14 10:25:17 +00:00
bjf-frz 1a4a042a83 [REFACT]Refactor diffusion outputs to payload metadata (#4922)
Signed-off-by: bjf-frz <frz123db@gmail.com>
2026-07-14 17:24:03 +08:00
Alex Steiner 4b9d09cb87 [Bugfix][Quantization] Support packed parameters with HSDP (#5088)
Signed-off-by: Alex Steiner <asteiner@nvidia.com>
2026-07-14 08:24:26 +00:00
wjsuijlenh 3589a676e2 [Bugfix] Accept kv_prefetch_jobs in ARDiffusionModelRunner.execute_model (#4941)
Signed-off-by: Wijnand Suijlen <wijnand.suijlen@huawei.com>
2026-07-14 08:22:40 +00:00
Zhang JianandChendi Xue b1809985ef [recipe] Add cosmos3-nano recipe for npu (1xA3) (#4978)
Signed-off-by: Zhang Jian <jianmusings@gmail.com>
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
Co-authored-by: Chendi Xue <chendi.xue@intel.com>
2026-07-14 16:19:44 +08:00
Diya Penganddiyapeng e0570a0859 [Quantization] Add BitsAndBytes W4 online quantization for diffusion transformer (#5037)
Signed-off-by: diyapeng <50388704+diyapeng@users.noreply.github.com>
Co-authored-by: diyapeng <50388704+diyapeng@users.noreply.github.com>
2026-07-14 15:48:48 +08:00
Weiming Liao b20ebc8f9b [NPU] Upgrade CI IMAGE to v0.25.0 (#5095)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-07-14 15:47:02 +08:00
akshatvishu 2c0d8399ac [Bugfix] Restore Qwen3-Omni speaker metadata during non-async handoff (#5086)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-14 04:35:44 +00:00
Hongsheng Liuandhsliu_ustc 625892032b [Doc] Standardize serving names and identifiers (#5081)
Signed-off-by: hsliu_ustc <hsliu_ustc@noreply.gitcode.com>
Co-authored-by: hsliu_ustc <hsliu_ustc@noreply.gitcode.com>
2026-07-13 23:59:42 +08:00
Rahul Steiger 66b9ad287a Extend Cosmos3 CPU offloading to component and layerwise paths (#4695) 2026-07-13 09:48:53 +00:00
wangyu 98229b08ba [Bugfix] Pass --trust-remote-code via HunyuanImage3 DFX serve_args (#5006)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-13 15:34:46 +08:00
Chendi.Xue 161b005cfc [XPU][CI] Fix xpu after rebasing for 0.25.0 (#5066)
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
2026-07-13 15:34:27 +08:00
Zheng Wengang 3f4abedbda [Perf] Ming-TTS Stage-0 flow-head speedup: RoPE/QKV fusion, opt-in torch.compile, PIECEWISE cudagraph (#4942) 2026-07-12 19:50:51 -07:00
WeiQing Chen 8e14f69d96 docs: update WeChat QR code (#5061)
Signed-off-by: David Chen <530634352@qq.com>
2026-07-13 10:24:17 +08:00
Yi Liu 9a02963acf docs: document Cosmos3-Super AutoRound world-model support (#5062)
Signed-off-by: yiliu30 <yi4.liu@intel.com>
2026-07-13 02:22:16 +00:00
Hongsheng Liu a6da469134 docs: update README for v0.24.0 (#5060)
Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
2026-07-13 08:26:37 +08:00
LHXuuu a28ded243f [Perf][Ming-TTS] Add initial latent chunk for lower streaming TTFP (#5011)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
2026-07-13 06:45:28 +08:00
Zhou TaichangandClaude Opus 4.8 d3c47efc4f [Rebase] Rebase to vllm v0.25.0 (#5042)
Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:39:53 +08:00
wangyu dda88a6f86 [BugFix] Align invalid layers DFX tests with 2-10 range (#5044) (#5047)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-12 09:50:54 +00:00
Alex Brooks 9014bb9917 [CI] Fix core_model Level for non-Diffusion Models (#5008) 2026-07-12 03:00:50 +00:00
Naga Sai Abhinay Devarinti 6581e2afa9 [Model] Add Krea 2 text-to-image diffusion model (#4730)
Signed-off-by: Abhinay1997 <devarintinagasaiabhinay@gmail.com>
2026-07-11 16:25:41 -07:00
Isotr0py b95905deb1 [Quantization] Migrate GGUF diffusion model support to OOT plugin (#4769)
Signed-off-by: Isotr0py <mozf@mail2.sysu.edu.cn>
Signed-off-by: Isotr0py <Isotr0py@outlook.com>
2026-07-11 18:48:43 +00:00
ff6f0da271 [Core] Composable parallel: Phase 1 strategy overlay (TP/DP/stage-replica) (RFC #4084) (#4281)
Signed-off-by: Kushan A. <kahmadian@nvidia.com>
Signed-off-by: kushanam <kushanam@users.noreply.github.com>
Signed-off-by: Kushan A <kahmadian@nvidia.com>
Signed-off-by: kahmadian <kahmadian@users.noreply.github.com>
Co-authored-by: kushanam <kushanam@users.noreply.github.com>
Co-authored-by: kahmadian <kahmadian@users.noreply.github.com>
2026-07-10 21:29:24 -06:00
NumberWan fe478a95ab [BugFix] Restore vllm_c IR op priority and torch.nn.RMSNorm for Qwen-Image (#4964) (#5009)
Signed-off-by: NumberWan <wantszkin2003@gmail.com>
2026-07-10 17:39:07 +00:00
amy-why-3459 cbd3939c3d [BugFix] Fix CI failures caused by stale test expectations after recent stage-payload / deploy-config changes. (#5015)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-10 18:02:17 +08:00
amy-why-3459 9a44e7e019 [Refactor][Phase 1]Remove redundant functions and logs (#4986)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-10 15:13:35 +08:00
LHXuuu 5c3923509d [BugFix][Ming-TTS] Use uploaded direct speaker embeddings by voice (#5005)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
2026-07-10 07:06:18 +00:00
Zheng Wengang 9fe26cfacb [Bugfix][Model] Fix Qwen3-Omni video metadata handling for use_audio_in_video (#4959)
Signed-off-by: ZhengWG <zwg0606@gmail.com>
2026-07-10 14:24:18 +08:00
林鑫andyurain 020792e6be [Perf][Qwen3-TTS] Sample code predictor outputs via Gumbel-max (#4261)
Signed-off-by: 林鑫 <77673148+l-wave@users.noreply.github.com>
Co-authored-by: yurain <yurain26@users.noreply.github.com>
2026-07-10 05:41:54 +00:00
leo b3a4819694 Fix VoxCPM2 perf server trust remote code (#4984)
Signed-off-by: leo <yaoliu548926@gmail.com>
2026-07-10 04:01:10 +00:00
amy-why-3459 5dc787d5e8 [Perf][Qwen3-TTS] Align talker MTP CUDA graph capture with Qwen3-Omni & Adapt to async output (#4923)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-10 11:11:29 +08:00
Ricardo Noriega ca0ae7269c Bump safetensors to the 0.8.0 release (#4713)
Signed-off-by: Ricardo Noriega De Soto <rnoriega@redhat.com>
2026-07-09 15:09:23 +00:00
Alex Brooks 690864f277 [Tests] Tiny Diffusion Model Pattern (#4524)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-07-09 09:03:51 -06:00
Samit a5db2d839a [Diffusion] Improve HuggingFace hub kernel loading in flash_attn_hub (#4977)
Signed-off-by: samithuang <285365963@qq.com>
2026-07-09 12:10:10 +08:00
Yueqian Lin 3a64da194c [Perf][Qwen3-TTS] Drop default seed from qwen3_tts.yaml to restore batched MTP sampling (#4970)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-08 19:25:18 +00:00
Yueqian Lin 6d50348ef1 [Perf][Qwen3-TTS] Skip per-step hidden-state D2H via hidden pooler payload opt-out (#4879)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-08 11:59:41 -07:00
Yueqian Lin da15a4cb1c [Bugfix] Drop out-of-vocabulary stop ids from min-tokens masking (qwen3-tts min_tokens engine crash) (#4971)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-08 11:24:31 -07:00
leo 267b49b880 Fix Voxtral TTS feedback and short ASR checks (#4954)
Signed-off-by: leo <yaoliu548926@gmail.com>
2026-07-08 16:52:48 +00:00
Alex Brooks b7d08fe5f6 [Core / Bugfix] Add Mechanism for Endpoint Rejection (#4762)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-07-08 09:00:47 -06:00
amy-why-3459 7d4decc1d8 docs(recipe): fix MiniCPM-o 4.5 curl TTS example and clarify chat_template_kwargs usage (#4950)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-08 17:45:02 +08:00
Samit b96bc5ac87 Support HuggingFace kernels package for native diffusion attention backends (#4926)
Signed-off-by: samithuang <285365963@qq.com>
Signed-off-by: Samit <285365963@qq.com>
2026-07-08 14:34:36 +08:00
Inesh Reddy Chappidi 4908b85731 [Bugfix] MOSS-TTS codec: resolve decode method across remote-code and vendored tokenizers (#4760)
Signed-off-by: Inesh Reddy <ineshreddy249@gmail.com>
2026-07-08 05:23:13 +00:00
17e27c80e3 [Test] Add image-to-video offline example docs and tests (#3573)
Signed-off-by: loveysuby <loveysuby@users.noreply.github.com>
Signed-off-by: Hyoseop Song <crad_on25@naver.com>
Signed-off-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
Co-authored-by: loveysuby <loveysuby@users.noreply.github.com>
Co-authored-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
2026-07-08 11:20:30 +08:00
Zhang Jian d5e197fb97 [Diffusion][Feature] Add SP for Omnigen2 (#3206)
Signed-off-by: Zhang Jian <jianmusings@gmail.com>
2026-07-08 10:29:41 +08:00
Yukim1andAdvik 460a5c6b48 [Refactor] Migrate MammothModa2 and OmniVoice to pipeline registry (#4647)
Signed-off-by: Advik <scince5678@gmail.com>
Signed-off-by: Nightwing-77 <scince5678@gmail.com>
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
Co-authored-by: Advik <scince5678@gmail.com>
2026-07-08 00:44:33 +00:00
WeiQing Chen 7ab50965e8 Update WeChat group QR code (#4939) 2026-07-07 19:27:46 +08:00
Ting FU 815abce2ba [BugFix] fix possible shape mismatch when using ROPE (#4655)
Signed-off-by: Semmer <semmer@live.cn>
2026-07-07 17:54:39 +08:00
SamitandCursor 31c9c751fc [Bugfix] Fix LoRA arguments passing in offline text-to-image script (#4936)
Signed-off-by: SamitHuang <285365963@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 09:32:32 +00:00
Yuanheng Zhao d365d3a69e [Refactor] Migrate Ming-flash-omni-2.0 Image-gen examples with model_extras (#4835)
Signed-off-by: Yuanheng <jonathan.zhaoyh@gmail.com>
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
2026-07-07 08:09:12 +00:00
herotai214 d4a869fe5e [Bugfix] Fix tokenizer config for higgs-audio-v3 test error (#4918)
Signed-off-by: herotai214 <herotai214@gmail.com>
2026-07-06 10:53:24 +00:00
amy-why-3459 9ceca4ec85 [Bugfix] Fix full-payload mm splitting for dual hidden/scheduled batch axes (#4870 follow-up) (#4910)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-06 15:08:05 +08:00
Vensen ba7e9e6496 [CI][sleep mode] fix sleep pytest CI error (#4912)
Signed-off-by: vensen <vensenmu@gmail.com>
2026-07-06 15:07:01 +08:00
汪志鹏 14fad9835d [BugFix]: fix #3236 bug (#4877)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-05 17:26:09 +00:00
汪志鹏 862e0a2b27 [BugFix] Preserve diffusion extra_body params for out-of-process CFG Parallel (#4900)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-07-05 17:06:30 +00:00
TaffyOfficialandzuiho 66ec3a2aff [Bugfix] Fix HunyuanImage3 MoE groups for vLLM 0.24 (#4893)
Signed-off-by: zuiho <2324465096@qq.com>
Co-authored-by: zuiho <2324465096@qq.com>
2026-07-05 15:37:42 +00:00
Vensen ddba6de2ab [Bugfix][sleep mode]: guard generation on partial wake and ensure wake idempotency (#4834)
Signed-off-by: vensen <vensenmu@gmail.com>
2026-07-05 14:50:08 +00:00
Yueqian Lin d7b365df64 [Bugfix][Qwen3-TTS] Keep seeded residual MTP sampling batched (#4889)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-05 21:47:06 +08:00
Renzheng Wang 02d654760f [BugFix] Drop removed get_cache_scale call in HunyuanImage3 diffusion loader (#4892)
Signed-off-by: wangrzneu <wangrzneu@gmail.com>
2026-07-05 09:50:43 +00:00
Zhou Taichang 86bdcaf3d5 [BDE] Phase 1: engine-level KV cache management for DreamZero (RFC #4366) (#4534) 2026-07-05 07:17:58 +08:00
Sy03 aa21412c01 [Fix][VoxCPM2] Follow up unified graph config gate (#4878)
Signed-off-by: Sy03 <1370724210@qq.com>
2026-07-04 19:58:21 +00:00
Sy03andYueqian Lin 1b31f96240 [Bugfix] Fix Qwen3-TTS no-async-chunk payload splitting (#4870)
Signed-off-by: Sy03 <1370724210@qq.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-04 19:57:55 +00:00
Sy03andYueqian Lin 0798b0bf03 [Bugfix][Qwen3-TTS] Seed residual MTP sampling (#4869)
Signed-off-by: Sy03 <1370724210@qq.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
2026-07-04 17:47:11 +00:00
boatman 29dcdec66d [Cleanup]Replace legacy logging branches with PreparedRequest.model_type (#4862)
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
2026-07-04 05:39:20 +00:00
Sy03andYueqian Lin 9eaca72382 [Perf][VoxCPM2] Add unified decode graph optimization (#4606)
Signed-off-by: Sy03 <1370724210@qq.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-04 05:30:48 +00:00
CAICAII 51c14eeaed [BugFix] Preserve explicit deploy stage engine_extras (#4255)
Signed-off-by: CAICAIIs <3360776475@qq.com>
2026-07-04 04:16:21 +00:00
Yuanheng Zhao e73245c60f [Bugfix] Adapt ZImagePipeline.forward calling in MingImagePipeline with DiffusionRequestBatch (#4866)
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
2026-07-04 03:45:49 +00:00
Haco f7cdc45977 [BugFix] deploy schema stage runtime overrides for CLI diffusion flags no longer works (#4101)
Signed-off-by: xiaohajiayou <923390377@qq.com>
2026-07-04 03:17:25 +00:00
Kotaro Kikuchi 46f10478dc [Bugfix] Qwen-Image-Layered: allow layers=2 to match upstream demo (#4777)
Signed-off-by: Kotaro Kikuchi <ktrk115@gmail.com>
2026-07-04 03:06:24 +00:00
amy-why-3459 20d43ce24d [BugFix] Adapt to pin_memory in vLLM v0.24.0 (#4860)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-03 21:35:26 +08:00
LHXuuu 991fb7408b [BugFix][Ming-TTS] Improve Seed-TTS WER accuracy (#4859)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
2026-07-03 12:15:03 +02:00
Canlin Guo a8b2bf11d2 [Feature] Support MOSS-TTS-Local-v1.5 Streaming (#4804)
Signed-off-by: gcanlin <canlinguosdu@gmail.com>
2026-07-03 16:00:30 +08:00
Weiming Liao d8db832fc2 [NPU] Upgrade to v0.24.0 (#4848)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-07-03 07:01:25 +00:00
Aleksi VesantoandWeiQing Chen 0455bffc37 [ROCm][Perf] Add ROCm support for MXFP4 (w4a4) online quantization (#4104)
Signed-off-by: Aleksi Vesanto <avesanto@amd.com>
Co-authored-by: WeiQing Chen <40507679+david6666666@users.noreply.github.com>
2026-07-03 13:17:32 +08:00
akshatvishu 04f400d36c [Bugfix] Report stepwise Qwen-Image profiler metrics (#4517)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-03 04:32:22 +00:00
wangyu 0b59dfb94a [Bugfix] Fix pytest 9.1.0 duplicate parametrization in run_benchmark.py (#4784)
Signed-off-by: wangyu <410167048@qq.com>
2026-07-03 04:15:32 +00:00
akshatvishu d9cf85d5e2 [BugFix] Use KV cache scale mapper in custom loaders (#4810)
Signed-off-by: akshatvishu <akshatnayak197@gmail.com>
2026-07-03 04:11:28 +00:00
Mu GuanLin 3023bc40c2 [Feature][Refactor] LTX-2.3 I2V Support, Public Examples, and Shared Pipeline Refactor (#4739)
Signed-off-by: mglyn <1203789601@qq.com>
2026-07-03 11:29:22 +08:00
CAICAII b443504d61 [Diffusion] Add Diffusers quantization config bridge (#3837)
Signed-off-by: CAICAIIs <3360776475@qq.com>
2026-07-03 03:06:44 +00:00
Yuanheng Zhao 06329c6450 [Bugfix] Fix request batching regression on Ming-flash-omni ImageGen (#4837)
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
2026-07-03 03:04:17 +00:00
Jiaqian Liu f00caf35c4 [image][bugfix] Fix HunyuanImage3 bridge request batching (#4849)
Signed-off-by: Celeste-jq <591998922@qq.com>
2026-07-03 02:58:13 +00:00
Sean Gillen 431a7c71ac [Model] Cosmos3: Skip unused action conditioning frames (#4789)
Signed-off-by: Sean Gillen <sgillen@nvidia.com>
2026-07-03 01:45:44 +00:00
Jun Hee YooandClaude Opus 4.8 9d8089095e [Bugfix] Support append/extend/count actions in TrackingArgumentParser (#4639)
Signed-off-by: Junhee Yoo <junhee.yoo@navercorp.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:29:24 +00:00
Zeyu Huang | 黃澤宇andHongsheng Liu 1b0de21c55 [Chore]: refactor out unused/redundant params in diffusion pipelines (#1235)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-07-02 16:32:05 +02:00
Alex Brooks 5c51782c6b [Bugfix] Realign Serving Tokenization Name to Fix Error Handling Routes (#4816)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-07-02 15:23:35 +08:00
f11b32a42e [Bugfix] Qwen3-TTS talker handles multi-token replay on resume (#4559)
Signed-off-by: Sy03 <1370724210@qq.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-07-02 04:46:05 +00:00
Jiaqian Liu a25636d780 [NPU] Fix HunyuanImage3 MoE EP+SP parallel mapping (#4344)
Signed-off-by: Celeste-jq <591998922@qq.com>
2026-07-02 04:14:12 +00:00
ZacheryAU b0f6b9de96 [Bugfix] clean per-stage audio RTF and align audio metrics (#4794) 2026-07-02 02:55:44 +00:00
NumberWanandCursor bbc0476237 [CI] Lower Qwen-Image e2e SSIM threshold from 0.97 to 0.94 (#4613)
Signed-off-by: NumberWan <wantszkin2003@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 02:22:10 +00:00
ChenWenjing 720bd756bf [ci]loose voxcpm2 HNR baseline (#4801)
Signed-off-by: CHEN <116010019@link.cuhk.edu.cn>
2026-07-02 02:19:05 +00:00
4d2ee15156 [BugFix] Fix Code2Wav async_chunk streaming tail drop (boundary clicks + ~1.2% time compression) (#4706)
Signed-off-by: zhuxinlong <zhuxinlong959@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-07-02 09:13:42 +08:00
Thanaji Rao Thakkalapelli 1788d76eb3 [Feature] Improve diffusion LoRA compatibility for SDXL (#4825)
Signed-off-by: Thanaji Rao Thakkalapelli <thanaji.rao.thakkalapelli@intel.com>
2026-07-01 23:41:16 +00:00
Alex BrooksandDidan Deng d526dc93e8 [Fix]: Set .transformer on SenseNova pipeline, warn if no .transformer in CacheDiT summary (#4326)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
Co-authored-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
2026-07-01 17:40:07 +00:00
Renzheng Wang 6b11f6b41d [Bugfix][Quant] Gate quack FP8 to datacenter Blackwell (sm_100.x) only (#4817)
Signed-off-by: wangrzneu <wangrzneu@gmail.com>
2026-07-01 16:51:17 +00:00
Hongsheng Liu e4a2d3676e [codex] Update maintainers and code owners (#4823)
Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
2026-07-01 18:11:11 +02:00
TJian efc6b391e4 [ROCm] [CI] Fix AMD CI after v0.24.0 rebase (#4821)
Signed-off-by: tjtanaa <tunjian.tan@embeddedllm.com>
2026-07-01 15:18:24 +02:00
Chendi.Xue e7b281799e [XPU CI][0.24] fix xpu ci by update pipeline-intel.yaml and triton version (#4805)
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
2026-07-01 03:51:06 +00:00
Ayaka MikazukiandSy03 c21e9a35f8 [Doc] Add Voxtral TTS RTX 5090 recipe (#4774)
Signed-off-by: Ayaka Mikazuki <ayaka@mail.shn.hk>
Signed-off-by: Ayaka <ayaka@mail.shn.hk>
Co-authored-by: Sy03 <1370724210@qq.com>
2026-07-01 04:56:23 +02:00
Zhou Taichang a560ed184d [Rebase] Rebase to vllm v0.24.0 (#4709) 2026-06-30 19:41:06 +08:00
fywcandprincepride 9a105bf90d [Feat] Support teacache for SenseNova-U1 (#4164)
Signed-off-by: hanzheli <hanzheli@kuaishou.com>
Signed-off-by: princepride <wangzhipeng628@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
Co-authored-by: princepride <wangzhipeng628@gmail.com>
2026-06-30 09:24:46 +00:00
SYLAR bb8614595d [BugFix][Cosmos3] Pad sound latents so video+sound runs under sequence parallelism (#4678)
Signed-off-by: lishunyang12 <125541396+lishunyang12@users.noreply.github.com>
Signed-off-by: lishunyang <lishunyang12@163.com>
2026-06-30 17:23:36 +08:00
boatman 4028680b7e [Perf]: Fused RMSNorm+3D Rope kernel in Sensenova-U1 (#4669)
Signed-off-by: boatman <109857087+sphinxkkkbc@users.noreply.github.com>
2026-06-30 16:32:47 +08:00
Yi LiuandCopilot 99234881f5 [Quant][AutoRound] Add W4A16 support for Qwen-Image (#3588)
Signed-off-by: yiliu30 <yi4.liu@intel.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-30 16:27:28 +08:00
dd3a4d0a29 [Feat] Support CFG-Parallel For Sensenova-U1-8B-MoT (#4188)
Signed-off-by: sphinxkkkbc <binchengkang8@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
Co-authored-by: sphinxkkkbc <binchengkang8@gmail.com>
Co-authored-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-06-30 08:03:26 +00:00
Jae 0899a1a666 Migrate audiox examples (#4607)
Signed-off-by: zzehli <jaeli_ottawa@outlook.com>
2026-06-30 04:41:30 +00:00
Mohammed Saif AbedandClaude 2fc00efa49 [Model] Migrate MammothModa2-Preview example to standard task example + model_extras (#4691)
Signed-off-by: mo saif <moisf56@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-30 04:34:06 +00:00
faceless void 11f6a0b72e Make speech streaming default to SSE (#4679)
Signed-off-by: syd520zy <529477025@qq.com>
2026-06-30 02:17:24 +00:00
JiangJie ZhangandSamit c45ac74d43 [Core][Frontend] Support request-level batching for diffusion pipelines (#4079)
Signed-off-by: jader <yjader@foxmail.com>
Co-authored-by: Samit <285365963@qq.com>
2026-06-29 18:09:19 +02:00
504698dec8 [Core] Performance fix for orchestrator bottleneck: separates inter-stage from client outputs (#4527)
Signed-off-by: yinpeiqi <yinpeiqi809@gmail.com>
Co-authored-by: Chenguang ZHENG <645327136@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-06-29 17:43:36 +02:00
Weiming Liao 724f5d132d [BugFix] Restore pre-#9572 NPU graph behavior (cap cudagraph_mode to PIECEWISE) (#4674)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-06-29 07:54:26 +00:00
Ayaka Mikazuki deb9bd4efc Fix Qwen2.5-Omni AutoRound loading (#4781)
Signed-off-by: Ayaka <ayaka@mail.shn.hk>
2026-06-29 07:34:27 +00:00
wangyuandHongsheng Liu 7619ed6b82 [CI] Reducing mithril-h100-pool in ready&merge CI, optimize ready CI duration (#4354)
Signed-off-by: [Your Name] <your.email@example.com>
Signed-off-by: wangyu <410167048@qq.com>
Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Signed-off-by: [Your Name] <[Your Email]>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-29 05:17:57 +00:00
WeiQing Chen e4026a50ad Update WeChat QR code asset (#4778)
Signed-off-by: David Chen <530634352@qq.com>
2026-06-29 05:43:25 +02:00
Isaac Hung e9d4931781 [Core] Remove dead custom_process_input_func hooks in stage input processors (#4531)
Signed-off-by: Isaac Hung <manhei5001@gmail.com>
2026-06-29 05:17:25 +02:00
bjf-frzandAlicia cd35572069 [CI]Add Cosmos3 L2 serving tests (#4535)
Signed-off-by: bjf-frz <frz123db@gmail.com>
Co-authored-by: Alicia <115451386+congw729@users.noreply.github.com>
2026-06-29 09:15:17 +08:00
SuyanLiandsuyan.li 1b318d11d1 [Refactor] Reuse CFGParallelMixin in Bagel for CFG-parallel denoising (#4768)
Signed-off-by: suyan.li <suyan.li@bytedance.com>
Co-authored-by: suyan.li <suyan.li@bytedance.com>
2026-06-28 07:16:10 +00:00
wangyu be60d7c7c7 [CI][Bugfix]Split nightly Diffusion X2V function tests by T2V/I2V to fix timeout (#4744)
Signed-off-by: wangyu <410167048@qq.com>
2026-06-28 06:43:26 +02:00
Chendi.Xue 60ccadfbb6 [WAN_S2V] Enable HSDP for wan s2v (#4458)
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
2026-06-28 06:27:58 +02:00
Yueqian Lin 92f7208559 [Bugfix] CosyVoice3: wrap ref_text in instruction template (#4644) (#4756) 2026-06-27 14:38:33 -07:00
Yueqian Lin 05a86ed10e [Test] Un-skip Qwen3-TTS batch E2E; match documented omit-null response shape (#4757) (#4759)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
2026-06-26 23:31:44 -07:00
wangyu c6ee3f7c18 [Test] Skip Qwen3-TTS batch E2E tests (#4758) 2026-06-27 10:45:40 +08:00
Rahul SteigerandHongsheng Liu 327e9dcaf2 [Feature] Spatially-sharded (SP) decode for the Wan VAE (#4620)
Signed-off-by: Rahul Steiger <rsteiger@nvidia.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-27 09:01:25 +08:00
MaciejBalaNV 47871d5e20 Updated Cosmos3 docstrings (#4727)
Signed-off-by: Maciej Bala <mbala@nvidia.com>
2026-06-27 06:39:42 +08:00
Yueqian LinandSy03 b66cd024b9 [Bugfix] Fix /v1/audio/speech usage token accounting for Qwen3-TTS (#4646) (#4673)
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Sy03 <1370724210@qq.com>
2026-06-27 06:13:31 +08:00
Gao Han c582805e7a Revert "[Bugfix] Use MediaConnector for image/video URL fetching to prevent SSRF" (#4751) 2026-06-27 01:18:48 +08:00
wangyu 908e7d32d9 [CI][Bugfix] Fix nightly L2/L3 E2E-only upload and Buildkite EXTRA escaping (#4734)
Signed-off-by: wangyu <410167048@qq.com>
Signed-off-by: [Your Name] <your.email@example.com>
Signed-off-by: wangyu <53896905+yenuo26@users.noreply.github.com>
2026-06-26 23:10:19 +08:00
d6f1d3d61c [Doc] Add code-quality dimension to precheck-pr skill (#4697)
Signed-off-by: hsliu_ustc <hsliu_ustc@noreply.gitcode.com>
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: hsliu_ustc <hsliu_ustc@noreply.gitcode.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-26 20:31:10 +08:00
Sy03 c39ac9fffd [Bugfix] Stream Qwen3-TTS WebSocket input as one request (#4731)
Signed-off-by: Sy03 <1370724210@qq.com>
2026-06-26 07:48:30 +00:00
Yuanheng Zhao 580a0efe40 [Bugfix] Add back resolving from deploy config written pipeline in StageConfigFactory (#4729)
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
2026-06-25 22:11:49 -06:00
bmengkeandHongsheng Liu 329c98ff9d Wan2.2: Fix the bug of using cache-dit with ulysses in t2v and i2v (#3927)
Signed-off-by: Mengkejiergeli Ba <mengkejiergeli.ba@intel.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-25 15:15:59 +00:00
36a5e9cfd2 [skip ci][Misc] LVSA showcase (training-free block-sparse attention) (#4192)
Signed-off-by: Gael Glorian <gael.glorian@gmail.com>
Signed-off-by: Ioannis Lamprou <yiannis.lamprou@gmail.com>
Signed-off-by: Zhen Zhang <zhen.zhang.fr@huawei.com>
Co-authored-by: Ioannis Lamprou <yiannis.lamprou@gmail.com>
Co-authored-by: Zhen Zhang <zhen.zhang.fr@huawei.com>
2026-06-25 22:20:14 +08:00
0b04f2a0d6 [Model] Add Ming-omni-tts MoE 16.8B-A3B + CFM CUDAGraph (#4341)
Signed-off-by: LHXuuu <xulianhao.xlh@antgroup.com>
Signed-off-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Yuanheng Zhao <jonathan.zhaoyh@gmail.com>
Co-authored-by: Yuanheng Zhao <54058983+yuanheng-zhao@users.noreply.github.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-25 22:11:35 +08:00
5db89b41c4 [Core] hunyuan-image prefetch kv (#4448)
Signed-off-by: z00806815 <zhuhonghan@huawei.com>
Signed-off-by: zhuhh97 <zhuhonghan@huawei.com>
Signed-off-by: dph97 <nenbaying@163.com>
Signed-off-by: zhh <zhh@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: zhuhh97 <zhuhh97@users.noreply.github.com>
2026-06-25 21:31:49 +08:00
Weiming Liao e500c00545 [Bugfix][NPU] Register vllm-ascend custom ops in NPUOmniPlatform.set_device (#4712)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-06-25 18:50:08 +08:00
8ddcb3621f [Config] Add structured VllmOmniConfig classes (#4425)
Signed-off-by: Acerak01-fy <wfy2003324@163.com>
Signed-off-by: zwhzzz0821 <2831474076@qq.com>
Signed-off-by: Wang  fuyin <wfy2003324@163.com>
Co-authored-by: zwhzzz0821 <2831474076@qq.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-25 17:48:20 +08:00
Canlin Guo 2e6c83c89c [Model] Support MOSS-TTS-local-v1.5 (#4664)
Signed-off-by: gcanlin <canlinguosdu@gmail.com>
2026-06-25 15:43:03 +08:00
wangyu d9063d7141 [CI] Run L2/L3 E2E group on main nightly builds (#4693)
Signed-off-by: wangyu <410167048@qq.com>
2026-06-25 14:35:43 +08:00
rein yang 8c33793ffc [Bugfix]Unified import of PretrainedConfig (#4692)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-06-25 13:48:03 +08:00
amy-why-3459 4024a8ccd6 [BugFix] Remove prefix-cache test cases (#4703)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-06-25 13:47:41 +08:00
Daniel SocekandDidan Deng fb563fbd19 [Bugfix] Fix CFG-parallel broadcast dtype mismatch in GLM-Image (#3956)
Signed-off-by: Daniel Socek <daniel.socek@intel.com>
Co-authored-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
2026-06-25 13:14:29 +08:00
0fd2620d56 [BugFix] Fix MammothModa2 Text-to-Image Bug (#4299)
Signed-off-by: menjiantong <menjiantong@foxmail.com>
Co-authored-by: menjiantong <menjiantong@foxmail.com>
Co-authored-by: Didan Deng <33117903+wtomin@users.noreply.github.com>
2026-06-25 13:14:02 +08:00
zhumingjue138 0d0f4e669e [Test] add reliability test case for HunyuanImage-3.0-Instruct and reliability/stability test for VoxCPM2 (#4600)
Signed-off-by: zhumingjue <zhumingjue@huawei.com>
Signed-off-by: [Your Name] [Your Email]
2026-06-25 04:41:19 +00:00
WeiQing ChenandIanniu d94108693a [BugFix] Fix Wan2.2-VACE-Fun cache and serving lifecycle (#4667)
Signed-off-by: Ianniu <985683179yzy@gmail.com>
Signed-off-by: david6666666 <530634352@qq.com>
Co-authored-by: Ianniu <985683179yzy@gmail.com>
2026-06-25 11:20:58 +08:00
bjf-frz d612233bef [Bugfix][CI]Fix HSDP regional compile boundary (#4668)
Signed-off-by: bjf-frz <frz123db@gmail.com>
2026-06-25 02:52:52 +00:00
wangyu f6e8b77642 [Test] Skip MOSS TTS offline E2E tests (issue #4700) (#4701)
Signed-off-by: wangyu <410167048@qq.com>
2026-06-25 10:20:34 +08:00
Nick CaoandHongsheng Liu d8edf0c9d5 [Bugfix] Use MediaConnector for image/video URL fetching to prevent SSRF (#2565)
Signed-off-by: Nick Cao <ncao@redhat.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-25 06:28:26 +08:00
Zeng ChuangandHongsheng Liu 67bd02f767 [Feat] Enable streaming CoT display for HunyuanImage-3.0 AR generation (#4148)
Signed-off-by: zengchuang <zengchuang3@huawei.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-24 22:08:30 +08:00
Zhisen Zhang 0814d845dc [Refactor] Migrate VACE example to standard task examples + model_extras (#4648)
Signed-off-by: ForestWisdom <zszhang01@gmail.com>
2026-06-24 13:54:36 +00:00
rein yang bb973cb10c [Bugfix] [AURA] Correct aura results when use qwen3-tts in custom voice mode (#4650)
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-06-24 17:29:48 +08:00
Yuanheng Zhao fb3abb38fb [refactor] Flatten Ming-flash-omni-2.0 imagegen args (#4587)
Signed-off-by: Yuanheng <jonathan.zhaoyh@gmail.com>
2026-06-24 17:01:58 +08:00
Chendi.Xue eb81914c64 [S2V] Add sequence parallelism support to WanS2VTransformer3DModel (#4276)
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
2026-06-24 14:04:04 +08:00
1951dca786 [Model] add soulx-singer support (#3862)
Signed-off-by: Mr.Dong <1042542469@qq.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Mr.Dong <1042542469@qq.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
2026-06-24 05:36:45 +00:00
d71cacc74c [perf] avoid HunyuanImage3 timestep scalar sync (#4363)
Signed-off-by: TaffyOfficial <2324465096@qq.com>
Co-authored-by: TaffyOfficial <2324465096@qq.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-06-24 11:05:35 +08:00
Alex Brooks 465f1464d2 [Feat] Support Pipeline Resolution Based on HF Config & Make Pipeline Registry Eager (#3760)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
2026-06-24 11:02:29 +08:00
amy-why-3459 f6894f4308 [BugFix] Delete unnecessary log printing (#4566)
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-06-24 09:40:07 +08:00
rongfu.lengandGao Han a2d1dafc65 [Feature] add a new response_format is file type when image generate (#1673)
Signed-off-by: rongfu.leng <lenronfu@gmail.com>
Co-authored-by: Gao Han <hgaoaf@connect.ust.hk>
2026-06-24 09:04:13 +08:00
MaciejBalaNVandHongsheng Liu 6dc4638a7e Fixed Cosmos3 regression (#4627)
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-24 09:03:34 +08:00
SYLAR d35cdd2dab [Fix] JoyVL serving: align with reference engine (bounded long-term memory, timestamps, max_pixels) + recipe updates (#4623)
Signed-off-by: lishunyang12 <125541396+lishunyang12@users.noreply.github.com>
2026-06-24 07:04:17 +08:00
wangyu 0958e62ecc Add field IDs to bug report issue template (#4605)
Signed-off-by: wangyu <410167048@qq.com>
2026-06-23 20:26:25 +08:00
3901ad8165 [feat] Streaming diffusion video generation output (#3737)
Signed-off-by: Huang, Zeyu <11222265+fhfuih@users.noreply.github.com>
Signed-off-by: Zeyu Huang | 黃澤宇 <11222265+fhfuih@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 09:57:53 +00:00
QianCyrusandHongsheng Liu b84c99c122 [Bugfix] Fix make_request_output TypeError on multimodal generation-stage outputs (#4579)
Signed-off-by: QianCyrus <happyloser233@gmail.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-23 14:42:30 +08:00
Guanzhe (Leo) Huangand汪志鹏 733f4f6a36 [Refactor] Migrate cosmos3 example to standard task example + model_extra (#4581)
Signed-off-by: leohuang257 <masugchds@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
Co-authored-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-06-23 14:42:05 +08:00
Nick Cao 67d14b5ac4 [Refactor] Replace hardcoded CUDA device selection with platform-agnostic API (#4496)
Signed-off-by: Nick Cao <ncao@redhat.com>
2026-06-23 14:38:32 +08:00
Y. Fisher 64efa66869 [NPU] Initialize Ascend config for diffusion workers (#4386)
Signed-off-by: KexiongYu <yukexiong1@huawei.com>
2026-06-23 03:12:44 +00:00
Nick CaoandClaude 6646a66d41 [BugFix] Use ModuleDiscovery for HSDP DiT sharding to support nested pipelines (#3456)
Signed-off-by: Nick Cao <ncao@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-23 02:54:14 +00:00
CrazyCoder 378359fc11 [Doc] Stability AI/Stable-Audio-Open (#3664)
Signed-off-by: CrazyCoder <18235787078@163.com>
2026-06-23 10:03:02 +08:00
9c260b3774 Qwen3-TTS full-payload: emit empty-finished payload on degenerate take instead of dropping (fixes Stage-1 300s hang) (#4465)
Signed-off-by: jjw <m@jjw.in>
Signed-off-by: henryj <349043+henryj@users.noreply.github.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 00:21:11 +00:00
Yuanheng Zhao 9177b37e2f [NFC] Update misleading seed-tts-eval optional dependency guidance (#4619)
Signed-off-by: Yuanheng <jonathan.zhaoyh@gmail.com>
2026-06-22 16:35:42 -07:00
50bc51ffdf fix: return proper HTTP status codes for audio voice endpoints (#3969)
Signed-off-by: Ian Eaves <ian.k.eaves@gmail.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
Co-authored-by: Yueqian Lin <70319226+linyueqian@users.noreply.github.com>
2026-06-22 22:57:07 +00:00
BeatSeat 044240d8eb [Model] Add IndexTTS2 text-to-speech support (#3838)
Signed-off-by: BeatSeat <wendavid552@gmail.com>
Signed-off-by: David <david@podcast.ai>
Signed-off-by: wendavid552 <wendavid552@gmail.com>
Signed-off-by: WenDavid <davidzhangcf@foxmail.com>
2026-06-22 19:24:01 +00:00
TaffyOfficialandTaffyOfficial f4d922d8f6 [Bugfix][HunyuanImage3] Align AR RGB conversion with official semantics (#4502)
Signed-off-by: TaffyOfficial <2324465096@qq.com>
Co-authored-by: TaffyOfficial <2324465096@qq.com>
2026-06-22 16:09:03 +00:00
Chenguang Zhengandamy-why-3459 eaa16e1941 [Feature] Support Async Omni output materialization (#4476)
Signed-off-by: Chenguang ZHENG <645327136@qq.com>
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-06-22 16:07:07 +00:00
Zhou TaichangandClaude Opus 4.8 8a6786731e [CI][Rebase] Fix Ready/Merge pipeline upload by stripping source_file_dependencies (#4532)
Signed-off-by: tzhouam <tzhouam@connect.ust.hk>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 15:22:11 +00:00
Weiming Liao fb0f17858f [CI][NPU] Update VLLM ASCEND IMAGE (#4602)
Signed-off-by: Weiming Liao <liaowm5@gmail.com>
2026-06-22 22:33:06 +08:00
bjf-frz 2447740308 [Perf]perf: skip unused Cosmos3 I2V conditioning latents (#4614)
Signed-off-by: bjf-frz <frz123db@gmail.com>
2026-06-22 09:51:47 +00:00
汪志鹏 a10eac0f8c [Feature]: Migrate magi human example (#4572)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
Signed-off-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-06-22 15:17:00 +08:00
+2 ec4ec0f604 Add SSE stream_format support for audio speech streaming (#4490)
Signed-off-by: syd520zy <529477025@qq.com>
Signed-off-by: faceless void <100186390+syd520zy@users.noreply.github.com>
Signed-off-by: Nick Cao <ncao@redhat.com>
Signed-off-by: Chendi Xue <chendi.xue@intel.com>
Signed-off-by: kTorp <Kristoffer.Torp@amd.com>
Signed-off-by: Junhong Liu <98734602+LJH-LBJ@users.noreply.github.com>
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Signed-off-by: Hyoseop Song <crad_on25@naver.com>
Signed-off-by: Hyoseop Song  <crad_on25@naver.com>
Signed-off-by: amy-why-3459 <wuhaiyan17@huawei.com>
Co-authored-by: Nick Cao <ncao@redhat.com>
Co-authored-by: Chendi.Xue <chendi.xue@intel.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Kristoffer <kristoffer.torp@amd.com>
Co-authored-by: Junhong Liu <ljh_lbj@163.com>
Co-authored-by: lishunyang <lishunyang12@163.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Hyoseop Song <crad_on25@naver.com>
Co-authored-by: Zhou Taichang <tzhouam@connect.ust.hk>
Co-authored-by: Alicia <115451386+congw729@users.noreply.github.com>
Co-authored-by: amy-why-3459 <wuhaiyan17@huawei.com>
2026-06-22 06:42:25 +00:00
ad07f98b73 [Feat] Streaming TTS word-level timestamps via forced aligner (#4034)
Signed-off-by: wjinxu <1299461899@qq.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 04:51:45 +00:00
Yihong JinandClaude Opus 4.8 a60242092a [Bugfix][Qwen3-Omni] Pass Thinker lm_head prefix so NVFP4 exclude-list is honored (#4528)
Signed-off-by: Yihong Jin <yihongjin404@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 12:16:44 +08:00
WeiQing Chen 991b1ec752 Update WeChat group QR code (#4601)
Signed-off-by: David Chen <530634352@qq.com>
2026-06-22 10:30:22 +08:00
Kwokho TsuiandKwokho Tsui 6bdd85b384 [Doc] validate Cosmos3-Super online FP8 (#4584)
Signed-off-by: Kwokho Tsui <kh_tsui@163.com>
Co-authored-by: Kwokho Tsui <kh_tsui@163.com>
2026-06-22 02:24:04 +00:00
LancerandHongsheng Liu 36bd8029f3 [chore][skills]: tightens the add-diffusion-model skill under .claude/skills to better match the current vllm-omni codebase and repo conventions (#4110)
Signed-off-by: Lancer <maruixiang6688@gmail.com>
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-22 10:17:27 +08:00
WeiQing ChenandHongsheng Liu f0d7fe18f2 [Perf][Cosmos3] Optimize I2V conditioning transfer (8.63% faster x-inference) (#4467)
Signed-off-by: david6666666 <530634352@qq.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-22 01:59:03 +00:00
yangyonggit ccb5c53ea5 [Cleanup] Remove dead/stale modules with no repo references (fixes #4009) (#4044)
Signed-off-by: leo.yang <leo.yang.engineer@gmail.com>
2026-06-22 09:23:04 +08:00
Optance 8efd9d832d [Bugfix] Fix Fish Speech kvcache attention KV cache unpacking for vLLM 0.23.0 (#4428)
Signed-off-by: nagelanping <xiao.yi.ming@foxmail.com>
2026-06-22 09:22:41 +08:00
Alex Brooksand汪志鹏 7ff11d8d0f [Perf/Fix] Reimplement Batched CFG Forward for Bagel (#4098)
Signed-off-by: Alex Brooks <albrooks@redhat.com>
Co-authored-by: 汪志鹏 <wangzhipeng628@gmail.com>
2026-06-22 07:37:21 +08:00
MaciejBalaNVandHongsheng Liu fc32d9fe6f Improve Cosmos3 v2v quality (#4514)
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
2026-06-21 22:20:30 +08:00
rein yang afbcc51672 [Model] Aura support - Non async chunk path (#4257)
Signed-off-by: Rein Yang <ruiruyang2@gmail.com>
Signed-off-by: R2-Y <ruiruyang2@gmail.com>
2026-06-21 22:08:26 +08:00
Shin 1292c47804 [BugFix]Fix diffusion profile RPC None results (#4372)
Signed-off-by: yixiaoer <shin@yixiaoer.sg>
2026-06-21 17:14:21 +08:00
e241005a71 [Feature] JoyAI-VL-Interaction streaming interaction serving layer (#4575)
Signed-off-by: lishunyang12 <125541396+lishunyang12@users.noreply.github.com>
Signed-off-by: Yueqian Lin <linyueqian@outlook.com>
Signed-off-by: lishunyang <lishunyang12@163.com>
Co-authored-by: Hongsheng Liu <liuhongsheng4@huawei.com>
Co-authored-by: Yueqian Lin <linyueqian@outlook.com>
2026-06-21 07:42:51 +00:00
汪志鹏 950e66a44c [Feature]Migrate helios example (#4569)
Signed-off-by: princepride <wangzhipeng628@gmail.com>
2026-06-21 07:37:16 +00:00
MaciejBalaNV a1e1ac0155 Cosmos3 transfer (#4379)
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: MaciejBalaNV <mbala@nvidia.com>
2026-06-21 09:59:18 +08:00
1793 changed files with 228807 additions and 45767 deletions

No files matched your search

@@ -6,6 +6,8 @@
set -euo pipefail
source .buildkite/common/scripts/resolve_skip_ci.sh
if [[ -z "${RUN_ALL:-}" ]]; then
RUN_ALL=0
fi
@@ -22,10 +24,6 @@ if [[ -z "${AMD_MIRROR_HW:-}" ]]; then
AMD_MIRROR_HW="amdproduction"
fi
if [[ -z "${DOCS_ONLY_DISABLE:-}" ]]; then
DOCS_ONLY_DISABLE=0
fi
fail_fast() {
DISABLE_LABEL="ci-no-fail-fast"
# If BUILDKITE_PULL_REQUEST != "false", then we check the PR labels using curl and jq
@@ -56,88 +54,6 @@ check_run_all_label() {
fi
}
is_docs_only_change() {
local file_path
local has_any=0
while IFS= read -r file_path; do
[[ -z "${file_path}" ]] && continue
has_any=1
if [[ "${file_path}" == docs/* ]]; then
continue
fi
if [[ "${file_path}" == *.md ]]; then
continue
fi
if [[ "${file_path}" == "mkdocs.yml" ]]; then
continue
fi
return 1
done
[[ "${has_any}" -eq 1 ]]
}
resolve_skip_ci() {
local is_pr_build=0
local files
local base_branch base_ref
if [[ "${BUILDKITE_PULL_REQUEST:-false}" != "false" && -n "${BUILDKITE_PULL_REQUEST:-}" ]]; then
is_pr_build=1
fi
if [[ "${is_pr_build}" -eq 1 ]]; then
base_branch="${BUILDKITE_PULL_REQUEST_BASE_BRANCH:-main}"
if ! git rev-parse --verify "origin/${base_branch}" >/dev/null 2>&1; then
echo "resolve_skip_ci: origin/${base_branch} not found locally; trying fetch" >&2
git fetch --depth=200 origin "${base_branch}" >/dev/null 2>&1 || true
fi
base_ref=""
if git rev-parse --verify "origin/${base_branch}" >/dev/null 2>&1; then
base_ref="origin/${base_branch}"
elif git rev-parse --verify "${base_branch}" >/dev/null 2>&1; then
base_ref="${base_branch}"
else
echo "resolve_skip_ci: cannot resolve PR base ${base_branch}; skip-ci=0" >&2
echo -n 0
return 0
fi
if ! files="$(git diff --name-only "${base_ref}...${BUILDKITE_COMMIT}" 2>/dev/null)"; then
echo "resolve_skip_ci: failed to compute PR changed files; skip-ci=0" >&2
echo -n 0
return 0
fi
elif [[ "${BUILDKITE_BRANCH:-}" == "main" ]]; then
if ! git rev-parse --verify "${BUILDKITE_COMMIT}^" >/dev/null 2>&1; then
echo "resolve_skip_ci: commit has no parent on main; skip-ci=0" >&2
echo -n 0
return 0
fi
if ! files="$(git diff --name-only "${BUILDKITE_COMMIT}^..${BUILDKITE_COMMIT}" 2>/dev/null)"; then
echo "resolve_skip_ci: failed to compute main changed files; skip-ci=0" >&2
echo -n 0
return 0
fi
else
echo "resolve_skip_ci: not PR/main build; skip-ci=0" >&2
echo -n 0
return 0
fi
if is_docs_only_change <<< "${files}"; then
echo "resolve_skip_ci: docs-only change detected; skip-ci=1" >&2
echo -n 1
return 0
fi
echo "resolve_skip_ci: non-doc changes detected; skip-ci=0" >&2
echo -n 0
}
if [[ -z "${COV_ENABLED:-}" ]]; then
COV_ENABLED=0
fi
@@ -154,14 +70,14 @@ upload_pipeline() {
fi
# Use local template file for vllm-omni
cp .buildkite/test-template-amd-omni.j2 .buildkite/test-template.j2
cp .buildkite/amd/test-template-amd-omni.j2 .buildkite/amd/test-template.j2
# (WIP) Use pipeline generator instead of jinja template
if [ -e ".buildkite/pipeline_generator/pipeline_generator.py" ]; then
if [ -e ".buildkite/amd/pipeline_generator/pipeline_generator.py" ]; then
python -m pip install click pydantic
python .buildkite/pipeline_generator/pipeline_generator.py --run_all=$RUN_ALL --list_file_diff="$LIST_FILE_DIFF" --nightly="$NIGHTLY" --mirror_hw="$AMD_MIRROR_HW"
buildkite-agent pipeline upload .buildkite/pipeline.yaml
python .buildkite/amd/pipeline_generator/pipeline_generator.py --run_all=$RUN_ALL --list_file_diff="$LIST_FILE_DIFF" --nightly="$NIGHTLY" --mirror_hw="$AMD_MIRROR_HW"
buildkite-agent pipeline upload .buildkite/amd/pipeline.yaml
exit 0
fi
echo "List file diff: $LIST_FILE_DIFF"
@@ -171,7 +87,7 @@ upload_pipeline() {
FAIL_FAST=$(fail_fast)
cd .buildkite
cd .buildkite/amd
# Select test definition file: merge suite for main, ready suite for PRs.
# For debugging, DEBUG_TEST_YAML can override the selection — accepts
@@ -182,7 +98,7 @@ upload_pipeline() {
TEST_YAML="test-amd-merge.yml"
;;
ready)
TEST_YAML="test-amd-ready.yaml"
TEST_YAML="test-amd-ready.yml"
;;
*)
echo "ERROR: DEBUG_TEST_YAML must be 'merge' or 'ready', got '$DEBUG_TEST_YAML'" >&2
@@ -193,7 +109,7 @@ upload_pipeline() {
elif [[ $BUILDKITE_BRANCH == "main" ]]; then
TEST_YAML="test-amd-merge.yml"
else
TEST_YAML="test-amd-ready.yaml"
TEST_YAML="test-amd-ready.yml"
fi
(
@@ -234,23 +150,13 @@ if [[ $BUILDKITE_BRANCH == "main" ]]; then
file_diff=$(get_diff_main)
fi
# ----------------------------------------------------------------------
# Early exit start: skip pipeline if conditions are met
# ----------------------------------------------------------------------
# Match CUDA Buildkite skip-ci behavior for docs/markdown-only changes.
if [[ "${DOCS_ONLY_DISABLE}" != "1" ]]; then
SKIP_CI="$(resolve_skip_ci)"
if [[ "${SKIP_CI}" == "1" ]]; then
echo "[docs-only] Docs/markdown-only changes detected. Exiting before pipeline upload."
exit 0
fi
# Early exit: unified skip-ci (docs / skip marks) and CI-yaml-only level targeting.
if [[ $BUILDKITE_BRANCH == "main" ]]; then
gate_bootstrap_ci amd l3
else
gate_bootstrap_ci amd l2
fi
# ----------------------------------------------------------------------
# Early exit end
# ----------------------------------------------------------------------
patterns=(
"docker/Dockerfile"
"CMakeLists.txt"
@@ -56,7 +56,7 @@ container_name="rocm_${BUILDKITE_COMMIT}_$(tr -dc A-Za-z0-9 < /dev/urandom | hea
# # Install AWS CLI to authenticate to ECR Public Gallery to get higher rate limit for pulling images
# sudo apt-get update && sudo apt-get install -y awscli
## Use safe docker login helper to prevent race conditions
# source "$(dirname "${BASH_SOURCE[0]}")/../docker_login_ecr_public.sh"
# source "$(dirname "${BASH_SOURCE[0]}")/../../common/scripts/docker_login_ecr_public.sh"
# safe_docker_login_ecr_public
## Pull the container from AMD Docker Hub
@@ -7,17 +7,29 @@ steps:
- group: ":card_index_dividers: Simple Test"
steps:
- label: "Simple · Diffusion & Model Executor Test"
- label: "Simple · Diffusion & Model Executor Test (1/2)"
agent_pool: mi325_1
depends_on: amd-build
timeout_in_minutes: 50
timeout_in_minutes: 70
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export VLLM_ROCM_USE_AITER=0
# ignore test_teacache_extractors.py because it use rocm gemm kernel from vLLM
# that is not supported on CPU
- "timeout 40m pytest -sv tests/diffusion tests/model_executor -m 'core_model and cpu' --ignore=tests/diffusion/cache/test_teacache_extractors.py --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
# CPU tests on ROCm gpu machines are very slow, so we give them more time.
- "timeout 60m pytest -sv tests/diffusion -m 'core_model and cpu' --ignore=tests/diffusion/cache/test_teacache_extractors.py --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
- label: "Simple · Diffusion & Model Executor Test (2/2)"
agent_pool: mi325_1
depends_on: amd-build
timeout_in_minutes: 70
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export VLLM_ROCM_USE_AITER=0
# CPU tests on ROCm gpu machines are very slow, so we give them more time.
- "timeout 60m pytest -sv tests/model_executor -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
- label: "Simple · Other Test"
agent_pool: mi325_1
@@ -77,7 +89,7 @@ steps:
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- pytest -s -v tests/diffusion/distributed/test_zimage_parallelism.py
- pytest -s -v tests/diffusion/distributed/test_tensor_parallel.py
- label: "Diffusion Model Test"
agent_pool: mi325_1
@@ -158,7 +170,7 @@ steps:
grade: Blocking
commands:
- |
timeout 20m bash -c '
timeout 50m bash -c '
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
@@ -170,39 +182,14 @@ steps:
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- |
timeout 30m bash -c '
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py tests/e2e/offline_inference/test_qwen3_tts_base.py -m "advanced_model" --run-level "advanced_model"
'
# It is the whisper ASR validation step that is slow, not the Voxtral TTS generation.
# whisper ASR runs on CPU.
- label: "Voxtral-TTS E2E Test (Online Serving)"
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
timeout_in_minutes: 50
commands:
- |
timeout 40m bash -c '
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/online_serving/test_voxtral_tts.py -m "advanced_model" --run-level "advanced_model"
'
- label: "Voxtral-TTS E2E Test (Offline Inference)"
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- |
timeout 30m bash -c '
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/offline_inference/test_voxtral_tts.py -m "advanced_model" --run-level "advanced_model"
export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py tests/e2e/offline_inference/test_qwen3_tts_base.py -m 'advanced_model and cuda' --run-level 'advanced_model'
'
# TODO: Bagel test on ROCm is very unstable. @tjtanaa
@@ -35,7 +35,7 @@ steps:
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- timeout 20m pytest -s -v tests/e2e/offline_inference/custom_pipeline/ -m "core_model"
- timeout 20m pytest -s -v tests/e2e/features/custom_pipeline/ -m "core_model"
- label: "Voxtral TTS CUDA Unit Test"
@@ -161,19 +161,6 @@ steps:
- group: ":card_index_dividers: E2E Test"
steps:
- label: "MiMo-Audio E2E Test with H100"
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- |
timeout 30m bash -c '
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/online_serving/test_mimo_audio.py -m "core_model" --run-level "core_model"
'
- label: "Qwen3-TTS E2E Test"
agent_pool: mi325_1
depends_on: amd-build
@@ -193,7 +180,7 @@ steps:
commands:
- |
timeout 20m bash -c '
pytest -s -v tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py -m "full_model" --run-level "core_model"
pytest -s -v tests/e2e/online_serving/test_cosyvoice3_tts_expansion.py -m "slow" --run-level "core_model"
'
# TODO: Bagel test on ROCm is very unstable. @tjtanaa
@@ -57,7 +57,7 @@ steps:
{% endif %}
{% set cmd_body = (step.command or (step.commands | join("\n"))) | trim %}
{% set indented_cmd = cmd_body | replace("\n", "\n ") %}
command: bash .buildkite/scripts/hardware_ci/run-amd-test.sh
command: bash .buildkite/amd/scripts/run-amd-test.sh
env:
DOCKER_BUILDKIT: "1"
{% if step.env %}
@@ -104,7 +104,7 @@ steps:
{% endif %}
{% set cmd_body = (step.command or (step.commands | join("\n"))) | trim %}
{% set indented_cmd = cmd_body | replace("\n", "\n ") %}
command: bash .buildkite/scripts/hardware_ci/run-amd-test.sh
command: bash .buildkite/amd/scripts/run-amd-test.sh
env:
DOCKER_BUILDKIT: "1"
{% if step.env %}
-51
View File
@@ -1,51 +0,0 @@
#!/bin/bash
# vllm-omni Intel bootstrap
# Uses static pipeline-intel.yaml for Intel XPU tests
# Based on: bootstrap-amd-omni.sh
set -euo pipefail
if [[ -z "${DOCS_ONLY_DISABLE:-}" ]]; then
DOCS_ONLY_DISABLE=0
fi
upload_pipeline() {
echo "--- 🛠 Preparing Intel pipeline"
buildkite-agent pipeline upload .buildkite/pipeline-intel.yaml
}
get_diff() {
$(git add .)
echo $(git diff --name-only --diff-filter=ACMDR $(git merge-base origin/main HEAD))
}
get_diff_main() {
$(git add .)
echo $(git diff --name-only --diff-filter=ACMDR HEAD~1)
}
file_diff=$(get_diff)
if [[ $BUILDKITE_BRANCH == "main" ]]; then
file_diff=$(get_diff_main)
fi
# ----------------------------------------------------------------------
# Early exit: skip pipeline if all changed files are under docs/
# ----------------------------------------------------------------------
if [[ "${DOCS_ONLY_DISABLE}" != "1" ]] && [[ -n "${file_diff:-}" ]]; then
docs_only=1
while IFS= read -r f; do
[[ -z "$f" ]] && continue
if [[ "$f" != docs/* ]]; then
docs_only=0
break
fi
done < <(printf '%s\n' "$file_diff" | tr ' ' '\n' | tr -d '\r')
if [[ "$docs_only" -eq 1 ]]; then
buildkite-agent annotate ":memo: CI skipped — docs only" --style "info"
exit 0
fi
fi
upload_pipeline
+239
View File
@@ -0,0 +1,239 @@
# Uploader-only hardware presets for CUDA / NPU test YAML.
# Referenced as ``mirror_hardwares: l4_1`` on a step; ``upload_pipeline.py`` expands to
# ``agents`` (+ optional top-level ``image`` for NPU) + ``plugins``, then strips
# ``mirror_hardwares`` before Buildkite upload.
#
# CUDA naming: {chip}_{count}
# l4_1, l4_4, h100_1 … h100_4
# NPU naming: {queue}_{resource_class}
# a2b3_npu_1 — ascend-a2b3, resource_class npu-1 (A2/B3 CI image)
# a2b3_npu_4 — ascend-a2b3, resource_class npu-4
# a3_npu_2 — ascend-a3, resource_class npu-2 (A3 CI image tag …:$BUILDKITE_COMMIT-a3)
x-npu-k8s-plugins: &npu_k8s_plugins
- kubernetes:
podSpecPatch:
imagePullSecrets:
- name: swr-secret
mirror_hardwares:
l4_1:
agents:
queue: gpu_1_queue
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- HF_HOME=/fsx/hf_cache
- HF_TOKEN
volumes:
- /fsx/hf_cache:/fsx/hf_cache
l4_4:
agents:
queue: gpu_4_queue
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- HF_HOME=/fsx/hf_cache
- HF_TOKEN
volumes:
- /fsx/hf_cache:/fsx/hf_cache
h100_1:
agents:
queue: mithril-h100-pool
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
h100_2:
agents:
queue: mithril-h100-pool
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
h100_3:
agents:
queue: mithril-h100-pool
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 3
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
h100_4:
agents:
queue: mithril-h100-pool
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 4
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
a2b3_npu_1:
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}"
plugins: *npu_k8s_plugins
a2b3_npu_4:
agents:
queue: "ascend-a2b3"
resource_class: "npu-4"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}"
plugins: *npu_k8s_plugins
a2b3_npu_8:
agents:
queue: "ascend-a2b3"
resource_class: "npu-8"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}"
plugins: *npu_k8s_plugins
a3_npu_2:
agents:
queue: "ascend-a3"
resource_class: "npu-2"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}-a3"
plugins: *npu_k8s_plugins
a3_npu_4:
agents:
queue: "ascend-a3"
resource_class: "npu-4"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}-a3"
plugins: *npu_k8s_plugins
a3_npu_8:
agents:
queue: "ascend-a3"
resource_class: "npu-8"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}-a3"
plugins: *npu_k8s_plugins
a3_npu_16:
agents:
queue: "ascend-a3"
resource_class: "npu-16"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}-a3"
plugins: *npu_k8s_plugins
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Shared Buildkite skip-ci helpers for AMD / Intel bootstrap scripts.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKIP_CI_PY="${SCRIPT_DIR}/skip_ci.py"
# Resolve git diff once. Exit 0 when this bootstrap should stop uploading.
# Decision details are logged by skip_ci.py; this helper only annotates skip-all.
# Usage: gate_bootstrap_ci <platform> <l2|l3>
gate_bootstrap_ci() {
local platform="$1"
local level="$2"
local kind
if kind="$(python3 "${SKIP_CI_PY}" gate "${platform}" "${level}")"; then
if [[ "${kind}" == "skip-all" ]]; then
buildkite-agent annotate \
":memo: CI skipped — docs or pytest skip-mark changes only" \
--style "info" 2>/dev/null || true
fi
exit 0
fi
}
+617
View File
@@ -0,0 +1,617 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Shared Buildkite skip-ci and CI-YAML level targeting logic.
``resolve_ci_decision(changed_files, ...)`` buckets explicit file lists (tests, dry-run).
``resolve_ci_context_from_git()`` resolves git diff once and returns decision + changed files
for Buildkite bootstrap / upload scripts.
CLI (for bootstrap scripts; exit code is the signal):
python3 skip_ci.py gate <platform> <level>
Exit 0 when bootstrap should stop (skip-all, or that L2/L3 target is off).
Prints ``skip-all`` or ``skip-l23`` on stdout; logs the decision once.
python3 skip_ci.py check-skip-all
Exit 0 when only docs/skip-mark changes → bootstrap skips entire CI upload.
python3 skip_ci.py check-skip-l2-l3 <platform> <level>
Exit 0 when that L2/L3 pipeline should be skipped (CI config YAML-only diffs).
python3 skip_ci.py print-annotate
Print decision message for Buildkite annotation.
"""
from __future__ import annotations
import argparse
import os
import re
import subprocess
import sys
from dataclasses import dataclass, field, replace
from pathlib import Path
LOG = "[skip-ci]"
ROOT = Path(__file__).resolve().parent.parent.parent.parent
PLATFORMS = ("cuda", "amd", "intel", "npu")
L23_LEVELS = frozenset({"l2", "l3"})
L2_YAML_FILES: dict[str, str] = {
".buildkite/cuda/test-ready.yml": "cuda",
".buildkite/npu/test-npu-ready.yml": "npu",
".buildkite/amd/test-amd-ready.yml": "amd",
".buildkite/intel/pipeline-intel.yml": "intel",
}
L3_YAML_FILES: dict[str, str] = {
".buildkite/cuda/test-merge.yml": "cuda",
".buildkite/amd/test-amd-merge.yml": "amd",
}
L45_YAML_FILES: dict[str, str] = {
".buildkite/cuda/test-nightly.yml": "cuda",
".buildkite/cuda/test-weekly.yml": "cuda",
".buildkite/npu/test-npu-nightly.yml": "npu",
}
def _empty_platform_buckets() -> dict[str, list[str]]:
return {platform: [] for platform in PLATFORMS}
@dataclass(frozen=True)
class CiDevice:
"""Per-platform / per-level skip flags for yaml-gated bootstrap (``skip_l2_l3``)."""
skip_cuda_l2: bool = False
skip_cuda_l3: bool = False
skip_amd_l2: bool = False
skip_amd_l3: bool = False
skip_intel_l2: bool = False
skip_intel_l3: bool = False
skip_npu_l2: bool = False
skip_npu_l3: bool = False
def is_skip(self, platform: str, level: str) -> bool:
return bool(getattr(self, f"skip_{platform}_{level}", True))
@dataclass
class DiffBuckets:
"""Changed files grouped by doc / skip-mark / CI yaml / other."""
docs: list[str] = field(default_factory=list)
skip_tests: list[str] = field(default_factory=list)
other: list[str] = field(default_factory=list)
l2: dict[str, list[str]] = field(default_factory=_empty_platform_buckets)
l3: dict[str, list[str]] = field(default_factory=_empty_platform_buckets)
l45: dict[str, list[str]] = field(default_factory=_empty_platform_buckets)
@property
def has_doc_changes(self) -> bool:
return bool(self.docs)
@property
def has_skip_test_changes(self) -> bool:
return bool(self.skip_tests)
@property
def has_other_changes(self) -> bool:
"""Product code or paths outside skip-ci scope."""
return bool(self.other)
@property
def has_l23_yaml_changes(self) -> bool:
"""At least one whitelisted L2/L3 CI yaml file changed."""
return any(self.l2[platform] or self.l3[platform] for platform in PLATFORMS)
@property
def has_l45_yaml_changes(self) -> bool:
"""At least one whitelisted L4/L5 (nightly/weekly) CI yaml file changed."""
return any(self.l45[platform] for platform in PLATFORMS)
@property
def has_skip_ci_scope_changes(self) -> bool:
"""At least one doc / skip-mark / whitelisted CI yaml change."""
return (
self.has_doc_changes or self.has_skip_test_changes or self.has_l23_yaml_changes or self.has_l45_yaml_changes
)
def l2_platforms(self) -> frozenset[str]:
return frozenset(platform for platform in PLATFORMS if self.l2[platform])
def l3_platforms(self) -> frozenset[str]:
return frozenset(platform for platform in PLATFORMS if self.l3[platform])
@dataclass(frozen=True)
class SkipL2L3Basis:
skip_all_l2: bool
skip_all_l3: bool
@classmethod
def from_buckets(cls, buckets: DiffBuckets) -> SkipL2L3Basis | None:
"""L4/L5 yaml → skip both L2 and L3 (L2/L3 buckets may rescue).
Docs / skip-mark changes do not block this path; they are ignored for
L2/L3 targeting when CI YAML is also present.
"""
if buckets.has_other_changes:
return None
if not buckets.has_l45_yaml_changes:
return None
return cls(
skip_all_l2=not buckets.l2_platforms(),
skip_all_l3=not buckets.l3_platforms(),
)
@dataclass(frozen=True)
class SkipL3Basis:
enable_l2_platforms: frozenset[str]
@classmethod
def from_buckets(cls, buckets: DiffBuckets) -> SkipL3Basis | None:
"""L2 yaml changed → skip L3; keep L2 on touched platforms."""
platforms = buckets.l2_platforms()
if not platforms:
return None
return cls(enable_l2_platforms=platforms)
@dataclass(frozen=True)
class SkipL2Basis:
enable_l3_platforms: frozenset[str]
@classmethod
def from_buckets(cls, buckets: DiffBuckets) -> SkipL2Basis | None:
"""L3 yaml changed → skip L2; keep L3 on touched platforms."""
platforms = buckets.l3_platforms()
if not platforms:
return None
return cls(enable_l3_platforms=platforms)
@dataclass(frozen=True)
class CiDecision:
"""Final CI skip decision for one diff."""
skip_all: bool = False
skip_l2_l3: bool = False
device: CiDevice = field(default_factory=CiDevice)
message: str = ""
@classmethod
def skip_all_basis(cls, buckets: DiffBuckets, *, diff_range: str | None) -> bool:
"""Docs / pytest skip-mark only → suppress entire default CI."""
if buckets.has_other_changes:
return False
if (buckets.has_l23_yaml_changes or buckets.has_l45_yaml_changes) and (
buckets.has_doc_changes or buckets.has_skip_test_changes
):
return False
if not buckets.has_doc_changes and not buckets.has_skip_test_changes:
return False
if diff_range is None and not buckets.has_doc_changes:
return False
return True
@classmethod
def from_yaml_basis(
cls,
l2_l3_basis: SkipL2L3Basis | None,
l3_basis: SkipL3Basis | None,
l2_basis: SkipL2Basis | None,
) -> CiDecision:
"""Build a yaml-gated decision by merging L2/L3 skip bases.
Bases are applied as a union of enables: L2 yaml keeps L2 on touched
platforms, L3 yaml keeps L3 on touched platforms. Cross-platform mixes
(e.g. CUDA ready + AMD merge) must preserve both enables. The resulting
per-platform / per-level matrix is stored on ``device`` as ``skip_*``.
"""
run = {platform: {"l2": True, "l3": True} for platform in PLATFORMS}
if l2_l3_basis is not None:
if l2_l3_basis.skip_all_l2:
for platform in PLATFORMS:
run[platform]["l2"] = False
if l2_l3_basis.skip_all_l3:
for platform in PLATFORMS:
run[platform]["l3"] = False
if l3_basis is not None:
for platform in PLATFORMS:
run[platform]["l3"] = False
run[platform]["l2"] = platform in l3_basis.enable_l2_platforms
if l2_basis is not None:
for platform in PLATFORMS:
if platform in l2_basis.enable_l3_platforms:
run[platform]["l3"] = True
if l3_basis is None or platform not in l3_basis.enable_l2_platforms:
run[platform]["l2"] = False
elif l3_basis is None:
# L3-yaml-only: disable platforms that did not change L3.
run[platform]["l2"] = False
run[platform]["l3"] = False
# else: leave L2 enables from SkipL3Basis; keep this platform's L3 off.
return cls(
skip_l2_l3=True,
device=cls._device_from_run(run),
)
@staticmethod
def _device_from_run(run: dict[str, dict[str, bool]]) -> CiDevice:
return CiDevice(
**{f"skip_{platform}_{level}": not run[platform][level] for platform in PLATFORMS for level in ("l2", "l3")}
)
def is_run(self, platform: str, level: str) -> bool:
if self.skip_all:
return False
if not self.skip_l2_l3:
return True
if level not in L23_LEVELS:
return True
return not self.device.is_skip(platform, level)
@dataclass(frozen=True)
class CiContext:
"""Skip-ci decision plus git diff inputs used to compute it."""
decision: CiDecision
changed_files: list[str] | None
diff_range: str | None
def _log(message: str) -> None:
print(f"{LOG}: {message}", file=sys.stderr)
def _git(*args: str) -> subprocess.CompletedProcess[str]:
return subprocess.run(
["git", *args],
check=False,
capture_output=True,
text=True,
)
# --- Diff helpers ---
def _resolve_diff_range() -> str | None:
"""Return a git diff range for PR or main builds, or None when unavailable."""
is_pr = os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" and os.environ.get(
"BUILDKITE_PULL_REQUEST", ""
)
commit = os.environ.get("BUILDKITE_COMMIT", "")
if is_pr:
base_branch = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH", "main")
base_ref = f"origin/{base_branch}"
if _git("rev-parse", "--verify", base_ref).returncode != 0:
_log(f"origin/{base_branch} not found locally; trying fetch")
_git("fetch", "--depth=200", "origin", base_branch)
if _git("rev-parse", "--verify", base_ref).returncode != 0:
if _git("rev-parse", "--verify", base_branch).returncode == 0:
base_ref = base_branch
else:
_log(f"cannot resolve PR base {base_branch}; using safe defaults")
return None
return f"{base_ref}...{commit}"
if os.environ.get("BUILDKITE_BRANCH", "") == "main":
if _git("rev-parse", "--verify", f"{commit}^").returncode != 0:
_log("main commit has no parent; using safe defaults")
return None
return f"{commit}^..{commit}"
_log("not PR/main build; using safe defaults")
return None
def _changed_files_for_diff_range(diff_range: str | None) -> list[str] | None:
"""Return changed file paths for *diff_range*, or None when unavailable."""
if diff_range is None:
return None
result = _git("diff", "--name-only", diff_range)
if result.returncode != 0:
_log(f"git diff failed ({diff_range}); using safe defaults")
return None
files = [line for line in result.stdout.splitlines() if line.strip()]
_log(f"{len(files)} changed file(s)")
return files
def resolve_ci_context_from_git() -> CiContext:
"""Resolve git diff once and return skip-ci decision plus changed files."""
diff_range = _resolve_diff_range()
changed_files = _changed_files_for_diff_range(diff_range)
decision = resolve_ci_decision(changed_files, diff_range=diff_range)
return CiContext(decision=decision, changed_files=changed_files, diff_range=diff_range)
# --- Doc / skip-mark helpers ---
_SKIP_MARK_RE = re.compile(r"pytest\.mark\.skip(?:if)?\b|pytest\.skip\s*\(")
_PYTESTMARK_SKIP_RE = re.compile(r"pytest\.mark\.skip\b")
_PYTEST_MARK_ONLY_RE = re.compile(r"pytest\.mark\.\w+")
def _diff_only_contains_skip_mark_changes(diff_text: str) -> bool:
"""Return True when a unified diff only *adds* pytest skip marks.
Deleting a skip mark re-enables the test and must not suppress CI. Editing an
existing skip (``-`` old / ``+`` new) still qualifies when at least one skip
mark is added.
"""
def paren_balance(line: str) -> int:
return line.count("(") - line.count(")")
def is_blank_or_comment(line: str) -> bool:
stripped = line.strip()
return not stripped or stripped.startswith("#")
def is_skip_mark_line(line: str) -> bool:
return _SKIP_MARK_RE.search(line.strip()) is not None
def is_pytestmark_adjacent_line(line: str) -> bool:
stripped = line.strip().rstrip(",")
if not stripped or stripped in {"[", "]"} or stripped.startswith("#"):
return True
if stripped.startswith("pytestmark"):
return True
return _PYTEST_MARK_ONLY_RE.search(stripped) is not None
pending_depth = 0
saw_change = False
has_added_skip_mark = False
for raw_line in diff_text.splitlines():
if raw_line.startswith("@@"):
pending_depth = 0
continue
if not (raw_line.startswith("+") or raw_line.startswith("-")):
continue
if raw_line.startswith("+++") or raw_line.startswith("---"):
continue
saw_change = True
is_add = raw_line.startswith("+")
content = raw_line[1:]
if pending_depth > 0:
pending_depth += paren_balance(content)
if pending_depth < 0:
pending_depth = 0
continue
if is_blank_or_comment(content):
continue
if is_skip_mark_line(content):
if is_add:
has_added_skip_mark = True
pending_depth = max(0, paren_balance(content))
continue
if is_pytestmark_adjacent_line(content):
continue
return False
return saw_change and has_added_skip_mark
def _is_skip_testcase_change(file_path: str, *, diff_range: str) -> bool:
"""Return True when a test file diff is skip-mark-only (including new-file cases)."""
diff_result = _git("diff", diff_range, "--", file_path)
if diff_result.returncode != 0:
_log(f"skip-mark-only: git diff failed for {file_path}")
return False
diff_text = diff_result.stdout
if not diff_text.strip():
_log(f"skip-mark-only: empty diff for {file_path}")
return False
if _diff_only_contains_skip_mark_changes(diff_text):
return True
if "new file mode" not in diff_text and "--- /dev/null" not in diff_text:
_log(f"skip-mark-only: non-skip changes in {file_path}")
return False
commit = os.environ.get("BUILDKITE_COMMIT", "")
if not commit:
return False
content_result = _git("show", f"{commit}:{file_path}")
if content_result.returncode != 0:
_log(f"skip-mark-only: cannot read {file_path} at {commit}")
return False
content = content_result.stdout
match = re.search(r"^pytestmark\s*=\s*\[(.*?)^\s*\]", content, re.MULTILINE | re.DOTALL)
if match is not None and _PYTESTMARK_SKIP_RE.search(match.group(1)) is not None:
_log(f"skip-mark-only: new test file with module-level pytest.mark.skip: {file_path}")
return True
if re.search(r"^pytestmark\s*=\s*pytest\.mark\.skip\b", content, re.MULTILINE):
_log(f"skip-mark-only: new test file with module-level pytest.mark.skip: {file_path}")
return True
_log(f"skip-mark-only: new test file without module-level pytest.mark.skip: {file_path}")
return False
def _classify_changed_files_into_buckets(changed_files: list[str], *, diff_range: str | None) -> DiffBuckets:
"""Classify each changed file path into a ``DiffBuckets`` category."""
buckets = DiffBuckets()
for file_path in changed_files:
if not file_path:
continue
if file_path.startswith("docs/") or file_path.endswith(".md") or file_path == "mkdocs.yml":
buckets.docs.append(file_path)
continue
path = Path(file_path)
if path.suffix == ".py" and path.parts and path.parts[0] == "tests":
if diff_range is not None and _is_skip_testcase_change(file_path, diff_range=diff_range):
buckets.skip_tests.append(file_path)
else:
buckets.other.append(file_path)
continue
if file_path in L2_YAML_FILES:
platform = L2_YAML_FILES[file_path]
buckets.l2[platform].append(file_path)
elif file_path in L3_YAML_FILES:
platform = L3_YAML_FILES[file_path]
buckets.l3[platform].append(file_path)
elif file_path in L45_YAML_FILES:
platform = L45_YAML_FILES[file_path]
buckets.l45[platform].append(file_path)
else:
buckets.other.append(file_path)
return buckets
# --- Decision ---
def _finish(decision: CiDecision, message: str) -> CiDecision:
finished = replace(decision, message=message)
_log(message)
return finished
def _format_yaml_gated_message(buckets: DiffBuckets, decision: CiDecision) -> str:
"""Human-readable summary of which CI YAML changed and which L2/L3 targets run."""
changed_parts: list[str] = []
for level_name, by_platform in (("L2", buckets.l2), ("L3", buckets.l3), ("L4/L5", buckets.l45)):
files = [path for platform in PLATFORMS for path in by_platform[platform]]
if files:
changed_parts.append(f"{level_name}=[{', '.join(files)}]")
run_targets = [
f"{platform}/{level}" for platform in PLATFORMS for level in ("l2", "l3") if decision.is_run(platform, level)
]
skip_targets = [
f"{platform}/{level}"
for platform in PLATFORMS
for level in ("l2", "l3")
if not decision.is_run(platform, level)
]
changed = "; ".join(changed_parts) if changed_parts else "none"
run = ", ".join(run_targets) if run_targets else "none"
skip = ", ".join(skip_targets) if skip_targets else "none"
if buckets.has_doc_changes or buckets.has_skip_test_changes:
return (
"CI config YAML + docs/skip-mark changed — follow CI YAML gating; "
f"changed: {changed}; run: {run}; skip: {skip}"
)
return f"only CI config YAML changed — changed: {changed}; run: {run}; skip: {skip}"
def resolve_ci_decision(
changed_files: list[str] | None = None,
*,
diff_range: str | None = None,
) -> CiDecision:
if changed_files is None:
return _finish(CiDecision(), "could not resolve changed files; run normal CI")
buckets = _classify_changed_files_into_buckets(changed_files, diff_range=diff_range)
if buckets.has_other_changes or not buckets.has_skip_ci_scope_changes:
return _finish(CiDecision(), "product or non-whitelisted changes present; run normal CI")
if CiDecision.skip_all_basis(buckets, diff_range=diff_range):
return _finish(
CiDecision(skip_all=True),
"CI skipped — docs or pytest skip-mark changes only",
)
# Docs / skip-mark mixed with whitelisted CI YAML → same yaml-gated path
# as CI-YAML-only (docs/skip-mark do not widen to normal CI).
if not buckets.has_l23_yaml_changes and not buckets.has_l45_yaml_changes:
if buckets.has_skip_test_changes and diff_range is None:
message = (
"only pytest skip-mark test changes detected, but no git diff range "
"is available to verify them (skip-all requires diff_range); run normal CI"
)
elif buckets.has_skip_test_changes:
message = "pytest skip-mark test changes did not qualify for skip-all and no ci yaml changed; run normal CI"
else:
message = "doc/skip-mark changes did not qualify for skip-all; run normal CI"
return _finish(CiDecision(), message)
decision = CiDecision.from_yaml_basis(
SkipL2L3Basis.from_buckets(buckets),
SkipL3Basis.from_buckets(buckets),
SkipL2Basis.from_buckets(buckets),
)
return _finish(decision, _format_yaml_gated_message(buckets, decision))
def main() -> int:
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
subparsers = parser.add_subparsers(dest="command", required=True)
gate_parser = subparsers.add_parser(
"gate",
help="exit 0 when bootstrap should stop (skip-all or PLATFORM/LEVEL disabled); logs once",
)
gate_parser.add_argument("platform", help="cuda, amd, intel, or npu")
gate_parser.add_argument("level", choices=("l2", "l3"), help="test level")
subparsers.add_parser(
"check-skip-all",
help="exit 0 when docs/skip-mark-only diff should skip entire CI upload",
)
skip_parser = subparsers.add_parser(
"check-skip-l2-l3",
help="exit 0 when PLATFORM l2/l3 pipeline should be skipped (CI config YAML-only diffs)",
)
skip_parser.add_argument("platform", help="cuda, amd, intel, or npu")
skip_parser.add_argument("level", choices=("l2", "l3"), help="test level")
subparsers.add_parser(
"print-annotate",
help="print human-readable skip reason for Buildkite annotation",
)
args = parser.parse_args()
decision = resolve_ci_context_from_git().decision
if args.command == "gate":
if decision.skip_all:
print("skip-all")
return 0
if not decision.is_run(args.platform, args.level):
print("skip-l23")
return 0
return 1
if args.command == "check-skip-all":
return 0 if decision.skip_all else 1
if args.command == "check-skip-l2-l3":
return 0 if not decision.is_run(args.platform, args.level) else 1
if args.command == "print-annotate":
print(decision.message or "CI will run normally")
return 0
return 1
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,449 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Render and optionally upload Buildkite pipeline YAML with diff-aware logic.
Bootstrap mode (``bootstrap-upload-steps.yml``):
- Hook uploads the entry YAML (``pipeline.yml`` / ``pipeline-npu.yml``) with one step that runs
``upload_pipeline.py --upload <platform>/bootstrap-upload-steps.yml``.
- Injects ``if`` by step ``key`` from skip-ci and uploads child steps (image build, L2–L5 upload).
- Detect docs-only, pytest skip-mark-only, or combined skip-ci from git diff.
- When only CI level YAML changes, enable **L2/L3** upload steps for affected levels only.
Test pipeline mode (e.g. test-merge.yml):
- Drop steps whose ``source_file_dependencies`` do not match changed files.
- Expand uploader-only ``mirror_hardwares: l4_1`` into ``agents`` (+ optional ``image``
for NPU) + ``plugins`` (see ci_mirror_hardwares.yml).
Usage:
python3 upload_pipeline.py [--upload] [--all | --e2e] <pipeline.yml>
Requires PyYAML (``pip install pyyaml``); installs it automatically when missing.
"""
from __future__ import annotations
import argparse
import copy
import subprocess
import sys
from functools import lru_cache
from pathlib import Path
from typing import Any
try:
import yaml
except ModuleNotFoundError:
subprocess.run(
[sys.executable, "-m", "pip", "install", "-q", "pyyaml"],
check=True,
)
import yaml
from skip_ci import (
ROOT,
resolve_ci_context_from_git,
)
# --- Constants ---
LOG = "upload_pipeline"
BOOTSTRAP_STEPS_FILENAME = "bootstrap-upload-steps.yml"
BOOTSTRAP_IMAGE_BUILD_KEYS = frozenset({"image-build", "image-build-a2", "image-build-a3"})
BOOTSTRAP_UPLOAD_IF_KEYS = {
"upload-ready-pipeline": "ready",
"upload-merge-pipeline": "merge",
"upload-nightly-pipeline": "nightly",
"upload-weekly-pipeline": "weekly",
}
E2E_GROUP_MARKER = "E2E Test"
CI_MIRROR_HARDWARES_PATH = ROOT / ".buildkite/common/ci_mirror_hardwares.yml"
CUDA_NIGHTLY_ONLY = (
'(build.pull_request.labels includes "nightly-test") || (build.branch == "main" && build.env("NIGHTLY") == "1")'
)
NPU_NIGHTLY_ONLY = (
'(build.branch == "main" && build.env("NIGHTLY") == "1") || '
'(build.branch != "main" && ('
'build.pull_request.labels includes "nightly-test" || '
'build.pull_request.labels includes "omni-test" || '
'build.pull_request.labels includes "tts-test" || '
'build.pull_request.labels includes "diffusion-x2iat-test" || '
'build.pull_request.labels includes "diffusion-x2v-test"'
"))"
)
# --- Logging ---
def _log(message: str) -> None:
print(f"{LOG}: {message}", file=sys.stderr)
# --- Bootstrap pipeline (bootstrap-upload-steps.yml) ---
def _get_bootstrap_platform(path: Path) -> str:
parts = path.as_posix().split("/")
return "npu" if "npu" in parts else "cuda"
def _load_bootstrap_steps(path: Path) -> str:
if path.name != BOOTSTRAP_STEPS_FILENAME:
raise ValueError(f"expected {BOOTSTRAP_STEPS_FILENAME}, got {path.name}")
return path.read_text(encoding="utf-8")
def _format_bootstrap_if(expr: str) -> str:
"""Return a Buildkite ``if`` string. Buildkite rejects YAML bool ``if`` values."""
if expr in ("true", "false"):
return expr
return f"({expr})"
def _compute_bootstrap_if_exprs(*, decision, platform: str) -> dict[str, str]:
disabled = "false"
nightly_main = 'build.branch == "main" && build.env("NIGHTLY") == "1"'
nightly_only = NPU_NIGHTLY_ONLY if platform == "npu" else CUDA_NIGHTLY_ONLY
if platform == "npu":
ready_pr = (
'build.branch != "main" && ('
'build.pull_request.labels includes "npu-test" || '
'build.pull_request.labels includes "ready"'
")"
)
nightly_label_if = nightly_only
weekly_label_if = disabled
merge_base = disabled
else:
ready_pr = 'build.branch != "main" && build.pull_request.labels includes "ready"'
merge_main = 'build.branch == "main" && build.env("NIGHTLY") != "1" && build.env("WEEKLY") != "1"'
merge_pr = 'build.branch != "main" && build.pull_request.labels includes "merge-test"'
nightly_label_if = (
'(build.branch == "main" && build.env("NIGHTLY") == "1") || '
'(build.branch != "main" && ('
'build.pull_request.labels includes "nightly-test" || '
'build.pull_request.labels includes "omni-test" || '
'build.pull_request.labels includes "tts-test" || '
'build.pull_request.labels includes "diffusion-x2iat-test" || '
'build.pull_request.labels includes "diffusion-x2v-test"'
"))"
)
weekly_label_if = (
'(build.branch == "main" && build.env("WEEKLY") == "1") || '
'(build.branch != "main" && build.pull_request.labels includes "weekly-test")'
)
merge_base = f"({nightly_main}) || (({merge_main}) || ({merge_pr}))"
ready_base = f"({nightly_main}) || ({ready_pr})"
weekly_main = 'build.branch == "main" && build.env("WEEKLY") == "1"'
if decision.skip_all:
# Docs / skip-mark only: no PR-label escape hatch. Main scheduled
# NIGHTLY=1 still runs L4 + L2/L3 (--e2e); WEEKLY=1 still runs L5.
image_expr = f"({nightly_main}) || ({weekly_main})" if platform == "cuda" else nightly_main
ready_expr = nightly_main
merge_expr = nightly_main if platform == "cuda" else disabled
nightly_expr = nightly_main
weekly_expr = weekly_main if platform == "cuda" else disabled
elif decision.skip_l2_l3:
l2_enabled = decision.is_run("npu", "l2") if platform == "npu" else decision.is_run("cuda", "l2")
l3_enabled = platform == "cuda" and decision.is_run("cuda", "l3")
ready_expr = ready_base if l2_enabled else disabled
merge_expr = merge_base if l3_enabled else disabled
nightly_expr = nightly_label_if
weekly_expr = weekly_label_if if platform == "cuda" else disabled
image_parts = [f"({nightly_label_if})"]
if platform == "cuda":
image_parts.append(f"({weekly_label_if})")
if l2_enabled:
image_parts.insert(0, f"({ready_base})")
if l3_enabled:
image_parts.insert(1 if l2_enabled else 0, f"({merge_base})")
image_expr = " || ".join(image_parts)
else:
image_expr = "true"
ready_expr = ready_base
merge_expr = merge_base if platform == "cuda" else disabled
nightly_expr = nightly_label_if
weekly_expr = weekly_label_if if platform == "cuda" else disabled
return {
"image": _format_bootstrap_if(image_expr),
"ready": _format_bootstrap_if(ready_expr),
"merge": _format_bootstrap_if(merge_expr),
"nightly": _format_bootstrap_if(nightly_expr),
"weekly": _format_bootstrap_if(weekly_expr),
}
def _apply_bootstrap_if(steps: list[Any], if_exprs: dict[str, str]) -> list[Any]:
"""Inject ``if`` by step key; drop steps that are unconditionally disabled."""
kept: list[Any] = []
for step in steps:
if not isinstance(step, dict):
kept.append(step)
continue
nested = step.get("steps")
if isinstance(nested, list):
nested_kept = _apply_bootstrap_if(nested, if_exprs)
if nested_kept:
kept.append({**step, "steps": nested_kept})
continue
key = step.get("key")
if key in BOOTSTRAP_IMAGE_BUILD_KEYS:
step["if"] = if_exprs["image"]
elif key in BOOTSTRAP_UPLOAD_IF_KEYS:
step["if"] = if_exprs[BOOTSTRAP_UPLOAD_IF_KEYS[key]]
if_expr = step.get("if")
if if_expr == "false":
_log(f"omit disabled bootstrap step {key!r}")
continue
if if_expr == "true":
# Unconditional step: omit ``if`` (Buildkite requires string ``if``, not YAML bool).
step.pop("if", None)
kept.append(step)
return kept
def _render_bootstrap_pipeline(
steps_yaml: str,
*,
decision,
path: Path,
) -> str:
"""Load bootstrap steps YAML and inject ``if`` expressions from skip-ci decision."""
doc = yaml.safe_load(steps_yaml)
if not isinstance(doc, dict):
raise ValueError(f"invalid bootstrap steps YAML for {path}")
steps = doc.get("steps")
if not isinstance(steps, list):
raise ValueError(f"bootstrap steps YAML must contain steps: list in {path}")
platform = _get_bootstrap_platform(path)
if_exprs = _compute_bootstrap_if_exprs(decision=decision, platform=platform)
doc["steps"] = _apply_bootstrap_if(steps, if_exprs)
return yaml.safe_dump(doc, sort_keys=False)
# --- Test pipeline (test-ready.yml, test-merge.yml) ---
@lru_cache(maxsize=1)
def _load_mirror_hardwares() -> dict[str, dict[str, Any]]:
if not CI_MIRROR_HARDWARES_PATH.is_file():
raise FileNotFoundError(f"missing CI mirror_hardwares registry: {CI_MIRROR_HARDWARES_PATH}")
doc = yaml.safe_load(CI_MIRROR_HARDWARES_PATH.read_text(encoding="utf-8"))
if not isinstance(doc, dict):
raise ValueError(f"invalid CI mirror_hardwares registry: {CI_MIRROR_HARDWARES_PATH}")
presets = doc.get("mirror_hardwares")
if not isinstance(presets, dict):
raise ValueError(f"mirror_hardwares must be a mapping in {CI_MIRROR_HARDWARES_PATH}")
return presets
def _expand_mirror_hardwares(step: dict[str, Any]) -> dict[str, Any]:
"""Replace uploader-only ``mirror_hardwares`` with preset fields from ci_mirror_hardwares.yml."""
hardware = step.get("mirror_hardwares")
if hardware is None:
return step
if not isinstance(hardware, str) or not hardware.strip():
raise ValueError(
f"mirror_hardwares must be a non-empty string in step {_get_step_label(step)!r}",
)
preset = _load_mirror_hardwares().get(hardware)
if preset is None:
known = ", ".join(sorted(_load_mirror_hardwares()))
raise ValueError(
f"unknown mirror_hardwares {hardware!r} in step {_get_step_label(step)!r}; known: {known}",
)
if step.get("agents") is not None or step.get("plugins") is not None or step.get("image") is not None:
raise ValueError(
f"step {_get_step_label(step)!r} sets mirror_hardwares together with agents/plugins/image; "
"use mirror_hardwares only",
)
expanded = copy.deepcopy(preset)
return {key: value for key, value in step.items() if key != "mirror_hardwares"} | expanded
def _match_source_file(changed_files: list[str], prefixes: list[str]) -> bool:
for path in changed_files:
for prefix in prefixes:
normalized = prefix.rstrip("/")
if path == normalized or path.startswith(f"{normalized}/"):
return True
return False
def _get_step_label(step: dict[str, Any]) -> str:
return str(step.get("group") or step.get("label") or "<step>")
def _process_test_steps(
steps: list[Any],
changed_files: list[str] | None,
) -> list[Any]:
"""Drop steps by ``source_file_dependencies`` when *changed_files* is set; always strip that field."""
processed: list[Any] = []
for step in steps:
if not isinstance(step, dict):
processed.append(step)
continue
deps = step.get("source_file_dependencies")
if deps is not None and not isinstance(deps, list):
raise ValueError(
f"source_file_dependencies must be a list in step {_get_step_label(step)!r}",
)
if changed_files is not None and deps is not None and not _match_source_file(changed_files, deps):
_log(f"skip {_get_step_label(step)!r} (no changes under {deps})")
continue
nested = step.get("steps")
if nested is not None:
kept_nested = _process_test_steps(nested, changed_files)
if changed_files is not None and not kept_nested:
_log(f"omit empty group {_get_step_label(step)!r}")
continue
new_step = {key: value for key, value in step.items() if key != "source_file_dependencies"}
new_step["steps"] = kept_nested
processed.append(new_step)
continue
if deps is not None:
processed.append(
_expand_mirror_hardwares(
{key: value for key, value in step.items() if key != "source_file_dependencies"},
),
)
else:
processed.append(_expand_mirror_hardwares(step))
return processed
def _select_e2e_group_steps(steps: list[Any]) -> list[Any]:
"""Keep only top-level groups whose name contains ``E2E_GROUP_MARKER``."""
selected = [
step
for step in steps
if isinstance(step, dict) and isinstance(step.get("group"), str) and E2E_GROUP_MARKER in step["group"]
]
if not selected:
_log(f"no group matching {E2E_GROUP_MARKER!r} found")
else:
_log(f"keep {len(selected)} group(s) matching {E2E_GROUP_MARKER!r}")
return selected
def _render_test_pipeline(
doc: dict[str, Any],
changed_files: list[str] | None,
*,
e2e_only: bool = False,
) -> dict[str, Any]:
"""Filter steps by PR diff and strip uploader-only ``source_file_dependencies`` metadata."""
steps = doc.get("steps")
if not isinstance(steps, list):
return doc
if e2e_only:
steps = _select_e2e_group_steps(steps)
steps = _process_test_steps(steps, changed_files)
return {**doc, "steps": steps}
# --- Entry (read file → bootstrap or test render → YAML string) ---
def _render_pipeline(
path: Path,
*,
force_all: bool = False,
e2e_only: bool = False,
) -> str:
if path.name == BOOTSTRAP_STEPS_FILENAME:
ctx = resolve_ci_context_from_git()
continuation = _load_bootstrap_steps(path)
return _render_bootstrap_pipeline(
continuation,
decision=ctx.decision,
path=path,
)
text = path.read_text(encoding="utf-8")
ctx = resolve_ci_context_from_git()
if force_all or e2e_only:
changed_files = None
else:
changed_files = ctx.changed_files
doc = yaml.safe_load(text)
if not isinstance(doc, dict):
raise ValueError(f"invalid pipeline YAML: {path}")
doc = _render_test_pipeline(doc, changed_files, e2e_only=e2e_only)
return yaml.safe_dump(doc, sort_keys=False)
def _upload_to_buildkite(content: str) -> None:
subprocess.run(
["buildkite-agent", "pipeline", "upload"],
input=content,
text=True,
check=True,
)
# --- CLI ---
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"pipeline",
nargs="?",
default=".buildkite/cuda/bootstrap-upload-steps.yml",
help="Pipeline YAML path (default: .buildkite/cuda/bootstrap-upload-steps.yml)",
)
parser.add_argument(
"--upload",
action="store_true",
help="Pipe rendered YAML to buildkite-agent pipeline upload",
)
mode = parser.add_mutually_exclusive_group()
mode.add_argument(
"--all",
action="store_true",
help="Keep all steps (disable diff-aware skipping)",
)
mode.add_argument(
"--e2e",
action="store_true",
help="Keep only the E2E Test group",
)
args = parser.parse_args()
path = Path(args.pipeline)
if not path.is_absolute():
path = ROOT / path
if not path.is_file():
_log(f"missing pipeline file: {path}")
return 1
rendered = _render_pipeline(path, force_all=args.all, e2e_only=args.e2e)
if args.upload:
_upload_to_buildkite(rendered)
else:
sys.stdout.write(rendered)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,55 @@
# Uploaded by upload_pipeline.py --upload (not the Buildkite hook).
# ``if`` is injected by step ``key`` from skip-ci at upload time.
steps:
- label: ":docker: Build image"
key: image-build
commands:
- "bash .buildkite/cuda/scripts/build-ci-image.sh"
agents:
queue: "cpu_queue_premerge"
# L2 Test — PR ready label (diff-aware) or main+NIGHTLY=1 (--e2e, full E2E group)
- label: "Upload Ready Pipeline"
depends_on: image-build
key: upload-ready-pipeline
commands:
- |
EXTRA=""
if [ "${NIGHTLY:-}" = "1" ] && [ "${BUILDKITE_BRANCH}" = "main" ]; then
EXTRA="--e2e"
fi
python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/cuda/test-ready.yml
agents:
queue: "cpu_queue_premerge"
# L3 Test — PR merge-test label (diff-aware) or main+NIGHTLY=1 (--e2e, full E2E group)
- label: "Upload Merge Pipeline"
depends_on: image-build
key: upload-merge-pipeline
commands:
- |
EXTRA=""
if [ "${NIGHTLY:-}" = "1" ] && [ "${BUILDKITE_BRANCH}" = "main" ]; then
EXTRA="--e2e"
fi
python3 .buildkite/common/scripts/upload_pipeline.py --upload $$EXTRA .buildkite/cuda/test-merge.yml
agents:
queue: "cpu_queue_premerge"
# L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild)
- label: "Upload Nightly Pipeline"
depends_on: image-build
key: upload-nightly-pipeline
commands:
- python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/cuda/test-nightly.yml
agents:
queue: "cpu_queue_premerge"
# L5 Test — main+WEEKLY=1 (scheduled), or PR with weekly-test label
- label: "Upload Weekly Pipeline"
depends_on: image-build
key: upload-weekly-pipeline
commands:
- python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/cuda/test-weekly.yml
agents:
queue: "cpu_queue_premerge"
+9
View File
@@ -0,0 +1,9 @@
# Hook uploads this entry YAML; upload_pipeline.py --upload reads bootstrap-upload-steps.yml
# and injects ``if`` by step ``key`` from skip-ci.
steps:
- label: ":github: Resolve skip-ci & upload pipeline"
key: upload-ci-pipeline
commands:
- "python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/cuda/bootstrap-upload-steps.yml"
agents:
queue: "cpu_queue_premerge"
@@ -2,10 +2,7 @@ steps:
- label: ":docker: Build image"
key: image-build
commands:
- "aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/q9t5s3a7"
- "docker build --progress=plain --file docker/Dockerfile.ci -t vllm-omni-ci ."
- "docker tag vllm-omni-ci public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT"
- "docker push public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT"
- "bash .buildkite/cuda/scripts/build-ci-image.sh"
agents:
queue: "cpu_queue_premerge"
@@ -14,7 +11,7 @@ steps:
depends_on: image-build
key: upload-ready-pipeline
commands:
- buildkite-agent pipeline upload .buildkite/test-ready.yml
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-ready.yml
agents:
queue: "cpu_queue_premerge"
@@ -23,7 +20,7 @@ steps:
depends_on: image-build
key: upload-merge-pipeline
commands:
- buildkite-agent pipeline upload .buildkite/test-merge.yml
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-merge.yml
agents:
queue: "cpu_queue_premerge"
@@ -33,6 +30,6 @@ steps:
key: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1"
commands:
- buildkite-agent pipeline upload .buildkite/test-nightly.yml
- python3 .buildkite/common/scripts/upload_pipeline.py --upload --all .buildkite/cuda/test-nightly.yml
agents:
queue: "cpu_queue_premerge"
+52
View File
@@ -0,0 +1,52 @@
#!/bin/bash
set -euo pipefail
# Build and push the CI Docker image with registry-based layer caching.
#
# Usage: build-ci-image.sh
#
# Expects the following environment variables (set by Buildkite):
# BUILDKITE_COMMIT - commit SHA used as the image tag
ECR_NAMESPACE="public.ecr.aws/q9t5s3a7"
REGISTRY="${ECR_NAMESPACE}/vllm-ci-test-repo"
REGION="us-east-1"
DOCKERFILE="docker/Dockerfile.ci"
BUILDER_NAME="vllm-omni-builder"
# Ensure that the env vars are actually set, otherwise exit early
if [ -z "${BUILDKITE_COMMIT:-}" ]; then
echo "ERROR: BUILDKITE_COMMIT is not set"
exit 1
fi
echo "BUILDKITE_COMMIT: ${BUILDKITE_COMMIT}"
# Authenticate to ECR Public
aws ecr-public get-login-password --region "$REGION" \
| docker login --username AWS --password-stdin "$ECR_NAMESPACE"
# Compute the cache tag for the dependencies image as the hash of the contents.
# This is because dependencies don't change often, so most PRs will have the same hash.
#
# The Dockerfile is also included to avoid churn in the cached image based on the vLLM version.
DEP_FILES="pyproject.toml setup.py requirements/*.txt docker/Dockerfile.ci"
CACHE_KEY=$(cat ${DEP_FILES} | sha256sum | cut -c1-16)
CACHE_TAG="deps-cache-${CACHE_KEY}"
echo "Cache key: ${CACHE_TAG}"
# Set up buildx with docker-container driver; we need to do this
# since cache export is not supported for the default docker driver
# that is running in the CI.
docker buildx inspect $BUILDER_NAME >/dev/null 2>&1 \
|| docker buildx create --name $BUILDER_NAME --driver docker-container
docker buildx use $BUILDER_NAME
echo "Building image tag: ${REGISTRY}:${BUILDKITE_COMMIT}"
# Build + push the image to the registry, using the hash from the dependencies.
# Note that the caching here is layerwise, so we're just making sure we always
# can cache hit on everything but the last copy at the moment.
docker buildx build --push --progress=plain \
--cache-from "type=registry,ref=${REGISTRY}:${CACHE_TAG}" \
--cache-to "type=registry,ref=${REGISTRY}:${CACHE_TAG},mode=max,compression=zstd" \
--file "$DOCKERFILE" \
-t "${REGISTRY}:${BUILDKITE_COMMIT}" .
+259
View File
@@ -0,0 +1,259 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- group: ":card_index_dividers: Simple Test"
depends_on: upload-merge-pipeline
steps:
- label: "Simple · Model Executor Test"
commands:
- "timeout 20m pytest -sv tests/model_executor -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Diffusion Test"
commands:
- "timeout 20m pytest -sv tests/diffusion -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Engine&Entrypoints Test"
commands:
- "timeout 20m pytest -sv tests/entrypoints tests/engine -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Other Test"
commands:
- "timeout 20m pytest -sv tests/ -m 'core_model and cpu' --ignore=tests/diffusion --ignore=tests/model_executor --ignore=tests/entrypoints --ignore=tests/engine --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- group: ":card_index_dividers: Diffusion Test"
depends_on: upload-merge-pipeline
steps:
- label: "Diffusion · LoRA Test"
timeout_in_minutes: 30
commands:
- pytest -sv tests/diffusion/lora/ -m 'advanced_model and cuda' --run-level "advanced_model"
mirror_hardwares: l4_1
- label: "Distributed Test"
depends_on: upload-merge-pipeline
timeout_in_minutes: 60
commands:
- |
timeout 55m bash -c "
set -e
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/distributed -m 'advanced_model and cuda and H100' --run-level 'advanced_model'
"
mirror_hardwares: h100_1
- group: ":card_index_dividers: Entrypoints Test"
depends_on: upload-merge-pipeline
steps:
- label: "Entrypoint Test with H100"
# TEMPORARY 60 -> 90: engine startup/sleep-wake is ~13-15 min slower per
# run on the vLLM 0.26 image (model loading ~2x, init ~2x; see builds
# 2915 vs 2916), which pushed this suite past 60 min. Revert once the
# 0.26 startup regression is understood and fixed.
timeout_in_minutes: 90
commands:
- pytest -s -v tests/entrypoints/ -m "advanced_model and cuda and H100" --run-level "advanced_model"
mirror_hardwares: h100_2
- label: "Entrypoint Test with L4"
timeout_in_minutes: 60
commands:
- pytest -s -v tests/entrypoints/ -m "advanced_model and cuda and L4" --run-level "advanced_model"
mirror_hardwares: l4_1
- group: ":card_index_dividers: E2E Test"
depends_on: upload-merge-pipeline
steps:
- label: "TTS · Qwen3-TTS CustomVoice Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_customvoice.py
- tests/e2e/offline_inference/test_qwen3_tts_customvoice.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 40m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py tests/e2e/offline_inference/test_qwen3_tts_customvoice.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
mirror_hardwares: l4_1
- label: "TTS · Qwen3-TTS Base Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_base.py
- tests/e2e/offline_inference/test_qwen3_tts_base.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 40m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py tests/e2e/offline_inference/test_qwen3_tts_base.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
mirror_hardwares: l4_1
- label: "TTS · Higgs-Audio-V3 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_higgs_audio_v3.py
- vllm_omni/model_executor/models/higgs_audio_v3/
- vllm_omni/model_executor/stage_input_processors/higgs_audio_v3.py
- vllm_omni/deploy/higgs_multimodal_qwen3.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_USE_DEEP_GEMM=0
export VLLM_MOE_USE_DEEP_GEMM=0
pytest -s -v tests/e2e/online_serving/test_higgs_audio_v3.py -m 'advanced_model' --run-level 'advanced_model'
"
mirror_hardwares: l4_1
- label: "Omni · Qwen3-Omni Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_qwen3_omni.py
- tests/e2e/online_serving/test_qwen3_omni.py
- vllm_omni/model_executor/models/qwen3_omni/
- vllm_omni/model_executor/stage_input_processors/qwen3_omni.py
- vllm_omni/deploy/qwen3_omni_moe.yaml
timeout_in_minutes: 50
commands:
- pytest -s -v tests/e2e/offline_inference/test_qwen3_omni.py tests/e2e/online_serving/test_qwen3_omni.py -m 'advanced_model and cuda' --run-level 'advanced_model'
mirror_hardwares: h100_2
- label: "Omni · MiniCPM-o 4.5 Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_minicpmo_4_5.py
- tests/e2e/online_serving/test_minicpmo_4_5.py
- vllm_omni/deploy/minicpmo_4_5.yaml
timeout_in_minutes: 50
commands:
- pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5.py -m 'advanced_model and cuda' --run-level 'advanced_model'
mirror_hardwares: h100_2
- label: "Omni · MiniCPM-o 4.5 Duplex Test"
source_file_dependencies:
- tests/assets/minicpmo_4_5/response_required_16k.wav
- tests/assets/minicpmo_4_5/soft_interrupt_16k.wav
- tests/e2e/online_serving/test_minicpmo_4_5_duplex.py
- tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py
- tests/e2e/online_serving/test_minicpmo_realtime_duplex_drivers.py
- tests/e2e/online_serving/minicpmo_realtime_duplex_scenarios.py
- tests/e2e/online_serving/run_minicpmo_realtime_duplex_multi_session.py
- tests/e2e/online_serving/run_minicpmo_realtime_duplex_soft_interrupt.py
- tests/helpers/minicpmo_4_5_duplex.py
- vllm_omni/deploy/minicpmo_4_5_duplex.yaml
- vllm_omni/experimental/fullduplex/
- vllm_omni/model_executor/models/minicpmo_4_5/
- vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py
- vllm_omni/core/sched/
- vllm_omni/outputs/multimodal_accumulation.py
- vllm_omni/engine/stage_init_utils.py
- vllm_omni/engine/async_omni_engine.py
- vllm_omni/entrypoints/cli/serve.py
timeout_in_minutes: 50
commands:
- pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5_duplex.py -m 'advanced_model and cuda' --run-level 'advanced_model'
mirror_hardwares: h100_2
- label: "TTS · VoxCPM2 Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_voxcpm2_tts.py
- tests/e2e/online_serving/test_voxcpm2_tts.py
- vllm_omni/model_executor/models/voxcpm2/
- vllm_omni/deploy/voxcpm2.yaml
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/offline_inference/test_voxcpm2_tts.py tests/e2e/online_serving/test_voxcpm2_tts.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
mirror_hardwares: l4_1
- label: "Diffusion · Qwen Image Edit Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_edit.py
- vllm_omni/diffusion/models/qwen_image/
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/online_serving/test_qwen_image_edit.py -m 'advanced_model and cuda' --run-level 'advanced_model'
mirror_hardwares: h100_1
- label: "Diffusion · Bagel Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_bagel.py
- tests/e2e/online_serving/test_bagel.py
- vllm_omni/model_executor/models/bagel/
- vllm_omni/diffusion/models/bagel/
- vllm_omni/model_executor/stage_input_processors/bagel.py
- vllm_omni/deploy/bagel.yaml
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/offline_inference/test_bagel.py tests/e2e/online_serving/test_bagel.py -m 'advanced_model and cuda' --run-level 'advanced_model'
mirror_hardwares: h100_1
- label: "Diffusion · Qwen Image Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c '
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image.py -m 'advanced_model and cuda' --run-level 'advanced_model'
'
mirror_hardwares: h100_1
- label: "Diffusion · Qwen Image Layered Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_layered.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image_layered.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Wan22 Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_wan22_t2v.py
- tests/e2e/online_serving/test_wan22_t2v.py
- vllm_omni/diffusion/models/wan2_2/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/offline_inference/test_wan22_t2v.py tests/e2e/online_serving/test_wan22_t2v.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Z Image Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_z_image.py
- tests/e2e/online_serving/test_z_image.py
- vllm_omni/diffusion/models/z_image/
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/offline_inference/test_z_image.py tests/e2e/online_serving/test_z_image.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
mirror_hardwares: l4_1
- label: "Diffusion · FLUX.2 Klein Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_flux2_klein.py
- vllm_omni/diffusion/models/flux2_klein/
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/offline_inference/test_flux2_klein.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
mirror_hardwares: l4_1
+557
View File
@@ -0,0 +1,557 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
# Group: collapses under one heading in the Buildkite UI; child steps still run in parallel.
- group: ":card_index_dividers: Omni Model Test"
key: nightly-omni-test-group
depends_on: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "omni-test"
steps:
- label: ":full_moon: Omni · Function Test with H100"
timeout_in_minutes: 120
commands:
- pytest -sv tests/e2e --run-level "full_model" -m "full_model and H100 and omni" --ignore=tests/e2e/accuracy --ignore=tests/e2e/online_serving/test_qwen3_omni_multi_replicas.py --ignore=tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py
mirror_hardwares: h100_2
- label: ":full_moon: Omni · MiniCPM-o 4.5 Duplex Test"
timeout_in_minutes: 50
commands:
- pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py -m "full_model and cuda and H100 and omni" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Doc Test with L4"
timeout_in_minutes: 90
commands:
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- pytest -s -v tests/examples/ -m "full_model and omni and L4" --run-level "full_model"
mirror_hardwares: l4_4
- label: ":full_moon: Omni · Doc Test with H100"
timeout_in_minutes: 90
commands:
- pytest -s -v tests/examples/ -m "full_model and omni and H100" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Accuracy Test"
timeout_in_minutes: 180
commands:
- export SEED_TTS_WER_EVAL=1
- export SEED_TTS_EVAL_DEVICE=cuda:1
- |
set +e
pytest -s -v tests/e2e/accuracy/qwen3_omni/test_qwen3_omni.py -m "full_model" --run-level full_model
EXIT=$$?
buildkite-agent artifact upload "tests/e2e/accuracy/qwen3_omni/results/qwen_omni_acc/*.json"
exit $$EXIT
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Perf Test · No Async Chunk"
key: nightly-omni-performance-no-async-chunk
timeout_in_minutes: 300
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen3_omni_no_async_chunk.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Perf Test · Async Chunk"
key: nightly-omni-performance-async-chunk
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen3_omni_async_chunk.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Perf Test · vLLM Text"
key: nightly-omni-performance-vllm-text
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen3_omni_vllm_text.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_2
- label: ":full_moon: Omni · Perf Test · Multi-Replica"
key: nightly-omni-performance-multi-replicas
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen3_omni_multi_replicas.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_3
- label: ":full_moon: Omni · Multi-Replica Startup Test with 4x H100"
timeout_in_minutes: 45
commands:
- pytest -s -v tests/e2e/online_serving/test_qwen3_omni_multi_replicas.py -m "full_model" --run-level "core_model"
mirror_hardwares: h100_4
- group: ":card_index_dividers: TTS Model Test"
key: nightly-tts-test-group
depends_on: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "tts-test"
steps:
- label: ":full_moon: TTS · Function Test with L4"
timeout_in_minutes: 120
commands:
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- export VLLM_USE_DEEP_GEMM="0"
- export VLLM_MOE_USE_DEEP_GEMM="0"
- pytest -s -v tests/e2e/ -m "full_model and L4 and tts" --run-level "full_model" --ignore=tests/e2e/accuracy --ignore=tests/e2e/online_serving/test_voxcpm2_tts_expansion.py
mirror_hardwares: l4_1
- label: ":full_moon: TTS · Accuracy Test · VoxCPM2"
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_voxcpm2_tts_expansion.py -m 'full_model and cuda and tts' --run-level 'full_model'
"
mirror_hardwares: l4_1
- label: ":full_moon: TTS · Perf Test"
key: nightly-tts-performance
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_tts.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_2
- label: ":full_moon: TTS · VoxCPM2 · Perf Test"
key: nightly-tts-performance-voxcpm2
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_voxcpm2.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_1
- label: ":full_moon: TTS · Higgs-Audio-V3 · Perf Test"
key: nightly-tts-performance-higgs-audio-v3
timeout_in_minutes: 180
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- export VLLM_USE_DEEP_GEMM="0"
- export VLLM_MOE_USE_DEEP_GEMM="0"
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py --test-config-file tests/dfx/perf/tests/test_higgs_audio_v3.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
mirror_hardwares: h100_1
- group: ":card_index_dividers: Tiny Model Tests [Multi-GPU]"
key: nightly-tiny-model-test-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test"
steps:
- label: ":full_moon: Tiny Model Tests · Diffusion (Multi-GPU accelerations)"
timeout_in_minutes: 30
# NOTE: Single-GPU (core_model) tiny model tests run on the ready label,
# so nightly only adds the multi-GPU parallelism configurations.
#
# This is a bit confusing, but `full_model` is used to mark the multigpu tests, and
# --run-level `core_model` is used to indicate that we should use tiny model weights
# for the CI, since these tests should pass irrespective of whether or not we use
# the full weights or not.
commands:
- timeout 25m pytest -sv tests/model_tests/diffusion -m 'full_model and cuda' --run-level "core_model"
mirror_hardwares: l4_4
- group: ":card_index_dividers: Diffusion X2I(&A&T) Model Test"
key: nightly-diffusion-x2iat-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2iat-test"
steps:
# Use explicit file shards so single-card cases do not reserve 2+ GPUs,
# and Bagel feature coverage is not duplicated via a broad tests/e2e sweep.
- label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · Single-GPU"
timeout_in_minutes: 120
commands:
- >-
pytest -sv
tests/e2e/online_serving/test_qwen_image_expansion.py
tests/e2e/online_serving/test_qwen_image_edit_expansion.py
tests/e2e/online_serving/test_qwen_image_layered_expansion.py
tests/e2e/online_serving/test_boogu_image.py
tests/e2e/online_serving/test_boogu_image_edit.py
tests/e2e/online_serving/test_boogu_image_expansion.py
tests/e2e/online_serving/test_boogu_image_edit_expansion.py
tests/e2e/online_serving/test_bagel_expansion.py
tests/e2e/online_serving/test_krea2_expansion.py
tests/e2e/offline_inference/test_krea2_expansion.py
-m "full_model and diffusion and H100 and not distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_1
- label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · Multi-GPU Qwen-Image"
timeout_in_minutes: 120
commands:
- >-
pytest -sv
tests/e2e/online_serving/test_qwen_image_expansion.py
tests/e2e/online_serving/test_qwen_image_edit_expansion.py
tests/e2e/offline_inference/test_krea2_expansion.py
-m "full_model and diffusion and H100 and distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · Multi-GPU Layered/LongCat/FLUX"
timeout_in_minutes: 90
commands:
- >-
pytest -sv
tests/e2e/online_serving/test_qwen_image_layered_expansion.py
-m "full_model and diffusion and H100 and distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2I(&A&T) · Function Test with H100 · Multi-GPU Bagel"
timeout_in_minutes: 120
commands:
- >-
pytest -sv
tests/e2e/online_serving/test_bagel_expansion.py
-m "full_model and diffusion and H100 and distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2I(&A&T) · GLM-Image Function Test with H100"
timeout_in_minutes: 120
commands:
- >-
pytest -sv
tests/e2e/online_serving/test_glm_image_expansion.py
tests/e2e/offline_inference/test_glm_image_autoround_w4a16_expansion.py
-m "full_model and diffusion and H100"
--run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2I(&A&T) · Function Test with L4"
timeout_in_minutes: 120
commands:
- pytest -sv tests/e2e/ -k "not test_wan and not test_bagel_expansion and not hunyuan" -m "full_model and diffusion and L4" --run-level "full_model" --ignore=tests/e2e/accuracy
mirror_hardwares: l4_4
- label: ":full_moon: Diffusion X2I(&A&T) · Doc Test"
timeout_in_minutes: 60
commands:
- pytest -s -v tests/examples/*/test_text_to_image.py -m "full_model and example and H100" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2I(&A&T) · Accuracy Test"
timeout_in_minutes: 180
commands:
- export VLLM_HTTP_TIMEOUT_KEEP_ALIVE=120
- pytest -s -v tests/e2e/accuracy/test_qwen_image*.py --run-level full_model
- pytest -s -v tests/e2e/accuracy/test_diffusers_backend_similarity.py -k '2i_matches_diffusers' -m full_model --run-level full_model
mirror_hardwares: h100_1
- label: ":full_moon: HunyuanImage3-DIT · Accuracy Test"
timeout_in_minutes: 180
commands:
- export HUNYUAN_IMAGE3_MODEL="tencent/HunyuanImage-3.0-Instruct"
- export HUNYUAN_IMAGE3_DEVICES="0,1,2,3"
- pytest -s -v tests/e2e/accuracy/test_hunyuan_image3_pixel_accuracy.py -m full_model --run-level full_model
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image"
key: nightly-diffusion-x2iat-performance-qwen-image
timeout_in_minutes: 180
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_image_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image-Edit"
key: nightly-diffusion-x2iat-performance-qwen-image-edit
timeout_in_minutes: 180
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_image_edit_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image-Edit-2511"
key: nightly-diffusion-x2iat-performance-qwen-image-edit-2511
timeout_in_minutes: 180
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_image_edit_2511_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image-Layered"
key: nightly-diffusion-x2iat-performance-qwen-image-layered
timeout_in_minutes: 120
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_qwen_image_layered_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
mirror_hardwares: h100_1
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · BAGEL"
key: nightly-diffusion-x2iat-performance-bagel
timeout_in_minutes: 180
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_bagel_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
mirror_hardwares: h100_1
- group: ":card_index_dividers: Diffusion X2V Model Test"
key: nightly-diffusion-x2v-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2v-test"
steps:
- label: ":full_moon: Diffusion X2V · Wan2.2 T2V Function Test"
timeout_in_minutes: 90
commands:
- pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "t2v" -m "full_model and cuda" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2V · Wan2.2 I2V/TI2V Function Test"
timeout_in_minutes: 90
commands:
- pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k "i2v" -m "full_model and cuda" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2V · LingBot Video MoE Function Test"
timeout_in_minutes: 90
commands:
- pytest -s -v tests/e2e/online_serving/test_lingbot_video_moe.py -m "full_model and cuda" --run-level "full_model"
mirror_hardwares: h100_1
- label: ":full_moon: Diffusion X2V · Doc Test"
timeout_in_minutes: 60
commands:
- pytest -s -v tests/examples/offline_inference/test_image_to_video.py -m "full_model and example and H100" --run-level "full_model"
mirror_hardwares: h100_1
- label: ":full_moon: Diffusion X2V · Other Function Test"
timeout_in_minutes: 90
commands:
- pytest -s -v tests/e2e/offline_inference/test_wan22_autoround_w4a16_expansion.py -m "full_model and cuda" --run-level "full_model"
- pytest -s -v tests/e2e/online_serving/test_wan_2_1_vace_expansion.py tests/e2e/online_serving/test_ltx2_expansion.py -m "full_model and cuda" --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2V · Wan2.2 Accuracy Test"
timeout_in_minutes: 180
commands:
- pytest -s -v tests/e2e/accuracy/wan22_i2v/test_wan22_i2v_video_similarity.py -m full_model --run-level full_model
- pytest -s -v tests/e2e/accuracy/test_diffusers_backend_similarity.py -k '2v_matches_diffusers' -m full_model --run-level full_model
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2V · MiniMax H3 T2VA Accuracy Test"
timeout_in_minutes: 180
commands:
- pytest -s -v tests/e2e/accuracy/minimax_h3/test_minimax_h3_t2va_similarity.py -m full_model --run-level full_model
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion X2V · Other Accuracy Test"
timeout_in_minutes: 180
commands:
- pytest -s -v tests/e2e/accuracy/hunyuanvideo15_t2v/test_hunyuanvideo15_t2v_video_similarity.py -m full_model --run-level full_model
- pytest -s -v tests/e2e/accuracy/hunyuanvideo15_i2v/test_hunyuanvideo15_i2v_video_similarity.py -m full_model --run-level full_model
- pytest -s -v 'tests/e2e/accuracy/ltx/test_ltx_official_similarity.py::test_ltx_one_stage_matches_official[ltx2_3_i2v]' -m full_model --run-level full_model
- pytest -s -v tests/e2e/accuracy/test_video_streaming_output_similarity.py -m full_model --run-level full_model
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion X2V · Perf Test"
key: nightly-diffusion-x2v-performance
timeout_in_minutes: 180
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_wan22_i2v_vllm_omni.json
EXIT1=$$?
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py --test-config-file tests/dfx/perf/tests/test_cosmos3_vllm_omni.json
EXIT2=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
if [ $$EXIT1 -ne 0 ]; then exit $$EXIT1; fi
exit $$EXIT2
mirror_hardwares: h100_2
- group: ":card_index_dividers: Diffusion Test"
key: nightly-diffusion-test-group
depends_on: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test"
steps:
- label: ":full_moon: Diffusion · Distributed Test with L4"
timeout_in_minutes: 60
commands:
- pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and L4' --run-level "full_model"
mirror_hardwares: l4_4
- label: ":full_moon: Diffusion · Distributed Test with H100"
timeout_in_minutes: 60
commands:
- pytest -sv tests/diffusion/distributed/ -m 'full_model and cuda and H100' --run-level "full_model"
mirror_hardwares: h100_4
- label: ":full_moon: Diffusion · Offloader Test"
timeout_in_minutes: 60
commands:
- pytest -sv tests/diffusion/offloader -m "full_model and cuda"
mirror_hardwares: l4_1
- label: ":full_moon: Diffusion · Quantization Test with H100 · Single-GPU"
timeout_in_minutes: 60
commands:
- pytest -sv tests/diffusion/quantization -m 'full_model and cuda and H100' --run-level "full_model"
mirror_hardwares: h100_1
- label: ":full_moon: Diffusion · MiniMax H3 FP8 Quality Test with H100 · 2-GPU"
timeout_in_minutes: 60
commands:
- pytest -sv tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py -m 'full_model and cuda and H100' --run-level "full_model"
mirror_hardwares: h100_2
- label: ":full_moon: Diffusion · Quantization Test with L4"
timeout_in_minutes: 60
commands:
- pip install "vllm-gguf-plugin>=0.0.3"
- pytest -sv tests/diffusion/quantization -m 'full_model and cuda and L4' --run-level "full_model"
mirror_hardwares: l4_1
- label: ":bar_chart: Testcase Statistics"
key: nightly-testcase-statistics
timeout_in_minutes: 120
depends_on: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1"
commands:
- python tools/nightly/buildkite_testcase_statistics.py -o tests/dfx/perf/results/buildkite_testcase_statistics.html
- buildkite-agent artifact upload "tests/dfx/perf/results/*.html"
mirror_hardwares: h100_1
# NOTE: ":email: Nightly Collection & Email" is deprecated and will be removed soon.
# Do not add new depends_on entries or extend this step.
- label: ":email: Nightly Collection & Email"
key: nightly-perf-distribution
depends_on:
- nightly-omni-performance-no-async-chunk
- nightly-omni-performance-async-chunk
- nightly-omni-performance-vllm-text
- nightly-omni-performance-multi-replicas
- nightly-tts-performance
- nightly-tts-performance-higgs-audio-v3
- nightly-diffusion-x2iat-performance-qwen-image
- nightly-diffusion-x2iat-performance-qwen-image-edit
- nightly-diffusion-x2iat-performance-qwen-image-edit-2511
- nightly-diffusion-x2iat-performance-qwen-image-layered
- nightly-diffusion-x2iat-performance-bagel
- nightly-diffusion-x2v-performance
- nightly-testcase-statistics
if: build.env("NIGHTLY") == "1" && build.env("EMAIL_DISTRIBUTION") == "1"
commands:
- pip install openpyxl
- export DEFAULT_INPUT_DIR=tests/dfx/perf/results
- export DEFAULT_OUTPUT_DIR=tests/dfx/perf/results
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-tts-performance
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-tts-performance-higgs-audio-v3
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-omni-performance-no-async-chunk
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-omni-performance-async-chunk
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-omni-performance-vllm-text
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-omni-performance-multi-replicas
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2iat-performance-qwen-image
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2iat-performance-qwen-image-edit
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2iat-performance-qwen-image-edit-2511
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2iat-performance-qwen-image-layered
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2iat-performance-bagel
- buildkite-agent artifact download "tests/dfx/perf/results/*.json" . --step nightly-diffusion-x2v-performance
- buildkite-agent artifact download "tests/dfx/perf/results/*.html" . --step nightly-testcase-statistics
- python tools/nightly/generate_nightly_perf_excel.py
- python tools/nightly/generate_nightly_perf_html.py
- python tools/nightly/send_nightly_email.py --report-file "tests/dfx/perf/results/*.xlsx, tests/dfx/perf/results/*.html"
- buildkite-agent artifact upload "tests/dfx/perf/results/*.xlsx"
- buildkite-agent artifact upload "tests/dfx/perf/results/*.html"
agents:
queue: "cpu_queue_premerge"
+346
View File
@@ -0,0 +1,346 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- group: ":card_index_dividers: Simple Test"
depends_on: upload-ready-pipeline
steps:
- label: "Simple · Model Executor Test"
commands:
- "timeout 20m pytest -sv tests/model_executor -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Diffusion Test"
commands:
- "timeout 20m pytest -sv tests/diffusion -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Engine&Entrypoints Test"
commands:
- "timeout 20m pytest -sv tests/entrypoints tests/engine -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- label: "Simple · Other Test"
commands:
- "timeout 20m pytest -sv tests/ -m 'core_model and cpu' --ignore=tests/diffusion --ignore=tests/model_executor --ignore=tests/entrypoints --ignore=tests/engine --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
mirror_hardwares: l4_1
- group: ":card_index_dividers: Diffusion Test"
depends_on: upload-ready-pipeline
steps:
- label: "Diffusion · Offloader Test"
commands:
- timeout 40m pytest -s -v tests/diffusion/offloader -m "core_model and cuda" --run-level "core_model"
mirror_hardwares: l4_1
- label: "Diffusion · Cache Test"
commands:
- timeout 15m pytest -sv tests/diffusion/cache -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_1
- label: "Diffusion · Batch Test"
commands:
- timeout 15m pytest -sv tests/diffusion/batching -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_1
- label: "Diffusion · Distributed Test"
source_file_dependencies:
- tests/diffusion/distributed/
- vllm_omni/diffusion/distributed/
- vllm_omni/diffusion/attention/parallel/
- vllm_omni/diffusion/data.py
- vllm_omni/diffusion/models/
commands:
- timeout 20m pytest -sv tests/diffusion/distributed -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_4
- label: "Diffusion · Model Test"
commands:
- timeout 15m pytest -sv tests/diffusion/models/ -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_1
- label: "Diffusion · Other Test"
commands:
- timeout 15m pytest -sv tests/diffusion/*.py -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_1
- group: ":card_index_dividers: Tiny Model Tests [Single GPU]"
depends_on: upload-ready-pipeline
steps:
- label: "Tiny Model Tests · Diffusion (base)"
commands:
- timeout 15m pytest -sv tests/model_tests/diffusion -m 'core_model and cuda' --run-level "core_model"
mirror_hardwares: l4_1
- label: "Engine&Model Executor Test"
depends_on: upload-ready-pipeline
commands:
- |
timeout 15m bash -c "
pytest -sv tests/engine/ tests/model_executor/ -m 'core_model and cuda' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "Distributed Test"
depends_on: upload-ready-pipeline
commands:
- |
timeout 20m bash -c "
pytest -sv tests/distributed/ -m 'core_model and cuda and L4' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "Entrypoints Test"
depends_on: upload-ready-pipeline
commands:
- |
timeout 30m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -sv tests/entrypoints/ -m 'core_model and cuda' --run-level 'core_model'
"
mirror_hardwares: l4_1
- group: ":card_index_dividers: E2E Test"
depends_on: upload-ready-pipeline
steps:
- label: "Custom Pipeline Test"
source_file_dependencies:
- tests/e2e/features/custom_pipeline/
- tests/e2e/features/helpers/custom_pipeline.py
- vllm_omni/diffusion/
- vllm_omni/engine/
- vllm_omni/entrypoints/
- vllm_omni/inputs/
- vllm_omni/outputs/
commands:
- timeout 20m pytest -s -v tests/e2e/features/custom_pipeline/ -m "core_model"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "RLHF · VeRL-Omni E2E Test"
source_file_dependencies:
- tests/e2e/features/rlhf_test/test_verl_omni_e2e.py
- tests/e2e/features/helpers/verl_omni_server.py
- tests/e2e/features/helpers/custom_pipeline.py
- vllm_omni/diffusion/
- vllm_omni/engine/
- vllm_omni/entrypoints/
- vllm_omni/inputs/
- vllm_omni/outputs/
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/features/rlhf_test/test_verl_omni_e2e.py
"
mirror_hardwares: l4_1
- label: "Omni · Qwen3-Omni Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_omni.py
- vllm_omni/model_executor/models/qwen3_omni/
- vllm_omni/model_executor/stage_input_processors/qwen3_omni.py
- vllm_omni/deploy/qwen3_omni_moe.yaml
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_qwen3_omni.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_2
- label: "Omni · MiniCPM-o 4.5 Offline Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_minicpmo_4_5.py
- vllm_omni/deploy/minicpmo_4_5.yaml
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_2
- label: "Omni · MiniCPM-o 4.5 Online Test"
source_file_dependencies:
- tests/e2e/online_serving/test_minicpmo_4_5.py
- vllm_omni/deploy/minicpmo_4_5.yaml
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_2
- label: "Omni · MiniCPM-o 4.5 Duplex Test"
source_file_dependencies:
- tests/assets/minicpmo_4_5/response_required_16k.wav
- tests/assets/minicpmo_4_5/soft_interrupt_16k.wav
- tests/e2e/online_serving/test_minicpmo_4_5_duplex.py
- tests/e2e/online_serving/test_minicpmo_4_5_duplex_expansion.py
- tests/e2e/online_serving/test_minicpmo_realtime_duplex_drivers.py
- tests/e2e/online_serving/minicpmo_realtime_duplex_scenarios.py
- tests/e2e/online_serving/run_minicpmo_realtime_duplex_multi_session.py
- tests/e2e/online_serving/run_minicpmo_realtime_duplex_soft_interrupt.py
- tests/helpers/minicpmo_4_5_duplex.py
- vllm_omni/deploy/minicpmo_4_5_duplex.yaml
- vllm_omni/experimental/fullduplex/
- vllm_omni/model_executor/models/minicpmo_4_5/
- vllm_omni/model_executor/stage_input_processors/minicpmo_4_5_omni.py
- vllm_omni/core/sched/
- vllm_omni/outputs/multimodal_accumulation.py
- vllm_omni/engine/stage_init_utils.py
- vllm_omni/engine/async_omni_engine.py
- vllm_omni/entrypoints/cli/serve.py
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_minicpmo_4_5_duplex.py -m 'core_model and cuda' --run-level 'core_model'
"
mirror_hardwares: h100_2
- label: "TTS · VoxCPM2 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_voxcpm2_tts.py
- vllm_omni/model_executor/models/voxcpm2/
- vllm_omni/deploy/voxcpm2.yaml
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/online_serving/test_voxcpm2_tts.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "TTS · Qwen3-TTS CustomVoice Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_customvoice.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "TTS · Qwen3-TTS Base Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_base.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
export VLLM_OMNI_USE_V2_RUNNER=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "TTS · Higgs-Audio-V3 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_higgs_audio_v3.py
- vllm_omni/model_executor/models/higgs_audio_v3/
- vllm_omni/model_executor/stage_input_processors/higgs_audio_v3.py
- vllm_omni/deploy/higgs_multimodal_qwen3.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_USE_DEEP_GEMM=0
export VLLM_MOE_USE_DEEP_GEMM=0
pytest -s -v tests/e2e/online_serving/test_higgs_audio_v3.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: l4_1
- label: "Diffusion · Qwen Image Edit Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_edit.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_qwen_image_edit.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Bagel Test"
source_file_dependencies:
- tests/e2e/online_serving/test_bagel.py
- vllm_omni/model_executor/models/bagel/
- vllm_omni/diffusion/models/bagel/
- vllm_omni/model_executor/stage_input_processors/bagel.py
- vllm_omni/deploy/bagel.yaml
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_bagel.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Wan22 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_wan22_t2v.py
- vllm_omni/diffusion/models/wan2_2/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_wan22_t2v.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Cosmos3 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_cosmos3.py
- vllm_omni/diffusion/models/cosmos3/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_cosmos3.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Qwen Image Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
- label: "Diffusion · Qwen Image Layered Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_layered.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image_layered.py -m 'core_model' --run-level 'core_model'
"
mirror_hardwares: h100_1
+136
View File
@@ -0,0 +1,136 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- label: "Reliability Test - qwen3-omni"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_qwen3_omni.py -m "slow"
mirror_hardwares: h100_2
- label: "Reliability Test - wan22"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_wan22.py -m "slow"
mirror_hardwares: h100_2
- label: "Reliability Test - hunyuan-image"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_hunyuan_image.py -m "slow"
mirror_hardwares: h100_4
- label: "Reliability Test - voxcpm2"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_voxcpm2.py -m "slow"
mirror_hardwares: l4_1
- group: "Reliability Test - Invalid parameters Test"
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
steps:
- label: "Invalid parameters Test · H100"
timeout_in_minutes: 120
commands:
- pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and H100"
mirror_hardwares: h100_2
- label: "Invalid parameters Test · L4"
timeout_in_minutes: 120
commands:
- pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and L4"
mirror_hardwares: l4_1
- group: ":card_index_dividers: E2E Tests"
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
steps:
- label: "Omni · L4"
timeout_in_minutes: 90
commands:
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- pytest -s -v tests/e2e/*/test_qwen2_5_omni_expansion.py --run-level "core_model"
- >-
pytest -s -v tests/e2e/
--ignore=tests/e2e/online_serving/test_qwen2_5_omni_expansion.py
--ignore=tests/e2e/offline_inference/test_qwen2_5_omni_expansion.py
-m "slow and L4 and omni"
--run-level "full_model"
mirror_hardwares: l4_4
- label: "Omni · H100"
timeout_in_minutes: 90
commands:
- >-
pytest -sv
tests/e2e/ -m "slow and H100 and omni"
--run-level "full_model"
mirror_hardwares: h100_2
- label: "TTS · L4"
timeout_in_minutes: 90
commands:
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- export VLLM_USE_DEEP_GEMM="0"
- export VLLM_MOE_USE_DEEP_GEMM="0"
- |
failed=0
for f in $(pytest --collect-only -q tests/e2e/ -m "slow and L4 and tts" --run-level "full_model" | grep '\.py::' | sed -E 's|::.*||' | sort -u); do
pytest -s -v "$$f" -m "slow and L4 and tts" --run-level "full_model" || failed=1
done
exit $$failed
mirror_hardwares: l4_1
- label: "TTS · H100"
timeout_in_minutes: 90
commands:
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- export VLLM_USE_DEEP_GEMM="0"
- export VLLM_MOE_USE_DEEP_GEMM="0"
- >-
pytest -sv
tests/e2e/ -m "slow and H100 and tts"
--run-level "full_model"
mirror_hardwares: h100_1
- label: "Diffusion · L4"
timeout_in_minutes: 60
commands:
- >-
pytest -sv
tests/e2e/ -m "slow and diffusion and L4"
--run-level "full_model"
mirror_hardwares: l4_4
- label: "Diffusion · H100 · Single-GPU"
timeout_in_minutes: 120
commands:
- >-
pytest -sv
tests/e2e/ -m "slow and diffusion and H100 and not distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_1
- label: "Diffusion · H100 · Multi-GPU"
timeout_in_minutes: 90
commands:
- >-
pytest -sv
tests/e2e/ -m "slow and diffusion and H100 and distributed_cuda"
--run-level "full_model"
mirror_hardwares: h100_2
@@ -1,16 +1,16 @@
# .buildkite/pipeline-intel.yaml
# .buildkite/intel/pipeline-intel.yml
steps:
- group: "INTEL Tests"
steps:
- label: "Intel: XPU Test"
command: "bash .buildkite/scripts/hardware_ci/run-xpu-test.sh"
command: "bash .buildkite/intel/scripts/run-xpu-test.sh"
agents:
queue: "intel-gpu-omni"
env:
DOCKER_BUILDKIT: "1"
# Buildkite will automatically replace this with the actual commit hash
VLLM_IMAGE_TAG: "${BUILDKITE_COMMIT}"
VLLM_VERSION: "v0.23.0"
VLLM_VERSION: "v0.26.0"
priority: 100
timeout_in_minutes: 60
soft_fail: false
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
# vllm-omni Intel bootstrap
# Uses static pipeline-intel.yml for Intel XPU tests
set -euo pipefail
source .buildkite/common/scripts/resolve_skip_ci.sh
upload_pipeline() {
echo "--- 🛠 Preparing Intel pipeline"
buildkite-agent pipeline upload .buildkite/intel/pipeline-intel.yml
}
gate_bootstrap_ci intel l2
upload_pipeline
@@ -13,12 +13,33 @@ container_name="xpu_${BUILDKITE_COMMIT}_$(
)"
cd "${omni_source_dir}"
# The XPU base image is ~37GB; the default gzip layer exporter is single-threaded
# and takes ~16min to compress it. zstd is multi-threaded (uses all cores) at a
# similar ratio; set EXPORT_COMPRESSION=uncompressed to skip compression entirely
# for local-only images. This requires the containerd image store (buildx docker
# driver), which is the default here.
EXPORT_COMPRESSION="${EXPORT_COMPRESSION:-zstd}"
if [ "${EXPORT_COMPRESSION}" = "uncompressed" ]; then
export_args=(--output "type=image,name={{IMAGE}},compression=uncompressed")
else
export_args=(--output "type=image,name={{IMAGE}},compression=${EXPORT_COMPRESSION},compression-level=3,force-compression=true")
fi
docker_build() {
# $1 = image name; remaining args passed through to docker build.
local image="$1"
shift
local out=("${export_args[@]/'{{IMAGE}}'/${image}}")
docker build "${out[@]}" "$@" -f docker/Dockerfile.xpu .
}
if [ -z "$(docker images -q "${base_image_name}")" ]; then
docker build --target vllm-base -t "${base_image_name}" --build-arg "VLLM_VERSION=${VLLM_VERSION}" -f docker/Dockerfile.xpu .
docker_build "${base_image_name}" --target vllm-base --build-arg "VLLM_VERSION=${VLLM_VERSION}"
fi
# Try building the docker image
docker build --build-arg "VLLM_BASE=${base_image_name}" --build-arg "VLLM_VERSION=${VLLM_VERSION}" -t "${image_name}" -f docker/Dockerfile.xpu .
docker_build "${image_name}" --build-arg "VLLM_BASE=${base_image_name}" --build-arg "VLLM_VERSION=${VLLM_VERSION}"
# Setup cleanup
remove_docker_container() {
@@ -53,6 +74,6 @@ time timeout -k 30 30m docker run \
cd /workspace/vllm-omni
pytest -v -s -m "core_model and xpu and B60"
pytest -v -s tests/diffusion/quantization/test_mxfp8_config.py
export VLLM_XPU_USE_SAMPLER_KERNEL=0 # NOTE: Remove this after vLLM v0.21.1 is merged. Fixes Qwen2-5 omni-expansion tests.
pytest -v -s -m "advanced_model and xpu and B60"
pytest -v -s -m "omni and xpu and B60"
'
+181
View File
@@ -0,0 +1,181 @@
# Uploaded by upload_pipeline.py --upload (not the Buildkite hook).
# ``if`` is injected by step ``key`` from skip-ci at upload time.
steps:
- label: ":buildkit: Build and Push NPU Test Image - A2"
key: image-build-a2
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
plugins:
- kubernetes:
metadata:
annotations:
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-perms-ca.pem: "0400"
vault.hashicorp.com/agent-inject-perms-cert.pem: "0400"
vault.hashicorp.com/agent-inject-perms-config.json: "0400"
vault.hashicorp.com/agent-inject-perms-key.pem: "0400"
vault.hashicorp.com/agent-inject-secret-ca.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-cert.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-config.json: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-key.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-template-ca.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.RootCA }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-cert.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaCert }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-config.json: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.dockerConfig }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-key.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaKey }}\n{{- end }}"
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-run-as-group: "1000"
vault.hashicorp.com/agent-run-as-user: "1000"
vault.hashicorp.com/agent-service-account-token-volume-name: token-vol
vault.hashicorp.com/role: ascend-gha-runners
vault.hashicorp.com/secret-volume-path: /home/user/.docker/
vault.hashicorp.com/tls-skip-verify: "true"
podSpecPatch:
volumes:
- name: token-vol
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 600
path: token
env:
VLLM_IMAGE_TAG: "${BUILDKITE_COMMIT}"
IMAGE_NAME: "vllm-omni-ci-npu"
IMAGE_REGISTRY: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry"
BUILDKITD_ADDR: "tcp://buildkitd-service.buildkitd:1234"
command: |
set -ex
echo "--- Building and pushing NPU Test Image"
echo "Image: $${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
echo "buildkitd address: $${BUILDKITD_ADDR}"
if ! command -v buildctl &> /dev/null; then
echo "Installing buildctl..."
mkdir -p /tmp/buildkit
BUILDKIT_VERSION="v0.29.0"
wget -q "https://github.com/moby/buildkit/releases/download/$${BUILDKIT_VERSION}/buildkit-$${BUILDKIT_VERSION}.linux-arm64.tar.gz" -O /tmp/buildkit.tar.gz
tar -xzf /tmp/buildkit.tar.gz -C /tmp/buildkit
cp /tmp/buildkit/bin/buildctl /usr/local/bin/
fi
export DOCKER_CONFIG=/home/user/.docker
buildctl \
--addr="$${BUILDKITD_ADDR}" \
--tlscacert=/home/user/.docker/ca.pem \
--tlscert=/home/user/.docker/cert.pem \
--tlskey=/home/user/.docker/key.pem \
build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=./docker \
--opt filename=Dockerfile.npu.ci \
--secret id=dockerconfig,src=/home/user/.docker/config.json \
--output type=image,name=$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG},push=true \
--progress=plain
echo "--- Image pushed successfully"
echo "$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
- label: ":buildkit: Build and Push NPU Test Image - A3"
key: image-build-a3
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
plugins:
- kubernetes:
metadata:
annotations:
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-perms-ca.pem: "0400"
vault.hashicorp.com/agent-inject-perms-cert.pem: "0400"
vault.hashicorp.com/agent-inject-perms-config.json: "0400"
vault.hashicorp.com/agent-inject-perms-key.pem: "0400"
vault.hashicorp.com/agent-inject-secret-ca.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-cert.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-config.json: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-key.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-template-ca.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.RootCA }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-cert.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaCert }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-config.json: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.dockerConfig }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-key.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaKey }}\n{{- end }}"
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-run-as-group: "1000"
vault.hashicorp.com/agent-run-as-user: "1000"
vault.hashicorp.com/agent-service-account-token-volume-name: token-vol
vault.hashicorp.com/role: ascend-gha-runners
vault.hashicorp.com/secret-volume-path: /home/user/.docker/
vault.hashicorp.com/tls-skip-verify: "true"
podSpecPatch:
volumes:
- name: token-vol
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 600
path: token
env:
VLLM_IMAGE_TAG: "${BUILDKITE_COMMIT}-a3"
IMAGE_NAME: "vllm-omni-ci-npu"
IMAGE_REGISTRY: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry"
BUILDKITD_ADDR: "tcp://buildkitd-service.buildkitd:1234"
command: |
set -ex
echo "--- Building and pushing NPU Test Image"
echo "Image: $${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
echo "buildkitd address: $${BUILDKITD_ADDR}"
if ! command -v buildctl &> /dev/null; then
echo "Installing buildctl..."
mkdir -p /tmp/buildkit
BUILDKIT_VERSION="v0.29.0"
wget -q "https://github.com/moby/buildkit/releases/download/$${BUILDKIT_VERSION}/buildkit-$${BUILDKIT_VERSION}.linux-arm64.tar.gz" -O /tmp/buildkit.tar.gz
tar -xzf /tmp/buildkit.tar.gz -C /tmp/buildkit
cp /tmp/buildkit/bin/buildctl /usr/local/bin/
fi
export DOCKER_CONFIG=/home/user/.docker
buildctl \
--addr="$${BUILDKITD_ADDR}" \
--tlscacert=/home/user/.docker/ca.pem \
--tlscert=/home/user/.docker/cert.pem \
--tlskey=/home/user/.docker/key.pem \
build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=./docker \
--opt filename=Dockerfile.npu.ci.a3 \
--secret id=dockerconfig,src=/home/user/.docker/config.json \
--output type=image,name=$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG},push=true \
--progress=plain
echo "--- Image pushed successfully"
echo "$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
- label: "Upload Ready Pipeline"
depends_on:
- image-build-a2
- image-build-a3
key: upload-ready-pipeline
agents:
queue: "cpu_queue_premerge"
command: |
python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/npu/test-npu-ready.yml
# L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild)
- label: "Upload Nightly Pipeline"
depends_on:
- image-build-a2
- image-build-a3
key: upload-nightly-pipeline
commands:
- python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/npu/test-npu-nightly.yml
agents:
queue: "cpu_queue_premerge"
@@ -88,7 +88,7 @@
# # queue: "ascend-a3"
# # resource_class: "npu-2"
# # command: |
# # buildkite-agent pipeline upload .buildkite/test-npu-ready.yaml
# # buildkite-agent pipeline upload .buildkite/npu/test-npu-ready.yml
# # L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild)
# - label: "Upload Nightly Pipeline"
@@ -104,7 +104,7 @@
# build.pull_request.labels includes "diffusion-x2v-test"
# ))
# commands:
# - buildkite-agent pipeline upload .buildkite/test-npu-nightly.yaml
# - buildkite-agent pipeline upload .buildkite/npu/test-npu-nightly.yml
# agents:
# queue: "ascend-a3"
# resource_class: "npu-2"
+9
View File
@@ -0,0 +1,9 @@
# Hook uploads this entry YAML; upload_pipeline.py --upload reads bootstrap-upload-steps.yml
# and injects ``if`` by step ``key`` from skip-ci.
steps:
- label: ":github: Resolve skip-ci & upload pipeline"
key: upload-ci-pipeline
commands:
- "python3 .buildkite/common/scripts/upload_pipeline.py --upload .buildkite/npu/bootstrap-upload-steps.yml"
agents:
queue: "cpu_queue_premerge"
+205
View File
@@ -0,0 +1,205 @@
steps:
- group: ":card_index_dividers: Omni Model Test"
key: nightly-omni-test-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "omni-test"
steps:
- label: ":full_moon: Omni · Perf Test · No Async Chunk"
key: nightly-omni-performance-no-async-chunk
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py -m npu --test-config-file tests/dfx/perf/tests/test_qwen3_omni_no_async_chunk.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
- label: ":full_moon: Omni · Perf Test · Async Chunk"
key: nightly-omni-performance-async-chunk
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py -m npu --test-config-file tests/dfx/perf/tests/test_qwen3_omni_async_chunk.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
- label: ":robot: Omni · MiniCPM-o 4.5 Test"
mirror_hardwares: a3_npu_2
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5_expansion.py -m 'full_model' --run-level 'full_model'
- group: ":card_index_dividers: TTS Model Test"
key: nightly-tts-test-group
depends_on: upload-nightly-pipeline
if: build.env("NIGHTLY") == "1" || build.pull_request.labels includes "nightly-test" || build.pull_request.labels includes "tts-test"
steps:
- label: ":full_moon: TTS · Perf Test"
timeout_in_minutes: 180
mirror_hardwares: a3_npu_2
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- export BENCHMARK_DIR=tests/dfx/perf/results
- export VLLM_ALLOW_LONG_MAX_MODEL_LEN="1"
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_benchmark.py -m npu --test-config-file tests/dfx/perf/tests/test_tts.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/*.json"
exit $$EXIT
- group: ":card_index_dividers: Diffusion X2I(&A&T) Model Test"
key: nightly-diffusion-x2iat-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2iat-test"
steps:
- label: ":full_moon: Diffusion X2I(&A&T) · Perf Test · Qwen-Image-Edit-2511"
key: nightly-diffusion-x2iat-performance-qwen-image-edit-2511
timeout_in_minutes: 180
mirror_hardwares: a3_npu_8
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- export CACHE_DIT_VERSION=1.3.0
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py -m npu --test-config-file tests/dfx/perf/tests/test_qwen_image_edit_2511_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
- group: ":card_index_dividers: Diffusion I2I Model Test"
key: nightly-HunyuanImage3-x2i-test-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2iat-test"
steps:
- label: ":full_moon: HunyuanImage3-DIT · Accuracy Test"
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
HUNYUAN_IMAGE3_MODEL: "tencent/HunyuanImage-3.0-Instruct"
HUNYUAN_IMAGE3_DEVICES: "0,1,2,3"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- pytest -s -v tests/e2e/accuracy/test_hunyuan_image3_pixel_accuracy.py -m "full_model and A3" --run-level full_model
- group: ":card_index_dividers: Diffusion Benchmark Perf Test"
key: nightly-diffusion-benchmark-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2iat-test"
steps:
- label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=2 CFGP=2"
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
HF_TOKEN: "${HF_TOKEN}"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py -m A3 --test-config-file tests/dfx/perf/tests/test_hunyuan_image_tp2_cfgp2.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
- label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=2 SP=2"
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
HF_TOKEN: "${HF_TOKEN}"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py -m A3 --test-config-file tests/dfx/perf/tests/test_hunyuan_image_tp2_sp2.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
- label: ":full_moon: Diffusion Perf · HunyuanImage3 TP=4"
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
HF_TOKEN: "${HF_TOKEN}"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py -m A3 --test-config-file tests/dfx/perf/tests/test_hunyuan_image_tp4.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
- group: ":card_index_dividers: Diffusion X2V Model Test"
key: nightly-diffusion-x2v-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2v-test"
steps:
- label: ":full_moon: Diffusion X2V · Function Test"
mirror_hardwares: a2b3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k npu_i2v --run-level "full_model"
- label: ":full_moon: Diffusion X2V · Perf Test"
key: nightly-diffusion-x2v-performance
timeout_in_minutes: 180
mirror_hardwares: a3_npu_4
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
DIFFUSION_ATTENTION_BACKEND: TORCH_SDPA
commands:
- export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
- |
set +e
pytest -s -v tests/dfx/perf/scripts/run_diffusion_benchmark.py -m npu --test-config-file tests/dfx/perf/tests/test_wan22_i2v_vllm_omni.json
EXIT=$$?
buildkite-agent artifact upload "tests/dfx/perf/results/diffusion_result_*.json"
buildkite-agent artifact upload "tests/dfx/perf/results/logs/*.log"
exit $$EXIT
+34
View File
@@ -0,0 +1,34 @@
steps:
- group: ":card_index_dividers: Omni Model Test"
key: ready-omni-group
depends_on: upload-ready-pipeline
steps:
- label: ":robot: Omni · MiniCPM-o 4.5 Test"
agents:
queue: "ascend-a3"
resource_class: "npu-2"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}-a3"
plugins:
- kubernetes:
podSpecPatch:
imagePullSecrets:
- name: swr-secret
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/offline_inference/test_minicpmo_4_5.py tests/e2e/online_serving/test_minicpmo_4_5.py -m 'core_model' --run-level 'core_model'
- group: ":card_index_dividers: TTS Model Test"
key: ready-tts-group
depends_on: upload-ready-pipeline
steps:
- label: ":sound: TTS · Qwen3-TTS CustomVoice Test"
mirror_hardwares: a2b3_npu_1
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py -m 'core_model and npu' --run-level 'core_model'
-112
View File
@@ -1,112 +0,0 @@
steps:
- label: ":buildkit: Build and Push NPU Test Image - A2"
key: image-build
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
plugins:
- kubernetes:
metadata:
annotations:
vault.hashicorp.com/agent-init-first: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-perms-ca.pem: "0400"
vault.hashicorp.com/agent-inject-perms-cert.pem: "0400"
vault.hashicorp.com/agent-inject-perms-config.json: "0400"
vault.hashicorp.com/agent-inject-perms-key.pem: "0400"
vault.hashicorp.com/agent-inject-secret-ca.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-cert.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-config.json: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-secret-key.pem: internal/data/ascend/buildkitd
vault.hashicorp.com/agent-inject-template-ca.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.RootCA }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-cert.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaCert }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-config.json: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.dockerConfig }}\n{{- end }}"
vault.hashicorp.com/agent-inject-template-key.pem: "{{- with secret \"internal/data/ascend/buildkitd\" -}}\n{{ .Data.data.ClientCaKey }}\n{{- end }}"
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-run-as-group: "1000"
vault.hashicorp.com/agent-run-as-user: "1000"
vault.hashicorp.com/agent-service-account-token-volume-name: token-vol
vault.hashicorp.com/role: ascend-gha-runners
vault.hashicorp.com/secret-volume-path: /home/user/.docker/
vault.hashicorp.com/tls-skip-verify: "true"
podSpecPatch:
volumes:
- name: token-vol
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 600
path: token
env:
VLLM_IMAGE_TAG: "${BUILDKITE_COMMIT}"
IMAGE_NAME: "vllm-omni-ci-npu"
IMAGE_REGISTRY: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry"
BUILDKITD_ADDR: "tcp://buildkitd-service.buildkitd:1234"
command: |
set -ex
echo "--- Building and pushing NPU Test Image"
echo "Image: $${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
echo "buildkitd address: $${BUILDKITD_ADDR}"
if ! command -v buildctl &> /dev/null; then
echo "Installing buildctl..."
mkdir -p /tmp/buildkit
BUILDKIT_VERSION="v0.29.0"
wget -q "https://github.com/moby/buildkit/releases/download/$${BUILDKIT_VERSION}/buildkit-$${BUILDKIT_VERSION}.linux-arm64.tar.gz" -O /tmp/buildkit.tar.gz
tar -xzf /tmp/buildkit.tar.gz -C /tmp/buildkit
cp /tmp/buildkit/bin/buildctl /usr/local/bin/
fi
export DOCKER_CONFIG=/home/user/.docker
buildctl \
--addr="$${BUILDKITD_ADDR}" \
--tlscacert=/home/user/.docker/ca.pem \
--tlscert=/home/user/.docker/cert.pem \
--tlskey=/home/user/.docker/key.pem \
build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=./docker \
--opt filename=Dockerfile.npu.ci \
--secret id=dockerconfig,src=/home/user/.docker/config.json \
--output type=image,name=$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG},push=true \
--progress=plain
echo "--- Image pushed successfully"
echo "$${IMAGE_REGISTRY}/$${IMAGE_NAME}:$${VLLM_IMAGE_TAG}"
- label: "Upload Ready Pipeline"
depends_on: image-build
key: upload-ready-pipeline
if: >-
build.branch != "main" && (
build.pull_request.labels includes "npu-test" ||
build.pull_request.labels includes "ready"
)
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
command: |
buildkite-agent pipeline upload .buildkite/test-npu-ready.yaml
# L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild)
- label: "Upload Nightly Pipeline"
depends_on: image-build
key: upload-nightly-pipeline
if: >-
(build.branch == "main" && build.env("NIGHTLY") == "1") ||
(build.branch != "main" && (
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "omni-test" ||
build.pull_request.labels includes "tts-test" ||
build.pull_request.labels includes "diffusion-x2iat-test" ||
build.pull_request.labels includes "diffusion-x2v-test"
))
commands:
- buildkite-agent pipeline upload .buildkite/test-npu-nightly.yaml
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
-77
View File
@@ -1,77 +0,0 @@
# Document 1: Buildkite loads only this block on first parse. The next step resolves docs-only,
# pytest skip-mark-only, or combined skip-ci from git diff, then uploads document 2. When skip-ci
# applies, image-build still runs for the nightly exception in upload_pipeline.py (nightly-test
# label or main NIGHTLY=1); otherwise upload-nightly can be skipped together with test-ready/test-merge.
# Weekly uploads also depend on image-build.
# Document 2: appended after `---`; same file, read by upload_pipeline.py (not evaluated as a second pipeline by Buildkite). Child uploads include test-ready.yml, test-merge.yml, test-nightly.yml, and test-weekly.yml.
steps:
- label: ":github: Resolve skip-ci (docs / skip marks) & upload pipeline"
key: upload-ci-pipeline
commands:
- "python3 .buildkite/scripts/upload_pipeline.py --upload .buildkite/pipeline.yml"
agents:
queue: "cpu_queue_premerge"
---
steps:
- label: ":docker: Build image"
key: image-build
if: __IMAGE_BUILD_IF__
commands:
- "aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/q9t5s3a7"
- "docker build --progress=plain --file docker/Dockerfile.ci -t vllm-omni-ci ."
- "docker tag vllm-omni-ci public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT"
- "docker push public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT"
agents:
queue: "cpu_queue_premerge"
# L2 Test
- label: "Upload Ready Pipeline"
depends_on: image-build
key: upload-ready-pipeline
if: __UPLOAD_READY_IF__
commands:
- python3 .buildkite/scripts/upload_pipeline.py --upload .buildkite/test-ready.yml
agents:
queue: "cpu_queue_premerge"
# L3 Test
- label: "Upload Merge Pipeline"
depends_on: image-build
key: upload-merge-pipeline
if: __UPLOAD_MERGE_IF__
commands:
- python3 .buildkite/scripts/upload_pipeline.py --upload .buildkite/test-merge.yml
agents:
queue: "cpu_queue_premerge"
# L4 Test — main+NIGHTLY=1 (scheduled), or PR with specific label (e.g. add label then Rebuild)
- label: "Upload Nightly Pipeline"
depends_on: image-build
key: upload-nightly-pipeline
if: >-
(build.branch == "main" && build.env("NIGHTLY") == "1") ||
(build.branch != "main" && (
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "omni-test" ||
build.pull_request.labels includes "tts-test" ||
build.pull_request.labels includes "diffusion-x2iat-test" ||
build.pull_request.labels includes "diffusion-x2v-test"
))
commands:
- buildkite-agent pipeline upload .buildkite/test-nightly.yml
agents:
queue: "cpu_queue_premerge"
# L5 Test — main+WEEKLY=1 (scheduled), or PR with weekly-test label
- label: "Upload Weekly Pipeline"
depends_on: image-build
key: upload-weekly-pipeline
if: >-
(build.branch == "main" && build.env("WEEKLY") == "1") ||
(build.branch != "main" && build.pull_request.labels includes "weekly-test")
commands:
- buildkite-agent pipeline upload .buildkite/test-weekly.yml
agents:
queue: "cpu_queue_premerge"
@@ -16,7 +16,7 @@ steps:
- "uv venv --python=3.12 && source .venv/bin/activate"
- "uv pip install --upgrade build"
- "python3 -m build"
- "bash .buildkite/scripts/upload-nightly-wheels.sh"
- "bash .buildkite/release/scripts/upload-nightly-wheels.sh"
- label: "Generate and upload wheel indices"
depends_on: "build-wheel"
@@ -24,7 +24,7 @@ steps:
agents:
queue: small_cpu_queue_release
commands:
- "bash .buildkite/scripts/generate-and-upload-nightly-index.sh"
- "bash .buildkite/release/scripts/generate-and-upload-nightly-index.sh"
- block: "Upload release wheels to PyPI"
depends_on: "build-wheel"
@@ -38,7 +38,7 @@ steps:
agents:
queue: small_cpu_queue_release
commands:
- "bash .buildkite/scripts/publish-release-wheels-pypi.sh"
- "bash .buildkite/release/scripts/publish-release-wheels-pypi.sh"
- block: "Unblock to build release Docker images"
depends_on: ~
@@ -100,7 +100,7 @@ steps:
agents:
queue: small_cpu_queue_release
commands:
- "bash .buildkite/scripts/publish-release-images.sh"
- "bash .buildkite/release/scripts/publish-release-images.sh"
plugins:
- docker-login#v3.0.0:
username: vllmbot
@@ -36,12 +36,12 @@ mkdir -p "$INDICES_OUTPUT_DIR"
# HACK: we do not need regex module here, but it is required by pre-commit hook
# To avoid any external dependency, we simply replace it back to the stdlib re module
sed -i.bak 's/import regex as re/import re/g' .buildkite/scripts/generate-nightly-index.py && rm -f .buildkite/scripts/generate-nightly-index.py.bak
sed -i.bak 's/import regex as re/import re/g' .buildkite/release/scripts/generate-nightly-index.py && rm -f .buildkite/release/scripts/generate-nightly-index.py.bak
# Generate indices -- the version is just the commit hash (not omni/{commit})
# because relative paths are computed between the index and wheel directories,
# both of which live under the omni/ prefix in S3.
$PYTHON .buildkite/scripts/generate-nightly-index.py \
$PYTHON .buildkite/release/scripts/generate-nightly-index.py \
--version "$BUILDKITE_COMMIT" \
--current-objects "$obj_json" \
--output-dir "$INDICES_OUTPUT_DIR" \
@@ -78,7 +78,7 @@ if [[ "$version" != *"dev"* ]]; then
rm -rf "${INDICES_OUTPUT_DIR:?}"
mkdir -p "$INDICES_OUTPUT_DIR"
# wheel-dir is overridden to be the commit directory, so that the indices point to the correct wheel path
$PYTHON .buildkite/scripts/generate-nightly-index.py \
$PYTHON .buildkite/release/scripts/generate-nightly-index.py \
--version "$s3_version" \
--wheel-dir "$BUILDKITE_COMMIT" \
--current-objects "$obj_json" \
@@ -1,73 +0,0 @@
#!/bin/bash
# Helper function to safely login to ECR Public with per-job config isolation
# Uses DOCKER_CONFIG environment variable to prevent race conditions
#
# This script prevents the "device or resource busy" error by giving each
# Buildkite job its own isolated Docker config directory.
#
# Usage:
# source docker_login_ecr_public.sh && safe_docker_login_ecr_public
set -euo pipefail
# Configuration
ECR_REGISTRY="public.ecr.aws"
setup_isolated_docker_config() {
# Use BUILDKITE_JOB_ID for job-specific isolation
# Fallback to PID if running outside Buildkite
local job_id="${BUILDKITE_JOB_ID:-$$}"
# Set Docker config to job-specific directory
export DOCKER_CONFIG="/tmp/docker-config-${job_id}"
# Create directory if it doesn't exist
mkdir -p "$DOCKER_CONFIG"
echo "[docker-config] Using isolated Docker config: $DOCKER_CONFIG"
}
check_docker_auth() {
# Check if already authenticated to the given registry
# Returns 0 if authenticated, 1 if not
local registry="$1"
# Check if credentials exist in the isolated config
if [[ -f "$DOCKER_CONFIG/config.json" ]]; then
# Check if registry is present in config
if grep -q "$registry" "$DOCKER_CONFIG/config.json" 2>/dev/null; then
return 0
fi
fi
return 1
}
safe_docker_login_ecr_public() {
# Setup isolated config first
setup_isolated_docker_config
local registry="$ECR_REGISTRY"
# Check if already authenticated (within this job)
if check_docker_auth "$registry"; then
echo "[docker-login] Already authenticated to $registry in this job"
return 0
fi
# Perform login to isolated config directory
echo "[docker-login] Logging in to $ECR_REGISTRY (isolated config)..."
if aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin "$ECR_REGISTRY"; then
echo "[docker-login] Login successful (config: $DOCKER_CONFIG)"
return 0
else
local exit_code=$?
echo "[docker-login] ERROR: Login failed with exit code $exit_code" >&2
return $exit_code
fi
}
# Execute if run as script (not sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
safe_docker_login_ecr_public
fi
@@ -1,145 +0,0 @@
#!/bin/bash
# This script build the Ascend NPU docker image and run the offline inference inside the container.
# It serves a sanity check for compilation and basic model usage.
set -ex
# Base ubuntu image with basic ascend development libraries and python installed
VLLM_OMNI_REPO="https://github.com/vllm-project/vllm-omni.git"
BASE_IMAGE_NAME="quay.nju.edu.cn/ascend/vllm-ascend:v0.11.0rc2"
image_name="npu/vllm-omni-ci:${BUILDKITE_COMMIT}_${EPOCHSECONDS}"
# image_name="npu/vllm-ci:${BUILDKITE_COMMIT}_${EPOCHSECONDS}"
container_name="npu_${BUILDKITE_COMMIT}_$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 10; echo)"
# BUILDKITE_AGENT_NAME format is {hostname}-{agent_idx}-{npu_card_num}cards
agent_idx=$(echo "${BUILDKITE_AGENT_NAME}" | awk -F'-' '{print $(NF-1)}')
echo "agent_idx: ${agent_idx}"
builder_name="cachebuilder${agent_idx}"
builder_cache_dir="/mnt/docker-cache${agent_idx}"
mkdir -p ${builder_cache_dir}
# Try building the docker image
cat <<EOF | DOCKER_BUILDKIT=1 docker build \
--add-host pypi-cache:${PYPI_CACHE_HOST} \
--builder ${builder_name} --cache-from type=local,src=${builder_cache_dir} \
--cache-to type=local,dest=${builder_cache_dir},mode=max \
--build-arg BUILDKITE_PULL_REQUEST="${BUILDKITE_PULL_REQUEST}" \
--build-arg BUILDKITE_PULL_REQUEST_REPO="${BUILDKITE_PULL_REQUEST_REPO}" \
--progress=plain --load -t ${image_name} -f - .
FROM ${BASE_IMAGE_NAME}
# Define environments
ENV DEBIAN_FRONTEND=noninteractive
RUN pip config set global.index-url http://pypi-cache:${PYPI_CACHE_PORT}/pypi/simple && \
pip config set global.trusted-host pypi-cache && \
apt-get update -y && \
apt-get install -y python3-pip git vim wget net-tools gcc g++ cmake libnuma-dev && \
rm -rf /var/cache/apt/* && \
rm -rf /var/lib/apt/lists/*
# Install for pytest to make the docker build cache layer always valid
RUN --mount=type=cache,target=/root/.cache/pip \
pip install pytest>=6.0 pytest-cov modelscope
COPY . .
# Install vllm-omni
WORKDIR /workspace
ARG VLLM_OMNI_REPO=https://github.com/vllm-project/vllm-omni.git
ARG VLLM_OMNI_TAG=main
ARG BUILDKITE_PULL_REQUEST
ARG BUILDKITE_PULL_REQUEST_REPO
RUN git config --global url."https://gh-proxy.test.osinfra.cn/https://github.com/".insteadOf "https://github.com/" && \
if [ "\$BUILDKITE_PULL_REQUEST" != "false" ] && [ -n "\$BUILDKITE_PULL_REQUEST" ]; then \
echo "Cloning and checking out PR #\$BUILDKITE_PULL_REQUEST..." && \
git clone \$VLLM_OMNI_REPO /workspace/vllm-omni && \
cd /workspace/vllm-omni && \
git fetch origin pull/\$BUILDKITE_PULL_REQUEST/head:pr-\$BUILDKITE_PULL_REQUEST && \
git checkout pr-\$BUILDKITE_PULL_REQUEST; \
else \
echo "Not a PR build, using main branch" && \
git clone --depth 1 \$VLLM_OMNI_REPO /workspace/vllm-omni; \
fi
RUN --mount=type=cache,target=/root/.cache/pip \
export PIP_EXTRA_INDEX_URL=https://mirrors.huaweicloud.com/ascend/repos/pypi && \
source /usr/local/Ascend/ascend-toolkit/set_env.sh && \
source /usr/local/Ascend/nnal/atb/set_env.sh && \
export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/Ascend/ascend-toolkit/latest/`uname -i`-linux/devlib && \
python3 -m pip install -v -e /workspace/vllm-omni/
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
WORKDIR /workspace/vllm-omni
CMD ["/bin/bash"]
EOF
# Setup cleanup
remove_docker_container() {
docker rm -f "${container_name}" || true;
docker image rm -f "${image_name}" || true;
docker system prune -f || true;
}
trap remove_docker_container EXIT
# Generate corresponding --device args based on BUILDKITE_AGENT_NAME
# Ascend NPU BUILDKITE_AGENT_NAME format is {hostname}-{agent_idx}-{npu_card_num}cards, and agent_idx starts from 1.
# e.g. atlas-a2-001-1-2cards means this is the 1-th agent on atlas-a2-001 host, and it has 2 NPU cards.
# returns --device /dev/davinci0 --device /dev/davinci1
parse_and_gen_devices() {
local input="$1"
local index cards_num
if [[ "$input" =~ ([0-9]+)-([0-9]+)cards$ ]]; then
index="${BASH_REMATCH[1]}"
cards_num="${BASH_REMATCH[2]}"
else
echo "parse error" >&2
return 1
fi
local devices=""
local i=0
while (( i < cards_num )); do
local dev_idx=$(((index - 1)*cards_num + i ))
devices="$devices --device /dev/davinci${dev_idx}"
((i++))
done
# trim leading space
devices="${devices#"${devices%%[![:space:]]*}"}"
# Output devices: assigned to the caller variable
printf '%s' "$devices"
}
devices=$(parse_and_gen_devices "${BUILDKITE_AGENT_NAME}") || exit 1
# Run the image and execute the Out-Of-Tree (OOT) platform interface test case on Ascend NPU hardware.
# This test checks whether the OOT platform interface is functioning properly in conjunction with
# the hardware plugin vllm-ascend.
hf_model_cache_dir=/mnt/hf_cache${agent_idx}
ms_model_cache_dir=/mnt/modelscope${agent_idx}
mkdir -p ${hf_model_cache_dir}
mkdir -p ${ms_model_cache_dir}
docker run \
--init \
${devices} \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v ${hf_model_cache_dir}:/root/.cache/huggingface \
-v ${ms_model_cache_dir}:/root/.cache/modelscope \
--network host \
--entrypoint="" \
--name "${container_name}" \
"${image_name}" \
bash -c '
set -e
VLLM_USE_MODELSCOPE=True pytest -s -v tests/e2e/offline_inference/test_qwen2_5_omni_expansion.py
'
-499
View File
@@ -1,499 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: Apache-2.0
"""Render and optionally upload Buildkite pipeline YAML with diff-aware logic.
Bootstrap mode (pipeline.yml with __IMAGE_BUILD_IF__ placeholders):
- Detect docs-only, pytest skip-mark-only, or combined docs+skip-mark PR/main changes and
substitute skip-ci ``if`` expressions.
Test pipeline mode (e.g. test-merge.yml):
- Drop steps or groups whose ``source_file_dependencies`` do not match changed files.
- ``source_file_dependencies`` may be set on a leaf step or on a group step.
- Always strip ``source_file_dependencies`` from uploaded YAML (Buildkite does not
recognize this uploader-only key).
Usage:
python3 upload_pipeline.py [--upload] <pipeline.yml>
# Bootstrap (replaces upload_pipeline_with_skip_ci.sh):
python3 upload_pipeline.py --upload .buildkite/pipeline.yml
# Test pipeline (replaces upload_test_pipeline_with_diff_skip.py):
python3 upload_pipeline.py --upload .buildkite/test-merge.yml
"""
from __future__ import annotations
import argparse
import os
import re
import subprocess
import sys
from pathlib import Path
from typing import Any
try:
import yaml
except ImportError:
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "-q", "pyyaml"],
)
import yaml
LOG = "upload_pipeline"
ROOT = Path(__file__).resolve().parent.parent.parent
DOC_SEP = "\n---\n"
BOOTSTRAP_MARKER = "__IMAGE_BUILD_IF__"
def _log(message: str) -> None:
print(f"{LOG}: {message}", file=sys.stderr)
def _git(*args: str) -> subprocess.CompletedProcess[str]:
return subprocess.run(
["git", *args],
check=False,
capture_output=True,
text=True,
)
def resolve_diff_range() -> str | None:
"""Return a git diff range for PR or main builds, or None when unavailable."""
is_pr = os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false" and os.environ.get(
"BUILDKITE_PULL_REQUEST", ""
)
commit = os.environ.get("BUILDKITE_COMMIT", "")
if is_pr:
base_branch = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH", "main")
base_ref = f"origin/{base_branch}"
if _git("rev-parse", "--verify", base_ref).returncode != 0:
_log(f"origin/{base_branch} not found locally; trying fetch")
_git("fetch", "--depth=200", "origin", base_branch)
if _git("rev-parse", "--verify", base_ref).returncode != 0:
if _git("rev-parse", "--verify", base_branch).returncode == 0:
base_ref = base_branch
else:
_log(f"cannot resolve PR base {base_branch}; using safe defaults")
return None
return f"{base_ref}...{commit}"
if os.environ.get("BUILDKITE_BRANCH", "") == "main":
if _git("rev-parse", "--verify", f"{commit}^").returncode != 0:
_log("main commit has no parent; using safe defaults")
return None
return f"{commit}^..{commit}"
_log("not PR/main build; using safe defaults")
return None
def resolve_changed_files() -> list[str] | None:
"""Return changed file paths, or None when diff cannot be resolved."""
diff_range = resolve_diff_range()
if diff_range is None:
return None
result = _git("diff", "--name-only", diff_range)
if result.returncode != 0:
_log(f"git diff failed ({diff_range}); using safe defaults")
return None
files = [line for line in result.stdout.splitlines() if line.strip()]
_log(f"{len(files)} changed file(s)")
return files
def _is_doc_file(file_path: str) -> bool:
if not file_path:
return False
if file_path.startswith("docs/"):
return True
if file_path.endswith(".md"):
return True
return file_path == "mkdocs.yml"
def is_docs_only_change(changed_files: list[str]) -> bool:
has_any = False
for file_path in changed_files:
if not file_path:
continue
has_any = True
if not _is_doc_file(file_path):
return False
return has_any
def _is_test_python_file(file_path: str) -> bool:
path = Path(file_path)
return path.suffix == ".py" and bool(path.parts) and path.parts[0] == "tests"
_SKIP_MARK_RE = re.compile(r"pytest\.mark\.skip(?:if)?\b|pytest\.skip\s*\(")
_PYTESTMARK_SKIP_RE = re.compile(r"pytest\.mark\.skip\b")
_PYTEST_MARK_ONLY_RE = re.compile(r"pytest\.mark\.\w+")
def _paren_balance(line: str) -> int:
return line.count("(") - line.count(")")
def _is_skip_mark_related_content(line: str) -> bool:
stripped = line.strip()
if not stripped:
return True
if stripped.startswith("#"):
return True
return _SKIP_MARK_RE.search(stripped) is not None
def _is_pytestmark_adjacent_content(line: str) -> bool:
"""Allow pytestmark list refactors that only add skip/skipif alongside existing marks."""
stripped = line.strip().rstrip(",")
if not stripped:
return True
if stripped in {"[", "]"}:
return True
if stripped.startswith("#"):
return True
if stripped.startswith("pytestmark"):
return True
return _PYTEST_MARK_ONLY_RE.search(stripped) is not None
def diff_only_contains_skip_mark_changes(diff_text: str) -> bool:
"""True when diff only edits skip marks or reformats pytestmark to add them."""
pending_depth = 0
saw_change = False
has_skip_mark_edit = False
for raw_line in diff_text.splitlines():
if raw_line.startswith("@@"):
pending_depth = 0
continue
if not (raw_line.startswith("+") or raw_line.startswith("-")):
continue
if raw_line.startswith("+++") or raw_line.startswith("---"):
continue
saw_change = True
content = raw_line[1:]
if pending_depth > 0:
pending_depth += _paren_balance(content)
if pending_depth < 0:
pending_depth = 0
continue
if _is_skip_mark_related_content(content):
has_skip_mark_edit = True
pending_depth = max(0, _paren_balance(content))
continue
if _is_pytestmark_adjacent_content(content):
continue
return False
return saw_change and has_skip_mark_edit
def _git_file_diff(file_path: str, diff_range: str) -> str | None:
result = _git("diff", diff_range, "--", file_path)
if result.returncode != 0:
_log(f"skip-mark-only: git diff failed for {file_path}")
return None
return result.stdout
def _is_new_file_diff(diff_text: str) -> bool:
return "new file mode" in diff_text or "--- /dev/null" in diff_text
def _file_has_module_level_pytest_skip(content: str) -> bool:
"""True when ``pytestmark`` applies unconditional ``pytest.mark.skip`` to the module."""
match = re.search(r"^pytestmark\s*=\s*\[(.*?)^\s*\]", content, re.MULTILINE | re.DOTALL)
if match is not None:
return _PYTESTMARK_SKIP_RE.search(match.group(1)) is not None
match = re.search(r"^pytestmark\s*=\s*pytest\.mark\.skip\b", content, re.MULTILINE)
return match is not None
def _file_content_at_commit(file_path: str, commit: str) -> str | None:
result = _git("show", f"{commit}:{file_path}")
if result.returncode != 0:
_log(f"skip-mark-only: cannot read {file_path} at {commit}")
return None
return result.stdout
def _qualifies_as_skip_mark_test_change(file_path: str, diff_range: str) -> bool:
diff_text = _git_file_diff(file_path, diff_range)
if diff_text is None:
return False
if not diff_text.strip():
_log(f"skip-mark-only: empty diff for {file_path}")
return False
if diff_only_contains_skip_mark_changes(diff_text):
return True
if not _is_new_file_diff(diff_text):
_log(f"skip-mark-only: non-skip changes in {file_path}")
return False
commit = os.environ.get("BUILDKITE_COMMIT", "")
if not commit:
return False
content = _file_content_at_commit(file_path, commit)
if content is None:
return False
if _file_has_module_level_pytest_skip(content):
_log(f"skip-mark-only: new test file with module-level pytest.mark.skip: {file_path}")
return True
_log(f"skip-mark-only: new test file without module-level pytest.mark.skip: {file_path}")
return False
def is_skip_mark_only_change(changed_files: list[str], *, diff_range: str) -> bool:
"""True when every changed file is a tests/ module with only skip-mark edits."""
has_any = False
for file_path in changed_files:
if not file_path:
continue
has_any = True
if not _is_test_python_file(file_path):
return False
if not _qualifies_as_skip_mark_test_change(file_path, diff_range):
return False
return has_any
def is_docs_or_skip_mark_only_change(changed_files: list[str], *, diff_range: str) -> bool:
"""True when each changed file is a doc path or a qualifying skip-mark test change."""
has_any = False
for file_path in changed_files:
if not file_path:
continue
has_any = True
if _is_doc_file(file_path):
continue
if _is_test_python_file(file_path) and _qualifies_as_skip_mark_test_change(file_path, diff_range):
continue
_log(f"docs/skip-mark-only: rejecting {file_path}")
return False
return has_any
def resolve_skip_ci(changed_files: list[str] | None, *, diff_range: str | None = None) -> bool:
if changed_files is None:
_log("skip-ci=0 (could not resolve changed files)")
return False
if diff_range is not None and is_docs_or_skip_mark_only_change(changed_files, diff_range=diff_range):
if is_docs_only_change(changed_files):
_log("docs-only change detected; skip-ci=1")
elif is_skip_mark_only_change(changed_files, diff_range=diff_range):
_log("pytest skip-mark-only change detected; skip-ci=1")
else:
_log("docs + pytest skip-mark-only change detected; skip-ci=1")
return True
if diff_range is None and is_docs_only_change(changed_files):
_log("docs-only change detected; skip-ci=1")
return True
_log("non-doc/non-skip-mark changes detected; skip-ci=0")
return False
def render_bootstrap_pipeline(text: str, *, skip_ci: bool) -> str:
if DOC_SEP in text:
_, continuation = text.split(DOC_SEP, 1)
else:
continuation = text
nightly_only = (
'(build.pull_request.labels includes "nightly-test") || (build.branch == "main" && build.env("NIGHTLY") == "1")'
)
if skip_ci:
image_if = f"'{nightly_only}'"
ready_if = "'false'"
merge_if = "'false'"
else:
image_if = "'true'"
ready_if = '\'build.branch != "main" && build.pull_request.labels includes "ready"\''
merge_if = (
'\'(build.branch == "main" && build.env("NIGHTLY") != "1" '
'&& build.env("WEEKLY") != "1") || '
'(build.branch != "main" && build.pull_request.labels includes "merge-test")\''
)
return (
continuation.replace("__IMAGE_BUILD_IF__", image_if)
.replace("__UPLOAD_READY_IF__", ready_if)
.replace("__UPLOAD_MERGE_IF__", merge_if)
)
def _matches_dependencies(changed_files: list[str], prefixes: list[str]) -> bool:
for path in changed_files:
for prefix in prefixes:
normalized = prefix.rstrip("/")
if path == normalized or path.startswith(f"{normalized}/"):
return True
return False
def _strip_source_file_dependencies(step: dict[str, Any]) -> dict[str, Any]:
return {key: value for key, value in step.items() if key != "source_file_dependencies"}
def _step_label(step: dict[str, Any]) -> str:
return str(step.get("group") or step.get("label") or "<step>")
def _filter_steps(steps: list[Any], changed_files: list[str]) -> list[Any]:
filtered: list[Any] = []
for step in steps:
if not isinstance(step, dict):
filtered.append(step)
continue
deps = step.get("source_file_dependencies")
if deps is not None and not isinstance(deps, list):
raise ValueError(
f"source_file_dependencies must be a list in step {_step_label(step)!r}",
)
if deps is not None and not _matches_dependencies(changed_files, deps):
_log(
f"skip {_step_label(step)!r} (no changes under {deps})",
)
continue
nested = step.get("steps")
if nested is not None:
kept_nested = _filter_steps(nested, changed_files)
if not kept_nested:
_log(f"omit empty group {_step_label(step)!r}")
continue
new_step = _strip_source_file_dependencies(step)
new_step["steps"] = kept_nested
filtered.append(new_step)
continue
if deps is not None:
filtered.append(_strip_source_file_dependencies(step))
else:
filtered.append(step)
return filtered
def _strip_uploader_metadata_from_steps(steps: list[Any]) -> list[Any]:
"""Remove uploader-only keys while keeping all steps (no diff filtering)."""
stripped: list[Any] = []
for step in steps:
if not isinstance(step, dict):
stripped.append(step)
continue
deps = step.get("source_file_dependencies")
if deps is not None and not isinstance(deps, list):
raise ValueError(
f"source_file_dependencies must be a list in step {_step_label(step)!r}",
)
nested = step.get("steps")
new_step = _strip_source_file_dependencies(step)
if nested is not None:
new_step["steps"] = _strip_uploader_metadata_from_steps(nested)
stripped.append(new_step)
return stripped
def render_test_pipeline(
doc: dict[str, Any],
changed_files: list[str] | None,
) -> dict[str, Any]:
steps = doc.get("steps")
if not isinstance(steps, list):
return doc
if changed_files is not None:
steps = _filter_steps(steps, changed_files)
else:
steps = _strip_uploader_metadata_from_steps(steps)
return {**doc, "steps": steps}
def resolve_pipeline_path(arg: str) -> Path:
path = Path(arg)
if path.is_absolute():
return path
return ROOT / path
def render_pipeline(path: Path) -> str:
text = path.read_text(encoding="utf-8")
diff_range = resolve_diff_range()
changed_files = resolve_changed_files()
if BOOTSTRAP_MARKER in text:
rendered = render_bootstrap_pipeline(
text,
skip_ci=resolve_skip_ci(changed_files, diff_range=diff_range),
)
return rendered
doc = yaml.safe_load(text)
if not isinstance(doc, dict):
raise ValueError(f"invalid pipeline YAML: {path}")
doc = render_test_pipeline(doc, changed_files)
return yaml.safe_dump(doc, sort_keys=False)
def upload_to_buildkite(content: str) -> None:
subprocess.run(
["buildkite-agent", "pipeline", "upload"],
input=content,
text=True,
check=True,
)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"pipeline",
nargs="?",
default=".buildkite/pipeline.yml",
help="Pipeline YAML path (default: .buildkite/pipeline.yml)",
)
parser.add_argument(
"--upload",
action="store_true",
help="Pipe rendered YAML to buildkite-agent pipeline upload",
)
args = parser.parse_args()
path = resolve_pipeline_path(args.pipeline)
if not path.is_file():
_log(f"missing pipeline file: {path}")
return 1
rendered = render_pipeline(path)
if args.upload:
upload_to_buildkite(rendered)
else:
sys.stdout.write(rendered)
return 0
if __name__ == "__main__":
raise SystemExit(main())
-118
View File
@@ -1,118 +0,0 @@
steps:
- label: "Diffusion Model Test"
timeout_in_minutes: 30
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- pytest -s -v tests/e2e/offline_inference/test_z_image.py
- label: "Diffusion Images API LoRA E2E"
timeout_in_minutes: 30
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/diffusion/lora/test_images_generations_lora.py
- label: "Diffusion Model CPU offloading Test"
timeout_in_minutes: 20
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/diffusion/offloader/test_diffusion_cpu_offload.py
- pytest -s -v tests/diffusion/offloader/test_diffusion_layerwise_offload.py
- label: "Diffusion Cache Backend Test"
timeout_in_minutes: 15
agent_pool: mi325_1
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v -m 'core_model and cache and diffusion and not distributed_rocm and MI325'
- label: "Diffusion Sequence Parallelism Test"
timeout_in_minutes: 20
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/diffusion/distributed/test_sequence_parallel.py -m core_model
- label: "Diffusion Tensor Parallelism Test"
timeout_in_minutes: 20
agent_pool: mi325_2
depends_on: amd-build
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/diffusion/distributed/test_zimage_parallelism.py
- label: "Diffusion GPU Worker Test"
timeout_in_minutes: 20
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- pytest -s -v tests/diffusion/test_diffusion_worker.py
- label: "Omni Model Test Qwen2-5-Omni"
timeout_in_minutes: 15
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/e2e/offline_inference/test_qwen2_5_omni_expansion.py
- pytest -s -v tests/engine/test_async_omni_engine_abort.py
- label: "Omni Model Test Qwen3-Omni"
timeout_in_minutes: 15
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- export VLLM_ROCM_USE_AITER=0
- pytest -s -v tests/e2e/offline_inference/test_qwen3_omni.py
- pytest -s -v tests/e2e/online_serving/test_qwen3_omni.py
- label: "Omni Sleep Mode Test"
timeout_in_minutes: 40
agent_pool: mi325_2
depends_on: amd-build
mirror_hardwares: [amdproduction]
grade: Blocking
commands:
- export GPU_ARCHS=gfx942
- export VLLM_LOGGING_LEVEL=DEBUG
- export VLLM_WORKER_MULTIPROC_METHOD=spawn
- pytest -s -v tests/entrypoints/test_omni_sleep_mode.py -m "advanced_model and omni and MI325" --run-level "advanced_model"
-943
View File
@@ -1,943 +0,0 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- group: ":card_index_dividers: Simple Test"
depends_on: upload-merge-pipeline
steps:
- label: "Simple · Diffusion & Model Executor Test"
commands:
- "timeout 20m pytest -sv tests/diffusion tests/model_executor -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Simple · Other Test"
commands:
- "timeout 20m pytest -sv -m 'core_model and cpu' --ignore=tests/diffusion --ignore=tests/model_executor --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- group: ":card_index_dividers: Diffusion Test"
depends_on: upload-merge-pipeline
steps:
- label: "Diffusion · LoRA Test"
timeout_in_minutes: 30
commands:
- pytest -sv tests/diffusion/lora/ -m 'advanced_model and cuda' --run-level "advanced_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Distributed Test"
timeout_in_minutes: 60
commands:
- |
timeout 55m bash -c "
set -e
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/distributed -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- group: ":card_index_dividers: Entrypoints Test"
depends_on: upload-merge-pipeline
steps:
- label: "Entrypoint Test with H100"
timeout_in_minutes: 60
commands:
- pytest -s -v tests/entrypoints/ -m "advanced_model and cuda and H100" --run-level "advanced_model"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Entrypoint Test with L4"
timeout_in_minutes: 30
commands:
- pytest -s -v tests/entrypoints/ -m "advanced_model and cuda and L4" --run-level "advanced_model"
agents:
queue: "gpu_4_queue" # g6.12xlarge instance on AWS, has 4 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- group: ":card_index_dividers: E2E Test"
depends_on: upload-merge-pipeline
steps:
- label: "TTS · Step-Audio2 E2E Test"
timeout_in_minutes: 20
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/offline_inference/test_step_audio2.py -m 'advanced_model' --run-level 'advanced_model'
"
agents:
queue: "gpu_4_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Qwen3-TTS CustomVoice Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_customvoice.py
- tests/e2e/offline_inference/test_qwen3_tts_customvoice.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py tests/e2e/offline_inference/test_qwen3_tts_customvoice.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Qwen3-TTS Base Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_base.py
- tests/e2e/offline_inference/test_qwen3_tts_base.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py tests/e2e/offline_inference/test_qwen3_tts_base.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Ming-Omni-TTS Test"
source_file_dependencies:
- tests/e2e/online_serving/test_ming_tts.py
- tests/e2e/offline_inference/test_ming_tts.py
- vllm_omni/model_executor/models/ming_tts/
- vllm_omni/model_executor/stage_input_processors/ming_tts.py
- vllm_omni/deploy/ming_tts.yaml
timeout_in_minutes: 20
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
pytest -s -v tests/e2e/online_serving/test_ming_tts.py tests/e2e/offline_inference/test_ming_tts.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Voxtral-TTS Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_voxtral_tts.py
- tests/e2e/online_serving/test_voxtral_tts.py
- vllm_omni/model_executor/models/voxtral_tts/
- vllm_omni/model_executor/stage_input_processors/voxtral_tts.py
- vllm_omni/deploy/voxtral_tts.yaml
timeout_in_minutes: 20
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
pytest -s -v tests/e2e/offline_inference/test_voxtral_tts.py tests/e2e/online_serving/test_voxtral_tts.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "TTS · GLM-TTS Test"
source_file_dependencies:
- tests/e2e/online_serving/test_glm_tts.py
- tests/e2e/offline_inference/test_glm_tts.py
- vllm_omni/model_executor/models/glm_tts/
- vllm_omni/model_executor/stage_input_processors/glm_tts.py
- vllm_omni/deploy/glm_tts.yaml
timeout_in_minutes: 20
commands:
- |
timeout 20m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
pytest -s -v tests/e2e/online_serving/test_glm_tts.py tests/e2e/offline_inference/test_glm_tts.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Omni · Qwen3-Omni Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_qwen3_omni.py
- tests/e2e/online_serving/test_qwen3_omni.py
- vllm_omni/model_executor/models/qwen3_omni/
- vllm_omni/model_executor/stage_input_processors/qwen3_omni.py
- vllm_omni/deploy/qwen3_omni_moe.yaml
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/offline_inference/test_qwen3_omni.py tests/e2e/online_serving/test_qwen3_omni.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Omni · Mimo Audio Test"
source_file_dependencies:
- tests/e2e/online_serving/test_mimo_audio.py
- vllm_omni/model_executor/models/mimo_audio/
- vllm_omni/model_executor/stage_input_processors/mimo_audio.py
- vllm_omni/deploy/mimo_audio.yaml
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/online_serving/test_mimo_audio.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "TTS · VoxCPM2 Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_voxcpm2_tts.py
- tests/e2e/online_serving/test_voxcpm2_tts.py
- vllm_omni/model_executor/models/voxcpm2/
- vllm_omni/deploy/voxcpm2.yaml
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/offline_inference/test_voxcpm2_tts.py tests/e2e/online_serving/test_voxcpm2_tts.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Omni · Higgs-Audio V2 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_higgs_audio_v2.py
- tests/e2e/offline_inference/test_higgs_audio_v2.py
- vllm_omni/model_executor/models/higgs_audio_v2/
- vllm_omni/model_executor/stage_input_processors/higgs_audio_v2.py
- vllm_omni/deploy/higgs_audio_v2.yaml
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_USE_DEEP_GEMM=0
export VLLM_MOE_USE_DEEP_GEMM=0
pytest -s -v tests/e2e/online_serving/test_higgs_audio_v2.py tests/e2e/offline_inference/test_higgs_audio_v2.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Qwen Image Edit Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_edit.py
- vllm_omni/diffusion/models/qwen_image/
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/online_serving/test_qwen_image_edit.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Longcat Image Edit Test"
source_file_dependencies:
- tests/e2e/online_serving/test_longcat_image_edit.py
- vllm_omni/diffusion/models/longcat_image/
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/online_serving/test_longcat_image_edit.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Longcat Image Test"
source_file_dependencies:
- tests/e2e/online_serving/test_longcat_image.py
- vllm_omni/diffusion/models/longcat_image/
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/online_serving/test_longcat_image.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Bagel Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_bagel.py
- tests/e2e/online_serving/test_bagel.py
- vllm_omni/model_executor/models/bagel/
- vllm_omni/diffusion/models/bagel/
- vllm_omni/model_executor/stage_input_processors/bagel.py
- vllm_omni/deploy/bagel.yaml
timeout_in_minutes: 20
commands:
- pytest -s -v tests/e2e/offline_inference/test_bagel.py tests/e2e/online_serving/test_bagel.py -m 'advanced_model and cuda' --run-level 'advanced_model'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Qwen Image Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c '
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image.py -m 'advanced_model and cuda' --run-level 'advanced_model'
'
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Qwen Image Layered Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_layered.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image_layered.py -m 'advanced_model and cuda' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Wan22 Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_wan22_t2v.py
- tests/e2e/online_serving/test_wan22_t2v.py
- vllm_omni/diffusion/models/wan2_2/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/offline_inference/test_wan22_t2v.py tests/e2e/online_serving/test_wan22_t2v.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · HunyuanVideo 1.5 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_hunyuan_video_15.py
- vllm_omni/diffusion/models/hunyuan_video/
timeout_in_minutes: 40
commands:
- |
timeout 40m bash -c "
pytest -s -v tests/e2e/online_serving/test_hunyuan_video_15.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Z Image Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_z_image.py
- tests/e2e/online_serving/test_z_image.py
- vllm_omni/diffusion/models/z_image/
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/offline_inference/test_z_image.py tests/e2e/online_serving/test_z_image.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · FLUX.2 Klein Test"
source_file_dependencies:
- tests/e2e/offline_inference/test_flux2_klein.py
- tests/e2e/online_serving/test_flux2_klein.py
- vllm_omni/diffusion/models/flux2_klein/
timeout_in_minutes: 30
commands:
- pytest -s -v tests/e2e/offline_inference/test_flux2_klein.py tests/e2e/online_serving/test_flux2_klein.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · SD3 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_sd3.py
- vllm_omni/diffusion/models/sd3/
timeout_in_minutes: 45
commands:
- |
timeout 45m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_sd3.py -m 'advanced_model and cuda and diffusion' --run-level 'advanced_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 4
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
File diff suppressed because it is too large. Load diff
-24
View File
@@ -1,24 +0,0 @@
steps:
- group: ":card_index_dividers: Diffusion X2V Model Test"
key: nightly-diffusion-x2v-group
depends_on: upload-nightly-pipeline
if: >-
build.env("NIGHTLY") == "1" ||
build.pull_request.labels includes "nightly-test" ||
build.pull_request.labels includes "diffusion-x2v-test"
steps:
- label: ":full_moon: Diffusion X2V · Function Test"
agents:
queue: "ascend-a2b3"
resource_class: "npu-4"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}"
plugins:
- kubernetes:
podSpecPatch:
imagePullSecrets:
- name: swr-secret
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/online_serving/test_wan22_expansion.py -k npu_i2v --run-level "full_model"
-21
View File
@@ -1,21 +0,0 @@
steps:
- group: ":card_index_dividers: TTS Model Test"
key: ready-tts-group
depends_on: upload-ready-pipeline
steps:
- label: ":sound: TTS · Qwen3-TTS CustomVoice Test"
agents:
queue: "ascend-a2b3"
resource_class: "npu-1"
image: "swr.cn-southwest-2.myhuaweicloud.com/modelfoundry/vllm-omni-ci-npu:${BUILDKITE_COMMIT}"
plugins:
- kubernetes:
podSpecPatch:
imagePullSecrets:
- name: swr-secret
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_ALLOW_LONG_MAX_MODEL_LEN: "1"
HF_TOKEN: "${HF_TOKEN}"
commands:
- pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py -m 'core_model' --run-level 'core_model'
-674
View File
@@ -1,674 +0,0 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- group: ":card_index_dividers: Simple Test"
depends_on: upload-ready-pipeline
steps:
- label: "Simple · Diffusion & Model Executor Test"
commands:
- "timeout 20m pytest -sv tests/diffusion tests/model_executor -m 'core_model and cpu' --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Simple · Other Test"
commands:
- "timeout 20m pytest -sv -m 'core_model and cpu' --ignore=tests/diffusion --ignore=tests/model_executor --cov=vllm_omni --cov-report=term-missing:skip-covered --cov-report=xml"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Custom Pipeline Test"
depends_on: upload-ready-pipeline
commands:
- timeout 20m pytest -s -v tests/e2e/offline_inference/custom_pipeline/ -m "core_model"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- group: ":card_index_dividers: Diffusion Test"
depends_on: upload-ready-pipeline
steps:
- label: "Diffusion · Offloader Test"
commands:
- timeout 40m pytest -s -v tests/diffusion/offloader -m "core_model and cuda" --run-level "core_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Cache Test"
commands:
- timeout 15m pytest -sv tests/diffusion/cache -m 'core_model and cuda' --run-level "core_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Batch Test"
commands:
- timeout 15m pytest -sv tests/diffusion/batching -m 'core_model and cuda' --run-level "core_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Distributed Test"
commands:
- timeout 20m pytest -sv tests/diffusion/distributed -m 'core_model and cuda' --run-level "core_model"
agents:
queue: "gpu_4_queue" # g6.12xlarge instance on AWS, has 4 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Model Test"
commands:
- timeout 15m pytest -sv tests/diffusion/models/ -m 'core_model and cuda' --run-level "core_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Other Test"
commands:
- timeout 15m pytest -sv tests/diffusion/*.py -m 'core_model and cuda' --run-level "core_model"
agents:
queue: "gpu_1_queue" # g6.4xlarge instance on AWS, has 1 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Engine&Model Executor Test"
depends_on: upload-ready-pipeline
commands:
- |
timeout 15m bash -c "
pytest -sv tests/engine/ tests/model_executor/ -m 'core_model and cuda' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue" # g6.12xlarge instance on AWS, has 4 L4 GPU
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Distributed Test"
depends_on: upload-ready-pipeline
commands:
- |
timeout 20m bash -c "
pytest -sv tests/distributed/ -m 'core_model and cuda' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- group: ":card_index_dividers: Entrypoints Test"
depends_on: upload-ready-pipeline
steps:
- label: "Entrypoints Test with H100"
commands:
- |
timeout 30m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -sv tests/entrypoints/ -m 'core_model and cuda and H100' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Entrypoints Test with L4"
commands:
- |
timeout 30m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -sv tests/entrypoints/ -m 'core_model and cuda and L4' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- group: ":card_index_dividers: E2E Test"
depends_on: upload-ready-pipeline
steps:
- label: "RLHF · VeRL-Omni E2E Test"
source_file_dependencies:
- tests/e2e/offline_inference/rlhf_test/test_verl_omni_e2e.py
- tests/e2e/offline_inference/custom_pipeline/
- vllm_omni/diffusion/
- vllm_omni/engine/
- vllm_omni/entrypoints/
- vllm_omni/inputs/
- vllm_omni/outputs/
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/offline_inference/rlhf_test/test_verl_omni_e2e.py
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Omni · Qwen3-Omni Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_omni.py
- vllm_omni/model_executor/models/qwen3_omni/
- vllm_omni/model_executor/stage_input_processors/qwen3_omni.py
- vllm_omni/deploy/qwen3_omni_moe.yaml
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_qwen3_omni.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "TTS · VoxCPM2 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_voxcpm2_tts.py
- vllm_omni/model_executor/models/voxcpm2/
- vllm_omni/deploy/voxcpm2.yaml
timeout_in_minutes: 30
commands:
- |
timeout 30m bash -c "
export VLLM_LOGGING_LEVEL=DEBUG
export VLLM_WORKER_MULTIPROC_METHOD=spawn
pytest -s -v tests/e2e/online_serving/test_voxcpm2_tts.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Qwen3-TTS CustomVoice Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_customvoice.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_customvoice.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Qwen3-TTS Base Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen3_tts_base.py
- vllm_omni/model_executor/models/qwen3_tts/
- vllm_omni/model_executor/stage_input_processors/qwen3_tts.py
- vllm_omni/deploy/qwen3_tts.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
export VLLM_OMNI_USE_V2_RUNNER=1
pytest -s -v tests/e2e/online_serving/test_qwen3_tts_base.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "TTS · Higgs-Audio-V3 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_higgs_audio_v3.py
- vllm_omni/model_executor/models/higgs_audio_v3/
- vllm_omni/model_executor/stage_input_processors/higgs_audio_v3.py
- vllm_omni/deploy/higgs_multimodal_qwen3.yaml
commands:
- |
timeout 20m bash -c "
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_USE_DEEP_GEMM=0
export VLLM_MOE_USE_DEEP_GEMM=0
pytest -s -v tests/e2e/online_serving/test_higgs_audio_v3.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
- label: "Diffusion · Qwen Image Edit Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_edit.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 20m bash -c "
pytest -s -v tests/e2e/online_serving/test_qwen_image_edit.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Bagel Test"
source_file_dependencies:
- tests/e2e/online_serving/test_bagel.py
- vllm_omni/model_executor/models/bagel/
- vllm_omni/diffusion/models/bagel/
- vllm_omni/model_executor/stage_input_processors/bagel.py
- vllm_omni/deploy/bagel.yaml
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_bagel.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Wan22 Test"
source_file_dependencies:
- tests/e2e/online_serving/test_wan22_t2v.py
- vllm_omni/diffusion/models/wan2_2/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_wan22_t2v.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Qwen Image Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Diffusion · Qwen Image Layered Test"
source_file_dependencies:
- tests/e2e/online_serving/test_qwen_image_layered.py
- vllm_omni/diffusion/models/qwen_image/
commands:
- |
timeout 40m bash -c "
export VLLM_IMAGE_FETCH_TIMEOUT=60
pytest -s -v tests/e2e/online_serving/test_qwen_image_layered.py -m 'core_model' --run-level 'core_model'
"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 1
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
-148
View File
@@ -1,148 +0,0 @@
env:
VLLM_WORKER_MULTIPROC_METHOD: spawn
VLLM_USE_FLASHINFER_MOE_FP16: 0
HF_HUB_DOWNLOAD_TIMEOUT: 300
HF_HUB_ETAG_TIMEOUT: 60
steps:
- label: "Reliability Test - qwen3-omni"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_qwen3_omni.py -m "slow"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
- label: "Reliability Test - wan22"
timeout_in_minutes: 180
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
commands:
- pytest -s -v tests/dfx/reliability/test_reliability_wan22.py -m "slow"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
# Invalid HTTP / WS payloads vs live Omni servers (Issue #3649 tracks known skips).
- group: "Reliability Test - Invalid parameters Test"
depends_on: upload-weekly-pipeline
if: build.env("WEEKLY") == "1" || build.pull_request.labels includes "weekly-test"
steps:
- label: "Invalid parameters Test · H100"
timeout_in_minutes: 120
commands:
- pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and H100"
agents:
queue: "mithril-h100-pool"
plugins:
- kubernetes:
podSpec:
containers:
- image: 936637512419.dkr.ecr.us-west-2.amazonaws.com/vllm-ci-pull-through-cache/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
resources:
limits:
nvidia.com/gpu: 2
volumeMounts:
- name: devshm
mountPath: /dev/shm
- name: hf-cache
mountPath: /root/.cache/huggingface
env:
- name: HF_HOME
value: /root/.cache/huggingface
- name: HF_TOKEN
valueFrom:
secretKeyRef:
name: hf-token-secret
key: token
nodeSelector:
node.kubernetes.io/instance-type: gpu-h100-sxm
volumes:
- name: devshm
emptyDir:
medium: Memory
- name: hf-cache
hostPath:
path: /mnt/hf-cache
type: DirectoryOrCreate
# Stable Audio Open, Qwen3-TTS speech/batch/voices paths marked ``L4``.
- label: "Invalid parameters Test · L4"
timeout_in_minutes: 120
commands:
- pytest -s -v tests/dfx/reliability/invalid_param_test/ -m "slow and L4"
agents:
queue: "gpu_1_queue"
plugins:
- docker#v5.2.0:
image: public.ecr.aws/q9t5s3a7/vllm-ci-test-repo:$BUILDKITE_COMMIT
always-pull: true
propagate-environment: true
shm-size: "8gb"
environment:
- "HF_HOME=/fsx/hf_cache"
- "HF_TOKEN"
volumes:
- "/fsx/hf_cache:/fsx/hf_cache"
+44 -16
View File
@@ -24,7 +24,7 @@ Check the model's HF repo for `model_index.json`. This determines your path:
| Scenario | How to identify | Migration path |
|----------|----------------|----------------|
| **Already supported** | `_class_name` in `model_index.json` matches a key in `_DIFFUSION_MODELS` in `registry.py` | Skip to Step 5 (test) and Step 7 (docs) |
| **Already supported** | `_class_name` in `model_index.json` matches a key in `_DIFFUSION_MODELS` in `registry.py` | Skip implementation, then validate model-specific examples, tests, and docs as needed |
| **Diffusers-based** | Has standard `model_index.json` with `_diffusers_version`, subfolders for `transformer/`, `vae/`, etc. | Follow **Path A** below |
| **Custom/private repo** | No diffusers `model_index.json`, weights in non-standard format, custom model code in a separate git repo | Follow **Path B** below |
| **Hybrid** | Has some diffusers components (VAE) but custom transformer/fusion | Mix of Path A and Path B |
@@ -52,7 +52,7 @@ vllm_omni/diffusion/models/your_model_name/
2. Replace attention with `vllm_omni.diffusion.attention.layer.Attention` (QKV shape: `[B, seq, heads, head_dim]`).
3. Add `od_config: OmniDiffusionConfig | None = None` to `__init__`.
4. Add `load_weights()` method mapping diffusers weight names to vllm-omni names.
5. Add class attributes: `_repeated_blocks`, `_layerwise_offload_blocks_attr`.
5. Add class attributes for acceleration features such as `_repeated_blocks` and `_layerwise_offload_blocks_attrs` (see [references/transformer-adaptation.md](references/transformer-adaptation.md) for examples).
### A4. Adapt pipeline
@@ -78,13 +78,34 @@ class YourPipeline(nn.Module):
Add post/pre-process functions in the same pipeline file. Register them in `registry.py`.
### A4.1 Add progress bar support (recommended)
For pipelines with a standard denoising loop, prefer the existing progress bar pattern instead of hand-rolled logging.
```python
from vllm_omni.diffusion.models.progress_bar import ProgressBarMixin
class YourPipeline(nn.Module, ProgressBarMixin):
def forward(self, req: OmniDiffusionRequest) -> DiffusionOutput:
# ... prepare timesteps / latents ...
with self.progress_bar(total=len(timesteps)) as progress_bar:
for i, t in enumerate(timesteps):
# predict noise / scheduler step
latents = ...
progress_bar.update()
return DiffusionOutput(output=output)
```
For custom loop structures, follow `vllm_omni/diffusion/models/progress_bar.py` and existing pipelines using `ProgressBarMixin`.
### A5. Register, test, docs → continue at Step 4 below.
---
## Path B: Custom/Private Repo Model
For models without a diffusers pipeline — weights in custom format, model code in a private repo. Real examples: DreamID-Omni, BAGEL, HunyuanImage3.
For models without a diffusers pipeline — weights in custom format, model code in a private repo. Real examples: DreamID-Omni, BAGEL, HunyuanImage3. See [references/custom-model-patterns.md](references/custom-model-patterns.md) for concrete custom-model integration patterns.
### B1. Understand the reference repo
@@ -134,7 +155,7 @@ Copy the essential model files into `vllm_omni/diffusion/models/<name>/` and ada
### B4. Handle custom weight loading
Custom models have two patterns for weight loading:
Custom models have two common patterns for weight loading:
**Pattern 1: Bypass standard loader** (DreamID-Omni style)
@@ -149,8 +170,10 @@ class CustomPipeline(nn.Module):
self.vae = custom_init_vae(model, device=self.device)
self.text_encoder = custom_init_text_encoder(model, device=self.device)
self.transformer = CustomFusionModel(CONFIG)
load_custom_checkpoint(self.transformer,
checkpoint_path=os.path.join(model, "model.safetensors"))
load_custom_checkpoint(
self.transformer,
checkpoint_path=os.path.join(model, "model.safetensors"),
)
# NO weights_sources defined — bypasses standard loader
def load_weights(self, weights):
@@ -162,6 +185,8 @@ class CustomPipeline(nn.Module):
When weights are in safetensors format but need name remapping:
```python
from vllm.model_executor.model_loader.weight_utils import default_weight_loader
class CustomPipeline(nn.Module):
def __init__(self, *, od_config, prefix=""):
super().__init__()
@@ -187,7 +212,9 @@ class CustomPipeline(nn.Module):
# Remap original weight names to vllm-omni module names
name = self._remap_weight_name(name)
if name in params:
default_weight_loader(params[name], tensor)
param = params[name]
weight_loader = getattr(param, "weight_loader", default_weight_loader)
weight_loader(param, tensor)
loaded.add(name)
return loaded
```
@@ -281,16 +308,16 @@ For Omni or custom models, create:
### Step 7: Update Documentation
Required updates:
1. `docs/user_guide/diffusion/parallelism_acceleration.md` — parallelism support table
1. `docs/user_guide/diffusion/parallelism/overview.md` — parallelism support overview/table
2. `docs/user_guide/diffusion/cpu_offload_diffusion.md` — if CPU offload supported (add to supported models table)
3. `docs/user_guide/diffusion/teacache.md` — if TeaCache supported
4. `docs/user_guide/diffusion/cache_dit_acceleration.md` — if Cache-DiT supported
5. `examples/offline_inference/xxx/README.md` — offline example docs
6. `examples/online_serve/xxx/README.md` — online serve docs
3. `docs/user_guide/diffusion/cache_acceleration/teacache.md` — if TeaCache supported
4. `docs/user_guide/diffusion/cache_acceleration/cache_dit.md` — if Cache-DiT supported
5. Offline example docs under `examples/offline_inference/<name>/` (`README.md` or category-specific `.md`)
6. `examples/online_serving/<name>/README.md` — online serving docs
### Step 8: Add E2E Tests
**Follow the [vllm-omni-test skill](../vllm-omni-test/SKILL.md)** for markers, file naming, Buildkite wiring, and run commands. Also read [l4_functionality_tests.inc.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_examples/l4_functionality_tests.inc.md) and [CI_5levels.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/CI_5levels.md).
**Follow the [vllm-omni-test skill](../vllm-omni-test/SKILL.md)** for markers, file naming, Buildkite wiring, and run commands. Also read [l4_functionality_tests.inc.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_examples/l4_functionality_tests.inc.md), [test_system_overview.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_system_overview.md), and [test_writing_guide.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_writing_guide.md).
Classify the model's **CI priority** first:
@@ -307,7 +334,7 @@ Classify the model's **CI priority** first:
| **L1** | `tests/diffusion/models/{slug}/`, `tests/diffusion/cache/`, transformer unit tests | `core_model` + `cpu` | `test-ready.yml` | Weight remap, `_sp_plan`, cache enabler registration, shape contracts |
| **L2** | `tests/e2e/online_serving/test_{slug}.py` (and offline if the category is offline-first) | **`core_model` + `advanced_model`** (both on baseline smoke) + `diffusion` + `@hardware_test` / `hardware_marks` | `test-ready.yml` | Default deploy smoke — minimal `num_inference_steps`, single prompt |
| **L3** | `tests/e2e/online_serving/test_{slug}.py` **and** `tests/e2e/offline_inference/test_{slug}.py` when offline matters | Baseline smoke: **`core_model` + `advanced_model`**; heavier cases: `advanced_model` only (+ `diffusion`) | `test-merge.yml` **or** merged into nightly diffusion function job | Real weights, streaming/API paths, LoRA/offload smoke |
| **L4** | `tests/e2e/online_serving/test_{slug}_expansion.py` (+ offline expansion if needed) | `full_model` + `diffusion` | `test-nightly.yml` (X2I / X2V / X2A function groups) | Feature combos per [#1832](https://github.com/vllm-project/vllm-omni/issues/1832); perf → `tests/dfx/perf/tests/test_{model}_vllm_omni.json` |
| **L4** | `tests/e2e/online_serving/test_{slug}_expansion.py` (+ offline expansion if needed) | `full_model` + `diffusion` | `test-nightly.yml` (X2I / X2V / X2A function groups) | Feature combos per [#1832](https://github.com/vllm-project/vllm-omni/issues/1832); perf → `tests/dfx/perf/tests/test_{model}_vllm_omni.json` with per-case **`mark`** (`hardware_marks` + `full_model` + `diffusion`) |
**L2 & L3 online — same file, dual marks on the baseline smoke:** The **first / simplest** case in `test_{slug}.py` (default deploy, minimal steps, single prompt) should carry **both** `@pytest.mark.core_model` and `@pytest.mark.advanced_model` on the **same** function so L2 (`test-ready.yml`) and L3 (`test-merge.yml`) share one smoke test. Heavier deploy variants or API paths in the same file use **`advanced_model` only**. When L3 moves to nightly, migrate those heavier cases into `test_{slug}_expansion.py` with `full_model` and remove the dedicated `test-merge.yml` job (see `test_longcat_image_expansion.py`, `test_qwen_image_expansion.py`).
@@ -391,7 +418,8 @@ def enable_cache_for_your_model(pipeline, cache_config):
#### 9d. Register the custom enabler
Add your enabler to `CUSTOM_DIT_ENABLERS` in `vllm_omni/diffusion/cache/cache_dit_backend.py`:
Add your enabler to `CUSTOM_DIT_ENABLERS` in
`vllm_omni/diffusion/cache/cachedit/model_specific.py`:
```python
CUSTOM_DIT_ENABLERS = {
@@ -537,7 +565,7 @@ class YourTransformer(nn.Module):
#### 10e. Update parallelism documentation
After adding parallelism support, update:
1. `docs/user_guide/diffusion/parallelism_acceleration.md` — add your model to the support table
1. `docs/user_guide/diffusion/parallelism/overview.md` — add your model to the support overview/table
2. Record which parallelism methods are supported (USP, Ring, CFG, TP, HSDP, VAE-Patch)
### Step 11: Add CPU Offload Support
@@ -29,8 +29,13 @@ vLLM-Omni integrates cache-dit through `CacheDiTBackend`:
| `cache_dit.refresh_context()` | Updates cache context when `num_inference_steps` changes |
**Source files**:
- `vllm_omni/diffusion/cache/cache_dit_backend.py` — `CacheDiTBackend`, enablers, `CUSTOM_DIT_ENABLERS`
- `vllm_omni/diffusion/cache/` — cache backend implementations
- `vllm_omni/diffusion/cache/cachedit/__init__.py` — public package API
- `vllm_omni/diffusion/cache/cachedit/backend.py` — generic backend lifecycle and integration
- `vllm_omni/diffusion/cache/cachedit/config.py` — Cache-DiT configuration types
- `vllm_omni/diffusion/cache/cachedit/model_specific.py` — model-specific adapters, enablers, and registry
Outside `vllm_omni/diffusion/cache`, import Cache-DiT symbols only from
`vllm_omni.diffusion.cache.cachedit`.
## Standard Models: Automatic Support
@@ -175,7 +180,8 @@ Inspect your block's `forward()` return type and residual connection pattern to
## Registering Custom Enablers
Add your enabler to `CUSTOM_DIT_ENABLERS` in `vllm_omni/diffusion/cache/cache_dit_backend.py`:
Add your enabler to `CUSTOM_DIT_ENABLERS` in
`vllm_omni/diffusion/cache/cachedit/model_specific.py`:
```python
CUSTOM_DIT_ENABLERS = {
@@ -248,7 +254,7 @@ Models listed in `_NO_CACHE_ACCELERATION` in `vllm_omni/diffusion/registry.py` d
| Model | Path | Notes |
|-------|------|-------|
| Standard DiT | `cache_dit_backend.py::enable_cache_for_dit` | Default enabler, automatic |
| Wan2.2 | `cache_dit_backend.py::enable_cache_for_wan22` | Dual-transformer, auto-detects mode |
| LongCat | `cache_dit_backend.py::enable_cache_for_longcat_image` | Multi-block-list |
| BAGEL | `cache_dit_backend.py::enable_cache_for_bagel` | Complex omni model |
| Standard DiT | `cachedit.backend::enable_cache_for_dit` | Default enabler, automatic |
| Wan2.2 | `cachedit.model_specific::enable_cache_for_wan22` | Dual-transformer, auto-detects mode |
| LongCat | `cachedit.config::CacheDiTAdapterConfig` | Declarative multi-block-list adapter |
| BAGEL | `cachedit.model_specific::BagelCachedAdapter` | Custom cached adapter |
@@ -569,4 +569,4 @@ Check which parallelism methods a model supports:
| **TP** | Uses `ColumnParallelLinear` / `QKVParallelLinear`. Search: `grep -r 'ParallelLinear\|QKVParallel' vllm_omni/diffusion/models/<model>/` |
| **HSDP** | Transformer defines `_hsdp_shard_conditions`. Search: `grep -r '_hsdp_shard_conditions' vllm_omni/diffusion/models/` |
The canonical per-model support table is in `docs/user_guide/diffusion/parallelism_acceleration.md`.
The canonical per-model support overview/table is in `docs/user_guide/diffusion/parallelism/overview.md`.
@@ -219,13 +219,14 @@ def load_weights(self, weights):
### Class-Level Attributes for Features
```python
class MyTransformer(nn.Module):
# torch.compile: list block class names that repeat and can be compiled
_repeated_blocks = ["MyTransformerBlock"]
# CPU offload: attribute name of the nn.ModuleList containing blocks
_layerwise_offload_blocks_attr = "blocks"
_layerwise_offload_blocks_attrs = ["blocks"]
# LoRA: mapping of fused param names to original param names
packed_modules_mapping = {"to_qkv": ["to_q", "to_k", "to_v"]}
+1 -1
View File
@@ -307,7 +307,7 @@ def build_voice_clone_prompt(ref_audio_path: str, text: str, codec) -> list:
### Test Case Writing (CI Levels)
**Follow the [vllm-omni-test skill](../vllm-omni-test/SKILL.md)** for markers, file naming (`test_{slug}.py` / `test_{slug}_expansion.py`), Buildkite wiring, and copy-paste run commands. Also read [CI_5levels.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/CI_5levels.md) and [tests_style.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/tests_style.md).
**Follow the [vllm-omni-test skill](../vllm-omni-test/SKILL.md)** for markers, file naming (`test_{slug}.py` / `test_{slug}_expansion.py`), Buildkite wiring, and copy-paste run commands. Also read [test_system_overview.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_system_overview.md) and [test_writing_guide.md](https://github.com/vllm-project/vllm-omni/blob/main/docs/contributing/ci/test_writing_guide.md).
Classify the model's **CI priority** first (high / medium / low). High-priority TTS models are typically those on the integration hot path or listed in tracking issues such as [#1832](https://github.com/vllm-project/vllm-omni/issues/1832); medium and low tiers cover the long tail. When unsure, ask the reviewer which tier applies.
+3
View File
@@ -63,6 +63,8 @@ If multiple rows apply (e.g., a diffusion model is also a new model), union the
Ask: "Quick mode or full mode?" Then walk the checklist for the detected PR type from [references/checklists.md](references/checklists.md). Each item produces ✓, ✗, or ⚠.
**Also run the Code-Quality sweep on every PR**, regardless of type or mode: the five diff-scoped checks in [references/code-quality.md](references/code-quality.md) — kwargs fragility, broad-except swallow, `Any`/wrong type hints, hot-path `.clone()`/`deepcopy`, and event-loop blocking — plus the advisory conventions (log level, structured logging, synchronization, cleanup, dependencies, naming) in [checklists.md](references/checklists.md). These count only lines the PR *adds* — the pre-existing backlog across the repo is out of scope.
### Step 5: Print Report
```
@@ -74,6 +76,7 @@ Pre-check report for <branch>
Dimension Result
───────────────── ──────
PR title format ✓
Code quality ⚠ 1 broad except, 2 Any hints
PR desc integrity ✓
Registry/config ✓
Dead code ⚠ 2 warnings
@@ -35,6 +35,31 @@ PR title must follow the project convention documented in `docs/contributing/REA
---
## All PRs: Code Quality (run on every PR, quick & full)
Diff-scoped sweep for five fragility patterns that are pervasive in the existing codebase — **only lines the PR adds count**, not the pre-existing backlog. Detection commands, codebase examples, and full severity rules live in [code-quality.md](code-quality.md).
- [ ] **No new `**kwargs` string-lookup plumbing:** the diff adds no `**kwargs` + `kwargs["..."]` / `kwargs.get("...")` / `"..." in kwargs`. ⚠ any new instance; ✗ if a new string key is duplicated across ≥2 files without a shared constant, or unknown keys are silently dropped on a fail-fast path.
- [ ] **No new broad exception swallow:** the diff adds no `except Exception:` / bare `except:`. ⚠ any new instance; ✗ for `except: pass` / `except Exception: return None` / `continue` on a fail-fast path (init, config validation, weight loading, request handling).
- [ ] **No new `Any` / wrong type hints:** the diff adds no `: Any` / `-> Any` / untyped production signature, and no new `SimpleNamespace` in tests faking an object that already has a real typed stub. ⚠ any new instance; ✗ for a *wrong* (actively misleading) annotation or a `SimpleNamespace` test fake of a typed object.
- [ ] **No new hot-path copy:** the diff adds no `.clone()` / `.copy_()` / `copy.deepcopy(...)` inside a per-step loop or per-request path. ⚠ any new instance; ✗ for `.clone()` of a full latent/activations tensor inside an AR or diffusion step loop without a comment, or `deepcopy` of a scheduler / sampling-config on the request path.
- [ ] **No new event-loop blocking:** the diff adds no `time.sleep` / blocking HTTP (`requests`, `urllib`) / `await` inside a held lock in `async def` code. ⚠ any new instance; ✗ for blocking sleep or HTTP on the serving path (`engine/`, `entrypoints/`, async `connectors/`), or a lock held across an `await`. Blocking inside a dedicated worker thread is fine.
Roll the ⚠/✗ counts into the report as a single **Code quality** dimension row.
### Conventions (eyeball — no grep)
Judgment calls that don't grep cleanly — apply them while reading the diff, not as a mechanical check:
- **Right log level** — `info` is for end-user-visible events; routine internal events are `debug`; hot paths are `trace` or removed. Logging is not free.
- **Structured fields over f-strings** — pass dynamic values as structured fields (`logger.info("msg", extra={...})`), not interpolated strings, so they stay greppable and parseable.
- **No reflexive synchronization** — don't add `threading.Lock` / `asyncio.Lock` / `deepcopy` / re-wrap shared state unless there is real concurrent mutation; the GIL covers most Python code. Owners decide their own synchronization — don't pre-lock in a constructor.
- **Context managers for cleanup** — use `with` / `contextlib` for files, locks, CUDA streams, and profilers; not raw `open()` + manual `.close()` or ad-hoc `finally`.
- **No new dependencies without justification** — prefer the stdlib and existing vllm-omni deps; a new top-level dep needs a reason (check `pyproject.toml` / `requirements*.txt`).
- **Naming / interface discipline** — don't rename or change interfaces just for taste in this PR, but do fix names that actively mislead (e.g. `serve` implying a long-running server, `Instance` where multiple instance kinds coexist).
---
## Bug Fix PRs
### Quick
@@ -49,7 +74,7 @@ PR title must follow the project convention documented in `docs/contributing/REA
- [ ] **Regression test exists:** `git diff --name-only` includes at least one `tests/` file
- [ ] **Regression test reproduces the original error:** the test would fail on main, pass on this branch
- [ ] **Fix matches root cause exactly:** no "fix the symptom + something else" — if the root cause is dtype, the fix is dtype, not dtype + reformatting
- [ ] **No silent failure risk:** no bare `except: pass`, no `try: ... except: return None`, no empty fallback added
- [ ] **No silent failure risk:** no bare `except: pass`, no `try: ... except: return None`, no empty fallback added. See the broad-except pattern in [code-quality.md](code-quality.md#2-broad-exception-swallow) for the full severity rule (⚠ any new broad catch; ✗ for a swallow on a fail-fast path).
- [ ] **Upstream pattern match:** the fix follows the same pattern as existing code for similar cases (grep for analogous `from_pretrained` calls, etc.)
- [ ] **Environment documented:** torch/transformers/vllm versions listed if the bug is version-dependent
@@ -0,0 +1,179 @@
# Code-Quality Patterns
Five fragility patterns to sweep on **every** PR, in both quick and full mode. These are pervasive in the existing codebase (hundreds of pre-existing sites) — so the checks are **diff-scoped**: only lines the PR *adds* count. Whole-repo greps light up every PR with the backlog and are useless.
All commands assume:
```bash
BASE="$(git merge-base HEAD origin/main)"
```
**Severity:** ⚠ for any *new* instance introduced by the diff; ✗ for the acute sub-cases defined per pattern. Acute ✗ findings belong in the report's blocking count.
---
## 1. `**kwargs` string-lookup passthrough
### Anti-pattern
```python
def forward(self, **kwargs):
# BLOCKER-prone: raw dict + string keys duplicated across files
if "runtime_additional_information" in kwargs and \
"model_intermediate_buffer" not in kwargs:
...
```
Real instances of this exact guard are copy-pasted across `cosyvoice3.py`, `indextts2_talker.py` (×2), `indextts2_s2mel_decoder.py`, `qwen3_tts_talker.py`, `qwen3_omni.py`. A typo in any string key silently no-ops; there is no type check, no IDE completion, and unknown keys are silently dropped.
### Why dangerous
Raw `dict` + `**kwargs` + lists of param-name strings is **fragile by construction**: the compiler can't see a missing or misspelled key, so failures are silent. Each duplicated copy is a new place for the strings to drift.
### Severity
- ⚠ any *new* `**kwargs` signature whose body does `kwargs["..."]` / `kwargs.get("...")` / `"..." in kwargs`.
- ✗ when the diff introduces a **new** string key that is duplicated across ≥2 files without a shared module constant, or when `**kwargs` plumbing **silently drops unknown keys** on a fail-fast path (init, config validation, weight loading).
### Detect (diff-scoped)
```bash
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" \
| grep -E '\*\*kwargs|kwargs(\.get|\[)|"[a-z_]+"\s+in\s+kwargs'
```
### Fix
Prefer explicit typed params. The repo already has the right primitive: `msgspec.Struct` with `forbid_unknown_fields=True` rejects unknown keys instead of silently dropping them — see `_StructBase` in `vllm_omni/data_entry_keys.py:105` and `MoriPullRequest` in `vllm_omni/distributed/omni_connectors/connectors/mori_transfer_engine_connector.py:81`. A `@dataclass` or `TypedDict` works too.
If `**kwargs` is unavoidable (vLLM base-class compat), centralize the key strings as module-level constants behind **one** typed accessor, instead of repeating the literal across files.
---
## 2. Broad exception swallow
### Anti-pattern
```python
# BLOCKER-prone: catches everything, returns None on any failure
try:
evt = build_event(...)
return evt
except Exception:
return None
```
Real clusters: `vllm_omni/metrics/stats.py:240,274,367,450` and `vllm_omni/metrics/{modality,utils}.py` — all `except Exception: return None`.
### Why dangerous
A generic `except Exception:` is **too flexible**. If we catch an exception type we don't expect, it is almost always an unhandled edge case that needs to be *fixed* — not swallowed into `None`/`pass`/`continue`. Broad catches turn fixable bugs into silent wrong behavior and make debugging impossible.
The repo backs this with ruff `BLE001` (broad-exception catch); it is currently suppressed via `# noqa: BLE001` in `vllm_omni/patch.py:413`. Prefer fixing over suppressing.
### Severity
- ⚠ any *new* `except Exception:` / `except BaseException:` / bare `except:`.
- ✗ for `except:` / `except Exception: pass|return None|continue` on a **fail-fast path** (init, config validation, weight loading, request handling, connector setup). This extends the Bug-Fix "No silent failure risk" ✗ in [checklists.md](checklists.md).
### Detect (diff-scoped)
```bash
# Any new broad catch (⚠ baseline):
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" \
| grep -E 'except\s*(Exception|BaseException)?\s*:'
# Note: this matches only the immediate-colon swallow forms (`except :`,
# `except Exception:`) — it deliberately excludes specific catches like
# `except ValueError:` and the `except Exception as e:` variant. Eyeball
# the latter; `as e` usually means it is logged, but still verify.
```
### Fix
Catch the **specific** types you actually expect (`ValueError`, `KeyError`, `AttributeError`, `OSError`, `torch.cuda.OutOfMemoryError`, `msgspec.ValidationError`, …). At a genuine top-level / best-effort boundary (metrics, signal handlers), at minimum **log** the exception; never swallow into a bare `pass`/`return None` on a path that should fail loudly.
---
## 3. `Any` / wrong type annotations
### Anti-pattern
```python
# ⚠ Any param + Any return — no contract, no narrowing
def _extract_mm_output(engine_outputs: Any) -> dict[str, Any]:
...
```
### Why dangerous (root cause)
`Any` disables the type checker for that position, so typos and wrong shapes pass silently. The repo has 636 `: Any` params, 244 `-> Any` returns, and **1,173 `SimpleNamespace` in `tests/`**. The `Any` leak is largely test-driven: vibe-coded unit tests fake objects with `SimpleNamespace`, which forces the production code consuming them to be typed `Any`, and the `Any` then propagates outward into public signatures.
### Severity
- ⚠ any *new* `: Any` / `-> Any` / fully-untyped signature in production code.
- ✗ for a **wrong** annotation (actively misleading — e.g. `-> bool` that returns `Optional[bool]`), or a *new* `SimpleNamespace` in a test that mimics an object which already has a real typed stub / `@dataclass` / `TypedDict` / `Protocol`.
### Detect (diff-scoped)
```bash
# Any leaking into new signatures:
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" \
| grep -E ':\s*Any\b|->\s*Any\b'
# SimpleNamespace newly added in tests (the Any-leak source):
git diff ${BASE}...HEAD -- "tests/" | grep "^+[^+]" | grep "SimpleNamespace"
```
### Fix
Replace `Any` with the concrete type, a `Protocol`, or a `Union`. If a type is genuinely dynamic, prefer `object` + `isinstance` narrowing over `Any` — `object` keeps the checker engaged. In tests, replace `SimpleNamespace` with the real class, a small `@dataclass`/`TypedDict`, or a `Protocol` + fake, so the system under test stays fully typed.
---
## 4. Unnecessary copy — `.clone()` / `copy.deepcopy` in hot paths
### Anti-pattern
```python
# Per-step in a diffusion/AR loop: clones the full latent every iteration
for t in timesteps:
trajectory_latents.append(x_t.clone()) # O(N) GPU alloc + memcpy each step
```
Real clusters: `vllm_omni/diffusion/models/bagel/bagel_transformer.py` calls `x_t.clone()` ~9× across a trajectory loop (lines 1820–2186); the cache hooks `vllm_omni/diffusion/cache/teacache/hook.py:155` and `magcache/hook.py:182` clone `hidden_states` per step. Separately, `copy.deepcopy(self.scheduler)` / `copy.deepcopy(req.sampling_params)` is copy-pasted across diffusion pipelines — `pipeline_qwen_image.py:786`, `pipeline_hunyuan_image3.py:1904`, `pipeline_ltx2*.py` (×3), `pipeline_dreamzero.py:1085`, `diffusion_model_runner.py:398` — a full object-graph deepcopy on the request path. (Contrast `dreamzero/causal_wan_model.py:203`, which carries a `# No .clone() needed.` comment — the aware pattern.)
### Why dangerous
A `.clone()` of a GPU tensor or a `copy.deepcopy` of a config object inside a per-step / per-request path is a hidden allocator: it reads as one Python line but triggers a GPU memcpy or a deep object-graph walk every iteration. Across 50 diffusion steps or hundreds of AR steps it dominates latency and VRAM bandwidth. `deepcopy` additionally ignores any custom device / `__copy__` logic and can drag tensors through CPU.
### Severity
- ⚠ any *new* `.clone()` / `.copy_()` / `copy.deepcopy(...)` inside a per-step loop or per-request path.
- ✗ for `.clone()` of a full latent/activations tensor inside an AR or diffusion step loop without an explanatory comment, or `copy.deepcopy` of a scheduler / sampling-config on the request hot path.
### Detect (diff-scoped)
```bash
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" \
| grep -E '\.clone\(\)|\.copy_\(|copy\.deepcopy|deepcopy\('
```
### Fix
Tensors: prefer a view (`x[..., :k]`, `torch.narrow`, `as_strided`) or write into a pre-allocated buffer with `dst.copy_(src)` instead of `.clone()`; if the caller no longer needs the original, `move`/`del` it rather than copy. Schedulers / configs: build a fresh lightweight instance per request, or split out the mutable per-request bits so the shared immutable part isn't deepcopied. If a copy is genuinely required (e.g. the source is mutated in place later), keep it and add a one-line comment saying why.
---
## 5. Blocking the asyncio event loop / lock held across `await`
### Anti-pattern
```python
# BLOCKER-prone: blocking sleep / blocking HTTP / lock held across an await,
# all inside an async (event-loop) function
async def handle(self, req):
with self._lock:
resp = await self._client.call(req) # lock held across await -> serializes all requests
time.sleep(0.1) # stalls the single loop for every concurrent request
```
### Why dangerous
vLLM-Omni serves over a single asyncio event loop. Any synchronous blocking work on an `async def` path — `time.sleep`, blocking HTTP (`requests`/`urllib`), heavy CPU work, or a lock held across an `await` — stalls the loop for *every* concurrent request, not just the blocking one. A lock held across `await` silently serializes the whole pipeline; blocking I/O tanks throughput and inflates tail latency.
### Severity
- ⚠ any *new* `time.sleep(`, blocking HTTP call (`requests.get/post`, `urllib.request`, `urlopen`), or `await` inside a `with Lock` / `async with` critical section, in `async def` code.
- ✗ for `time.sleep` or blocking HTTP on the serving path (`engine/`, `entrypoints/`, async `connectors/`), or a lock acquired and held across an `await` on the request path.
### Detect (diff-scoped)
```bash
# New blocking primitives introduced by the diff — then eyeball whether each
# sits in an async function on the loop vs a dedicated worker thread:
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" \
| grep -E 'time\.sleep|requests\.(get|post|put|delete)|urllib\.request|urlopen'
# Lock acquired with an await potentially inside the critical section (manual eyeball):
git diff ${BASE}...HEAD -- "*.py" | grep "^+[^+]" | grep -E 'async with|\.acquire\(\)'
```
Note: blocking inside a **dedicated worker thread is correct** — the repo already does this (`diffusion/model_loader/hub_prefetch.py`, `distributed/omni_connectors/kv_transfer_manager.py`, the `mooncake`/`mori` connectors poll with `time.sleep` on their own threads). The check targets the *event-loop* path only.
### Fix
Move blocking work off the loop with `asyncio.to_thread(...)` / `run_in_executor`, or use a native async client (`httpx.AsyncClient` / `aiohttp`). Never `await` while holding a lock — drop the lock before the `await` and re-acquire after, or restructure so the critical section contains no `await`.
---
## Running the sweep
Run all five detections against `${BASE}...HEAD`, then for each hit decide ⚠ vs ✗ using the severity rules above. Roll the results into the report as a single **Code quality** dimension row (count of ⚠ and ✗), alongside the type-specific checklist from [checklists.md](checklists.md).
+26 -22
View File
@@ -9,7 +9,7 @@ description: Generate and run tests for vllm-project/vllm-omni with CI-aligned l
Use this skill to generate minimal, stable test cases and run them with the correct marker/level strategy for [vllm-project/vllm-omni](https://github.com/vllm-project/vllm-omni).
**Link convention:** Paths such as `.buildkite/` and `docs/contributing/` live at the **vllm-omni repo root**. Markdown links use repo-relative paths from this skill file (e.g. `../../../.buildkite/test-ready.yml`, `../../../docs/contributing/ci/CI_5levels.md`).
**Link convention:** Paths such as `.buildkite/` and `docs/contributing/` live at the **vllm-omni repo root**. Markdown links use repo-relative paths from this skill file (e.g. `../../../.buildkite/cuda/test-ready.yml`, `../../../docs/contributing/ci/test_system_overview.md`).
Default priorities:
@@ -96,8 +96,8 @@ Existing references: `tests/e2e/offline_inference/test_qwen2_5_omni.py` (L2-styl
|----------|------------------|---------------------------|---------------------------|
| **Offline inference e2e** | `tests/e2e/offline_inference/` | **Module (default):** `omni_runner` + `omni_runner_handler`. **Function (isolation only):** `omni_runner_function` + `omni_runner_handler_function`. Diffusion/TTS may use `Omni(...).generate` directly | L2: `core_model` + **one of** `omni` / `tts` / `diffusion`; `@hardware_test(...)` when GPU/NPU is required |
| **Online serving e2e** | `tests/e2e/online_serving/` | **Module (default):** `omni_server` + `openai_client`. **Function (isolation only):** `omni_server_function` + `openai_client_function`. Clients: `send_omni_request` (omni), `send_audio_speech_request` (tts), `send_diffusion_request` / `send_video_diffusion_request` / `send_images_generations_request` (diffusion) | Baseline smoke: **`core_model` + `advanced_model`**; heavier paths: `advanced_model` only; L4 expansion: `full_model` |
| **Documentation / runnable examples** | `tests/examples/offline_inference/`, `tests/examples/online_serving/` | **Offline docs (preferred):** extract Python/Bash blocks from the doc README (e.g. `ReadmeSnippet.extract_readme_snippets`), `pytest.mark.parametrize` each snippet, run via `example_runner.run` with a stable `output_subfolder`. **Online docs:** copy client/request scripts into dedicated tests and keep them in sync with the doc page. | Usually **L4**: `advanced_model`, often `example` plus hardware marks matching the nightly docs-example job (see `.buildkite/test-nightly.yml`). Full conventions: [docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md](../../../docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md) (introduced in [PR #1910](https://github.com/vllm-project/vllm-omni/pull/1910): naming, output directory layout, skip rules, avoid trimming `num_inference_steps` without a strong CI reason). |
| **Performance / benchmark** | `tests/dfx/perf/tests/*.json` + `run_*_benchmark.py` | JSON or script-driven server + load config; assert explicit metrics / baselines | L4 Perf: `full_model` + `benchmark`; wire `test-nightly.yml` Perf steps |
| **Documentation / runnable examples** | `tests/examples/offline_inference/`, `tests/examples/online_serving/` | **Offline docs (preferred):** extract Python/Bash blocks from the doc README (e.g. `ReadmeSnippet.extract_readme_snippets`), `pytest.mark.parametrize` each snippet, run via `example_runner.run` with a stable `output_subfolder`. **Online docs:** copy client/request scripts into dedicated tests and keep them in sync with the doc page. | Usually **L4**: `advanced_model`, often `example` plus hardware marks matching the nightly docs-example job (see `.buildkite/cuda/test-nightly.yml`). Full conventions: [docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md](../../../docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md) (introduced in [PR #1910](https://github.com/vllm-project/vllm-omni/pull/1910): naming, output directory layout, skip rules, avoid trimming `num_inference_steps` without a strong CI reason). |
| **Performance / benchmark** | `tests/dfx/perf/tests/*.json` + `run_*_benchmark.py` | JSON or script-driven server + load config; assert explicit metrics / baselines | L4 Perf: JSON `mark` with `full_model` + `omni`/`tts`/`diffusion`; wire `test-nightly.yml` Perf steps |
| **Invalid parameter / negative HTTP validation** | `tests/dfx/reliability/invalid_param_test/` | Live `omni_server` + low-level `send_*_http_request` with `err_code` / `err_message` | `pytest.mark.slow` + `omni` / `tts` / `diffusion` + `@hardware_marks` (`H100` or `L4`); CI in **`test-weekly.yml`** (not ready/merge/nightly) |
**If the user’s test plan includes invalid parameter validation / invalid params / negative HTTP / 400 validation:** do **not** add those `test_*` functions to `tests/e2e/online_serving/test_*.py` or `*_expansion.py`. **Move or author them** under `tests/dfx/reliability/invalid_param_test/` in the **endpoint-matching script** (see **Invalid parameter validation** below). Success-path e2e and invalid-param dfx tests must stay in separate modules.
@@ -270,7 +270,7 @@ def test_text_to_video_001(omni_server, openai_client) -> None:
*Documentation example tests:* follow the **Preferred Test Strategy** in [l4_doc_example_tests.inc.md](../../../docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md): dynamic extraction for offline READMEs; explicit copied client code for online pages until extraction is justified; use the documented **naming**, **output directory** (page folder + case id), and **skipping** rules (e.g. Gradio-only scripts).
*Performance tests:* add or extend entries under `tests/perf/` (and JSON configs where the project uses them), with **explicit baselines** and the same marker/run-level pairing as the CI step that will execute them.
*Performance tests:* add or extend entries under `tests/dfx/perf/tests/` (and JSON configs where the project uses them), with **explicit baselines**, **`mark`** on each case (`hardware_marks` + `full_model` + type marker), and the same nightly Perf step pattern as in-tree configs.
**3. Cross-cutting rules**
@@ -460,7 +460,7 @@ When the user asks for **invalid parameter validation**, **invalid request bodie
4. **Adding a new model** to invalid-param coverage: append a `pytest.param(OmniServerParams(model="...", stage_config_path=..., server_args=...), ...)` entry to the script’s `_PARAMS` list — do **not** create `test_invalid_<model>.py` unless the route is new.
5. **CI — `.buildkite/test-weekly.yml` only** (not `test-ready.yml` / `test-merge.yml` / `test-nightly.yml`):
5. **CI — `.buildkite/cuda/test-weekly.yml` only** (not `test-ready.yml` / `test-merge.yml` / `test-nightly.yml`):
| Weekly step | Command | When your cases run |
|-------------|---------|---------------------|
@@ -559,7 +559,7 @@ L1 tests under `tests/entrypoints/` may keep **minimal** asserts next to the han
#### Omni Test Writing Guidance (L1-L4 Layering)
When the goal is a general Omni/multimodal test case, prioritize mapping the test to the correct purpose, directory, and resource assumptions aligned with the layers (see [CI_5levels.md](../../../docs/contributing/ci/CI_5levels.md)):
When the goal is a general Omni/multimodal test case, prioritize mapping the test to the correct purpose, directory, and resource assumptions aligned with the layers (see [test_system_overview.md](../../../docs/contributing/ci/test_system_overview.md) and [test_writing_guide.md](../../../docs/contributing/ci/test_writing_guide.md)):
- **L1**: Unit/logic validation on CPU (`core_model and cpu`). Cover input validation, branches, and exception paths (`tests/<component>/test_*.py`). **Mock with `mocker` / `monkeypatch` only — not `unittest.mock`.**
- **L2**: Basic e2e (online/offline basic scenarios). Prefer dummy/lightweight models to validate the end-to-end request-to-output-structure/streaming chain (typically `tests/e2e/online_serving/` and `tests/e2e/offline_inference/`).
@@ -592,27 +592,31 @@ Implementation strategy:
**When the user explicitly asks for L4 perf (or full L4 including perf):**
1. **Do not** put throughput/latency assertions inside `test_*_expansion.py` — perf uses the **dfx benchmark harness**, not `omni_server` e2e fixtures.
2. Add or extend a **JSON config** under `tests/dfx/perf/tests/` (mirror in-tree names: `test_qwen_image_vllm_omni.json`, `test_bagel_vllm_omni.json`).
3. Each JSON entry: `test_name`, `server_params` (`model`, `serve_args`), `benchmark_params[]` with explicit **`baseline`** (`throughput_qps`, `latency_mean`, `peak_memory_mb_mean`, …).
2. Add or extend a **JSON config** under `tests/dfx/perf/tests/` (mirror in-tree names: `test_qwen_image_vllm_omni.json`, `test_cosmos3_vllm_omni.json`, `test_qwen3_omni_async_chunk.json`).
3. Each JSON **case**: `test_name`, optional **`mark`** (`hardware_marks` required when present; `marks`: `full_model` + `omni`/`tts`/`diffusion`), `server_params` (`model`, `serve_args` or `stage_config_name`), `benchmark_params[]` with **`name`** and explicit **`baseline`** (`throughput_qps`, `latency_mean`, `peak_memory_mb_mean`, …). Diffusion cases also set `server_type` (e.g. `"vllm-omni"`) and usually `benchmark_endpoint`.
4. Run locally via the matching script (model type → runner):
| Model type | Runner script | Example config |
|------------|---------------|----------------|
| **Diffusion X2I/X2V** | `tests/dfx/perf/scripts/run_diffusion_benchmark.py` | `tests/dfx/perf/tests/test_qwen_image_vllm_omni.json` |
| **TTS** | `tests/dfx/perf/scripts/run_benchmark.py` | `tests/dfx/perf/tests/test_tts.json` (shared) or `test_{slug}.json` (dedicated; use when the model must not join the shared nightly matrix before integration — e.g. `test_voxcpm2.json`, `test_coqui_tts.json`) |
| **Omni** | (see existing Omni Perf steps — `run_benchmark.py` / dedicated omni configs in-tree) | `tests/dfx/perf/tests/test_omni*.json` |
| **Omni** | `tests/dfx/perf/scripts/run_benchmark.py` | `test_qwen3_omni_no_async_chunk.json`, `test_qwen3_omni_async_chunk.json`, `test_qwen3_omni_vllm_text.json`, `test_qwen3_omni_multi_replicas.json` |
5. Wire **`test-nightly.yml` · Perf Test** step for that model (separate from Function Test): export `DIFFUSION_BENCHMARK_DIR` / `BENCHMARK_DIR`, run pytest on the script with `--test-config-file`, **upload artifacts** (`buildkite-agent artifact upload`), often **multi-GPU H100** for diffusion perf.
5. Wire **`test-nightly.yml` · Perf Test** step for that model (separate from Function Test): export `DIFFUSION_BENCHMARK_DIR` / `BENCHMARK_DIR`, run pytest on the script with **`--test-config-file`** (nightly perf steps do not use `-m`), **upload artifacts** (`buildkite-agent artifact upload`), often **multi-GPU H100** for diffusion perf.
6. **One benchmark scenario → one `test_name` block** in JSON (same spirit as one `test_*` per function case). Combine server `serve_args` + workload in one entry; use multiple `benchmark_params` rows for size/step sweeps under the same server config.
**Perf local command (diffusion example):**
**Perf local commands:**
```bash
cd tests
export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
# Single file (CI-like)
pytest -s -v dfx/perf/scripts/run_diffusion_benchmark.py \
--test-config-file dfx/perf/tests/test_<model>_vllm_omni.json
# Bulk load + filter by JSON mark
pytest -sv dfx/perf/scripts/run_diffusion_benchmark.py -m "full_model and diffusion and H100"
pytest -sv dfx/perf/scripts/run_benchmark.py -m "full_model and omni and H100"
```
**Clarify in the test plan** which L4 pillars you deliver: `Function only` | `Function + Perf` | `Function + Accuracy + Perf`.
@@ -625,10 +629,10 @@ If the test is not already collected by an existing pipeline command (for exampl
| Test level | Edit this file | Typical trigger / intent |
|------------|----------------|---------------------------|
| **L1** and **L2** | [`.buildkite/test-ready.yml`](../../../.buildkite/test-ready.yml) | PR **ready** label; L1 CPU + L2 GPU/basic e2e (steps labeled **Omni ·**, **TTS ·**, **Diffusion ·**) |
| **L3** | [`.buildkite/test-merge.yml`](../../../.buildkite/test-merge.yml) | Post-merge; `advanced_model` integration per model type |
| **L4** | [`.buildkite/test-nightly.yml`](../../../.buildkite/test-nightly.yml) | Nightly; grouped by model type (see below) |
| **Invalid param / reliability (weekly)** | [`.buildkite/test-weekly.yml`](../../../.buildkite/test-weekly.yml) | Weekly; `tests/dfx/reliability/invalid_param_test/` — **not** L1–L4 e2e pipelines |
| **L1** and **L2** | [`.buildkite/cuda/test-ready.yml`](../../../.buildkite/cuda/test-ready.yml) | PR **ready** label; L1 CPU + L2 GPU/basic e2e (steps labeled **Omni ·**, **TTS ·**, **Diffusion ·**) |
| **L3** | [`.buildkite/cuda/test-merge.yml`](../../../.buildkite/cuda/test-merge.yml) | Post-merge; `advanced_model` integration per model type |
| **L4** | [`.buildkite/cuda/test-nightly.yml`](../../../.buildkite/cuda/test-nightly.yml) | Nightly; grouped by model type (see below) |
| **Invalid param / reliability (weekly)** | [`.buildkite/cuda/test-weekly.yml`](../../../.buildkite/cuda/test-weekly.yml) | Weekly; `tests/dfx/reliability/invalid_param_test/` — **not** L1–L4 e2e pipelines |
**Level-specific Buildkite delivery (follow the user’s requested level):**
@@ -805,21 +809,21 @@ Use **repo-relative paths** (no leading `./`). Prefer **directory** entries (`..
When extending an **existing** E2E step to run an additional test file, **append** that file (and any new model/deploy paths) to `source_file_dependencies` on the same step. When authoring a PR, mention the dependency list in the **Buildkite change** section of your test plan.
#### L3 / L4: validating Buildkite from a feature branch (root `pipeline.yml`)
#### L3 / L4: validating Buildkite from a feature branch (`cuda/pipeline.yml`)
Production behavior is driven by [`.buildkite/pipeline.yml`](../../../.buildkite/pipeline.yml): it builds the CI image, then uploads **L2** (`test-ready.yml` on non-`main`), **L3** (`test-merge.yml` when `build.branch == "main"`), and **L4** (`test-nightly.yml` when `build.env("NIGHTLY") == "1"`).
Production behavior is driven by [`.buildkite/cuda/pipeline.yml`](../../../.buildkite/cuda/pipeline.yml): it builds the CI image, then uploads **L2** (`test-ready.yml` on non-`main`), **L3** (`test-merge.yml` when `build.branch == "main"`), and **L4** (`test-nightly.yml` when `build.env("NIGHTLY") == "1"`).
When you add or debug **L3** or **L4** tests and need those child pipelines to run **off `main`** or **without** `NIGHTLY=1`, apply **temporary** edits (revert before merge):
1. **Point the upload at the right file (optional shortcut)**
In the **Upload Ready Pipeline** step, the command is `buildkite-agent pipeline upload .buildkite/test-ready.yml`. For a one-off run you may change that path to `.buildkite/test-merge.yml` (L3) or `.buildkite/test-nightly.yml` (L4), and adjust the step’s `if:` so it does not conflict with the other upload steps (avoid double-uploading unless intentional).
In the **Upload Ready Pipeline** step, the command is `buildkite-agent pipeline upload .buildkite/cuda/test-ready.yml`. For a one-off run you may change that path to `.buildkite/cuda/test-merge.yml` (L3) or `.buildkite/cuda/test-nightly.yml` (L4), and adjust the step’s `if:` so it does not conflict with the other upload steps (avoid double-uploading unless intentional).
2. **L3 — merge pipeline**
The gate `if: build.branch == "main"` lives on the **Upload Merge Pipeline** step in `pipeline.yml` (not inside `test-merge.yml`). **Comment out that `if` line** so `test-merge.yml` is uploaded on your feature branch. Alternatively rely on step (1) instead of the dedicated merge upload step.
The gate `if: build.branch == "main"` lives on the **Upload Merge Pipeline** step in `cuda/pipeline.yml` (not inside `test-merge.yml`). **Comment out that `if` line** so `test-merge.yml` is uploaded on your feature branch. Alternatively rely on step (1) instead of the dedicated merge upload step.
3. **L4 — nightly pipeline**
**Comment out** `if: build.env("NIGHTLY") == "1"` on the **Upload Nightly Pipeline** step in `pipeline.yml` so the nightly definition is uploaded without setting the env var.
Child steps in [`test-nightly.yml`](../../../.buildkite/test-nightly.yml) often repeat `if: build.env("NIGHTLY") == "1"`; **comment out those lines on the steps you need to run**, otherwise they will still be skipped after upload.
**Comment out** `if: build.env("NIGHTLY") == "1"` on the **Upload Nightly Pipeline** step in `cuda/pipeline.yml` so the nightly definition is uploaded without setting the env var.
Child steps in [`test-nightly.yml`](../../../.buildkite/cuda/test-nightly.yml) often repeat `if: build.env("NIGHTLY") == "1"`; **comment out those lines on the steps you need to run**, otherwise they will still be skipped after upload.
### Step 6: Run Tests
@@ -886,5 +890,5 @@ When completing a request, return:
## Additional Resources
- Marker and command routing: [references/test-routing.md](references/test-routing.md)
- CI pipelines (vllm-omni): [test-ready.yml](../../../.buildkite/test-ready.yml) (L1/L2), [test-merge.yml](../../../.buildkite/test-merge.yml) (L3), [test-nightly.yml](../../../.buildkite/test-nightly.yml) (L4), [test-weekly.yml](../../../.buildkite/test-weekly.yml) (invalid param / reliability)
- CI pipelines (vllm-omni): [test-ready.yml](../../../.buildkite/cuda/test-ready.yml) (L1/L2), [test-merge.yml](../../../.buildkite/cuda/test-merge.yml) (L3), [test-nightly.yml](../../../.buildkite/cuda/test-nightly.yml) (L4), [test-weekly.yml](../../../.buildkite/cuda/test-weekly.yml) (invalid param / reliability)
- L4 documentation example tests (naming, extraction vs copied scripts, output dirs, skips): [docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md](../../../docs/contributing/ci/test_examples/l4_doc_example_tests.inc.md) — see also [PR #1910](https://github.com/vllm-project/vllm-omni/pull/1910)
@@ -2,7 +2,7 @@
Use this reference to map testing goals to levels, markers, and runnable commands.
**Repo paths** (`.buildkite/`, `docs/contributing/…`): link with repo-relative paths from this file (e.g. `../../../../.buildkite/test-ready.yml`, `../../../../docs/contributing/ci/CI_5levels.md`).
**Repo paths** (`.buildkite/`, `docs/contributing/…`): link with repo-relative paths from this file (e.g. `../../../../.buildkite/cuda/test-ready.yml`, `../../../../docs/contributing/ci/test_system_overview.md`).
## Model-centric e2e filename convention (L2–L4)
@@ -127,8 +127,12 @@ pytest -s -v e2e/online_serving/test_qwen_image_expansion.py -m "full_model and
cd tests
export DIFFUSION_BENCHMARK_DIR=tests/dfx/perf/results
export DIFFUSION_ATTENTION_BACKEND=FLASH_ATTN
# CI-like: single JSON file (nightly Perf Test steps)
pytest -s -v dfx/perf/scripts/run_diffusion_benchmark.py \
--test-config-file dfx/perf/tests/test_qwen_image_vllm_omni.json
# Local bulk load: all *.json under tests/dfx/perf/tests/, filter by JSON mark
pytest -sv dfx/perf/scripts/run_diffusion_benchmark.py -m "full_model and diffusion and H100"
pytest -sv dfx/perf/scripts/run_benchmark.py -m "full_model and omni and H100"
```
Broad marker sweep (when no explicit file shard):
@@ -150,7 +154,26 @@ Nightly **L4** for a model is often **multiple jobs** in `test-nightly.yml`, not
**Rule:** “L4 functional cases” → **Function only** by default. State that Perf/Accuracy are separate pillars; add them only when requested.
**Diffusion perf JSON** (`tests/dfx/perf/tests/test_<slug>_vllm_omni.json`): array of objects with `test_name`, `server_params` (`model`, `serve_args`), `benchmark_params[]`, and per-workload **`baseline`** (`throughput_qps`, `latency_mean`, `peak_memory_mb_mean`). Copy structure from `test_qwen_image_vllm_omni.json` in-tree.
**Diffusion perf JSON** (`tests/dfx/perf/tests/test_<slug>_vllm_omni.json`): array of **case objects**, each with:
| Field | Required | Notes |
|-------|----------|-------|
| `test_name` | Yes | Unique server/workload id |
| `mark` | Recommended | When present: **`hardware_marks` required** + optional `marks` (`full_model`, `diffusion`, `local_model`, …). Parsed by `resolve_pytest_marks`; enables local `-m` filtering. |
| `server_type` | Diffusion | e.g. `"vllm-omni"` — routes case to `run_diffusion_benchmark.py` |
| `benchmark_endpoint` | Diffusion | e.g. `/v1/videos`, `/v1/images/generations` |
| `server_params` | Yes | `model`, `serve_args`, … |
| `benchmark_params[]` | Yes | Each row: **`name`** (pytest id suffix), workload fields, **`baseline`** |
Copy structure from `test_qwen_image_vllm_omni.json` or `test_cosmos3_vllm_omni.json` (2-GPU mark example).
**Omni perf JSON**: `test_qwen3_omni_*.json` — same `mark` shape with `"marks": ["full_model", "omni"]`; run via `run_benchmark.py`.
**Runner split**: `is_diffusion_perf_config()` → diffusion when `server_type` is set or `"diffusion"` ∈ `mark.marks`; otherwise omni/tts → `run_benchmark.py`.
**Param ids**: `{test_name}-{benchmark_params.name}` (e.g. `test_tts-p0`, not `test_tts-0`).
**Result filenames**: runtime hardware from `get_runtime_resource_label()`; `H100` omitted on default CI pool.
**Diffusion perf nightly step** (under **Diffusion X2I(&A&T)**; copy full `kubernetes` plugins from `· Perf Test · Qwen-Image`):
@@ -177,9 +200,9 @@ Nightly **L4** for a model is often **multiple jobs** in `test-nightly.yml`, not
| Model type | Perf runner | Config example |
|------------|-------------|----------------|
| Diffusion X2I/X2V | `dfx/perf/scripts/run_diffusion_benchmark.py` | `test_qwen_image_vllm_omni.json` |
| TTS | `dfx/perf/scripts/run_benchmark.py` | `test_tts.json` (`BENCHMARK_DIR`) |
| Omni | `run_benchmark.py` / omni configs in-tree | `test_omni*.json` |
| Diffusion X2I/X2V | `dfx/perf/scripts/run_diffusion_benchmark.py` | `test_qwen_image_vllm_omni.json`, `test_cosmos3_vllm_omni.json` |
| TTS | `dfx/perf/scripts/run_benchmark.py` | `test_tts.json`, `test_voxcpm2.json`, `test_higgs_audio_v3.json` |
| Omni | `dfx/perf/scripts/run_benchmark.py` | `test_qwen3_omni_async_chunk.json`, `test_qwen3_omni_no_async_chunk.json`, … |
Do **not** put throughput/latency baselines inside `test_*_expansion.py` — that belongs in the dfx perf JSON + nightly Perf job.
@@ -201,7 +224,7 @@ When the user’s test plan includes **invalid parameter validation**, **invalid
| Sleep / wakeup / server control | `test_invalid_server_control.py` |
3. **Style:** `pytestmark = [pytest.mark.slow, pytest.mark.<type>]`; `_PARAMS` + `hardware_marks`; `send_*_http_request` with `err_code` + `err_message`; parametrized `body_spec` rows with `id=`; `_minimal_*_json()` helpers; `_SKIP_ISSUE_3649` when tracked in [#3649](https://github.com/vllm-project/vllm-omni/issues/3649).
4. **CI:** [`.buildkite/test-weekly.yml`](../../../../.buildkite/test-weekly.yml) group **Reliability Test - Invalid parameters Test** — **not** ready/merge/nightly.
4. **CI:** [`.buildkite/cuda/test-weekly.yml`](../../../../.buildkite/cuda/test-weekly.yml) group **Reliability Test - Invalid parameters Test** — **not** ready/merge/nightly.
```bash
# Weekly H100 (diffusion / omni / video invalid-param)
@@ -268,10 +291,10 @@ When adding or modifying tests, do not stop at “where the file lives” — al
| Level | Repo file | Model-type grouping |
|-------|-----------|---------------------|
| L1, L2 | [`.buildkite/test-ready.yml`](../../../../.buildkite/test-ready.yml) | Steps prefixed **Omni ·**, **TTS ·**, **Diffusion ·** under **E2E Test** — **`source_file_dependencies` required** |
| L3 | [`.buildkite/test-merge.yml`](../../../../.buildkite/test-merge.yml) | Per-model E2E steps; `-m "advanced_model and …"` — **`source_file_dependencies` required** |
| L4 | [`.buildkite/test-nightly.yml`](../../../../.buildkite/test-nightly.yml) | **Omni / TTS / Diffusion X2I(&A&T) / X2V** — each group may have **Function**, **Accuracy**, **Perf**, **Doc** steps |
| Invalid param (weekly) | [`.buildkite/test-weekly.yml`](../../../../.buildkite/test-weekly.yml) | **Invalid parameters Test · H100** / **· L4** — sweeps `tests/dfx/reliability/invalid_param_test/` |
| L1, L2 | [`.buildkite/cuda/test-ready.yml`](../../../../.buildkite/cuda/test-ready.yml) | Steps prefixed **Omni ·**, **TTS ·**, **Diffusion ·** under **E2E Test** — **`source_file_dependencies` required** |
| L3 | [`.buildkite/cuda/test-merge.yml`](../../../../.buildkite/cuda/test-merge.yml) | Per-model E2E steps; `-m "advanced_model and …"` — **`source_file_dependencies` required** |
| L4 | [`.buildkite/cuda/test-nightly.yml`](../../../../.buildkite/cuda/test-nightly.yml) | **Omni / TTS / Diffusion X2I(&A&T) / X2V** — each group may have **Function**, **Accuracy**, **Perf**, **Doc** steps |
| Invalid param (weekly) | [`.buildkite/cuda/test-weekly.yml`](../../../../.buildkite/cuda/test-weekly.yml) | **Invalid parameters Test · H100** / **· L4** — sweeps `tests/dfx/reliability/invalid_param_test/` |
### `source_file_dependencies` (E2E Test only — ready & merge)
@@ -357,7 +380,7 @@ Common patterns in `test-ready.yml` / `test-merge.yml`:
When extending an existing step (e.g. add `tests/e2e/offline_inference/test_qwen_image.py` to **Diffusion · Qwen Image Test**), update `source_file_dependencies` and `commands` only; **keep the existing `agents` + `plugins` block unchanged** unless the hardware tier changes.
The root [`.buildkite/pipeline.yml`](../../../../.buildkite/pipeline.yml) decides **which** child file is uploaded. To run **L3** on a feature branch, comment out `if: build.branch == "main"` on the merge upload step. To run **L4** without `NIGHTLY=1`, comment out the nightly upload step’s `if: build.env("NIGHTLY") == "1"` and the same `if` on relevant steps inside `test-nightly.yml`. Revert such edits before merging.
[`.buildkite/cuda/pipeline.yml`](../../../../.buildkite/cuda/pipeline.yml) decides **which** child file is uploaded. To run **L3** on a feature branch, comment out `if: build.branch == "main"` on the merge upload step. To run **L4** without `NIGHTLY=1`, comment out the nightly upload step’s `if: build.env("NIGHTLY") == "1"` and the same `if` on relevant steps inside `test-nightly.yml`. Revert such edits before merging.
Platform-specific pipelines (e.g. AMD) follow the same level → file pairing under `.buildkite/`.
+10 -10
View File
@@ -22,30 +22,30 @@
/.buildkite/ @yenuo26 @congw729
# Engine and model_executor
/vllm_omni/core/ @tzhouam @yinpeiqi @fake0fan
/vllm_omni/engine/ @tzhouam @yinpeiqi @fake0fan
/vllm_omni/entrypoints/ @tzhouam @yinpeiqi @fake0fan
/vllm_omni/core/ @tzhouam @yinpeiqi @fake0fan @Sy0307
/vllm_omni/engine/ @tzhouam @yinpeiqi @fake0fan @Sy0307
/vllm_omni/entrypoints/ @tzhouam @yinpeiqi @fake0fan @alex-jw-brooks
/vllm_omni/model_executor/ @tzhouam @gcanlin
/vllm_omni/worker/ @tzhouam @gcanlin
# Diffusion
/vllm_omni/diffusion/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @david6666666
/vllm_omni/diffusion/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @david6666666 @xuechendi
/vllm_omni/lora/ @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @yuanheng-zhao
# Diffusion CPU offloading
/vllm_omni/diffusion/offloader/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @yuanheng-zhao
/vllm_omni/diffusion/offloader/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @yuanheng-zhao @xuechendi
# Omni and TTS support
/vllm_omni/transformers_utils/ @tzhouam @yuanheng-zhao
/vllm_omni/model_executor/models/ @linyueqian @ZeldaHuang @princepride @yuanheng-zhao @amy-why-3459 @Bounty-hunter
/vllm_omni/model_executor/models/ @linyueqian @ZeldaHuang @princepride @yuanheng-zhao @amy-why-3459 @Bounty-hunter @Sy0307 @gcanlin
# Benchmarks
/benchmarks/accuracy/ @david6666666
/benchmarks/build_dataset/ @linyueqian @yuanheng-zhao
/benchmarks/diffusion/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa
/benchmarks/diffusion/ @Isotr0py @princepride @SamitHuang @wtomin @ZJY0516 @RuixiangMa @xuechendi
/benchmarks/distributed/ @princepride
/benchmarks/glm_image/ @princepride @JaredforReal
/benchmarks/tts/ @linyueqian @ZeldaHuang @princepride
/benchmarks/tts/ @linyueqian @ZeldaHuang @princepride @Sy0307 @gcanlin
# Usability and Observability
/vllm_omni/deploy/ @tzhouam @lishunyang12
@@ -53,13 +53,13 @@
/vllm_omni/profiler/ @gcanlin
# ComfyUI
/apps/ @fhfuih
/apps/ @fhfuih @alex-jw-brooks
# Large Scale Serving
/vllm_omni/distributed/ @princepride @yuanheng-zhao @xuechendi @natureofnature @fake0fan
# Quantization and configuration
/vllm_omni/config/ @lishunyang12
/vllm_omni/config/ @lishunyang12 @alex-jw-brooks
/vllm_omni/quantization/ @david6666666 @Isotr0py @lishunyang12
# Hardware plugins and accelerators
@@ -19,6 +19,7 @@ body:
Consider redacting or replacing sensitive values with placeholders like `<YOUR_TOKEN_HERE>` when sharing configuration or code examples.
- type: textarea
id: current-environment
attributes:
label: Your current environment
description: |
@@ -42,6 +43,7 @@ body:
required: true
- type: textarea
id: code-version
attributes:
label: Your code version
description: |
@@ -66,6 +68,7 @@ body:
required: true
- type: textarea
id: bug-description
attributes:
label: 🐛 Describe the bug
description: |
+6
View File
@@ -24,3 +24,9 @@ jobs:
python-version: "3.12"
cache: 'pip'
- uses: pre-commit/action@v3.0.1
# Don't run the pytest mark check against everything in the CI
# for now since a lot of files are still missing them. This check
# is used to help contributors remember to add the marks when they
# commit.
env:
SKIP: check-test-ci-coverage
+3 -1
View File
@@ -208,6 +208,7 @@ cache/
.cache/
diffusion_cache/
kv_cache/
!vllm_omni/experimental/ar_diffusion/kv_cache/
# Logs
logs/
@@ -241,11 +242,13 @@ datasets/
*.json
!tests/dfx/perf/tests/*.json
!apps/ComfyUI-vLLM-Omni/example_workflows/*.json
!tests/assets/soulxsinger/*.json
*.jsonl
*.parquet
# Output files
outputs/
!vllm_omni/outputs/
results/
generated/
output_*/
@@ -256,7 +259,6 @@ configs/production.yaml
configs/development.yaml
# Docker
.dockerignore
Dockerfile.dev
discussion
tmp_test
+7
View File
@@ -54,6 +54,13 @@ repos:
verbose: true
stages: [commit-msg]
- id: check-test-ci-coverage
name: Ensure test files have pytestmarks
entry: python tools/pre_commit/check_test_marks.py
language: python
types: [python]
files: ^tests/
# Keep `suggestion` last
- id: suggestion
name: Suggestion
+9 -10
View File
@@ -16,13 +16,10 @@ Easy, fast, and cheap omni-modality model serving for everyone
---
*Latest News* 🔥
- [2026/06] We released [0.22.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.22.0) - an **omnimodal world-model** release aligned with vLLM 0.22, featuring [Nvidia Cosmos3](recipes/cosmos3/Cosmos3-Nano.md)/DreamZero world model support, expanded quantization coverage across Blackwell/NPU/XPU, TTS production improvements, new models including MiniCPM-o 4.5, MOSS-TTS, and Lance, plus RL integration with [VeRL-Omni](https://github.com/verl-project/verl-omni).
- [2026/05] We released [0.20.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.20.0) - refreshes the serving/runtime stack for large-scale omni workloads, and improves diffusion model performance, quantization, and hardware readiness across CUDA, ROCm, MUSA, NPU, and XPU backends.
- [2026/03] We released [0.18.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.18.0) - strengthens the core runtime through a large entrypoint refactor and scheduler/runtime cleanups, expands unified quantization and diffusion execution, broadens multimodal model coverage, and improves production readiness across audio, omni, image, video, RL, and multi-platform deployments.
- [2026/08] We released [0.26.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.26.0) - aligned with the vLLM 0.26 release line, featuring [MiniMax H3](recipes/MiniMaxAI/MiniMax-H3.md) joint video/audio generation, an experimental full-duplex realtime runtime for [MiniCPM-o 4.5](recipes/OpenBMB/MiniCPM-o-4_5.md), distributed layerwise diffusion offload, and broader model, hardware, streaming, TTS, and quantization support.
- [2026/07] We released [0.24.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.24.0) - aligned with the vLLM 0.24 release line, expanding production-ready coverage across TTS, speech, diffusion, image/video generation, and robot-policy serving, with major Omni stage runtime refactoring, diffusion request-level batching, async output materialization, quantization/cache/memory improvements, and broad CUDA/ROCm/XPU/NPU support.
- [2026/06] Starting with [0.14.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.14.0), vLLM-Omni publishes a stable release aligned with every even-numbered upstream vLLM minor version. [0.16.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.16.0), [0.18.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.18.0), [0.20.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.20.0), and [0.22.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.22.0) continued this cadence, expanding omni and world-model support with [NVIDIA Cosmos3](recipes/cosmos3/Cosmos3-Nano.md) and DreamZero, adding models such as MiniCPM-o 4.5, MOSS-TTS, and Lance, and advancing TTS, diffusion, distributed execution, quantization, RL integration through [VeRL-Omni](https://github.com/verl-project/verl-omni), and CUDA/ROCm/MUSA/NPU/XPU coverage.
- [2026/03] Check out our first public [project deepdive](https://youtu.be/sgwNfsNnR9I) at the vLLM Hong Kong Meetup!
- [2026/03] **[vllm-omni-skills](https://github.com/hsliuustc0106/vllm-omni-skills)** is a community-driven collection of AI assistant skills that help developers work with vLLM-Omni more effectively. These skills can be used with popular agentic AI coding assistants like **Cursor IDE**, **Claude**, **Codex**, and more.
- [2026/02] We released [0.16.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.16.0) - A major alignment + capability release that rebases onto **upstream vLLM v0.16.0** and significantly expands performance, distributed execution, and production readiness across **Qwen3-Omni / Qwen3-TTS**, **Bagel**, **MiMo-Audio**, **GLM-Image** and the **Diffusion (DiT) image/video stack**—while also improving platform coverage (CUDA / ROCm / NPU / XPU), CI quality, and documentation.
- [2026/02] We released [0.14.0](https://github.com/vllm-project/vllm-omni/releases/tag/v0.14.0) - This is the first **stable release** of vLLM-Omni that expands Omni’s diffusion / image-video generation and audio / TTS stack, improves distributed execution and memory efficiency, and broadens platform/backend coverage (GPU/ROCm/NPU/XPU). It also brings meaningful upgrades to serving APIs, profiling & benchmarking, and overall stability. Please check our latest [paper](https://arxiv.org/abs/2602.02204) for architecture design and performance results.
- [2025/11] vLLM community officially released [vllm-project/vllm-omni](https://github.com/vllm-project/vllm-omni) in order to support omni-modality models serving.
---
@@ -31,9 +28,9 @@ Easy, fast, and cheap omni-modality model serving for everyone
[vLLM](https://github.com/vllm-project/vllm) was originally designed to support large language models for text-based autoregressive generation tasks. vLLM-Omni is a framework that extends its support for omni-modality model inference and serving:
- **Omni-modality**: Text, image, video, and audio data processing
- **Omni-modality**: Text, image, audio, video, and action data processing
- **Non-autoregressive Architectures**: extend the AR support of vLLM to Diffusion Transformers (DiT) and other parallel generation models
- **Heterogeneous outputs**: from traditional text generation to multimodal outputs
- **Heterogeneous outputs**: from traditional text generation to multimodal and action outputs
<p align="center">
<picture>
@@ -54,12 +51,14 @@ vLLM-Omni is flexible and easy to use with:
- Tensor, pipeline, data and expert parallelism support for distributed inference
- Streaming outputs
- OpenAI-compatible API server
- Full-duplex realtime serving with streaming audio input and output (experimental)
vLLM-Omni seamlessly supports most popular open-source models on HuggingFace, including:
- **Omni-modality models** (e.g. Qwen3-Omni, Cosmos, HunyuanImage, BAGEL)
- **Omni-modality models** (e.g. Qwen3-Omni, MiniCPM-o 4.5, Cosmos3, HunyuanImage, BAGEL)
- **TTS models** (e.g. Qwen3-TTS, VoxCPM2, Ming-Omni-TTS, CosyVoice3)
- **Diffusion models** — image, video, and audio generation (e.g. Qwen-Image, Wan2.2, FLUX)
- **Diffusion models** — image, video, and audio generation (e.g. MiniMax H3, Qwen-Image, Wan2.2, FLUX)
- **Robot-policy and action models** (e.g. GR00T-N1.7, DreamZero-DROID, InternVLA-A1, Cosmos3 action policy)
## Getting Started
+7 -3
View File
@@ -47,7 +47,7 @@ If no, check your shell running the ComfyUI process. There may be some error mes
This extension offers the following nodes based on the output modalities (at **ComfyUI sidebar -> Node Library**):
- **Generate Image** for text-to-image and image-to-image tasks
- **Generate Video** for text-to-video and image-to-video tasks
- **Generate Video** for text-to-video, first-frame/image-to-video, and reference-conditioned video
- **Multimodality Understanding** for multimodality-to-text and multimodality-to-audio tasks
- **TTS** and **TTS Voice Clone** for TTS tasks
@@ -105,7 +105,7 @@ You can configure per-stage sampling parameters for multi-stage models.
> [!TIP]
> The node automatically choose text-to-image or image-to-image API endpoints depending on whether you connect an image input or not.
### Text-to-video and image-to-video generation (e.g., Wan)
### Text-to-video and image-to-video generation (e.g., Wan, MiniMax-H3)
(Also available at **ComfyUI sidebar->Template->vLLM-Omni->vLLM-Omni Video Generation**)
@@ -117,7 +117,11 @@ You can configure per-stage sampling parameters for multi-stage models.
</p>
> [!TIP]
> The node automatically choose text-to-video or image-to-video API endpoints depending on whether you connect an image input or not.
> Connect a **frame** image for first-frame / image-to-video (e.g., Wan I2V, MiniMax-H3 FL2VA).
>
> For reference-conditioned generation (MiniMax-H3 Ref2VA), connect a **Video References** node instead.
>
> Do not use `frame` and `references` together. Task routing is automatic from which inputs you connect.
### TTS (e.g., Qwen TTS series)
+6
View File
@@ -15,11 +15,13 @@ from .comfyui_vllm_omni.nodes import (
VLLMOmniDiffusionSampling,
VLLMOmniGenerateImage,
VLLMOmniGenerateVideo,
VLLMOmniMiniMaxH3Params,
VLLMOmniQwenTTSParams,
VLLMOmniRemoteLoRA,
VLLMOmniSamplingParamsList,
VLLMOmniTTS,
VLLMOmniUnderstanding,
VLLMOmniVideoReferences,
VLLMOmniVoiceClone,
VLLMOmniWanParams,
)
@@ -32,6 +34,7 @@ NODE_CLASS_MAPPINGS = {
"VLLMOmniUnderstanding": VLLMOmniUnderstanding,
"VLLMOmniTTS": VLLMOmniTTS,
"VLLMOmniVoiceClone": VLLMOmniVoiceClone,
"VLLMOmniVideoReferences": VLLMOmniVideoReferences,
# === Params ===
"VLLMOmniARSampling": VLLMOmniARSampling,
"VLLMOmniDiffusionSampling": VLLMOmniDiffusionSampling,
@@ -39,6 +42,7 @@ NODE_CLASS_MAPPINGS = {
"VLLMOmniRemoteLoRA": VLLMOmniRemoteLoRA,
"VLLMOmniQwenTTSParams": VLLMOmniQwenTTSParams,
"VLLMOmniWanParams": VLLMOmniWanParams,
"VLLMOmniMiniMaxH3Params": VLLMOmniMiniMaxH3Params,
}
# A dictionary that contains the friendly/humanly readable titles for the nodes
@@ -49,6 +53,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"VLLMOmniUnderstanding": "Multimodality Understanding",
"VLLMOmniTTS": "TTS (Text to Speech)",
"VLLMOmniVoiceClone": "TTS Voice Cloning",
"VLLMOmniVideoReferences": "Video References",
# === Params ===
"VLLMOmniARSampling": "AR Sampling Params",
"VLLMOmniDiffusionSampling": "Diffusion Sampling Params",
@@ -56,6 +61,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"VLLMOmniRemoteLoRA": "LoRA",
"VLLMOmniQwenTTSParams": "Qwen TTS Params",
"VLLMOmniWanParams": "Wan Video Params",
"VLLMOmniMiniMaxH3Params": "MiniMax-H3 Video Params",
}
WEB_DIRECTORY = "./web"
@@ -10,7 +10,9 @@ from .utils.types import (
AudioFormat,
AutoregressionSamplingParams,
DiffusionSamplingParams,
MiniMaxH3ModelSpecificParams,
QwenTTSModelSpecificParams,
VideoReferences,
WanModelSpecificParams,
)
from .utils.validators import (
@@ -163,7 +165,8 @@ class VLLMOmniGenerateVideo(_VLLMOmniGenerateBase):
"num_frames": ("INT", {"default": 41, "min": 1}),
},
"optional": {
"image": ("IMAGE",),
"frame": ("IMAGE",),
"references": ("VIDEO_REFERENCES",),
"sampling_params": ("SAMPLING_PARAMS",),
"lora": ("REMOTE_LORA",),
"model_params": ("VIDEO_PARAMS",),
@@ -174,6 +177,15 @@ class VLLMOmniGenerateVideo(_VLLMOmniGenerateBase):
RETURN_NAMES = ("video",)
FUNCTION = "generate"
@classmethod
def VALIDATE_INPUTS(cls, url, model, frame=None, references=None, **_kwargs) -> str | Literal[True]:
base = super().VALIDATE_INPUTS(url, model)
if base is not True:
return base
if frame is not None and references is not None:
return "Provide only one of frame or references, not both."
return True
async def generate(
self,
url: str,
@@ -184,7 +196,8 @@ class VLLMOmniGenerateVideo(_VLLMOmniGenerateBase):
fps: int,
num_frames: int,
negative_prompt: str | None = None,
image: torch.Tensor | None = None,
frame: torch.Tensor | None = None,
references: dict | None = None,
sampling_params: dict | list[dict] | None = None,
model_params: dict | None = None,
lora: dict | None = None,
@@ -207,14 +220,16 @@ class VLLMOmniGenerateVideo(_VLLMOmniGenerateBase):
if sampling_params is not None:
sampling_params.pop("type", None) # internal fields
if model_params is not None:
model_params.pop("type", None) # internal fields
# model_params["type"] is also an internal field, but is used in api_client
# if model_params is not None:
# model_params.pop("type", None) # internal fields
client = VLLMOmniClient(url)
output = await client.generate_video(
model=model,
prompt=prompt,
image=image, # image present => i2v, absent => t2v
frame=frame, # frame present => fl2va / Wan I2V
references=references,
width=width,
height=height,
num_frames=num_frames,
@@ -734,3 +749,78 @@ class VLLMOmniWanParams:
def get_params(self, **kwargs):
return (WanModelSpecificParams(kwargs),)
class VLLMOmniMiniMaxH3Params:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"audio_flow_shift": (
"FLOAT",
{"default": 3.0, "min": 0.0, "max": 100.0, "step": 0.1},
),
"flow_shift": (
"FLOAT",
{"default": 12.0, "min": 0.0, "max": 100.0, "step": 0.1},
),
}
}
RETURN_TYPES = ("VIDEO_PARAMS",)
RETURN_NAMES = ("MiniMax-H3 video params",)
FUNCTION = "get_params"
CATEGORY = "vLLM-Omni/Video Params"
def get_params(self, **kwargs):
params = MiniMaxH3ModelSpecificParams(kwargs)
params["type"] = "minimax_h3"
return (params,)
class VLLMOmniVideoReferences:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {
"image_1": ("IMAGE",),
"image_2": ("IMAGE",),
"audio_1": ("AUDIO",),
"audio_2": ("AUDIO",),
"video_1": ("VIDEO",),
"video_2": ("VIDEO",),
},
}
RETURN_TYPES = ("VIDEO_REFERENCES",)
RETURN_NAMES = ("references",)
FUNCTION = "get_references"
CATEGORY = "vLLM-Omni"
def get_references(
self,
image_1: torch.Tensor | None = None,
image_2: torch.Tensor | None = None,
audio_1: AudioInput | None = None,
audio_2: AudioInput | None = None,
video_1: VideoInput | None = None,
video_2: VideoInput | None = None,
**kwargs,
):
if kwargs:
logger.info("Uncaught kwargs: %s", kwargs)
refs = VideoReferences()
if image_1 is not None:
refs["image_1"] = image_1
if image_2 is not None:
refs["image_2"] = image_2
if audio_1 is not None:
refs["audio_1"] = audio_1
if audio_2 is not None:
refs["audio_2"] = audio_2
if video_1 is not None:
refs["video_1"] = video_1
if video_2 is not None:
refs["video_2"] = video_2
return (refs,)
@@ -24,6 +24,7 @@ from .format import (
image_tensor_to_base64,
image_tensor_to_png_bytes,
video_to_base64,
video_to_bytes,
)
from .logger import get_logger, pretty_printer
from .models import lookup_model_spec
@@ -63,7 +64,11 @@ async def url_bytes(session: aiohttp.ClientSession, url: str, verb: str = "get",
class VLLMOmniClient:
def __init__(
self, base_url: str, timeout: float | None = None, poll_interval: float = 5.0, max_poll_duration: float = 60 * 5
self,
base_url: str,
timeout: float | None = None,
poll_interval: float = 5.0,
max_poll_duration: float = 60 * 30,
):
self.base_url = base_url
self.timeout = aiohttp.ClientTimeout(total=timeout)
@@ -261,12 +266,17 @@ class VLLMOmniClient:
num_frames: int,
fps: int,
negative_prompt: str | None = None,
image: torch.Tensor | None = None,
frame: torch.Tensor | None = None,
references: dict | None = None,
sampling_params: dict | None = None,
model_params: dict | None = None,
lora: dict | None = None,
**extra_body,
**extra_params,
) -> VideoInput:
if frame is not None and references is not None:
raise ValueError("Provide only one of frame or references, not both.")
# === regular payload fields ===
form = aiohttp.FormData()
form.add_field("model", model)
form.add_field("prompt", prompt)
@@ -279,23 +289,91 @@ class VLLMOmniClient:
if sampling_params is not None:
for k, v in sampling_params.items():
form.add_field(k, str(v))
if model_params is not None:
for k, v in model_params.items():
form.add_field(k, str(v))
if lora is not None:
form.add_field("lora", json.dumps(lora, ensure_ascii=False))
if extra_body:
form.add_field("extra_body", json.dumps(extra_body, ensure_ascii=False))
if image is not None:
# === multimodal inputs (first-last-frames, references, etc.) ===
input_reference_image: torch.Tensor | None = None
audio_reference: AudioInput | None = None
reference_videos: list[VideoInput] = []
video_task: str | None = None
if frame is not None:
input_reference_image = frame
video_task = "fl2va"
elif references is not None:
images = [references[k] for k in ("image_1", "image_2") if k in references and references[k] is not None]
audios = [references[k] for k in ("audio_1", "audio_2") if k in references and references[k] is not None]
videos = [references[k] for k in ("video_1", "video_2") if k in references and references[k] is not None]
if not images and not audios and not videos:
raise ValueError("references is empty; connect at least one image/audio/video.")
if videos:
if images or audios:
raise ValueError(
"Video references cannot be combined with image or audio references. "
"Connect only video_1/video_2 for multi-video Ref2VA."
)
reference_videos = videos
video_task = "ref2va"
elif len(images) == 1 and len(audios) == 1:
input_reference_image = images[0]
audio_reference = audios[0]
video_task = "ref2va"
else:
raise ValueError(
"Invalid references combination. Supported modes: "
"(1) one or more videos only, or (2) exactly one image and one audio."
)
else:
video_task = "t2va"
if input_reference_image is not None:
image_filename = "image.png" # Required for multipart form
form.add_field(
"input_reference",
image_tensor_to_png_bytes(image, image_filename),
image_tensor_to_png_bytes(input_reference_image, image_filename),
filename=image_filename,
content_type="image/png",
)
if audio_reference is not None:
form.add_field(
"audio_reference",
json.dumps({"audio_url": audio_to_base64(audio_reference)}, ensure_ascii=False),
)
for idx, video in enumerate(reference_videos, start=1):
video_filename = f"reference_{idx}.mp4"
form.add_field(
"input_references",
video_to_bytes(video, video_filename),
filename=video_filename,
content_type="video/mp4",
)
# === model specific params. Either use a specialized builder, or add flattened fields as-is ===
if model_params is not None:
model_params = dict(model_params)
model_params.pop("type", None)
spec, _ = lookup_model_spec(model)
params_builder = spec.get("params_builder") if spec else None
if params_builder is not None:
form_fields = params_builder(
model_params or {},
extra_params={**extra_params, "task": video_task},
)
for k, v in form_fields.items():
form.add_field(k, v if isinstance(v, str) else str(v))
else:
if model_params is not None:
for k, v in model_params.items():
form.add_field(k, str(v))
if extra_params:
form.add_field("extra_params", json.dumps(extra_params, ensure_ascii=False))
async with aiohttp.ClientSession(timeout=self.timeout) as session:
# Start the video generation job
url = f"{self.base_url}/videos"
@@ -1,7 +1,12 @@
import json
import re
from typing import Any
from .logger import get_logger
from .types import Modality, ModelMode, Spec
logger = get_logger(__name__)
def _bagel_payload_preprocessor(payload: dict) -> dict:
try:
@@ -29,6 +34,30 @@ def _qwen25_payload_preprocessor(payload: dict) -> dict:
return payload
def _minimaxh3_params_builder(
model_params: dict[str, Any],
*,
extra_params: dict[str, Any],
) -> dict[str, Any]:
"""Build multipart form fields for MiniMax-H3 from model_params + routed task."""
params = dict(model_params)
params.pop("type", None)
form_fields: dict[str, Any] = {}
merged_extra_params: dict[str, Any] = dict(extra_params or {})
if "flow_shift" in params:
form_fields["flow_shift"] = params.pop("flow_shift")
for key in ("audio_flow_shift",):
if key in params:
merged_extra_params[key] = params.pop(key)
if params:
logger.warning("Unused MiniMax-H3 model params ignored: %s", sorted(params))
if merged_extra_params:
form_fields["extra_params"] = json.dumps(merged_extra_params, ensure_ascii=False)
return form_fields
_MODEL_PIPELINE_SPECS: dict[str, Spec] = {
r"BAGEL-7B-MoT": {
"stages": [
@@ -71,6 +100,21 @@ _MODEL_PIPELINE_SPECS: dict[str, Spec] = {
}
],
},
r"MiniMax-H3(/FL2VA|/Ref2VA)?": {
"stages": ["diffusion"],
"modes": [
{
"mode": ModelMode.VIDEO_GENERATION,
"input_modalities": [
Modality.TEXT,
Modality.IMAGE,
Modality.VIDEO,
Modality.AUDIO,
],
}
],
"params_builder": _minimaxh3_params_builder,
},
}
# Convert dict keys to regex patterns
MODEL_PIPELINE_SPECS: dict[re.Pattern, Spec] = {}
@@ -80,12 +124,10 @@ del _MODEL_PIPELINE_SPECS
def lookup_model_spec(model: str) -> tuple[Spec | None, str | None]:
try:
last_component = model.rstrip("/").rsplit("/", 1)[-1]
except IndexError:
last_component = model
normalized = model.rstrip("/").lstrip("/")
lookup_key = normalized.split("/", 1)[-1]
for pattern, spec in MODEL_PIPELINE_SPECS.items():
if pattern.search(last_component):
if pattern.search(lookup_key):
return spec, pattern.pattern
return None, None
@@ -101,6 +143,9 @@ if __name__ == "__main__":
"Qwen/Qwen3-Omni-30B-A3B-Instruct",
"Custom/Path/UnknownModel-Instruct",
"Not/Matching/Anything",
"/path/to/MiniMax-H3/FL2VA",
"/path/to/MiniMax-H3/Ref2VA",
"MiniMaxAI/MiniMax-H3",
]
test_payload = {"messages": [{"role": "user", "content": "prompt"}]}
@@ -112,7 +157,13 @@ if __name__ == "__main__":
if preprocessor := spec.get("payload_preprocessor"):
result = preprocessor(test_payload)
print(f"✓ {path:<40} → {result}")
elif params_builder := spec.get("params_builder"):
result = params_builder(
{"audio_flow_shift": 3.0, "flow_shift": 12.0, "type": "minimax_h3"},
extra_params={"task": "t2va"},
)
print(f"✓ {path:<40} → {result}")
else:
print(f"✓ {path:<40} → No preprocessor")
print(f"✓ {path:<40} → No preprocessor/params_builder")
else:
print(f"✗ {path:<40} → No match")
@@ -1,12 +1,8 @@
from collections.abc import Callable
from enum import Enum, auto
from typing import (
Any,
Literal,
NotRequired,
TypeAlias,
TypedDict,
)
from typing import Any, Literal, TypeAlias
from typing_extensions import NotRequired, TypedDict
AudioFormat: TypeAlias = Literal["mp3", "opus", "aac", "flac", "wav", "pcm"]
@@ -27,6 +23,14 @@ class WanModelSpecificParams(dict):
pass
class MiniMaxH3ModelSpecificParams(dict):
pass
class VideoReferences(dict):
pass
class ModelMode(Enum):
IMAGE_GENERATION = auto()
VIDEO_GENERATION = auto()
@@ -47,9 +51,11 @@ class ModelModeSpec(TypedDict):
PayloadPreprocessor: TypeAlias = Callable[[dict[str, Any]], dict[str, Any]]
ParamsBuilder: TypeAlias = Callable[..., dict[str, Any]]
class Spec(TypedDict):
stages: list[Literal["diffusion", "autoregression"]]
modes: list[ModelModeSpec]
payload_preprocessor: NotRequired[PayloadPreprocessor]
params_builder: NotRequired[ParamsBuilder]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 161 KiB

@@ -1,513 +1 @@
{
"id": "3aea1d08-7de5-4997-ba71-b2f66ad72a21",
"revision": 0,
"last_node_id": 14,
"last_link_id": 28,
"nodes": [
{
"id": 10,
"type": "MarkdownNote",
"pos": [
227.99306819575278,
-231.24143306069843
],
"size": [
240.3326478922474,
136.3505820791881
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [],
"title": "Note: Task and Input",
"properties": {},
"widgets_values": [
"vLLM-Omni nodes are categorized based on the output modality. The \"Generate Video\" node supports both text-to-video generation and image-to-video generation. The node will create corresponding payload depending on whether an input image is present or not."
],
"color": "#432",
"bgcolor": "#000"
},
{
"id": 4,
"type": "LoadImage",
"pos": [
496.31859627609606,
-229.71277089860084
],
"size": [
270,
314
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"localized_name": "image",
"name": "image",
"type": "COMBO",
"widget": {
"name": "image"
},
"link": null
},
{
"localized_name": "choose file to upload",
"name": "upload",
"type": "IMAGEUPLOAD",
"widget": {
"name": "upload"
},
"link": null
}
],
"outputs": [
{
"localized_name": "IMAGE",
"name": "IMAGE",
"type": "IMAGE",
"links": [
25
]
},
{
"localized_name": "MASK",
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"cute-cat.jpg",
"image"
]
},
{
"id": 8,
"type": "VLLMOmniDiffusionSampling",
"pos": [
465.5140218220927,
148.80072646828987
],
"size": [
284.205078125,
226
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"localized_name": "n",
"name": "n",
"type": "INT",
"widget": {
"name": "n"
},
"link": null
},
{
"localized_name": "num_inference_steps",
"name": "num_inference_steps",
"type": "INT",
"widget": {
"name": "num_inference_steps"
},
"link": null
},
{
"localized_name": "guidance_scale",
"name": "guidance_scale",
"type": "FLOAT",
"widget": {
"name": "guidance_scale"
},
"link": null
},
{
"localized_name": "true_cfg_scale",
"name": "true_cfg_scale",
"type": "FLOAT",
"widget": {
"name": "true_cfg_scale"
},
"link": null
},
{
"localized_name": "vae_use_slicing",
"name": "vae_use_slicing",
"type": "BOOLEAN",
"widget": {
"name": "vae_use_slicing"
},
"link": null
},
{
"localized_name": "vae_use_tiling",
"name": "vae_use_tiling",
"type": "BOOLEAN",
"widget": {
"name": "vae_use_tiling"
},
"link": null
},
{
"localized_name": "seed",
"name": "seed",
"type": "INT",
"widget": {
"name": "seed"
},
"link": null
}
],
"outputs": [
{
"localized_name": "diffusion sampling params",
"name": "diffusion sampling params",
"type": "SAMPLING_PARAMS",
"links": [
27
]
}
],
"properties": {
"Node name for S&R": "VLLMOmniDiffusionSampling"
},
"widgets_values": [
1,
50,
1,
1,
false,
false,
1992,
"randomize"
]
},
{
"id": 14,
"type": "VLLMOmniWanParams",
"pos": [
518.6005521845747,
428.4455663719664
],
"size": [
270,
106
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"localized_name": "guidance_scale_2",
"name": "guidance_scale_2",
"type": "FLOAT",
"widget": {
"name": "guidance_scale_2"
},
"link": null
},
{
"localized_name": "boundary_ratio",
"name": "boundary_ratio",
"type": "FLOAT",
"widget": {
"name": "boundary_ratio"
},
"link": null
},
{
"localized_name": "flow_shift",
"name": "flow_shift",
"type": "FLOAT",
"widget": {
"name": "flow_shift"
},
"link": null
}
],
"outputs": [
{
"localized_name": "Wan video params",
"name": "Wan video params",
"type": "VIDEO_PARAMS",
"links": [
28
]
}
],
"properties": {
"Node name for S&R": "VLLMOmniWanParams"
},
"widgets_values": [
4,
0.875,
5
]
},
{
"id": 12,
"type": "VLLMOmniGenerateVideo",
"pos": [
827.2566336087867,
-73.77449831827545
],
"size": [
400,
346
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"localized_name": "image",
"name": "image",
"shape": 7,
"type": "IMAGE",
"link": 25
},
{
"localized_name": "sampling_params",
"name": "sampling_params",
"shape": 7,
"type": "SAMPLING_PARAMS",
"link": 27
},
{
"localized_name": "lora",
"name": "lora",
"shape": 7,
"type": "REMOTE_LORA",
"link": null
},
{
"localized_name": "model_params",
"name": "model_params",
"shape": 7,
"type": "VIDEO_PARAMS",
"link": 28
},
{
"localized_name": "url",
"name": "url",
"type": "STRING",
"widget": {
"name": "url"
},
"link": null
},
{
"localized_name": "model",
"name": "model",
"type": "STRING",
"widget": {
"name": "model"
},
"link": null
},
{
"localized_name": "prompt",
"name": "prompt",
"type": "STRING",
"widget": {
"name": "prompt"
},
"link": null
},
{
"localized_name": "negative_prompt",
"name": "negative_prompt",
"type": "STRING",
"widget": {
"name": "negative_prompt"
},
"link": null
},
{
"localized_name": "width",
"name": "width",
"type": "INT",
"widget": {
"name": "width"
},
"link": null
},
{
"localized_name": "height",
"name": "height",
"type": "INT",
"widget": {
"name": "height"
},
"link": null
},
{
"localized_name": "fps",
"name": "fps",
"type": "INT",
"widget": {
"name": "fps"
},
"link": null
},
{
"localized_name": "num_frames",
"name": "num_frames",
"type": "INT",
"widget": {
"name": "num_frames"
},
"link": null
}
],
"outputs": [
{
"localized_name": "video",
"name": "video",
"type": "VIDEO",
"links": [
26
]
}
],
"properties": {
"Node name for S&R": "VLLMOmniGenerateVideo"
},
"widgets_values": [
"http://localhost:8000/v1",
"Wan-AI/Wan2.2-TI2V-5B-Diffusers",
"Make the cat in the attached video yawning. Eye closed and mouth wide open. Keep the original realistic style.",
"Cartoonish",
900,
1200,
12,
41
]
},
{
"id": 13,
"type": "SaveVideo",
"pos": [
1257.5441369501657,
-44.12956394419863
],
"size": [
374,
372.34896826553796
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"localized_name": "video",
"name": "video",
"type": "VIDEO",
"link": 26
},
{
"localized_name": "filename_prefix",
"name": "filename_prefix",
"type": "STRING",
"widget": {
"name": "filename_prefix"
},
"link": null
},
{
"localized_name": "format",
"name": "format",
"type": "COMBO",
"widget": {
"name": "format"
},
"link": null
},
{
"localized_name": "codec",
"name": "codec",
"type": "COMBO",
"widget": {
"name": "codec"
},
"link": null
}
],
"outputs": [],
"properties": {},
"widgets_values": [
"video/ComfyUI",
"auto",
"auto"
]
}
],
"links": [
[
25,
4,
0,
12,
0,
"IMAGE"
],
[
26,
12,
0,
13,
0,
"VIDEO"
],
[
27,
8,
0,
12,
1,
"SAMPLING_PARAMS"
],
[
28,
14,
0,
12,
3,
"VIDEO_PARAMS"
]
],
"groups": [
{
"id": 1,
"title": "Input",
"bounding": [
213.1706010087147,
-313.20095750667554,
560.8246471437027,
407.4246532472182
],
"color": "#3f789e",
"font_size": 24,
"flags": {}
}
],
"config": {},
"extra": {
"workflowRendererVersion": "LG",
"ds": {
"scale": 1.1469075819486894,
"offset": [
101.7632950847089,
492.29121889347806
]
}
},
"version": 0.4
}
{"id":"3aea1d08-7de5-4997-ba71-b2f66ad72a21","revision":0,"last_node_id":24,"last_link_id":35,"nodes":[{"id":13,"type":"SaveVideo","pos":[1315.729153459605,-137.92038948394355],"size":[374,313.7692307692308],"flags":{},"order":9,"mode":0,"inputs":[{"localized_name":"video","name":"video","type":"VIDEO","link":32},{"localized_name":"filename_prefix","name":"filename_prefix","type":"STRING","widget":{"name":"filename_prefix"},"link":null},{"localized_name":"format","name":"format","type":"COMBO","widget":{"name":"format"},"link":null},{"localized_name":"codec","name":"codec","type":"COMFY_DYNAMICCOMBO_V3","widget":{"name":"codec"},"link":null}],"outputs":[{"localized_name":"video","name":"video","type":"VIDEO","links":null}],"properties":{},"widgets_values":["video/ComfyUI","auto","auto"]},{"id":10,"type":"MarkdownNote","pos":[183.74636797766794,-571.2529158046766],"size":[240.3326478922474,136.3505820791881],"flags":{},"order":0,"mode":0,"inputs":[],"outputs":[],"title":"Note: Task and Input","properties":{},"widgets_values":["vLLM-Omni nodes are categorized based on the output modality. The \"Generate Video\" node supports both *text-to-video*, *frame-to-video*, and *reference-to-video* generation. The node will create corresponding payload depending on whether an input image is present or not."],"color":"#432","bgcolor":"#000"},{"id":4,"type":"LoadImage","pos":[452.07189605801125,-569.7242536425791],"size":[270,314],"flags":{},"order":1,"mode":0,"inputs":[{"localized_name":"image","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"choose file to upload","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","links":[29]},{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"LoadImage"},"widgets_values":["rap.png","image"]},{"id":23,"type":"LoadImage","pos":[9.206110246057657,-7.6955291509170785],"size":[270,314],"flags":{},"order":2,"mode":0,"inputs":[{"localized_name":"image","name":"image","type":"COMBO","widget":{"name":"image"},"link":null},{"localized_name":"choose file to upload","name":"upload","type":"IMAGEUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"IMAGE","name":"IMAGE","type":"IMAGE","links":[34]},{"localized_name":"MASK","name":"MASK","type":"MASK","links":null}],"properties":{"Node name for S&R":"LoadImage"},"widgets_values":["white-cat.jpg","image"]},{"id":22,"type":"MarkdownNote","pos":[-9.783113411416666,-148.8790300038605],"size":[297.3012007349086,88],"flags":{},"order":3,"mode":0,"inputs":[],"outputs":[],"title":"Note: Reference to video (r2v)","properties":{},"widgets_values":["For r2v tasks, connect this Video Reference block to the main Generate Video block. Then disconnect the \"frame\" input above."],"color":"#432","bgcolor":"#000"},{"id":24,"type":"LoadAudio","pos":[317.9929742385805,-141.44821500065095],"size":[282.798828125,136],"flags":{},"order":4,"mode":0,"inputs":[{"localized_name":"audio","name":"audio","type":"COMBO","widget":{"name":"audio"},"link":null},{"localized_name":"audioUI","name":"audioUI","type":"AUDIO_UI","widget":{"name":"audioUI"},"link":null},{"localized_name":"choose file to upload","name":"upload","type":"AUDIOUPLOAD","widget":{"name":"upload"},"link":null}],"outputs":[{"localized_name":"AUDIO","name":"AUDIO","type":"AUDIO","links":[35]}],"properties":{"Node name for S&R":"LoadAudio"},"widgets_values":["nothing-beats-a-jet2-holiday.mp3",null,""]},{"id":21,"type":"VLLMOmniVideoReferences","pos":[376.6129172897595,105.41557277556292],"size":[156.9380859375,126],"flags":{},"order":7,"mode":0,"inputs":[{"localized_name":"image_1","name":"image_1","shape":7,"type":"IMAGE","link":34},{"localized_name":"image_2","name":"image_2","shape":7,"type":"IMAGE","link":null},{"localized_name":"audio_1","name":"audio_1","shape":7,"type":"AUDIO","link":35},{"localized_name":"audio_2","name":"audio_2","shape":7,"type":"AUDIO","link":null},{"localized_name":"video_1","name":"video_1","shape":7,"type":"VIDEO","link":null},{"localized_name":"video_2","name":"video_2","shape":7,"type":"VIDEO","link":null}],"outputs":[{"localized_name":"references","name":"references","type":"VIDEO_REFERENCES","links":null}],"properties":{"Node name for S&R":"VLLMOmniVideoReferences"},"widgets_values":[]},{"id":8,"type":"VLLMOmniDiffusionSampling","pos":[83.24620208113915,422.08543477542605],"size":[284.205078125,226],"flags":{},"order":5,"mode":0,"inputs":[{"localized_name":"n","name":"n","type":"INT","widget":{"name":"n"},"link":null},{"localized_name":"num_inference_steps","name":"num_inference_steps","type":"INT","widget":{"name":"num_inference_steps"},"link":null},{"localized_name":"guidance_scale","name":"guidance_scale","type":"FLOAT","widget":{"name":"guidance_scale"},"link":null},{"localized_name":"true_cfg_scale","name":"true_cfg_scale","type":"FLOAT","widget":{"name":"true_cfg_scLine truncated
+87
View File
@@ -0,0 +1,87 @@
# LVSA Long-Video Showcase
**Training-free block-sparse attention for long-video diffusion**, running on
vLLM-Omni via the public plugin entry points (no core changes). LVSA speeds up
extended-horizon generation and prevents the freeze/loop failure mode dense
attention exhibits beyond a model's training length — with no fine-tuning and no
weight changes.
Upstream: **[LongVideoSparseAttention](https://github.com/JiusiServe/LongVideoSparseAttention)**
(algorithm, all model adapters, full docs).
## Results
Wan 2.1 1.3B, single A100 80 GB, mean over 5 prompts (Dense vs LVSA-FlashInfer):
| Horizon | 1× | 2× | 3× | 4× | 5× | 6× |
|---|---|---|---|---|---|---|
| **Speedup** | 0.9× | 1.4× | 1.9× | 2.5× | 3.0× | **3.5×** |
| **VQeval composite** (Dense→LVSA) | 63→63 | 59→63 | 61→63 | 61→64 | 59→64 | 59→63 |
The speedup **grows with length** (LVSA is the dense regime at 1× by design, so
the win starts at 2×), and quality *improves* at extension — LVSA's rotating
keyframes prevent the looping/static output dense produces beyond its horizon
(VQeval loop-quality +27 to +34 at ≥3×). At long horizons dense **OOMs on 80 GB**
(HunyuanVideo ≥2×, Wan2.1-14B and Cosmos at 6×) where LVSA still generates.
→ Full sweep (5 models × 6 horizons, VQeval + VBench-Long) and the
quality-metric methodology:
**[benchmarks/](https://github.com/JiusiServe/LongVideoSparseAttention/tree/main/benchmarks)**.
## Quickstart
```bash
# 1. vLLM-Omni 0.22.0 (stable) + matching vLLM
pip install "vllm==0.22.0"
pip install --no-build-isolation \
"vllm-omni @ git+https://github.com/vllm-project/vllm-omni.git@v0.22.0"
# 2. LVSA core + plugin
git clone https://github.com/JiusiServe/LongVideoSparseAttention.git
( cd LongVideoSparseAttention && pip install -e . && pip install -e lvsa-vllm-omni/ )
# 3. this showcase's client dep
pip install requests
```
FlashInfer (used by the default `flashinfer` backend) **ships with vLLM** — step 1
already pulls the pinned `flashinfer-python` + `flashinfer-cubin`, so the fused
backend works with no extra install. Two optional extras:
```bash
# (optional) faster startup — prebuilt JIT cache, matched to your CUDA + flashinfer
CU=cu128 # match your CUDA: cu121 / cu124 / cu128 / …
FIVER=$(python -c "import importlib.metadata as m; print(m.version('flashinfer-python'))")
pip install --extra-index-url "https://flashinfer.ai/whl/${CU}" \
"flashinfer-jit-cache==${FIVER}+${CU}"
# (fallback) no FlashInfer in your environment? run the SDPA backend instead:
export LVSA_BACKEND=sdpa
```
```bash
# Serve an LVSA-enabled endpoint (Wan 2.1 1.3B at 2× horizon):
MODEL=/path/to/Wan2.1-T2V-1.3B-Diffusers MODEL_FAMILY=wan FRAMES=161 \
bash serve_lvsa.sh
# In another shell — generate:
python generate.py --frames 161 --height 480 --width 832 \
--prompt "A dog running through a sunlit forest." --out wan_lvsa.mp4
```
`serve_lvsa.sh` sets the LVSA env vars for the chosen `MODEL_FAMILY`
(`wan` / `hunyuan`). Wan and HunyuanVideo run through the LVSA **attention
backend** by default — it stays sparse even under sequence-parallel, unlike the
monkey-patch hooks.
## Configuration
The one knob you must get right is the model's training horizon
(`LVSA_REFERENCE_LATENT_FRAMES`: Wan = 21, HunyuanVideo = 33); `serve_lvsa.sh`
sets it per family. For the full environment-variable reference, the multi-GPU
support matrix, and tuning (`sparsity_scale`, rotating keyframes, non-standard
resolutions), see the upstream docs:
- **[lvsa-vllm-omni plugin reference](https://github.com/JiusiServe/LongVideoSparseAttention/blob/main/lvsa-vllm-omni/README.md)** — every `LVSA_*` env var
- **[docs/parallelism.md](https://github.com/JiusiServe/LongVideoSparseAttention/blob/main/docs/parallelism.md)** — TP / Ulysses / HSDP support per model
- **[docs/tuning.md](https://github.com/JiusiServe/LongVideoSparseAttention/blob/main/docs/tuning.md)** — picking knobs for your model and horizon
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env python
"""Generate a long video through an LVSA-enabled vLLM-Omni server.
A thin client over the Omni video API — start the server first with
``serve_lvsa.sh``. The sparse attention runs server-side; this just submits a
job and saves the result.
Uses the **asynchronous** endpoint (``POST /v1/videos`` → poll
``GET /v1/videos/{id}`` → download ``GET /v1/videos/{id}/content``) rather than
``POST /v1/videos/sync``. The sync endpoint is capped by a fixed server-side
timeout (``VIDEO_SYNC_TIMEOUT_S``, 600 s) and is documented as
"for benchmark and testing scenarios" — long videos (LVSA's use case) routinely
exceed it. The async job has no such cap.
python generate.py --frames 481 --height 480 --width 832 \
--prompt "A golden retriever running through a sunlit forest." \
--out dog_forest_lvsa.mp4
"""
import argparse
import os
import time
import requests
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--server", default=os.environ.get("OMNI_SERVER", "http://localhost:8000"))
ap.add_argument("--prompt", default="A dog running through a sunlit forest.")
ap.add_argument("--frames", type=int, default=161) # Wan 2x horizon
ap.add_argument("--height", type=int, default=480)
ap.add_argument("--width", type=int, default=832)
ap.add_argument("--fps", type=int, default=16)
ap.add_argument("--steps", type=int, default=50)
ap.add_argument("--guidance", type=float, default=5.0)
ap.add_argument("--out", default="lvsa_long_video.mp4")
ap.add_argument("--poll-interval", type=float, default=5.0, help="Seconds between status polls.")
ap.add_argument(
"--max-wait", type=float, default=7200.0, help="Give up if the job hasn't finished after this many seconds."
)
args = ap.parse_args()
base = args.server.rstrip("/")
form = {
"prompt": args.prompt,
"size": f"{args.width}x{args.height}",
"num_frames": str(args.frames),
"fps": str(args.fps),
"num_inference_steps": str(args.steps),
"guidance_scale": str(args.guidance),
}
# ── 1. submit the async job ──────────────────────────────────────────────
print(f"[lvsa-app] POST {base}/v1/videos {args.width}x{args.height} {args.frames}f steps={args.steps}")
resp = requests.post(f"{base}/v1/videos", data=form, timeout=120)
resp.raise_for_status()
job = resp.json()
vid = job["id"]
print(f"[lvsa-app] job {vid} ({job.get('status', '?')})")
# ── 2. poll until completed / failed ─────────────────────────────────────
deadline = time.time() + args.max_wait
last = None
while True:
if time.time() > deadline:
raise SystemExit(f"[lvsa-app] timed out after {args.max_wait:.0f}s (job {vid} still running)")
time.sleep(args.poll_interval)
r = requests.get(f"{base}/v1/videos/{vid}", timeout=60)
if r.status_code != 200:
# retrieve_video returns a non-200 JSON when the job has FAILED
raise SystemExit(f"[lvsa-app] job failed: {r.text}")
st = r.json()
status = st.get("status")
progress = st.get("progress", 0)
if (status, progress) != last:
print(f"[lvsa-app] {status} {progress}%")
last = (status, progress)
if status == "completed":
break
if status == "failed":
raise SystemExit(f"[lvsa-app] job failed: {st.get('error')}")
# ── 3. download the rendered mp4 ─────────────────────────────────────────
c = requests.get(f"{base}/v1/videos/{vid}/content", timeout=600)
c.raise_for_status()
with open(args.out, "wb") as f:
f.write(c.content)
print(f"[lvsa-app] saved {args.out}")
if __name__ == "__main__":
main()
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# Start an LVSA-enabled vLLM-Omni server for Wan or HunyuanVideo.
#
# LVSA is selected as the attention backend via --diffusion-attention-config (see
# below); the `LVSA_*` env vars only tune it. The `lvsa-vllm-omni` plugin registers
# itself through vLLM-Omni's `general_plugins` entry points — nothing in vLLM-Omni
# core is modified. Watch the log for "[LVSA] Geometry detected" to confirm sparse
# attention is active for your request geometry.
#
# MODEL=/path/to/Wan2.1-T2V-1.3B-Diffusers MODEL_FAMILY=wan FRAMES=161 bash serve_lvsa.sh
# MODEL=/path/to/HunyuanVideo-1.5-... MODEL_FAMILY=hunyuan FRAMES=193 bash serve_lvsa.sh
set -euo pipefail
MODEL=${MODEL:?set MODEL=/path/to/Wan-or-HunyuanVideo-Diffusers}
MODEL_FAMILY=${MODEL_FAMILY:-wan} # wan | hunyuan
PORT=${PORT:-8000}
FRAMES=${FRAMES:-161} # target horizon in frames
VAE_T=${VAE_T:-4} # VAE temporal compression (Wan/Hunyuan = 4)
BACKEND=${LVSA_BACKEND:-flashinfer} # flashinfer (fused, fastest) | sdpa
T_LAT=$(( (FRAMES - 1) / VAE_T + 1 ))
# Per-family training reference horizon (Wan train ref = 21, Hunyuan = 33).
case "$MODEL_FAMILY" in
wan) REFERENCE=${REFERENCE:-21} ;;
hunyuan) REFERENCE=${REFERENCE:-33} ;;
*) echo "MODEL_FAMILY must be 'wan' or 'hunyuan'"; exit 1 ;;
esac
export LVSA_BACKEND="$BACKEND"
export LVSA_TOTAL_LATENT_FRAMES="$T_LAT"
export LVSA_REFERENCE_LATENT_FRAMES="$REFERENCE"
export LVSA_ROTATE_KEYFRAMES=${LVSA_ROTATE_KEYFRAMES:-1}
echo "[lvsa-app] serving $MODEL ($MODEL_FAMILY) on :$PORT"
echo "[lvsa-app] LVSA backend=$BACKEND T_lat=$T_LAT (frames=$FRAMES) reference=$REFERENCE"
echo "[lvsa-app] confirm activation by grep '\\[LVSA\\] Geometry detected' in this log"
# vLLM-Omni 0.22 selects the LVSA attention backend per-role via
# --diffusion-attention-config. The backend is what drives sparse attention
# here; it engages under tensor-parallel too, unlike the LVSA_*_HOOK monkey-patch
# path (which falls back to dense under sequence-parallel), so we deliberately do
# NOT set a hook.
exec vllm serve "$MODEL" --omni --host 0.0.0.0 --port "$PORT" \
--diffusion-attention-config '{"per_role": {"self": {"backend": "LVSA"}}}' \
--init-timeout 1800 ${EXTRA_ARGS:-}
+8
View File
@@ -28,6 +28,14 @@ Benchmarks for GLM-Image performance across HuggingFace baseline, vLLM-Omni offl
- **Tasks**: text-to-image and image-to-image
- **Key metrics**: request/image throughput, latency percentiles, optional per-stage pipeline timings
### [LingBot-Video](lingbot_video/README.md) — Dense and MoE Parity
Manual cross-runtime validation for the dense LingBot-Video pipeline and the
LingBot-Video MoE transformer.
- **Dense pipeline**: decoded-video MAE, MSE, PSNR, latency, and optional steady-state timings
- **MoE transformer**: bitwise router, sparse-block, shared-expert, and full-transformer parity
### [Distributed](distributed/omni_connectors/README.md) — RDMA Connector Testing
RDMA environment setup and transfer tests for `MooncakeTransferEngineConnector`, including pytest-based single-node checks and manual cross-node benchmarks.
+16 -1
View File
@@ -28,6 +28,7 @@ class RequestFuncInput:
slo_ms: float | None = None
extra_body: dict[str, Any] = field(default_factory=dict)
image_paths: list[str] | None = None
video_paths: list[str] | None = None
request_id: str = field(default_factory=lambda: str(uuid.uuid4()))
default_bot_task: str | None = DEFAULT_EDITS_BOT_TASK
@@ -338,6 +339,11 @@ async def async_request_v1_videos(
form.add_field(k, str(v))
image_file = None
if input.image_paths and input.video_paths:
output.error = "Only one of image_paths or video_paths can be provided"
output.success = False
return output
if input.image_paths and len(input.image_paths) > 0:
image_path = input.image_paths[0]
image_file = open(image_path, "rb")
@@ -345,7 +351,16 @@ async def async_request_v1_videos(
"input_reference",
image_file,
filename=os.path.basename(image_path),
content_type="application/octet-stream",
content_type=_guess_mime_type(image_path),
)
elif input.video_paths and len(input.video_paths) > 0:
video_path = input.video_paths[0]
image_file = open(video_path, "rb")
form.add_field(
"input_reference",
image_file,
filename=os.path.basename(video_path),
content_type=_guess_mime_type(video_path),
)
job_id = None
@@ -73,6 +73,10 @@ Usage:
{"width":854,"height":480,"num_inference_steps":18,"num_frames":120,"fps":24,"weight":1}
]'
v2v:
python3 benchmarks/diffusion/diffusion_benchmark_serving.py \
--endpoint /v1/videos --dataset random --task v2v --num-prompts 1 \
--height 720 --width 1280 --fps 24 --num-frames 189 --num-inference-steps 35
"""
@@ -542,11 +546,17 @@ class TraceDataset(BaseDataset):
if not image_paths:
single = row.get("image_path")
image_paths = [single] if single else None
video_paths = row.get("video_paths")
if not video_paths:
single_video = row.get("video_path")
video_paths = [single_video] if single_video else None
if not image_paths and self.args.task in ["i2v", "i2i", "ti2v", "ti2i", "it2i"]:
raise ValueError(
f"Task {self.args.task} requires image input, but no image_path or image_paths found in trace row."
)
if not video_paths and self.args.task == "v2v":
raise ValueError("Task v2v requires video input, but no video_path or video_paths found in trace row.")
override_w = self.args.width
override_h = self.args.height
@@ -570,6 +580,7 @@ class TraceDataset(BaseDataset):
timestamp=timestamp,
slo_ms=slo_ms,
image_paths=image_paths,
video_paths=video_paths,
request_id=str(row.get("request_id")) if row.get("request_id") is not None else str(uuid.uuid4()),
)
@@ -589,6 +600,8 @@ class CustomDataset(BaseDataset):
- seed (optional): Random seed
- image_paths (optional): List of input image paths for i2i/i2v/ti2i tasks
- image_urls (optional): List of input image URLs (alternative to image_paths)
- video_paths (optional): List of input video paths for v2v tasks
- video_urls (optional): List of input video URLs (alternative to video_paths)
Example JSONL for ti2i:
{"prompt": "Add sunset lighting", "width": 1024, "height": 1024, "image_urls": ["https://example.com/image.jpg"]}
@@ -660,6 +673,42 @@ class CustomDataset(BaseDataset):
return None
def _resolve_video_paths(self, item: dict) -> list[str] | None:
if "video_paths" in item and item["video_paths"]:
paths = item["video_paths"]
if isinstance(paths, str):
paths = [paths]
valid_paths = []
for path in paths:
if os.path.exists(path):
valid_paths.append(path)
else:
raise ValueError(f"Video file not found: {path}")
return valid_paths if valid_paths else None
if "video_urls" in item and item["video_urls"]:
urls = item["video_urls"]
if isinstance(urls, str):
urls = [urls]
downloaded_paths = []
for url in urls:
try:
response = requests.get(url, timeout=30)
response.raise_for_status()
suffix = os.path.splitext(url)[1] or ".mp4"
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
tmp.write(response.content)
downloaded_paths.append(tmp.name)
except Exception as e:
raise ValueError(f"Failed to download video from {url}: {e}")
return downloaded_paths if downloaded_paths else None
return None
def __len__(self) -> int:
return len(self.data)
@@ -672,11 +721,22 @@ class CustomDataset(BaseDataset):
height = item.get("height", self.args.height)
num_inference_steps = item.get("num_inference_steps", self.args.num_inference_steps)
seed = item.get("seed", self.args.seed)
reserved_keys = {"prompt", "width", "height", "num_inference_steps", "seed", "image_paths", "image_urls"}
reserved_keys = {
"prompt",
"width",
"height",
"num_inference_steps",
"seed",
"image_paths",
"image_urls",
"video_paths",
"video_urls",
}
extra_body = {k: v for k, v in item.items() if k not in reserved_keys}
# Handle image paths/URLs
image_paths = self._resolve_image_paths(item)
video_paths = self._resolve_video_paths(item)
return RequestFuncInput(
prompt=prompt,
@@ -684,6 +744,7 @@ class CustomDataset(BaseDataset):
model=self.model,
seed=seed,
image_paths=image_paths,
video_paths=video_paths,
extra_body=extra_body,
width=width,
height=height,
@@ -737,6 +798,10 @@ class RandomDataset(BaseDataset):
self._random_image_path = self._generate_random_image_paths()
else:
self._random_image_path = None
if self.args.task == "v2v":
self._random_video_path = self._generate_random_video_paths()
else:
self._random_video_path = None
def __len__(self) -> int:
return self.num_prompts
@@ -756,13 +821,15 @@ class RandomDataset(BaseDataset):
if self._sampled_requests:
profile = self._sampled_requests[idx]
params.update(profile)
prompt = str(params.pop("prompt", f"Random prompt {idx} for benchmarking diffusion models"))
return RequestFuncInput(
prompt=f"Random prompt {idx} for benchmarking diffusion models",
prompt=prompt,
api_url=self.api_url,
model=self.model,
seed=self.args.seed,
extra_body=extra_body,
image_paths=self._random_image_path,
video_paths=self._random_video_path,
**params,
)
@@ -781,6 +848,35 @@ class RandomDataset(BaseDataset):
image_paths.append(image_path)
return image_paths
def _generate_random_video_paths(self) -> list[str]:
video_path = os.path.join(tempfile.gettempdir(), "diffusion_benchmark_random_video.mp4")
try:
import cv2
profile = self.random_request_config[0] if self.random_request_config else {}
width = int(self.args.width or profile.get("width") or 1280)
height = int(self.args.height or profile.get("height") or 720)
num_frames = int(self.args.num_frames or profile.get("num_frames") or 16)
fps = float(self.args.fps or profile.get("fps") or 8)
writer = cv2.VideoWriter(video_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
if not writer.isOpened():
raise RuntimeError("cv2.VideoWriter failed to open")
for frame_idx in range(num_frames):
frame = np.zeros((height, width, 3), dtype=np.uint8)
x = int((frame_idx / max(num_frames - 1, 1)) * max(width - 96, 1))
y = height // 2
frame[:, :, 0] = 24
frame[:, :, 1] = 32
frame[:, :, 2] = 48
frame[max(y - 36, 0) : min(y + 36, height), x : min(x + 96, width), :] = (64, 128, 220)
writer.write(frame)
writer.release()
return [video_path]
except Exception as e:
raise RuntimeError(
"Failed to generate synthetic v2v input video. Install opencv-python or provide a custom dataset."
) from e
def _compute_expected_latency_ms_from_base(req: RequestFuncInput, args, base_time_ms: float | None) -> float | None:
"""Compute expected execution time (ms) based on a base per-step-per-frame unit time.
@@ -1031,6 +1127,14 @@ def _save_generated_outputs(
if not out.success or not out.response_body:
continue
if isinstance(out.response_body, bytes):
fname = f"req_{idx:04d}.mp4"
fpath = os.path.join(save_dir, fname)
with open(fpath, "wb") as f:
f.write(out.response_body)
saved += 1
continue
media_urls: list[str] = []
# Chat-completions style: choices[*].message.content[*].image_url.url
@@ -1104,7 +1208,7 @@ def wait_for_service(base_url: str, timeout: int = 120) -> None:
def _default_endpoint_for_task(task: str) -> str:
if task in {"t2v", "i2v", "ti2v"}:
if task in {"t2v", "i2v", "ti2v", "v2v"}:
return "/v1/videos"
if task in {"i2i", "ti2i", "it2i"}:
return "/v1/images/edits"
@@ -1118,7 +1222,7 @@ async def benchmark(args):
if args.base_url is None:
args.base_url = f"http://{args.host}:{args.port}"
VIDEO_TASKS = {"t2v", "i2v", "ti2v"}
VIDEO_TASKS = {"t2v", "i2v", "ti2v", "v2v"}
IMAGE_TASKS = {"t2i", "i2i", "ti2i", "it2i"}
if args.task in VIDEO_TASKS:
@@ -1169,6 +1273,10 @@ async def benchmark(args):
if args.return_stage_metrics and args.endpoint in _STAGE_METRICS_ENDPOINTS:
for req in requests_list:
req.extra_body.setdefault(_RETURN_STAGE_METRICS_FIELD, True)
if args.extra_body:
extra_body = json.loads(args.extra_body)
for req in requests_list:
req.extra_body.update(extra_body)
if args.endpoint == "/v1/images/edits":
for req in requests_list:
@@ -1320,7 +1428,7 @@ if __name__ == "__main__":
"--task",
type=str,
default="t2v",
choices=["t2v", "i2v", "ti2v", "ti2i", "i2i", "it2i", "t2i"],
choices=["t2v", "i2v", "ti2v", "v2v", "ti2i", "i2i", "it2i", "t2i"],
help="Task type.",
)
parser.add_argument(
@@ -1435,6 +1543,12 @@ if __name__ == "__main__":
'{"width":768,"height":768,"num_inference_steps":20,"weight":0.85}]'
),
)
parser.add_argument(
"--extra-body",
type=str,
default=None,
help="JSON object merged into every generated request body/form.",
)
parser.add_argument(
"--num-input-images",
type=int,
@@ -201,6 +201,7 @@ async def main():
"input": prompt,
"voice": "default",
"stream": True,
"stream_format": "audio",
"response_format": "pcm",
"ref_audio": ref_audio_b64,
"ref_text": args.ref_text,
@@ -240,6 +241,7 @@ async def main():
"input": prompt,
"voice": args.voice_name,
"stream": True,
"stream_format": "audio",
"response_format": "pcm",
"ref_text": args.ref_text,
"max_new_tokens": 2048,
+62
View File
@@ -0,0 +1,62 @@
# LingBot-Video Benchmarks
These manual benchmarks compare the upstream LingBot-Video implementation with
vLLM-Omni. Run all commands from the repository root.
| Benchmark | Script | Purpose |
|-----------|--------|---------|
| Dense pipeline parity | `dense_pipeline_parity.py` | Compare generated videos and report MAE, MSE, PSNR, latency, and optional steady-state timings |
| MoE numerical parity | `moe_transformer_parity.py` | Check bitwise parity for the sparse MoE block and the full MoE transformer |
Both benchmarks require a local LingBot-Video checkout and local model files.
They do not run in CI.
## Dense pipeline parity
The dense benchmark launches the upstream Diffusers inference script and the
vLLM-Omni offline example with identical prompts and sampling parameters. It
then compares the decoded MP4 frames.
```bash
CUDA_VISIBLE_DEVICES=0 \
python benchmarks/lingbot_video/dense_pipeline_parity.py \
--model /path/to/lingbot-video-dense-1.3b \
--official-repo /path/to/lingbot-video \
--output-dir /tmp/lingbot_dense_parity
```
Use `--runs N` to additionally measure repeated in-process vLLM-Omni
requests. The video comparison reports MAE, MSE, and PSNR; it is an end-to-end
pipeline diagnostic rather than a bitwise transformer check.
## MoE numerical parity
The lightweight block comparison uses deterministic weights and inputs to
cover correction-bias routing, group-limited top-k, routed experts, FP32
scatter-weighted restore, padding masks, and the shared expert.
```bash
CUDA_VISIBLE_DEVICES=0 \
python benchmarks/lingbot_video/moe_transformer_parity.py \
--scope block \
--official-repo /path/to/lingbot-video \
--output-json /tmp/lingbot_moe_block_parity.json
```
The full comparison loads the upstream and vLLM-Omni 30B transformers
sequentially and compares their output tensors. It requires a CUDA device with
`torch._grouped_mm` and enough memory for one 30B BF16 transformer.
```bash
CUDA_VISIBLE_DEVICES=0 \
python benchmarks/lingbot_video/moe_transformer_parity.py \
--scope transformer \
--official-repo /path/to/lingbot-video \
--model /path/to/lingbot-video-moe-30b-a3b \
--output-json /tmp/lingbot_moe_transformer_parity.json
```
For the correctness oracle, the upstream transformer uses
`diffusers:_native_math` and vLLM-Omni uses
`TORCH_SDPA + SDPBackend.MATH`. The command exits with a nonzero status unless
the selected comparisons are bitwise equal.
@@ -0,0 +1,217 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from __future__ import annotations
import argparse
import json
import re
import statistics
import subprocess
import sys
import time
from pathlib import Path
from typing import Any
import imageio.v3 as iio
import numpy as np
import torch
from vllm_omni.diffusion.data import DiffusionParallelConfig
from vllm_omni.entrypoints.omni import Omni
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
from vllm_omni.platforms import current_omni_platform
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="LingBot dense parity and timing harness.")
parser.add_argument("--model", default="/home/models/lingbot-video-dense-1.3b")
parser.add_argument("--official-repo", default="/tmp/lingbot-video")
parser.add_argument("--output-dir", default="/tmp/lingbot_dense_parity")
parser.add_argument("--prompt", default="a robotic arm picks up a red block")
parser.add_argument("--height", type=int, default=192)
parser.add_argument("--width", type=int, default=320)
parser.add_argument("--num-frames", type=int, default=9)
parser.add_argument("--steps", type=int, default=2)
parser.add_argument("--guidance-scale", type=float, default=3.0)
parser.add_argument("--shift", type=float, default=3.0)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--fps", type=int, default=24)
parser.add_argument("--runs", type=int, default=0, help="Optional in-process steady-state native runs.")
return parser.parse_args()
def _run(cmd: list[str], cwd: Path | None = None) -> tuple[float, str]:
start = time.perf_counter()
proc = subprocess.run(cmd, cwd=cwd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
elapsed = time.perf_counter() - start
if proc.returncode != 0:
print(proc.stdout)
raise subprocess.CalledProcessError(proc.returncode, proc.args, output=proc.stdout)
return elapsed, proc.stdout
def _read_video(path: Path) -> np.ndarray:
frames = iio.imread(path, plugin="pyav")
if frames.dtype != np.float32:
frames = frames.astype(np.float32) / 255.0
return frames
def _compare(a: np.ndarray, b: np.ndarray) -> dict[str, Any]:
if a.shape != b.shape:
return {"shape_a": list(a.shape), "shape_b": list(b.shape), "shape_match": False}
diff = a - b
mse = float(np.mean(diff * diff))
mae = float(np.mean(np.abs(diff)))
psnr = float("inf") if mse == 0 else float(20.0 * np.log10(1.0 / np.sqrt(mse)))
return {
"shape": list(a.shape),
"shape_match": True,
"mae": mae,
"mse": mse,
"psnr": psnr,
}
def _extract_total_generation_seconds(log: str) -> float | None:
match = re.search(r"Total generation time:\s*([0-9.]+)\s*seconds", log)
return float(match.group(1)) if match else None
def _peak_memory_mb(output: Any) -> float:
result = output[0] if isinstance(output, list) and output else output
return float(getattr(result, "peak_memory_mb", 0.0) or 0.0)
def _benchmark_native_requests(args: argparse.Namespace) -> dict[str, Any]:
load_start = time.perf_counter()
omni = Omni(
model=args.model,
model_class_name="LingBotVideoPipeline",
flow_shift=args.shift,
parallel_config=DiffusionParallelConfig(),
)
load_seconds = time.perf_counter() - load_start
prompt = {"prompt": args.prompt}
latencies: list[float] = []
peak_mb = 0.0
for _ in range(args.runs):
generator = torch.Generator(device=current_omni_platform.device_type).manual_seed(args.seed)
sampling_params = OmniDiffusionSamplingParams(
height=args.height,
width=args.width,
num_frames=args.num_frames,
num_inference_steps=args.steps,
guidance_scale=args.guidance_scale,
generator=generator,
output_type="pt",
extra_args={"shift": args.shift},
)
start = time.perf_counter()
output = omni.generate(prompt, sampling_params)
latencies.append(time.perf_counter() - start)
peak_mb = max(peak_mb, _peak_memory_mb(output))
del output
omni.close()
return {
"load_seconds": load_seconds,
"run_seconds": latencies,
"mean_seconds": statistics.mean(latencies) if latencies else None,
"median_seconds": statistics.median(latencies) if latencies else None,
"min_seconds": min(latencies) if latencies else None,
"max_seconds": max(latencies) if latencies else None,
"peak_mb": peak_mb,
}
def main() -> None:
args = parse_args()
output_dir = Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
official_out = output_dir / "official_diffusers.mp4"
native_out = output_dir / "vllm_omni_native.mp4"
official_cmd = [
sys.executable,
str(Path(args.official_repo) / "scripts" / "inference.py"),
"--backend",
"diffusers",
"--model_dir",
args.model,
"--mode",
"t2v",
"--prompt",
args.prompt,
"--output",
str(official_out),
"--height",
str(args.height),
"--width",
str(args.width),
"--num_frames",
str(args.num_frames),
"--steps",
str(args.steps),
"--guidance_scale",
str(args.guidance_scale),
"--shift",
str(args.shift),
"--seed",
str(args.seed),
"--fps",
str(args.fps),
"--quiet_progress",
]
native_cmd = [
sys.executable,
"examples/offline_inference/text_to_video/text_to_video_lingbot.py",
"--model",
args.model,
"--prompt",
args.prompt,
"--output",
str(native_out),
"--height",
str(args.height),
"--width",
str(args.width),
"--num-frames",
str(args.num_frames),
"--num-inference-steps",
str(args.steps),
"--guidance-scale",
str(args.guidance_scale),
"--flow-shift",
str(args.shift),
"--seed",
str(args.seed),
"--fps",
str(args.fps),
]
official_time, official_log = _run(official_cmd, cwd=Path(args.official_repo))
native_time, native_log = _run(native_cmd, cwd=Path.cwd())
result = {
"official_seconds": official_time,
"native_process_seconds": native_time,
"native_request_seconds": _extract_total_generation_seconds(native_log),
"official_output": str(official_out),
"native_output": str(native_out),
"accuracy": _compare(_read_video(official_out), _read_video(native_out)),
"official_log_tail": official_log.splitlines()[-20:],
"native_log_tail": native_log.splitlines()[-20:],
}
if args.runs > 0:
result["native_steady_state"] = _benchmark_native_requests(args)
result_path = output_dir / "comparison.json"
result_path.write_text(json.dumps(result, indent=2, sort_keys=True) + "\n")
print(json.dumps(result, indent=2, sort_keys=True))
if __name__ == "__main__":
main()
@@ -0,0 +1,399 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""Reproduce LingBot-Video MoE block and transformer numerical parity."""
from __future__ import annotations
import argparse
import gc
import importlib
import json
import os
import sys
import time
from pathlib import Path
from typing import Any
import torch
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--scope",
choices=("block", "transformer", "all"),
default="block",
help="Run the lightweight sparse-block check, the real transformer check, or both.",
)
parser.add_argument(
"--official-repo",
type=Path,
required=True,
help="Local checkout of https://github.com/Robbyant/lingbot-video.",
)
parser.add_argument(
"--model",
default=None,
help="Local MoE checkpoint path or a checkpoint already present in the Hugging Face cache.",
)
parser.add_argument("--transformer-subfolder", default="transformer")
parser.add_argument("--output-json", type=Path, default=None)
parser.add_argument("--device", default="cuda")
parser.add_argument("--seed", type=int, default=42)
parser.add_argument("--num-frames", type=int, default=1)
parser.add_argument("--height", type=int, default=8)
parser.add_argument("--width", type=int, default=8)
parser.add_argument("--text-length", type=int, default=16)
return parser.parse_args()
def _load_official_module(official_repo: Path):
transformer_file = official_repo / "lingbot_video" / "transformer_lingbot_video.py"
if not transformer_file.is_file():
raise FileNotFoundError(f"Upstream transformer not found: {transformer_file}")
sys.path.insert(0, str(official_repo))
module = importlib.import_module("lingbot_video.transformer_lingbot_video")
module_path = Path(module.__file__).resolve()
if official_repo.resolve() not in module_path.parents:
raise RuntimeError(f"Imported LingBot module from {module_path}, not {official_repo.resolve()}")
return module
def _load_native_module():
return importlib.import_module("vllm_omni.diffusion.models.lingbot_video.lingbot_video_transformer")
def _tensor_metrics(actual: torch.Tensor, expected: torch.Tensor) -> dict[str, Any]:
actual_float = actual.float()
expected_float = expected.float()
diff = (actual_float - expected_float).abs()
denominator = actual_float.norm() * expected_float.norm()
cosine = (
float(torch.dot(actual_float.flatten(), expected_float.flatten()) / denominator)
if float(denominator) > 0
else 1.0
)
return {
"shape": list(actual.shape),
"equal": bool(torch.equal(actual, expected)),
"max_abs": float(diff.max()) if diff.numel() else 0.0,
"mean_abs": float(diff.mean()) if diff.numel() else 0.0,
"rmse": float(torch.sqrt(torch.mean(diff.square()))) if diff.numel() else 0.0,
"cosine": cosine,
"finite": bool(torch.isfinite(actual).all() and torch.isfinite(expected).all()),
}
def _initialize_block(module: torch.nn.Module, seed: int) -> None:
generator = torch.Generator(device="cpu").manual_seed(seed)
with torch.no_grad():
for parameter in module.parameters():
values = torch.randn(parameter.shape, generator=generator, dtype=torch.float32)
parameter.copy_((values * 0.02).to(parameter.dtype))
module.router.e_score_correction_bias.copy_(torch.tensor([0.9, 0.8, 1.0, 0.0, 0.7, 0.6, 0.5, 0.4]))
def _apply_padding(
scores: torch.Tensor,
padding_mask: torch.Tensor,
route_scale: float,
) -> torch.Tensor:
scores = scores * padding_mask.unsqueeze(-1).to(scores.dtype)
scores = scores / (scores.sum(dim=-1, keepdim=True) + 1e-9)
return scores * route_scale
def _run_block_parity(
official_module,
native_module,
*,
device: torch.device,
seed: int,
) -> dict[str, Any]:
if not hasattr(torch, "_grouped_mm"):
raise RuntimeError("The block parity check requires torch._grouped_mm.")
common = {
"hidden_size": 16,
"num_experts": 8,
"top_k": 2,
"moe_intermediate_size": 8,
"score_func": "sigmoid",
"norm_topk_prob": True,
"n_group": 4,
"topk_group": 1,
"routed_scaling_factor": 1.5,
"n_shared_experts": 1,
}
official = official_module.LingBotVideoSparseMoeBlock(
intermediate_size=32,
**common,
)
native = native_module.LingBotVideoSparseMoeBlock(**common)
_initialize_block(official, seed)
native.load_state_dict(official.state_dict(), strict=True)
official = official.to(device=device, dtype=torch.bfloat16).eval()
native = native.to(device=device, dtype=torch.bfloat16).eval()
generator = torch.Generator(device=device).manual_seed(seed)
hidden_states = torch.randn(
2,
5,
common["hidden_size"],
generator=generator,
device=device,
dtype=torch.bfloat16,
)
padding_mask = torch.tensor(
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
device=device,
dtype=torch.float32,
)
tokens = hidden_states.reshape(-1, common["hidden_size"])
with torch.inference_mode():
official_router = official.router(tokens)
official_indices, official_scores = official_router[:2]
native_indices, native_scores = native.router(tokens)
official_scores = _apply_padding(
official_scores,
padding_mask,
official.router.route_scale,
)
native_scores = _apply_padding(
native_scores,
padding_mask,
native.router.route_scale,
)
official_routed = official._run_selected_experts(
tokens,
official_scores,
official_indices,
)
native_routed = native._run_selected_experts(
tokens,
native_scores,
native_indices,
)
official_shared = official.shared_experts(hidden_states)
native_shared = native.shared_experts(hidden_states)
official_output = official(hidden_states, padding_mask=padding_mask)
native_output = native(hidden_states, padding_mask=padding_mask)
result = {
"router_indices_equal": bool(torch.equal(native_indices, official_indices)),
"router_scores": _tensor_metrics(native_scores, official_scores),
"routed_output": _tensor_metrics(native_routed, official_routed),
"shared_output": _tensor_metrics(native_shared, official_shared),
"final_output": _tensor_metrics(native_output, official_output),
}
result["exact"] = bool(
result["router_indices_equal"]
and result["router_scores"]["equal"]
and result["routed_output"]["equal"]
and result["shared_output"]["equal"]
and result["final_output"]["equal"]
)
return result
def _release_cuda() -> None:
gc.collect()
torch.accelerator.empty_cache()
torch.accelerator.synchronize()
def _make_transformer_inputs(
config,
args: argparse.Namespace,
) -> dict[str, torch.Tensor]:
generator = torch.Generator(device="cpu").manual_seed(args.seed)
hidden_states = torch.randn(
1,
int(config.in_channels),
args.num_frames,
args.height,
args.width,
generator=generator,
dtype=torch.float32,
).to(torch.bfloat16)
encoder_hidden_states = torch.randn(
1,
args.text_length,
int(config.text_dim),
generator=generator,
dtype=torch.float32,
).to(torch.bfloat16)
return {
"hidden_states": hidden_states,
"timestep": torch.tensor([500.0], dtype=torch.float32),
"encoder_hidden_states": encoder_hidden_states,
"encoder_attention_mask": torch.ones(1, args.text_length, dtype=torch.long),
}
def _load_transformer(
transformer_cls,
args: argparse.Namespace,
device: torch.device,
):
start = time.perf_counter()
model = transformer_cls.from_pretrained(
args.model,
subfolder=args.transformer_subfolder,
torch_dtype=torch.bfloat16,
local_files_only=True,
low_cpu_mem_usage=True,
)
model = model.to(device=device, dtype=torch.bfloat16).eval()
torch.accelerator.synchronize()
return model, time.perf_counter() - start
def _forward_transformer(
model,
inputs: dict[str, torch.Tensor],
device: torch.device,
attention_context,
) -> tuple[torch.Tensor, float, float]:
torch.accelerator.reset_peak_memory_stats(device)
gpu_inputs = {name: value.to(device) for name, value in inputs.items()}
start = time.perf_counter()
with torch.inference_mode(), attention_context:
output = model(**gpu_inputs, return_dict=False)[0]
torch.accelerator.synchronize()
elapsed = time.perf_counter() - start
peak_gib = torch.accelerator.max_memory_reserved(device) / (1024**3)
return output.cpu(), elapsed, peak_gib
def _run_transformer_parity(
official_module,
native_module,
*,
args: argparse.Namespace,
device: torch.device,
) -> dict[str, Any]:
if args.model is None:
raise ValueError("--model is required for transformer parity.")
from diffusers.models.attention_dispatch import attention_backend
from torch.nn.attention import SDPBackend, sdpa_kernel
from vllm_omni.diffusion.config import set_current_diffusion_config
from vllm_omni.diffusion.data import AttentionConfig, AttentionSpec, OmniDiffusionConfig
official, official_load = _load_transformer(
official_module.LingBotVideoTransformer3DModel,
args,
device,
)
inputs = _make_transformer_inputs(official.config, args)
official_output, official_forward, official_peak = _forward_transformer(
official,
inputs,
device,
attention_backend("_native_math"),
)
del official
_release_cuda()
native_config = OmniDiffusionConfig(
diffusion_attention_config=AttentionConfig(
default=AttentionSpec(backend="TORCH_SDPA"),
),
)
with set_current_diffusion_config(native_config):
native, native_load = _load_transformer(
native_module.LingBotVideoTransformer3DModel,
args,
device,
)
native_backend_prefs = {block.attn.attn.backend_pref for block in native.blocks}
if native_backend_prefs != {"TORCH_SDPA"}:
raise RuntimeError(
f"Failed to force the native transformer to TORCH_SDPA: resolved preferences were {native_backend_prefs}."
)
native_output, native_forward, native_peak = _forward_transformer(
native,
inputs,
device,
sdpa_kernel(SDPBackend.MATH),
)
del native
_release_cuda()
metrics = _tensor_metrics(native_output, official_output)
return {
"backends": {
"official": "diffusers:_native_math",
"native": "TORCH_SDPA+SDPBackend.MATH",
},
"official": {
"load_seconds": official_load,
"forward_seconds": official_forward,
"peak_reserved_gib": official_peak,
},
"native": {
"load_seconds": native_load,
"forward_seconds": native_forward,
"peak_reserved_gib": native_peak,
},
"output": metrics,
"exact": metrics["equal"],
}
def main() -> int:
args = parse_args()
device = torch.device(args.device)
if device.type != "cuda" or not torch.cuda.is_available():
raise RuntimeError("LingBot MoE parity requires an available CUDA device.")
os.environ["DIFFUSERS_ATTN_BACKEND"] = "_native_math"
os.environ["DIFFUSION_ATTENTION_BACKEND"] = "TORCH_SDPA"
os.environ["LINGBOT_MOE_EXPERT_BACKEND"] = "grouped_mm"
os.environ["LINGBOT_MOE_PAD_BACKEND"] = "loop"
os.environ["LINGBOT_MOE_REORDER_BACKEND"] = "sort"
os.environ["LINGBOT_MOE_RESTORE_BACKEND"] = "scatter"
official_module = _load_official_module(args.official_repo)
native_module = _load_native_module()
result: dict[str, Any] = {
"settings": {
"scope": args.scope,
"seed": args.seed,
"device": str(device),
"official_repo": str(args.official_repo.resolve()),
"model": args.model,
}
}
if args.scope in {"block", "all"}:
result["block"] = _run_block_parity(
official_module,
native_module,
device=device,
seed=args.seed,
)
if args.scope in {"transformer", "all"}:
result["transformer"] = _run_transformer_parity(
official_module,
native_module,
args=args,
device=device,
)
result["exact"] = all(section["exact"] for name, section in result.items() if name in {"block", "transformer"})
payload = json.dumps(result, indent=2, sort_keys=True)
print(payload)
if args.output_json is not None:
args.output_json.parent.mkdir(parents=True, exist_ok=True)
args.output_json.write_text(payload + "\n", encoding="utf-8")
return 0 if result["exact"] else 1
if __name__ == "__main__":
raise SystemExit(main())
+11
View File
@@ -80,6 +80,17 @@ models:
task_extra_body:
voice_clone: {}
# MOSS-TTS-Local-Transformer-v1.5: Qwen3 backbone + 1-layer GPT2-style local
# depth transformer (n_vq=12), paired with the 48 kHz stereo
# MOSS-Audio-Tokenizer-v2 codec. Same voice-clone request shape as the
# other MOSS-TTS variants.
OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5:
supported_tasks: [voice_clone]
backend: openai-audio-speech
endpoint: /v1/audio/speech
task_extra_body:
voice_clone: {}
# MOSS-TTSD synthesizes [S1]/[S2] dialogue. The seed-tts voice_clone dataset
# has single-speaker rows; bench piggybacks on it (both speakers share the
# same ref_audio). For real dialogue evaluation use the ttsd dataset.
+44 -9
View File
@@ -1,12 +1,26 @@
# Target vllm version: v0.21.0 (releases/v0.21.0 branch).
# The pinned VLLM_PRECOMPILED_WHEEL_COMMIT and VLLM_BASE_TAG below must
# be updated on every rebase to match the new upstream vllm commit/tag.
# Target vllm version: v0.26.0 (releases/v0.26.0 branch).
# Keep VLLM_BASE_TAG aligned with the target vLLM release on every rebase.
ARG VLLM_BASE_IMAGE=vllm/vllm-openai
ARG VLLM_BASE_TAG=v0.23.0
FROM ${VLLM_BASE_IMAGE}:${VLLM_BASE_TAG}
ARG APP_DIR=/workspace/vllm-omni
ARG VLLM_BASE_TAG=v0.26.0
# We use registry-based layer caching for the dependencies,
# where the tag is determined based on the hash of the contents
# of files like pyproject.toml, etc. The deps stage should have
# everything except the actual project dir, since that should not
# change much across branches.
FROM ${VLLM_BASE_IMAGE}:${VLLM_BASE_TAG} AS deps
# Keep APP_DIR outside /workspace so k8s Buildkite workspace mounts cannot
# shadow the editable install target (#5364). Docker WORKDIR creates /opt if
# needed.
ARG APP_DIR=/opt/vllm-omni
WORKDIR ${APP_DIR}
COPY . .
RUN ln -sf /usr/bin/python3 /usr/bin/python
# Placeholder package tree so editable install can register APP_DIR.
# The final stage COPY --link fills this directory with the real sources;
# the editable .pth / egg-link keeps resolving imports there — no PYTHONPATH.
RUN mkdir -p vllm_omni && touch vllm_omni/__init__.py
# Install system dependencies
RUN apt-get update && \
@@ -14,9 +28,30 @@ RUN apt-get update && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN uv pip install --system ".[dev]"
# Copy dependency related things first and install deps/
# We set the version str to 0.0.0 since it doesn't matter
# for CI
COPY pyproject.toml setup.py ./
COPY requirements/ requirements/
ENV SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0
# Editable install: deps + project metadata are cached in this layer, while
# the package itself is linked to APP_DIR (populated later by COPY --link).
# Do NOT use a non-editable install here — that copies an empty stub into
# site-packages and breaks ``import vllm_omni.entrypoints``.
RUN uv pip install --system -e ".[dev]"
# The final stage just copies the working dir on top of the
# dependencies image. This uses --link so that we can skip
# the image pull in Buildkite when we have a cache hit.
#
# IMPORTANT: Do not make any modifications that depend on the
# file system after the --link copy, otherwise we'd need to pull
# the heavy base image to build it. Editable install above already
# registered APP_DIR, so we must not re-pip-install after COPY.
FROM deps
ARG APP_DIR=/opt/vllm-omni
WORKDIR ${APP_DIR}
RUN ln -sf /usr/bin/python3 /usr/bin/python
COPY --link . .
ENTRYPOINT []
+37
View File
@@ -0,0 +1,37 @@
# NOTE: this is largely taken from vLLM
# Exclude .git for CI builds — version is set via SETUPTOOLS_SCM_PRETEND_VERSION
.git
.venv
/build
dist
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
.mypy_cache
# Distribution / packaging
.Python
/build/
cmake-build-*/
CMakeUserPresets.json
develop-eggs/
/dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
rust/target/
+1 -1
View File
@@ -1,4 +1,4 @@
ARG BASE_IMAGE=vllm/vllm-openai:v0.23.0
ARG BASE_IMAGE=vllm/vllm-openai:v0.26.0
FROM ${BASE_IMAGE}
ARG COMMON_WORKDIR=/app
+6 -2
View File
@@ -1,5 +1,5 @@
ARG VLLM_ASCEND_IMAGE=quay.io/ascend/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.18.0rc1
ARG VLLM_ASCEND_IMAGE=quay.io/atlas-ci/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.26.0
FROM ${VLLM_ASCEND_IMAGE}:${VLLM_ASCEND_TAG}
# WORKDIR /vllm-workspace/vllm
@@ -26,6 +26,10 @@ RUN export PIP_EXTRA_INDEX_URL=https://mirrors.huaweicloud.com/ascend/repos/pypi
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/Ascend/ascend-toolkit/latest/`uname -i`-linux/devlib && \
python3 -m pip install -v -e /vllm-workspace/vllm-omni/ --no-build-isolation
RUN python3 -m pip install -v --no-deps \
"stepaudio2-minicpmo>=0.1.1" \
"step-audio2>=1.0.0"
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENTRYPOINT []
+6 -2
View File
@@ -1,5 +1,5 @@
ARG VLLM_ASCEND_IMAGE=quay.io/ascend/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.18.0rc1-a3
ARG VLLM_ASCEND_IMAGE=quay.io/atlas-ci/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.26.0-a3
FROM ${VLLM_ASCEND_IMAGE}:${VLLM_ASCEND_TAG}
# WORKDIR /vllm-workspace/vllm
@@ -26,6 +26,10 @@ RUN export PIP_EXTRA_INDEX_URL=https://mirrors.huaweicloud.com/ascend/repos/pypi
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/Ascend/ascend-toolkit/latest/`uname -i`-linux/devlib && \
python3 -m pip install -v -e /vllm-workspace/vllm-omni/ --no-build-isolation
RUN python3 -m pip install -v --no-deps \
"stepaudio2-minicpmo>=0.1.1" \
"step-audio2>=1.0.0"
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENTRYPOINT []
+23 -2
View File
@@ -1,11 +1,13 @@
ARG VLLM_ASCEND_IMAGE=quay.io/ascend/vllm-ascend
ARG VLLM_ASCEND_TAG=nightly-main
ARG VLLM_ASCEND_IMAGE=quay.io/atlas-ci/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.26.0
FROM ${VLLM_ASCEND_IMAGE}:${VLLM_ASCEND_TAG}
ARG APP_DIR=/vllm-workspace/vllm-omni
WORKDIR ${APP_DIR}
COPY . .
RUN sed -i "s@^\(deb.*\)https\?://[a-z0-9.-]*\.ubuntu\.com@\1http://cache-service.nginx-pypi-cache.svc.cluster.local:8081@g" /etc/apt/sources.list
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ffmpeg \
@@ -33,8 +35,16 @@ RUN source /usr/local/Ascend/ascend-toolkit/set_env.sh && \
"psutil>=7.2.0" \
"soundfile>=0.13.1" \
"pyttsx3>=2.99" \
"opencc==1.4.1" \
"opencv-python>=4.12.0.88" \
"imageio[ffmpeg]>=0.6.0" \
"jiwer>=3.0.0" \
"zhon>=2.0.0" \
"zhconv>=1.4.2" \
"funasr>=1.0.0" \
"hyperpyyaml>=1.2.0" \
"onnx>=1.16.0" \
"librosa>=0.10.0" \
--index-url http://cache-service.nginx-pypi-cache.svc.cluster.local/pypi/simple \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60 && \
@@ -43,6 +53,17 @@ RUN source /usr/local/Ascend/ascend-toolkit/set_env.sh && \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60
# MiniCPM-o 4.5 Stage-2 vocoder assets: s3tokenizer plus flashcosyvoice, which
# is shipped by step-audio2. --no-deps keeps pip from replacing the Ascend torch
# build and from shadowing onnxruntime-cann with the vanilla onnxruntime wheel;
# the deps these two actually need are installed above.
RUN python3 -m pip install -v --no-deps \
"s3tokenizer>=0.3.0" \
"step-audio2>=1.0.0" \
--index-url http://cache-service.nginx-pypi-cache.svc.cluster.local/pypi/simple \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENTRYPOINT []
+24 -2
View File
@@ -1,11 +1,13 @@
ARG VLLM_ASCEND_IMAGE=quay.io/ascend/vllm-ascend
ARG VLLM_ASCEND_TAG=nightly-main-a3
ARG VLLM_ASCEND_IMAGE=quay.io/atlas-ci/vllm-ascend
ARG VLLM_ASCEND_TAG=v0.26.0-a3
FROM ${VLLM_ASCEND_IMAGE}:${VLLM_ASCEND_TAG}
ARG APP_DIR=/vllm-workspace/vllm-omni
WORKDIR ${APP_DIR}
COPY . .
RUN sed -i "s@^\(deb.*\)https\?://[a-z0-9.-]*\.ubuntu\.com@\1http://cache-service.nginx-pypi-cache.svc.cluster.local:8081@g" /etc/apt/sources.list
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ffmpeg \
@@ -33,8 +35,17 @@ RUN source /usr/local/Ascend/ascend-toolkit/set_env.sh && \
"psutil>=7.2.0" \
"soundfile>=0.13.1" \
"pyttsx3>=2.99" \
"opencc==1.4.1" \
"opencv-python>=4.12.0.88" \
"imageio[ffmpeg]>=0.6.0" \
"jiwer>=3.0.0" \
"zhon>=2.0.0" \
"zhconv>=1.4.2" \
"funasr>=1.0.0" \
"hyperpyyaml>=1.2.0" \
"onnx>=1.16.0" \
"librosa>=0.10.0" \
"torchmetrics>=1.9.0" \
--index-url http://cache-service.nginx-pypi-cache.svc.cluster.local/pypi/simple \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60 && \
@@ -43,6 +54,17 @@ RUN source /usr/local/Ascend/ascend-toolkit/set_env.sh && \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60
# MiniCPM-o 4.5 Stage-2 vocoder assets: s3tokenizer plus flashcosyvoice, which
# is shipped by step-audio2. --no-deps keeps pip from replacing the Ascend torch
# build and from shadowing onnxruntime-cann with the vanilla onnxruntime wheel;
# the deps these two actually need are installed above.
RUN python3 -m pip install -v --no-deps \
"s3tokenizer>=0.3.0" \
"step-audio2>=1.0.0" \
--index-url http://cache-service.nginx-pypi-cache.svc.cluster.local/pypi/simple \
--trusted-host cache-service.nginx-pypi-cache.svc.cluster.local \
--default-timeout=60
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENTRYPOINT []
+27 -4
View File
@@ -1,4 +1,4 @@
ARG BASE_IMAGE=vllm/vllm-openai-rocm:v0.23.0
ARG BASE_IMAGE=vllm/vllm-openai-rocm:v0.26.0
FROM ${BASE_IMAGE} AS base
# Declare a variable to know if we want to use the nightly build or the stable build.
@@ -10,14 +10,14 @@ FROM ${BASE_IMAGE} AS base
# we should swap over to use stable release ASAP.
# We should avoid relying on custom commits.
ARG USE_NIGHTLY_BUILD=0
ARG VLLM_VERSION_OR_COMMIT_HASH=89138b21cc246ae944c741d5c399c148e2b770ab
ARG VLLM_VERSION_OR_COMMIT_HASH=v0.26.0
ARG ARG_PYTORCH_ROCM_ARCH
ENV PYTORCH_ROCM_ARCH=${ARG_PYTORCH_ROCM_ARCH:-${PYTORCH_ROCM_ARCH}}
ARG COMMON_WORKDIR=/app
WORKDIR ${COMMON_WORKDIR}
# Step 1: Setup - Install system dependencies
# Step 1: Setup - Install system dependencies.
# Need to include ffmpeg because vllm rocm upstream docker image
# does not include it.
RUN apt-get update && \
@@ -38,6 +38,26 @@ RUN if [ "${USE_NIGHTLY_BUILD}" = "1" ]; then \
rm -rf vllm/.git; \
fi
# Build TorchCodec after any optional nightly vLLM reinstall so it targets the
# final torch/ROCm ABI. Keep this layer before COPY . so source changes do not
# invalidate the expensive native build. FFmpeg development headers are
# removed after the wheel is built.
COPY tools/install_torchcodec_rocm.sh /tmp/install_torchcodec_rocm.sh
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=cache,target=/root/.cache/torchcodec-wheels \
apt-get update && \
apt-get install -y --no-install-recommends \
pkg-config \
libavcodec-dev libavformat-dev libavutil-dev \
libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev && \
bash /tmp/install_torchcodec_rocm.sh && \
apt-get purge -y \
libavcodec-dev libavformat-dev libavutil-dev \
libswscale-dev libavdevice-dev libavfilter-dev libswresample-dev && \
rm -f /tmp/install_torchcodec_rocm.sh && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Step 3: Copy vllm-omni code and install without uv
RUN mkdir -p ${COMMON_WORKDIR}/vllm-omni
COPY . ${COMMON_WORKDIR}/vllm-omni
@@ -59,7 +79,10 @@ RUN printf '%s\n' \
' os._exit(_exit_code)' \
> ${COMMON_WORKDIR}/vllm-omni/conftest.py
RUN cd ${COMMON_WORKDIR}/vllm-omni && uv pip install --python "$(python3 -c 'import sys; print(sys.executable)')" --no-cache-dir ".[dev]" --no-build-isolation
RUN cd ${COMMON_WORKDIR}/vllm-omni && \
uv pip install --python "$(python3 -c 'import sys; print(sys.executable)')" \
--no-cache-dir ".[dev]" --no-build-isolation && \
python3 -c "from torchcodec.decoders import VideoDecoder"
RUN ln -sf /usr/bin/python3 /usr/bin/python
+7 -6
View File
@@ -88,7 +88,7 @@ ENV UV_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
ENV UV_INDEX_STRATEGY="unsafe-best-match"
ENV UV_LINK_MODE="copy"
ARG VLLM_VERSION=v0.23.0
ARG VLLM_VERSION=v0.26.0
RUN git clone -b ${VLLM_VERSION} https://github.com/vllm-project/vllm
WORKDIR /workspace/vllm
@@ -101,13 +101,15 @@ RUN --mount=type=cache,target=/root/.cache/uv \
source /opt/intel/oneapi/ccl/2021.15/env/vars.sh --force && \
export CMAKE_PREFIX_PATH="$(python3 -c 'import site; print(site.getsitepackages()[0])'):${CMAKE_PREFIX_PATH}"
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib/"
ENV LD_LIBRARY_PATH="/opt/intel/oneapi/ccl/2021.15/lib:$LD_LIBRARY_PATH:/usr/local/lib/"
ENV VLLM_TARGET_DEVICE=xpu
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install --no-build-isolation .
uv pip uninstall triton triton-xpu && \
uv pip install triton-xpu==3.7.1 && \
uv pip install --no-build-isolation --no-deps .
CMD ["/bin/bash"]
@@ -143,12 +145,11 @@ COPY . .
ENV VLLM_OMNI_TARGET_DEVICE=xpu
RUN --mount=type=cache,target=/root/.cache/uv \
echo "triton @ https://example.com/blocked" > /tmp/vllm_omni_constraints.txt && \
PIP_CONSTRAINT=/tmp/vllm_omni_constraints.txt \
uv pip install --no-build-isolation \
--extra-index-url https://mirrors.ustc.edu.cn/pypi/simple/ \
".[dev]" && \
uv pip uninstall oneccl oneccl-devel
uv pip uninstall triton oneccl oneccl-devel && \
uv pip install triton-xpu==3.7.1 --reinstall
FROM vllm-omni AS vllm-omni-openai
+9 -6
View File
@@ -16,15 +16,12 @@ nav:
- Examples:
- examples/README.md
- Offline Inference:
- BAGEL-7B-MoT: user_guide/examples/offline_inference/bagel.md
- GLM-Image Multistage End-to-End Inference: user_guide/examples/offline_inference/glm_image.md
- Helios Video Generation: user_guide/examples/offline_inference/helios.md
- HunyuanImage-3.0 Image-to-Text Inference: user_guide/examples/offline_inference/hunyuan_image3.md
- Image-To-Image: user_guide/examples/offline_inference/image_to_image.md
- Image-To-Video: user_guide/examples/offline_inference/image_to_video.md
- InternVLA-A1: user_guide/examples/offline_inference/internvla_a1.md
- MammothModa2-Preview: user_guide/examples/offline_inference/mammothmodal2_preview.md
- MiMo-Audio Offline Inference: user_guide/examples/offline_inference/mimo_audio.md
- MiMo-Audio: user_guide/examples/offline_inference/mimo_audio.md
- Qwen2.5-Omni: user_guide/examples/offline_inference/qwen2_5_omni.md
- Qwen3-Omni: user_guide/examples/offline_inference/qwen3_omni.md
- Text-To-Audio: user_guide/examples/offline_inference/text_to_audio.md
@@ -39,7 +36,7 @@ nav:
- GLM-Image Online Serving: user_guide/examples/online_serving/glm_image.md
- Image-To-Image: user_guide/examples/online_serving/image_to_image.md
- Image-To-Video: user_guide/examples/online_serving/image_to_video.md
- Online serving Example of vLLM-Omni for MiMo-Audio: user_guide/examples/online_serving/mimo_audio.md
- MiMo-Audio: user_guide/examples/online_serving/mimo_audio.md
- Qwen2.5-Omni: user_guide/examples/online_serving/qwen2_5_omni.md
- Qwen3-Omni: user_guide/examples/online_serving/qwen3_omni.md
- Text-To-Speech: user_guide/examples/online_serving/text_to_speech.md
@@ -57,6 +54,7 @@ nav:
- Diffusion Features:
- Overview: user_guide/diffusion_features.md
- Feature Compatibility: user_guide/feature_compatibility.md
- Regional Compilation: user_guide/diffusion/regional_compilation.md
- Cache Acceleration:
- TeaCache: user_guide/diffusion/cache_acceleration/teacache.md
- Cache-DiT: user_guide/diffusion/cache_acceleration/cache_dit.md
@@ -69,10 +67,11 @@ nav:
- Hybrid Sharded Data Parallel: user_guide/diffusion/parallelism/hsdp.md
- Sequence Parallel: user_guide/diffusion/parallelism/sequence_parallel.md
- Tensor Parallel: user_guide/diffusion/parallelism/tensor_parallel.md
- VAE Patch Parallel: user_guide/diffusion/parallelism/vae_patch_parallel.md
- VAE Parallelism: user_guide/diffusion/parallelism/vae_parallelism.md
- CPU Offloading: user_guide/diffusion/cpu_offload_diffusion.md
- LoRA: user_guide/diffusion/lora.md
- Custom Pipeline: features/custom_pipeline.md
- Request-Level Batching: user_guide/diffusion/request_batching.md
- Step Execution: user_guide/diffusion/step_execution.md
- Quantization:
- Overview: user_guide/quantization/overview.md
@@ -80,6 +79,7 @@ nav:
- Quantized KV Cache: user_guide/quantization/quantized_kvcache.md
- FP8 W8A8: user_guide/quantization/fp8.md
- Int8 W8A8: user_guide/quantization/int8.md
- BitsAndBytes W4: user_guide/quantization/bitsandbytes.md
- MXFP8 W8A8: user_guide/quantization/mxfp8.md
- MXFP4 W4A4: user_guide/quantization/mxfp4.md
- ModelOpt: user_guide/quantization/modelopt.md
@@ -116,9 +116,12 @@ nav:
- design/feature/hsdp.md
- design/feature/cache_dit.md
- design/feature/teacache.md
- design/feature/skip_softmax.md
- design/feature/async_chunk.md
- design/feature/omni_async_output_materialization.md
- design/feature/vae_parallel.md
- design/feature/diffusion_step_execution.md
- design/feature/diffusion_request_level_batching.md
- design/feature/diffusion_continuous_batching.md
- Module Design:
- design/module/ar_module.md
+7 -4
View File
@@ -28,9 +28,9 @@ Easy, fast, and cheap omni-modality model serving for everyone
[vLLM](https://github.com/vllm-project/vllm) was originally designed to support large language models for text-based autoregressive generation tasks. vLLM-Omni is a framework that extends its support for omni-modality model inference and serving:
- **Omni-modality**: Text, image, video, and audio data processing
- **Omni-modality**: Text, image, audio, video, and action data processing
- **Non-autoregressive Architectures**: extend the AR support of vLLM to Diffusion Transformers (DiT) and other parallel generation models
- **Heterogeneous outputs**: from traditional text generation to multimodal outputs
- **Heterogeneous outputs**: from traditional text generation to multimodal and action outputs
<p align="center">
<picture>
@@ -52,11 +52,14 @@ vLLM-Omni is flexible and easy to use with:
- Tensor, pipeline, data and expert parallelism support for distributed inference
- Streaming outputs
- OpenAI-compatible API server
- Full-duplex realtime serving with streaming audio input and output (experimental)
vLLM-Omni seamlessly supports most popular open-source models on HuggingFace, including:
- Omni-modality models (e.g. Qwen2.5-Omni, Qwen3-Omni)
- Multi-modality generation models (e.g. Qwen-Image)
- Omni-modality models (e.g. Qwen3-Omni, MiniCPM-o 4.5, Cosmos3, HunyuanImage, BAGEL)
- TTS models (e.g. Qwen3-TTS, VoxCPM2, Ming-Omni-TTS, CosyVoice3)
- Diffusion models — image, video, and audio generation (e.g. MiniMax H3, Qwen-Image, Wan2.2, FLUX)
- Robot-policy and action models (e.g. GR00T-N1.7, DreamZero-DROID, InternVLA-A1, Cosmos3 action policy)
For more information, checkout the following:
+7 -8
View File
@@ -46,23 +46,22 @@ Engine classes for offline and online inference.
- [vllm_omni.engine.PromptEmbedsPayload][]
- [vllm_omni.engine.arg_utils.OmniEngineArgs][]
- [vllm_omni.engine.async_omni_engine.AsyncOmniEngine][]
- [vllm_omni.engine.mm_outputs.MultimodalCompletionOutput][]
- [vllm_omni.engine.mm_outputs.MultimodalPayload][]
- [vllm_omni.engine.orchestrator.Orchestrator][]
- [vllm_omni.engine.orchestrator.OrchestratorRequestState][]
- [vllm_omni.engine.output_modality.OutputModality][]
- [vllm_omni.engine.output_modality.TensorAccumulationStrategy][]
- [vllm_omni.engine.output_processor.MultimodalOutputProcessor][]
- [vllm_omni.engine.output_processor.OmniRequestState][]
- [vllm_omni.engine.stage_engine_core_client.StageEngineCoreClient][]
- [vllm_omni.engine.stage_init_utils.StageMetadata][]
- [vllm_omni.engine.stage_init_utils.StartedLlmStage][]
- [vllm_omni.outputs.mm_outputs.MultimodalCompletionOutput][]
- [vllm_omni.outputs.mm_outputs.MultimodalPayload][]
- [vllm_omni.outputs.output_modality.OutputModality][]
- [vllm_omni.outputs.output_modality.TensorAccumulationStrategy][]
- [vllm_omni.outputs.output_processor.MultimodalOutputProcessor][]
- [vllm_omni.outputs.output_processor.OmniRequestState][]
## Core
Core scheduling and caching components.
- [vllm_omni.core.sched.omni_ar_scheduler.KVCacheTransferData][]
- [vllm_omni.core.sched.omni_ar_scheduler.OmniARScheduler][]
- [vllm_omni.core.sched.omni_generation_scheduler.OmniGenerationScheduler][]
- [vllm_omni.core.sched.output.OmniCachedRequestData][]
@@ -131,7 +130,7 @@ Worker classes and model runners for distributed inference.
- [vllm_omni.diffusion.worker.diffusion_worker.DiffusionWorker][]
- [vllm_omni.diffusion.worker.diffusion_worker.WorkerProc][]
- [vllm_omni.diffusion.worker.diffusion_worker.WorkerWrapperBase][]
- [vllm_omni.diffusion.worker.utils.DiffusionRequestState][]
- [vllm_omni.diffusion.worker.utils.StepRequestState][]
- [vllm_omni.diffusion.worker.utils.RunnerOutput][]
- [vllm_omni.platforms.npu.worker.npu_ar_model_runner.ExecuteModelState][]
- [vllm_omni.platforms.npu.worker.npu_ar_model_runner.NPUARModelRunner][]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 274 KiB

+4 -4
View File
@@ -18,11 +18,11 @@ Specify the port:
vllm serve Qwen/Qwen2.5-Omni-7B --omni --port 8091
```
If you have custom stage configs file, launch the server with command below
```bash
vllm serve Qwen/Qwen2.5-Omni-7B --omni --stage-configs-path /path/to/stage_configs_file
```
Load a custom deploy configuration with `--deploy-config`:
```bash
vllm serve Qwen/Qwen2.5-Omni-7B --omni --deploy-config /path/to/deploy_config.yaml
```
## bench
+5 -5
View File
@@ -2,7 +2,7 @@
The vllm bench command launches the vLLM-Omni benchmark to evaluate the performance of multimodal models.
## Notes
We currently only support using the "openai-chat-omni" and "openai-image-edits-omni" backend.
vLLM-Omni registers the `openai-chat-omni`, `openai-audio-speech`, `openai-image-edits-omni`, and `daily-omni` serving benchmark backends.
## Basic Parameter Description
You can use `vllm bench serve --omni --help=all` to get descriptions of all parameters. The commonly used parameters are described below:
@@ -10,7 +10,7 @@ You can use `vllm bench serve --omni --help=all` to get descriptions of all para
Enable Omni (multimodal) mode, supporting multimodal inputs and outputs such as images, videos, and audio.
- `--backend`
Specify the backend adapter as openai-chat-omni, using OpenAI Chat compatible API behavior as the protocol. Currently only openai-chat-omni is supported.
Specify the backend adapter. vLLM-Omni adds `openai-chat-omni`, `openai-audio-speech`, `openai-image-edits-omni`, and `daily-omni` to the upstream vLLM backend choices.
- `--model`
The model identifier to load, filled according to the models supported by vLLM-Omni.
@@ -55,7 +55,7 @@ You can use `vllm bench serve --omni --help=all` to get descriptions of all para
'Allowed metric names are "ttft", "tpot", "itl", "ttfc", "tpoc", "icl", '
'"tpop", "e2el", "audio_ttfp", "audio_rtf", "audio_duration". '
- `-print-stage`
- `--print-stage`
Print per-stage benchmark metrics for --omni serving when stage metrics are returned by the server. Disabled by default.
- `--save-result`
@@ -312,7 +312,7 @@ vllm bench serve \
--ignore-eos \
--percentile-metrics ttft,tpot,itl \
--random-output-len 2 \
--extra_body '{"modalities": ["text"]}'
--extra-body '{"modalities": ["text"]}'
```
If successful, you will see the following output:
@@ -390,7 +390,7 @@ vllm bench serve --omni \
--ignore-eos \
--percentile-metrics ttft,tpot,itl,e2el,audio_ttfp,audio_rtf,ttfc,tpoc,icl \
--random-output-len 900 \
--extra_body '{"modalities": ["text","audio"]}' \
--extra-body '{"modalities": ["text","audio"]}' \
--print-stage
```
+1 -3
View File
@@ -8,8 +8,6 @@ The stage-based CLI is designed for deployments that require launching each pipe
- For **migrated models** that utilize the bundled deployment YAML configurations located in
`vllm_omni/deploy/`, the `--deploy-config` flag is only required to override the default configuration. By default, executing `vllm serve MODEL --omni ...`
automatically loads the bundled deployment configuration.
- For **legacy models** utilizing configuration files located in
`vllm_omni/model_executor/stage_configs/`, the `--stage-configs-path` parameter remains mandatory.
Example: Initializing Stage 0 (Orchestrator and API Server):
The commands below show a common device mapping where Stage 0 uses GPU 0 and
@@ -33,7 +31,7 @@ CUDA_VISIBLE_DEVICES=1 vllm serve Qwen/Qwen3-Omni-30B-A3B-Instruct --omni \
--omni-master-port 26000
```
When utilizing a custom deployment YAML based on the new schema, append `--deploy-config /path/to/override.yaml` to each command execution. Conversely, for legacy models, substitute this parameter with `--stage-configs-path /path/to/stage_configs.yaml`.
When utilizing a custom deployment YAML, append `--deploy-config /path/to/override.yaml` to each command execution.
In the standard execution paradigm, the `--stage-overrides` argument is utilized to apply stage-specific configurations from a single CLI command.
However, under the **stage-based CLI** paradigm, where each process strictly encapsulates a single stage, it is recommended to specify tuning parameters directly via discrete command-line flags for the respective stage, rather than constructing a composite `--stage-overrides` JSON string.
+7 -2
View File
@@ -33,16 +33,20 @@ Lead maintainers are responsible for the overall direction and strategy of the p
Committers have write access and merge rights. They typically have deep expertise in specific areas of this project and shepherd the community contributions:
- [@alex-jw-brooks](https://github.com/alex-jw-brooks): Frontend, Configuration, and Entrypoint Support
- [@amy-why-3459](https://github.com/amy-why-3459): Omni Modality Model and World Model Support
- [@david6666666](https://github.com/david6666666): Quantization and Community Relationship
- [@gcanlin](https://github.com/gcanlin): Hardware plugin and NPU integration
- [@gcanlin](https://github.com/gcanlin): Hardware plugin, NPU integration, and TTS Model Support
- [@Isotr0py](https://github.com/Isotr0py): Diffusion and Quantization
- [@linyueqian](https://github.com/linyueqian): TTS and Omni Support
- [@lishunyang12](https://github.com/lishunyang12): Quantization and Configuration
- [@princepride](https://github.com/princepride): Diffusion and Omni Support
- [@RuixiangMa](https://github.com/RuixiangMa): Diffusion models, parallel, cache, and docs
- [@SamitHuang](https://github.com/SamitHuang): RL, Diffusion, and cache
- [@Sy0307](https://github.com/Sy0307): TTS Model and AR Engine Support
- [@tzhouam](https://github.com/tzhouam): Engine and New Model Support
- [@wtomin](https://github.com/wtomin): Diffusion models, parallel, and docs
- [@xuechendi](https://github.com/xuechendi): Diffusion and Intel GPU Support
- [@ZeldaHuang](https://github.com/ZeldaHuang): Omni Support
- [@ZJY0516](https://github.com/ZJY0516): Diffusion attention backend, kernel fusion, and CustomOp
- [@yuanheng-zhao](https://github.com/yuanheng-zhao): Diffusion cache, offload, and Omni Support
@@ -53,7 +57,7 @@ This section breaks down diffusion-related responsibilities. If you have PRs tou
### Runtime-related
- Diffusion models: @RuixiangMa, @wtomin
- Diffusion models: @RuixiangMa, @wtomin, @xuechendi
### Optimization
@@ -61,6 +65,7 @@ This section breaks down diffusion-related responsibilities. If you have PRs tou
- Attention backend: @ZJY0516
- Cache: @yuanheng-zhao, @RuixiangMa, @SamitHuang
- Offload: @yuanheng-zhao
- Intel GPU support: @xuechendi
- Quantization: @lishunyang12, @david6666666
- Kernel fusion / communication-computation: @ZJY0516
+1 -1
View File
@@ -2,7 +2,7 @@
This section lists the most common options for running vLLM-Omni.
For options within a vLLM Engine. Please refer to [vLLM Configuration](https://docs.vllm.ai/en/v0.16.0/configuration/index.html)
For options within a vLLM Engine, please refer to the [vLLM 0.26 configuration guide](https://docs.vllm.ai/en/v0.26.0/configuration/index.html).
Currently, the main options are maintained by stage configs for each model.
+224
View File
@@ -0,0 +1,224 @@
# Composable parallel strategies
In vLLM-Omni, the `composable_parallel` system layers a declarative *parallel strategy* on top of the existing stage configs. A strategy YAML maps each pipeline stage (by its `model_stage` name) to a stack of axis declarations — one per parallelism dimension — that the engine translates into per-stage parallel sizing (`tensor_parallel_size`, `data_parallel_size`, `pipeline_parallel_size`, expert-parallel toggle, replica count) and, when relevant, an orchestrator-wide load-balancer policy.
Strategies are intentionally narrow: each one only writes the axes it declares, leaving every other engine arg untouched. This makes a strategy file a small, reusable overlay you can swap independently of the deploy YAML (see `configuration/stage_configs.md`).
!!! note
Composable parallel is **opt-in**. Passing `--strategy-config <path/to/strategy.yaml>` overlays the derived sizing onto the registry-merged stages *before* any CLI overrides are applied. When `--strategy-config` is omitted, stages remain exactly as their deploy YAML produces them.
## Top-level schema reference
A strategy file has a single top-level mapping, `strategies`, keyed by the `model_stage` name of each stage you want to overlay. Each value is a list of axis declarations (see [StrategySpec fields](#strategyspec-fields) below).
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `strategies` | `dict[str, list]` | required | — | Maps `model_stage` name (e.g. `thinker`, `talker`, `code2wav`, `dit`) to a list of axis declarations. The key MUST be the stage name, not the integer `stage_id`. See `vllm_omni/config/composable_parallel/strategy_loader.py`. |
### StrategySpec fields
Each entry in a stage's list becomes one `StrategySpec` (see `vllm_omni/config/composable_parallel/spec.py`). The loader fills in `routing` and `aggregation` from per-kind defaults, so the file stays compact.
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `axis` | str | required | — | Mesh-axis kind. One of `tp`, `dp`, `pp`, `ep`, `stage_replica` (wired today) or `sp_ulysses`, `sp_ring`, `cfg`, `vae_pp`, `hsdp`, `stage_pp`, `cp` (reserved; declaring one raises `AxisTranslationError` at translate time). See `MeshAxisKind` in `vllm_omni/config/composable_parallel/spec.py`. |
| `size` | int | required | — | Axis degree. Must be `> 0`. |
| `routing` | str | optional | per-kind default | Stateless routing policy. Accepted only for `dp` / `stage_replica`; other kinds reject it. Values: `random`, `round_robin`, `least_queue`. (`hash` is recognised but currently raises `NotImplementedError`.) See `RouteByStage` in `vllm_omni/config/composable_parallel/routing.py`. |
| `l1_owner` | str | optional | per-kind default | Overrides which layer owns request routing for this axis. `engine` for `tp`/`dp`/`pp`/`ep`, `delegated` for `stage_replica`. Recorded into `shard_extension`. |
| `name` | str | optional | axis kind | Human-readable label for this spec, used in error messages. |
Two additional `StrategySpec` slots — `layer_hook_specs` and `kernel_specs` — let advanced authors bind layer-walker hook IDs (`LayerHookSpec`) or kernel IDs (`KernelSpec`) onto an axis. These are not exposed by the YAML loader today and are intended for programmatic construction. See `vllm_omni/config/composable_parallel/spec.py` for the dataclasses.
### CLI flags
| Flag | Description |
|------|-------------|
| `--strategy-config PATH` | Path to a `strategy.yaml`. Only takes effect on registry-based deploy paths (`--deploy-config` or the bundled default deploy YAML). Its derived sizing is overlaid onto the merged stages *before* CLI overrides. |
| `--omni-lb-policy POLICY` | Orchestrator-wide load-balancer policy. Strategy-derived from any `stage_replica` axis; an explicit CLI value wins and must match the derived one or `AsyncOmniEngine` raises `Conflicting load-balancer policy` at construction. |
## Sub-schemas
### `axis`
The set of recognised axis kinds is the `MeshAxisKind` enum in `vllm_omni/config/composable_parallel/spec.py`:
```yaml
# Translatable today (see `_SUPPORTED_KINDS` in translator.py).
axis: tp # tensor parallel — sets tensor_parallel_size
axis: dp # engine data parallel — sets data_parallel_size (vLLM's intra-engine DP LB)
axis: pp # pipeline parallel — sets pipeline_parallel_size
axis: ep # dense expert parallel — sets enable_expert_parallel=True; size must equal tp*dp
axis: stage_replica # omni-coordinator-level replica fan-out — sets num_replicas + omni_lb_policy
# Reserved (raise AxisTranslationError today; declared in the type system for forward compat).
axis: sp_ulysses
axis: sp_ring
axis: cfg
axis: vae_pp
axis: hsdp
axis: stage_pp
axis: cp
```
### `routing`
The full closed hierarchy lives in `vllm_omni/config/composable_parallel/routing.py` (`Broadcast`, `PartitionByHash`, `ShardSequence`, `ShardSpatial`, `RouteByExpert`, `PipelineMicrobatch`, `DuplicateWithCondTag`, `RouteByStage`). For YAML authors only `RouteByStage` is exposed as a `routing:` string, and only for `dp` / `stage_replica` axes (other axes have fixed routing — `tp`/`ep` broadcast, `pp` microbatch). Recognised policies:
```yaml
routing: random # uniform-random across replicas/DP ranks
routing: round_robin # cycle through replicas/DP ranks (the default for dp/stage_replica)
routing: least_queue # send to the replica with the smallest backlog
# routing: hash # recognised but raises NotImplementedError; no key-stable balancer yet
```
### `aggregation`
Aggregation is filled in automatically by the loader (`_default_aggregation` in `vllm_omni/config/composable_parallel/strategy_loader.py`) from the axis kind, so users do not author it:
| Axis kind | Aggregation pattern |
|-----------|---------------------|
| `tp`, `ep` | `TakeRank` (all ranks agree; pick one) |
| `dp`, ep (in some flows) | `Union` (disjoint replica results) |
| `pp` | `StitchPipeline` |
| `stage_replica` | `FanInByStage` |
Full pattern hierarchy: `TakeRank`, `Union`, `GatherDim`, `AllGather`, `StitchSpatial`, `StitchPipeline`, `Combine`, `FanInByStage` (see `vllm_omni/config/composable_parallel/aggregation.py`).
## Precedence
From highest to lowest, when the same axis is touched by multiple layers:
1. **CLI overrides** (`--tensor-parallel-size`, `--stage-overrides`, `--omni-lb-policy`, etc.). A CLI value always wins; a warning is emitted whenever it overrides a strategy-declared axis (see `_reconcile_strategy_with_cli` in `vllm_omni/config/config_factory.py`).
2. **Strategy YAML** (`--strategy-config`). Derived sizing is written onto the merged stages with *conflict-on-explicit* semantics — if the deploy YAML already set a value to something different, application raises `StrategyApplyError`.
3. **Deploy YAML** (`--deploy-config` or the bundled `vllm_omni/deploy/<model_type>.yaml`).
4. **Parser defaults.**
After CLI overrides land, the device-layout guard re-runs (`check_device_layout`, called from `_reconcile_strategy_with_cli`) against the *effective* `tp * dp * pp * num_replicas` and the resolved `devices` string, so a `devices` value passed through `--stage-overrides` or a `--tensor-parallel-size` value that conflicts with the strategy's world size cannot slip past the pre-spawn check.
## Worked example
### Example 1 — `strategy_tp2.yaml`
Shard the `thinker` stage with TP=2 on top of the bundled Qwen2.5-Omni deploy YAML. Routing is fixed (broadcast) for TP, so no `routing:` field is needed.
```yaml
# examples/offline_inference/qwen2_5_omni/strategy_tp2.yaml
strategies:
thinker:
- axis: tp
size: 2
```
Launch:
```bash
python3 end2end.py --query-type text --num-prompts 6 \
--strategy-config strategy_tp2.yaml \
--stage-overrides '{"0": {"devices": "0,1"}, "1": {"devices": "2"}, "2": {"devices": "2"}}'
```
Effective `OmniParallelConfig` per stage after the overlay (see `OmniParallelConfig` in `vllm_omni/config/composable_parallel/translator.py`):
| Stage (`model_stage`) | `tensor_parallel_size` | `data_parallel_size` | `pipeline_parallel_size` | `stage_replica_size` | `omni_lb_policy` |
|-----------------------|------------------------|----------------------|--------------------------|----------------------|------------------|
| `thinker` | **2** (from strategy) | 1 | 1 | 1 | — |
| `talker` | 1 | 1 | 1 | 1 | — |
| `code2wav` | 1 | 1 | 1 | 1 | — |
### Example 2 — `strategy_stage_replica.yaml`
Replicate the `thinker` stage across two independent engines and let omni's StagePool round-robin requests across them.
```yaml
# examples/offline_inference/qwen2_5_omni/strategy_stage_replica.yaml
strategies:
thinker:
- axis: stage_replica
size: 2
routing: round_robin
```
Launch:
```bash
python3 end2end.py --query-type text --num-prompts 6 \
--strategy-config strategy_stage_replica.yaml \
--stage-overrides '{"0": {"devices": "0,1"}, "1": {"devices": "2"}, "2": {"devices": "2"}}'
```
Effective per-stage config and the derived orchestrator knob:
| Stage (`model_stage`) | `tensor_parallel_size` | `stage_replica_size` | `omni_lb_policy` (derived) |
|-----------------------|------------------------|----------------------|----------------------------|
| `thinker` | 1 | **2** | **`round-robin`** |
| `talker` | 1 | 1 | — |
| `code2wav` | 1 | 1 | — |
The derived `omni_lb_policy = round-robin` is **not** written into any stage's engine args. Instead it is surfaced on `StrategyApplyResult.omni_lb_policy` and applied once at orchestrator construction by `AsyncOmniEngine._apply_strategy_lb_policy` (see `vllm_omni/engine/async_omni_engine.py`, lines 1107–1134). If you also pass `--omni-lb-policy round-robin` the values must match; passing a different value raises `Conflicting load-balancer policy`.
## Per-field deep-dive
### `name`
Default: the axis kind (e.g. `"tp"`).
Human-readable label that appears in `AxisTranslationError` and `StrategyApplyError` messages. Set it to disambiguate two stages declaring the same axis kind when scanning logs.
### `mesh_axis` (`axis` + `size`)
Default: no default — both fields are required.
`axis` chooses the parallelism dimension; `size` is its degree. Five kinds are wired end-to-end today (`tp`, `dp`, `pp`, `ep`, `stage_replica`); the remaining kinds in `MeshAxisKind` are reserved and raise `AxisTranslationError` at translate time so a typo cannot silently become a no-op (see `_SUPPORTED_KINDS` in `vllm_omni/config/composable_parallel/translator.py`). For `ep`, the size MUST equal `tensor_parallel_size * data_parallel_size`.
### `routing`
Default: per-kind — `RouteByStage(round_robin)` for `dp` and `stage_replica`; `PipelineMicrobatch()` for `pp`; `Broadcast()` for `tp`/`ep` and any other kind.
User-facing string only on `dp` and `stage_replica` axes. The four recognised values are `random`, `round_robin`, `least_queue`, `hash`; `hash` is rejected today with `NotImplementedError`. See `RouteByStage` in `vllm_omni/config/composable_parallel/routing.py`.
### `l1_owner`
Default: per-kind — `engine` for `tp`/`dp`/`pp`/`ep`, `delegated` for `stage_replica`.
Overrides which layer owns request routing along this axis. `engine` means vLLM realizes routing intra-engine; `delegated` means the omni coordinator owns routing across independent replicas. Set this only when overriding the per-kind default in `_DEFAULT_L1_OWNER` (`vllm_omni/config/composable_parallel/translator.py`); invalid values fail fast in `_resolve_l1_owner`.
### `stage_replica` and `omni_lb_policy`
`stage_replica` is *not* a vLLM world dimension; it spins up `size` independent engine replicas of one stage, coordinated by the omni `StagePool` load balancer. The axis writes both:
- The stage's `num_replicas` (a per-stage deploy knob).
- The pipeline-wide `omni_lb_policy` string (an orchestrator-level knob).
Because `omni_lb_policy` is read once at `AsyncOmniEngine` construction — not from per-stage engine args — only one value is allowed across the whole pipeline. If two stages declare conflicting policies, application raises (see `apply_strategy_specs` in `vllm_omni/config/composable_parallel/apply.py`, lines 253–260). To set this knob manually instead, use `--omni-lb-policy` on the CLI; see [the model stage docs](stage_configs.md) for how stage replicas plug into the orchestrator at runtime.
### `model_stage` keys
Default: no default — required for every entry under `strategies:`.
Strategy keys MUST be `model_stage` *names* (strings), the same labels stage configs use for `engine_args.model_stage` (see [`model_stage` in `stage_configs.md`](stage_configs.md#engine_argsmodel_stage)). Integer `stage_id` values are not accepted; the resolver matches on `model_stage` exactly (`_resolve_stage` in `vllm_omni/config/composable_parallel/apply.py`).
## Common pitfalls
!!! warning "Using `stage_id` integers as keys"
Strategy keys are `model_stage` names (str), not integer stage IDs. A file that uses an integer index will raise at apply time:
```text
StrategyApplyError: strategy role model_stage=0 did not match any stage;
available stages: 'thinker'(id=0), 'talker'(id=1), 'code2wav'(id=2)
```
Use the `model_stage` name (e.g. `thinker`) instead.
!!! warning "Mixing CLI overrides with a strategy on the same axis"
A strategy is meant to be the single writer for the axes it declares. If a CLI override (`--tensor-parallel-size 2`, `--stage-overrides '{"0": {"tensor_parallel_size": 2}}'`) sets the same axis, the **CLI value wins** and a warning is emitted from `_reconcile_strategy_with_cli`. The device-layout guard then re-runs against the effective layout, so a CLI override that breaks `tp * dp * pp * num_replicas` will still fail fast at config time.
!!! warning "Conflicting `omni_lb_policy` across stages"
`omni_lb_policy` is a single pipeline-wide knob. If two `stage_replica` axes in different stages derive different policies, `apply_strategy_specs` raises:
```text
StrategyApplyError: role 'talker' derives omni_lb_policy='least-queue-length'
but role 'thinker' already derived 'round-robin'. The load-balancer policy is
pipeline-wide; only one value is allowed.
```
Make the policies match, drop one, or supply the value explicitly via `--omni-lb-policy`.
+3 -3
View File
@@ -123,7 +123,7 @@ After inserting the extra thinker stage, renumber the remaining stages:
runtime:
devices: "2"
engine_input_source: [1]
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.qwen3_omni.thinker2talker
sync_process_input_func: vllm_omni.model_executor.stage_input_processors.qwen3_omni.thinker2talker_token_only
- stage_id: 3
runtime:
@@ -131,7 +131,7 @@ After inserting the extra thinker stage, renumber the remaining stages:
engine_args:
max_num_seqs: 1
engine_input_source: [2]
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.qwen3_omni.talker2code2wav
sync_process_input_func: vllm_omni.model_executor.stage_input_processors.qwen3_omni.talker2code2wav_token_only
```
Compared with the default Qwen3-Omni config:
@@ -158,7 +158,7 @@ runtime:
```bash
vllm serve Qwen/Qwen3-Omni-30B-A3B-Instruct --omni --port 8091 \
--stage-configs-path /path/to/qwen3_omni_pd.yaml
--deploy-config /path/to/qwen3_omni_pd.yaml
```
## Operational Notes
+41 -28
View File
@@ -1,11 +1,11 @@
# Stage configs for vLLM-Omni
# Pipeline and deploy configurations
In vLLM-Omni, the target model is separated into multiple stages, which are processed by different LLMEngines, DiffusionEngines or other types of engines. Depending on different types of stages, such as Autoregressive (AR) stage or Diffusion transformer (DiT) stage, each can choose corresponding schedulers, model workers to load with the Engines in a plug-in fashion.
In vLLM-Omni, a model's `PipelineConfig` defines its fixed stage topology, while a deploy configuration controls how those stages run.
!!! note
Default deploy config YAMLs (for example, `vllm_omni/deploy/qwen2_5_omni.yaml`, `vllm_omni/deploy/qwen3_omni_moe.yaml`, and `vllm_omni/deploy/qwen3_tts.yaml`) are bundled and loaded automatically when neither `--stage-configs-path` nor `--deploy-config` is provided — the model registry resolves the right pipeline + deploy YAML by `model_type`. The bundled defaults have been verified on 1xH100 for Qwen2.5-Omni and 2xH100 for Qwen3-Omni. Models that have not yet migrated to the new schema continue to use the legacy `vllm_omni/model_executor/stage_configs/<model>.yaml` files via `--stage-configs-path`.
Default deploy config YAMLs (for example, `vllm_omni/deploy/qwen2_5_omni.yaml`, `vllm_omni/deploy/qwen3_omni_moe.yaml`, and `vllm_omni/deploy/qwen3_tts.yaml`) are bundled and loaded automatically when `--deploy-config` is omitted. The model registry resolves the right pipeline and deploy YAML by `model_type`.
## New deploy schema reference
## Deploy configuration schema
The new deploy schema lives under `vllm_omni/deploy/` and is paired with a frozen `PipelineConfig` registered by the model's `pipeline.py`. Each deploy YAML has these top-level fields:
@@ -65,7 +65,7 @@ connectors:
| Connector class | Use case | `extra` keys |
|-----------------|----------|--------------|
| `SharedMemoryConnector` | Same-host KV transfer between stages (default for bundled YAMLs). | `shm_threshold_bytes` (int, default `65536`). |
| `SharedMemoryConnector` | Same-host KV transfer between stages (default for bundled YAMLs). | None. All payloads use shared memory. |
| `MooncakeStoreConnector` | Cross-host KV transfer over TCP. Required for multi-node deployments. | `host`, `metadata_server`, `master`, `segment` (int bytes), `localbuf` (int bytes), `proto` (`"tcp"` / `"rdma"`). |
A stage references a connector by name in its `input_connectors` / `output_connectors`:
@@ -82,14 +82,13 @@ stages:
input_connectors: {from_stage_0: shm}
```
### CLI flags introduced in this refactor
### CLI flags
| Flag | Description |
|------|-------------|
| `--deploy-config PATH` | Load a new-schema deploy YAML. Takes precedence over `--stage-configs-path`. **Optional** — when omitted, the bundled `vllm_omni/deploy/<model_type>.yaml` is auto-loaded by the model registry. |
| `--deploy-config PATH` | Load a deploy YAML. **Optional** — when omitted, the bundled `vllm_omni/deploy/<model_type>.yaml` is auto-loaded by the model registry. |
| `--stage-overrides JSON` | Per-stage JSON overrides, e.g. `'{"0":{"gpu_memory_utilization":0.5}}'`. Per-stage values always win over global flags. |
| `--async-chunk` / `--no-async-chunk` | Flip the deploy YAML's `async_chunk:` bool. Unset (default) leaves the YAML value in force. |
| `--stage-configs-path` | **Deprecated.** Accepts legacy `stage_args` yamls and (auto-detected) new deploy yamls; emits a deprecation warning. Migrate to `--deploy-config`. To be removed in a follow-up PR. |
### Stage-Based CLI Paradigm
@@ -119,8 +118,7 @@ CUDA_VISIBLE_DEVICES=1 vllm serve Qwen/Qwen3-Omni-30B-A3B-Instruct --omni \
--omni-master-port 26000
```
When instantiating a custom deployment YAML conforming to the updated schema, append the `--deploy-config /path/to/override.yaml` directive
to all node invocations. For legacy architectures (e.g., BAGEL) configured via deprecated `stage_args:` schemas, continue to specify the relevant configuration via `--stage-configs-path /path/to/config.yaml`.
When instantiating a custom deployment YAML, append the `--deploy-config /path/to/override.yaml` directive to all node invocations.
In the context of standard initialization architectures, utilizing the `--stage-overrides` parameter operates as the optimal methodology
for delineating stage-specific tuning from the CLI interface:
@@ -146,7 +144,7 @@ CUDA_VISIBLE_DEVICES=1 vllm serve Qwen/Qwen3-Omni-30B-A3B-Instruct --omni \
From highest to lowest:
1. Per-stage flags (`--stage-overrides` JSON, `--stage-<id>-<key>` if registered)
1. Per-stage overrides (`--stage-overrides` JSON)
2. Explicit global CLI flags (`--gpu-memory-utilization 0.85`, etc.)
3. Platform section (`platforms.npu.stages`, etc.) on top of the base `stages:`
4. Overlay YAML (via `base_config:`) on top of the base YAML
@@ -210,7 +208,7 @@ Effective config per stage after the merge:
| 1 | `max_model_len` | `16384` | global CLI |
| 2 | (all defaults) | — | base YAML (no overrides apply) |
Therefore, as a core part of vLLM-Omni, the stage configs for a model have several main functions:
Therefore, as a core part of vLLM-Omni, a model's pipeline and deployment configurations have several main functions:
- Claim partition of stages and their corresponding class implementation in `model_executor/models`.
- The disaggregated configuration for each stage and the communication topology among them.
@@ -219,16 +217,15 @@ Therefore, as a core part of vLLM-Omni, the stage configs for a model have sever
- Default input parameters.
To override specific parameters, explicitly inject the customized configuration schema
in both online and offline instantiation flows. Prioritize the `--deploy-config` flag
when loading the new-schema deploy YAML schemas, reserving the `--stage-configs-path` parameter
exclusively to maintain compatibility with legacy `stage_args` YAML constructs.
in both online and offline instantiation flows. Use the `--deploy-config` flag
when loading a deploy configuration.
Examples:
For offline (Assume necessary dependencies have been imported):
For offline inference (assuming the necessary dependencies have been imported):
```python
model_name = "Qwen/Qwen2.5-Omni-7B"
omni = Omni(model=model_name, stage_configs_path="/path/to/custom_stage_configs.yaml")
omni = Omni(model=model_name, deploy_config="/path/to/deploy_config.yaml")
```
For online serving:
@@ -236,17 +233,15 @@ For online serving:
vllm serve Qwen/Qwen2.5-Omni-7B --omni --port 8091 --deploy-config /path/to/deploy_config.yaml
```
Legacy online serving:
```bash
vllm serve ByteDance-Seed/BAGEL-7B-MoT --omni --port 8091 --stage-configs-path /path/to/stage_configs_file
```
!!! important
We are actively iterating on the definition of stage configs, and we welcome all feedbacks from both community users and developers to help us shape the development!
We are actively iterating on the definition of deployment configurations, and we welcome feedback from users and developers.
## Legacy stage configuration reference
The remainder of this page documents the deprecated `stage_args` schema for models that have not migrated to deploy configurations. The following historical Qwen2.5-Omni configuration illustrates that schema; current Qwen2.5-Omni deployments should use `vllm_omni/deploy/qwen2_5_omni.yaml` instead.
Below is a specific example of stage_configs.yaml in Qwen2.5-omni.
```python
# stage config for running qwen2.5-omni with AsyncOmniEngine + Orchestrator runtime.
# Historical stage configuration for Qwen2.5-Omni.
stage_args:
- stage_id: 0 # mark the unique id for each stage
runtime: # The disaggregated configuration
@@ -290,7 +285,6 @@ stage_args:
enable_prefix_caching: false
engine_output_type: latent
engine_input_source: [0]
custom_process_input_func: vllm_omni.model_executor.stage_input_processors.qwen2_5_omni.thinker2talker
default_sampling_params:
temperature: 0.9
top_p: 0.8
@@ -339,7 +333,7 @@ runtime:
```
## Stage Configuration Arguments
## Legacy stage configuration arguments
Each stage in the `stage_args` list contains the following configuration options:
@@ -375,10 +369,29 @@ Default: `"0"`
#### `engine_args.max_num_seqs`
The maximum number of sequences for concurrent processing in this stage. For LLM stages, this controls the vLLM scheduler's maximum concurrent sequences. For all stage types, this also controls how many tasks can be batched together in the task processing loop.
The maximum number of sequences for concurrent processing in this stage. For
LLM stages, this controls the vLLM scheduler's maximum concurrent sequences.
For diffusion stages, this controls scheduler wave capacity in both request
batch mode and step batch mode. `max_num_seqs: 1` is the serial/conservative
path; values above `1` allow compatible requests to batch when the selected
diffusion pipeline supports that batching mode.
Default: `1`
#### `engine_args.request_batch_max_wait_ms`
The maximum time, in milliseconds, that a diffusion request-mode stage may wait
before the first `schedule()` of a new scheduler wave so compatible requests can
accumulate for request-level batching. This only applies to diffusion pipelines
that support request-level batching with `step_execution` disabled.
Use this together with `max_num_seqs > 1` for bursty serving traffic. `0`
disables admission waiting and preserves the lowest first-request latency.
For diffusion request-level batching tuning, see
[Request-Level Batching](../user_guide/diffusion/request_batching.md).
Default: `0.0`
### `engine_args`
Engine arguments for configuring the LLM engine, diffusion engine, or other engine types used by this stage.
Loaded 100 of 1793 files, more files were not shown because too many files have changed in this diff. Show more