Repository navigation
[3/N][Config] Enable Thinker prefix caching by default for Qwen3-Omni and MiniCPM-o - #9203
Conversation
Signed-off-by: ZhengWG <zwg0606@gmail.com>
…CUDA Signed-off-by: ZhengWG <zwg0606@gmail.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
This PR appears to belong to: docs/design/module/vllm_omni_config.md, docs/design/module/entrypoints.md. Module owners: @alex-jw-brooks @lishunyang12 @NickCao Routing: @alex-jw-brooks via module of the changed files, CODEOWNERS; @lishunyang12 via module of the changed files, CODEOWNERS; @NickCao via module of the changed files, CODEOWNERS @ZhengWG, please review your own changes and leave a short self-review comment describing what you checked. PRs without author self-review may not be assigned a reviewer. Please take a look when you have a chance. If you would like an automated review, mention @vllm-omni-review-bot in a comment. |
Omni ReviewBot triage noteAutomated triage of commit
These are automated triage suggestions only — the final decision belongs to the maintainers. |
|
@amy-why-3459 PTLA |
amy-why-3459
left a comment
There was a problem hiding this comment.
Thanks for the thorough matrix. Two things on the scope of the new default:
-
The PR describes the new default as CUDA turn serving, but in
qwen3_omni_moe.yamlthe flag is flipped in the platform-shared stage-0 block. None of theplatforms.npu/rocm/xpu/musablocks override it, so Qwen3-Omni stage 0 also gets the Thinker prefix cache on Ascend (TP=2, PIECEWISE graphs), ROCm, XPU and MUSA, none of which are in the validation runs. MiniCPM-o handles this with an explicit NPU-off override; Qwen3-Omni probably wants the same (either set it inplatforms.cudaonly, or turn it off in the non-CUDA blocks), plus matching rows intest_thinker_prefix_cache_defaults. -
The PR says it must land after #9162 and #9193, and that on main alone the cache collapses at C64 (Qwen3-Omni −68% to −77%) and costs MiniCPM-o ~19% on decode. Since this is a default flip, it would be safer to keep it blocked or in draft until both are merged, so it can't go in first by accident.
Signed-off-by: ZhengWG <zwg0606@gmail.com>
amy-why-3459
left a comment
There was a problem hiding this comment.
Looked at the new commit e091c85a. Turning stage 0 prefix caching off in the npu / rocm / xpu / musa blocks of qwen3_omni_moe.yaml, and adding the rocm / xpu / musa blocks to minicpmo_4_5_turn.yaml, resolves correctly: _merge_platforms deep-merges per platform and per stage_id, so the new stage-0 entries sit next to the existing stage-1/2 overrides and the base's NPU block is kept. Those are all the platforms under vllm_omni/platforms, and the new test_thinker_prefix_cache_defaults rows cover each one. That addresses my first point.
On the second point: the branch still only has the three config commits, and #9162 and #9193 are both still open. So if this merged first, main would get the default flip without the fixes the description depends on. Keeping it in draft or blocked until both land would still be the safer option.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
@amy-why-3459 PTLA |
| # This shared block leaves stage-level prefix caching unset (platforms.npu | ||
| # sets it off for the duplex KV window; minicpmo_4_5_turn.yaml turns it on | ||
| # for CUDA turn serving). Stage-0 n-gram |
There was a problem hiding this comment.
Why does minicpmo_4_5.yaml still leave Thinker prefix caching off?
This file is the model's default deploy config (default_deploy_config_name="minicpmo_4_5.yaml") and the base the other MiniCPM-o profiles inherit. Root enable_prefix_caching stays false (line 13), and this shared stage-0 block still does not set the stage key, so on CUDA stage 0 resolves to off (test_thinker_prefix_cache_defaults). The new default is only on minicpmo_4_5_turn.yaml, and only for CUDA.
That is the inverse of Qwen3-Omni, where the primary turn yaml turns stage 0 on and the duplex / MRv2 profiles opt back out. With this layout, vllm serve of MiniCPM-o 4.5 on the default config does not get the cache this PR says it enables by default; the caller has to pass the turn deploy config.
The new comment attributes that to the duplex KV window plus the turn overlay. validate_duplex_window_install does refuse enable_prefix_caching=True, but that only covers the duplex session — it does not say why the shared stage-0 block stays unset on CUDA instead of stating false the way the NPU block does. The previous text in this hunk gave a different reason: setting stage-level prefix caching in the platform-shared block killed the stage-1 replica on CUDA (empty TTS handoff, then an indexSelectSmallIndex device assert). This revision drops that rationale and still does not enable the flag.
Please spell out which constraint still keeps this file off on CUDA. If it is only the duplex window, stage 0 here should set enable_prefix_caching: false explicitly, same as platforms.npu, rather than inheriting the root default through a missing key. If that CUDA stage-1 failure no longer applies, why shouldn't stage 0 of this default profile follow minicpmo_4_5_turn.yaml?
There was a problem hiding this comment.
Prerequisites are met: #9162 (798fef99a3) and #9193 (949907817e) are both on main, so the earlier "must land after both" blocker is cleared. On e091c85a I ran tests/config/test_config_factory.py (507 passed) and walked _apply_platform_overrides → merge_pipeline_deploy by hand to check the final engine args:
qwen3_omni_moe.yaml: cuda[True, False, False], npu/rocm/xpu/musa[False, False, False]minicpmo_4_5_turn.yaml: cudaTrue, npu/rocm/xpu/musaFalse(the NPU off comes from the base'splatforms.npustage-0 entry;_merge_platformsdeep-merges per platform and perstage_id, so an overlay without annpublock does not drop it)minicpmo_4_5.yaml/_duplex_h200/ both mrv2 profiles: allFalse
The platform overrides, the MRv2/duplex fallbacks and the parametrization look right. The four inline comments below are the specific ones; three broader points first:
- The branch is 52 commits behind main. The merge base is
baa2f5adcb, which does not contain798fef99a3/949907817e. The throughput matrix in the description was measured on the stack, so please rebase onto a main that has both PRs and re-run at least the config unit tests plus one high-hit scenario, so the evidence behind "on by default" matches the target revision. - Host memory is a real cost of the new default. Stage-0
VmRSSgoes 5.2 → 15.2–16.1 GiB for Qwen3-Omni and 4.4 → 7.3–7.6 GiB for MiniCPM-o. The pinned pool is allocated asnum_blocks × block_size × featwith no YAML/CLI cap (vllm_omni/core/prefix_cache/block_pool.py, plus the staging note ininterface.py), and with N replicas it multiplies by N. Worth recording the measured numbers in the yaml comment, along with an overlay snippet for users who want it off. - The new
minicpmo_4_5.yamlcomment says the shared block "leaves stage-level prefix caching unset", but the pipeline-wideenable_prefix_caching: falseon line 13 of the same file is still what applies (theplatforms.npustage-0falseis extra belt-and-braces). As written it reads as if nothing is configured there. Suggest spelling out that the pipeline-wide value covers duplex and the turn profile overrides it at stage level.
Overall: the direction and the evidence are stronger than most config PRs in this repo. Fix the e2e assertion and move the test assertion down to the final engine args, and I think this can land.
| # Thinker prefix cache: hits reuse KV and the cached hidden rows the Talker | ||
| # consumes. Validated on CUDA V1 turn serving only: the non-CUDA platform | ||
| # blocks below and the MRv2 and duplex profiles keep it off. | ||
| enable_prefix_caching: true |
There was a problem hiding this comment.
This line breaks test_structured_multistage_config_reaches_runtime in tests/e2e/offline_inference/test_qwen3_omni.py, which runs in the merge gate at .buildkite/cuda/test-merge.yml:149:
# tests/e2e/offline_inference/test_qwen3_omni.py:109
assert all(config.cache_config.enable_prefix_caching is False for config in engine.stage_vllm_configs)That case runs production_test_params, i.e. this file, so with stage 0 now True the assertion must fail. The Test Plan only lists tests/core, tests/worker and tests/config, so the e2e run was not covered and this did not surface. Either flip the assertion to stage 0 True and stages 1/2 False, or move the case onto an overlay that explicitly disables the cache. If the intent is to keep checking that deploy values really reach the VllmConfig objects, the former is better.
Separately, tests/e2e/online_serving/test_qwen3_omni.py:31-36 still says "Prefix cache is opt-in on the deploy YAML", which is now stale; please update it in the same pass.
| platform=platform, | ||
| ) | ||
| stage0 = next(stage for stage in deploy.stages if stage.stage_id == 0) | ||
| assert stage0.engine_extras.get("enable_prefix_caching", deploy.enable_prefix_caching) is enabled |
There was a problem hiding this comment.
This assertion stops at the deploy layer and does not cover the mechanism it actually depends on. enable_prefix_caching is not a StageDeployConfig field, so it lands in engine_extras and is applied last by engine_args.update(ds.engine_extras) in _build_engine_args (around vllm_omni/config/stage_config.py:1324), overriding the pipeline-wide value. That precedence is exactly why this PR works, but the test never verifies it: if the merge order of engine_extras changes, this assertion stays green while production silently falls back to false.
Suggest adding at least one assertion per enabled profile that goes through merge_pipeline_deploy(...) and checks yaml_engine_args["enable_prefix_caching"], for qwen3_omni_moe.yaml/cuda and minicpmo_4_5_turn.yaml/cuda. The existing test_step_audio2_* cases nearby already use that pattern.
Also worth adding the two derived profiles that stay off only through inheritance: minicpmo_4_5_turn_mrv2_h200.yaml and qwen3_omni_duplex_mrv2.yaml. They do not change when the base does, but that is precisely the kind of inheritance that gets silently flipped the next time someone edits a base file.
| # Stage-level prefix caching is NPU-only (see platforms.npu below): in the | ||
| # platform-shared block it killed the stage-1 replica on CUDA (empty tts | ||
| # handoff, then an indexSelectSmallIndex device assert). Stage-0 n-gram | ||
| # This shared block leaves stage-level prefix caching unset (platforms.npu |
There was a problem hiding this comment.
This removes a CUDA regression note that had a clear provenance (added in b60a7e9e86): enabling stage-0 prefix caching in the platform-shared block once killed the stage-1 replica on CUDA — empty tts handoff, then an indexSelectSmallIndex device assert. This PR effectively lifts that constraint (the CUDA turn profile turns the same switch on) without saying why it no longer applies.
The Seed-TTS evidence (1088/1088 completed, WER 0.0207 vs 0.0215, 82.4% stage-0 hit) is strong, but please tie it to the conclusion in the description or this comment: was that failure specific to the duplex path (duplex now disables the cache explicitly, and window_kv.py:153 raises anyway), or was it fixed by a later change? Otherwise the next reader will assume the original note was overlooked.
| moe_backend: triton | ||
| trust_remote_code: true | ||
| enable_prefix_caching: false | ||
| # Thinker prefix cache: hits reuse KV and the cached hidden rows the Talker |
There was a problem hiding this comment.
Turning this on by default also has a consequence that is not in the PR description: the video streaming API silently switches to incremental prefill.
# vllm_omni/entrypoints/openai/video_stream_base.py:296-298
return self._incremental_prefill_supported and "audio" not in config.modalitieswhere _incremental_prefill_supported = _stage0_prefix_caching_enabled(engine_client) (line 321 of the same file) reads exactly this stage-0 flag. So under this profile, text-only /v1/video/chat/stream sessions move from the legacy path to incremental prefill: every buffered frame goes into the prompt instead of stride-sampling num_frames, a full buffer drops the oldest half at once, and each query waits for the whole window to finish decoding.
That is a default-value change and deserves a line in the PR description. docs/serving/video_stream_api.md:19-21 currently still says "to enable incremental prefill, set enable_prefix_caching: true"; it should say it is on by default and that disabling the cache falls back to legacy.
|
Ran main 798fef9 (with #9162 and #9193) + e091c85 on one RTX 6000 Ada (48 GB) with MiniCPM-o 4.5:
Results:
|
|
Daily-Omni, Qwen3-Omni, concurrency 10. Same code for both arms: main Setup. Accuracy. 857/1197 (0.7160) cache off, 856/1197 (0.7151) cache on. 1196/1197 predicted letters match. The one flip is Performance (
Stage-0 prefix-cache hit rate with the cache on is 1.97% (235,504 / 11,965,481 tokens). Daily-Omni reuses videos across questions, but the question text differs and the bench shuffles requests, so the video tokens are not a stable long prefix. Caveat. Single run. GPU 5 (also holding another process) spiked to 100% utilization during the cache-off run and stayed at or below 16% during cache-on, so the +18% is not a clean cache-only delta. The accuracy comparison is the firmer result: one answer changed out of 1197. |
|
Seed-TTS EN, MiniCPM-o 4.5, concurrency 16. Same code for both arms: main Setup. Local Accuracy. 1088/1088 completed in both arms, no missing PCM and no ASR failures.
Performance:
Stage-0 prefix-cache hit rate with the cache on is 82.4% (134,688 / 163,442 tokens). That matches the 82.4% hit this PR reports for the full 1088 utterances. Caveat. During startup the cache-off server failed two Code2Wav Whole-Euler graph captures with CUDA OOM and continued; the cache-on server captured those graphs. Both then served all 1088 requests. The accuracy numbers are unaffected. Part of the tail-latency and RTF gap can come from that eager fallback, not only from the prefix cache. |
Signed-off-by: ZhengWG <zwg0606@gmail.com>
amy-why-3459
left a comment
There was a problem hiding this comment.
Looked at tip 40a38318 ("[Tests] Expect the Thinker prefix cache on in the Qwen3-Omni e2e checks") after the merges onto main.
Addressed since e091c85a.
- Offline e2e
test_structured_multistage_config_reaches_runtimenow asserts Thinker True and Talker/Code2Wav False — that unblocks the merge-gate case that would have failed with the default flip. - Online-serving comment no longer says the deploy YAML is opt-in; it correctly notes that production turns stage 0 on and that
_PREFIX_CACHE_SERVER_ARGSstill force-enables Talker for that fixture. - Branch is no longer stuck on the pre-#9162/#9193 merge base (merges through
ea08ab61are present).
Still open from the earlier review on e091c85a (not changed by this tip).
test_thinker_prefix_cache_defaultsstill stops atstage0.engine_extras.get(...). Please push the assertion throughmerge_pipeline_deploy/_build_engine_argsand check the finalyaml_engine_args["enable_prefix_caching"]for at least the two CUDA-on profiles (and keep the derived off profiles that only inherit, e.g.minicpmo_4_5_turn_mrv2_h200.yaml/qwen3_omni_duplex_mrv2.yaml).minicpmo_4_5.yamlcomment / layout: please answer why the default MiniCPM-o profile stays off on CUDA while the turn overlay is on, and either set stage 0 to an explicitfalseor document that callers must pass the turn deploy config. The dropped CUDA stage-1 regression rationale is still unexplained relative to the turn profile flipping the same switch.- Default side effect: text-only
/v1/video/chat/streamunder Qwen3-Omni now silently takes the incremental-prefill path via_stage0_prefix_caching_enabled. Worth a line in the PR description and a touch ofdocs/serving/video_stream_api.md. - Host
VmRSScost of the new default (Qwen ~5→15 GiB, MiniCPM-o ~4→7 GiB) is still not recorded next to the yaml flip / overlay-off snippet.
No new blocking findings in the tip itself beyond those carry-overs. Once (1)–(2) land, this looks ready.
| platform=platform, | ||
| ) | ||
| stage0 = next(stage for stage in deploy.stages if stage.stage_id == 0) | ||
| assert stage0.engine_extras.get("enable_prefix_caching", deploy.enable_prefix_caching) is enabled |
There was a problem hiding this comment.
Still open from the earlier review: this only checks the deploy/engine_extras layer. enable_prefix_caching is applied last via engine_args.update(ds.engine_extras) in _build_engine_args, so a merge-order regression would leave this green while production silently falls back to false.
Please add at least one assertion per CUDA-on profile that goes through merge_pipeline_deploy(...) (same pattern as the nearby test_step_audio2_* cases) and checks yaml_engine_args["enable_prefix_caching"]. Also worth covering the derived off profiles that only inherit (minicpmo_4_5_turn_mrv2_h200.yaml, qwen3_omni_duplex_mrv2.yaml).
| # The production YAML turns the Thinker prefix cache on; the Talker and | ||
| # Code2Wav stages keep it off. | ||
| assert thinker_vllm.cache_config.enable_prefix_caching is True | ||
| assert talker_vllm.cache_config.enable_prefix_caching is False |
There was a problem hiding this comment.
This is the right fix for the merge-gate breakage called out earlier: stage 0 True, stages 1/2 False, and the assertion still exercises that deploy values reach VllmConfig. Thanks.
…the cost Signed-off-by: ZhengWG <zwg0606@gmail.com>
amy-why-3459
left a comment
There was a problem hiding this comment.
Looked at tip 0ee846a0 ("[Config] Check prefix-cache defaults on the engine args and document the cost").
Addressed since 40a38318.
test_thinker_prefix_cache_defaultsnow asserts throughmerge_pipeline_deployonyaml_engine_args["enable_prefix_caching"], and covers the derived-off profiles.minicpmo_4_5.yamlsets stage-0enable_prefix_caching: falseexplicitly and explains duplex KV-window vs the turn overlay.docs/serving/video_stream_api.mdnow matches the new Qwen3-Omni default for incremental prefill.- Yaml comments document the host-mirror cost and include an overlay-off snippet.
Still open on this tip.
- The new test monkeypatches
current_omni_platform.device_namebut never calls_apply_platform_overrides.load_deploy_configonly parses YAML; platform stage overrides are applied by_apply_platform_overrides(every sibling test in this file does that). As written, the npu/rocm/xpu/musa rows still see the shared-stage value and do not exercise the platform blocks the matrix is meant to lock. Please apply overrides forplatformbefore the merge, same astest_minicpmo_talker_multi_frame_is_npu_scoped. - MiniCPM rows resolve with
Q3_OMNI_ALL_STAGES_HF_CONFIG. Sibling MiniCPM tests useresolve_pipeline_config("minicpmo_4_5")(no Qwen HF config). Prefer that for theminicpmo_*cases so the pipeline under test matches the deploy.
Soft leftover: the host RSS note is still qualitative ("several GiB" / "a few GiB"); the measured ~5→15 GiB / ~4→7 GiB numbers from earlier would make the cost concrete next to the overlay snippet.
Once (1) lands, the config matrix looks ready to me.
| pipeline = resolve_pipeline_config(deploy.pipeline or "qwen3_omni_moe", Q3_OMNI_ALL_STAGES_HF_CONFIG) | ||
| assert pipeline is not None | ||
| stage0 = next(stage for stage in merge_pipeline_deploy(pipeline, deploy) if stage.stage_id == 0) | ||
| assert stage0.yaml_engine_args["enable_prefix_caching"] is enabled |
There was a problem hiding this comment.
load_deploy_config does not apply platforms.* overrides — that happens in _apply_platform_overrides (optionally reading current_omni_platform.device_name). Monkeypatching device_name alone leaves the shared-stage value in place, so the npu/rocm/xpu/musa parametrized rows do not actually check the platform blocks.
Please do something like:
deploy = _apply_platform_overrides(
load_deploy_config(Path(get_deploy_config_path(yaml_name))),
platform=platform,
)before merge_pipeline_deploy, matching the other platform-scoped tests in this file.
Also, for the minicpmo_* cases, resolve with resolve_pipeline_config("minicpmo_4_5") (or deploy.pipeline) without Q3_OMNI_ALL_STAGES_HF_CONFIG — that HF stub is Qwen3-Omni-specific.
…ults Signed-off-by: ZhengWG <zwg0606@gmail.com>
Signed-off-by: ZhengWG <zwg0606@gmail.com>
amy-why-3459
left a comment
There was a problem hiding this comment.
Looked at tip def52c83 (two commits since 0ee846a0: platform-override test fix, then drop host-RSS yaml notes).
Addressed since 0ee846a0.
test_thinker_prefix_cache_defaultsnow calls_apply_platform_overrides(..., platform=platform)and pinscurrent_omni_platform.device_namebeforemerge_pipeline_deploy. That is what the npu/rocm/xpu/musa rows needed — they no longer stop at the shared-stage value.- MiniCPM rows resolve via
deploy.pipelinewhen present (falling back to the Qwen HF path only when the deploy has no pipeline key), which matches how the turn/base MiniCPM profiles are wired.
On def52c83. Dropping the qualitative host-RSS lines from the yaml comments is fine; the overlay-off snippet stays. The measured ~5→15 / ~4→7 GiB figures remain in the PR discussion if anyone wants them later.
No new blocking findings on this tip. The config matrix looks ready from my side.
Contributor intent (required human answers)
1. What outcome do you want to achieve?
Improve latency and throughput for shared-prefix requests in Qwen3-Omni and MiniCPM-o turn serving.
2. What is the highest-leverage variable for that outcome?
The reuse of cached KV states and Thinker outputs across requests.
3. How will this work move that variable?
Enable Thinker prefix caching by default for supported V1 turn profiles, while keeping MRv2 and duplex profiles disabled.
4. Whose customer or user needs does this address, and what are those needs?
Users serving repeated or shared-prefix requests need better performance without manual cache configuration.
Purpose
Part [3/N] of #7902: [1/N] #9162 fixes the collapse under concurrent hits, [2/N] #9193 removes the per-step cost at 0% hit, and this PR turns the Thinker prefix cache on by default for Qwen3-Omni and MiniCPM-o 4.5 (CUDA turn serving). Merge after #9162 and #9193: on main alone the cache collapses on long shared prefixes at C64 (Qwen3-Omni −68% to −77%) and costs MiniCPM-o 19% on decode (column "main, cache on" below).
With the stack, the cache costs at most 3.0% when nothing hits and speeds up any traffic that shares a prompt prefix (system prompts, multi-turn history, shared media).
qwen3_omni_moe.yaml: stage 0 on;qwen3_omni_moe_mrv2.yamlandqwen3_omni_duplex.yamlset it back to false (not validated with the cache).minicpmo_4_5_turn.yaml: stage 0 on for CUDA; the NPU platform block, the base and duplex profiles stay off;minicpmo_4_5_turn_mrv2.yamlsets it back to false (MRv2 does not merge cached Thinker rows yet).Follow-up: #9039 replaces the mirror/COW core with refcounted payload references. It can land after this series and take over the code from #9162 / #9193 under the same defaults, with this test matrix as its acceptance check.
Prefix-cache scope by model
qwen3_omni_moe.yaml(Thinker)minicpmo_4_5_turn.yaml(LLM, CUDA)Test Plan
vLLM Version: 0.32.0
vLLM-Omni Commit: #9162 + #9193 + these commits
Test bases: GPU runs on main
da572cddb38383deae9caef33b8d490e292ef071.Hardware: H20 (96 GB).
pytest tests/core tests/worker/test_gpu_ar_model_runner.py tests/worker/test_gpu_ar_model_runner_cuda.py tests/config/test_config_factory.pyon the stack;pytest tests/config/test_config_factory.pyfor this PR alone, also on the latest main15bce345863c6e2db882534876b8977f5b1ae1e3.DECV_*4 / 3). Metric:request_throughputfromvllm bench serve --save-result; ratio = mean over rounds / mean over rounds of the same run's cache off − 1; range = min..max of the per-round ratios. Hit rate = delta of stage 0'svllm:prefix_cache_{hits,queries}_totalon/metricsaround each bench.VmRSS(/proc/<pid>/status) after each throughput run.reproduction commands
Servers (
overlay.yamlsets stage 0enable_prefix_caching: falsefor cache off; the stack runs the shipped yaml):Benches, in this order on each server:
Test Result
15bce3458,tests/config/test_config_factory.py500 passed (main 492).Qwen3-Omni (
request_throughputvs cache off; TTFP = median audio time to first packet)P1024_h0_c1P1024_h0_c8P1024_h0_c64P4096_h0_c1P4096_h0_c64P16384_h0_c64P1024_h50_c32P1024_h50_c64P4096_h50_c32P4096_h50_c64P1024_h94_c64P4096_h94_c32P4096_h94_c64P16384_h94_c32P16384_h94_c64O256_L4096_h94_c64AUD_L4096_h94_c32MP32_c64DEC100_c32DEC100_c64DECV_c32DECV_c64MiniCPM-o (
request_throughputvs cache off; TTFP = median audio time to first packet)P256_h0_c32P1024_h0_c32P1024_h0_c64P4096_h0_c32P4096_h0_c64P8192_h0_c32P16384_h0_c32P16384_h0_c64DEC100_c32DEC100_c64P1024_h50_c64P4096_h50_c64P16384_h50_c64P4096_h94_c32P4096_h94_c64P16384_h94_c64MP32_c64SEEDTTS_c8AUD_L2048_h94_c32DECV_c32DECV_c64VmRSS: Qwen3-Omni 15.2–16.1 GiB (main cache on 21.7–32.5, off 5.2–5.3); MiniCPM-o 7.3–7.6 GiB (main 9.0–9.1, off 4.4–4.7).BEFORE SUBMITTING: read CONTRIBUTING.md and run the precheck-pr skill with the code agent for a self-check against project conventions.
Note
To avoid agent spam, vLLM-Omni limits contributors without write access to 5 open PRs. If this blocks well-intentioned critical work, please contact a committer to request bypass list access.
(anything written below this line will be removed by GitHub Actions)