Repository navigation
Add Qwen-Image-2.1 recipe - #996
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new model recipe for Qwen-Image-2.1, including its metadata, dependencies, variants, and a comprehensive guide for offline inference, online serving, quantization, and limitations. Feedback on the changes suggests setting pip: false to avoid displaying a non-executable string in the UI, fixing a typo in the docker note, and explicitly pinning vllm==0.29.0 in the dependencies installation command to ensure consistency with the guide.
| note: "The PR is stil under review - use docker until the PR is merged." | ||
| pip: | ||
| command: "The PR is stil under review - use docker until the PR is merged." | ||
| note: "Base environment only; vLLM-Omni itself has to come from source." |
There was a problem hiding this comment.
The pip.command is currently set to a text description rather than a valid shell command, which will cause the UI to display a non-executable string in the pip installation tab. Since the model is not yet in a tagged release and must be installed from source (as documented in the dependencies block), it is cleaner to set pip: false to hide the pip tab entirely. Additionally, this fixes a typo ('stil' -> 'still') in the docker note.
note: "The PR is still under review - use docker until the PR is merged."
pip: falseThere was a problem hiding this comment.
To ensure compatibility and match the installation instructions in the guide, explicitly pin vllm==0.29.0 in the dependencies installation command, similar to how it is done in other recipes (e.g., Qwen-Image.yaml).
command: "git clone https://github.com/vllm-project/vllm-omni.git && cd vllm-omni && git fetch origin pull/7759/head:qwen-image-2.1 && git checkout qwen-image-2.1 && uv pip install -e . vllm==0.29.0"710298b to
9796bd5
Compare
9796bd5 to
ba93f65
Compare
ba93f65 to
80017e5
Compare
Unified text-to-image and image-conditioned generation through one pipeline class: a 7.1B single-stream DiT with block-causal attention and an exact cross-step prefix KV cache, a Qwen3-VL-8B text encoder, and a 16x RGBA autoencoder. Verified end to end on one NVIDIA GB300 built from PR #7759. The guide carries the facts an operator acts on; the evidence for each is below. What was measured (1024x1024, 40 steps, CFG off, seed fixed, --vae-use-tiling): - serves and returns a valid PNG, checked by decoding it and asserting magic bytes, byte length and IHDR dimensions rather than accepting HTTP 200 - 4.5 s per image, 34.0 GB peak in BF16 - DiT FP8 (img_mlp kept BF16): 32.0-32.7 GB, slightly slower - text-encoder FP8: 27.5-28.1 GB -- about three times the DiT-only saving - prefix KV cache: a repeated prompt costs 0.31x the first submission; changing only the prompt tail returns it to 2432 ms, which rules out warm-up - prefix_kv_cache_dtype=fp8_v serves, and returns 0.50x instead of 0.31x - Ulysses SP across 2 GPUs: 3851 ms at 33.1 GB, against 4492 ms and 34.0 GB on 1 - step execution: 4 concurrent requests in 4019 ms against ~5870 ms serial - dimensions floored to a multiple of 32 (1000 -> 992, 1328 -> 1312), never rejected; 1024x1536 and n=2 both fine - seed determinism: byte-identical output - RGBA survives the round trip -- PNG colour-type 6 - up to 4 reference images; a 5th is refused by the server Bugs found by running it, neither visible from reading the source: - --revision is not honoured. omni_base.py:110 calls download_weights_from_hf_specific() with no revision=, so the engine resolves "main"; a cache staged by commit sha has no refs/main and fails offline with LocalEntryNotFoundError despite every shard being present. - The PR #7759 images set WORKDIR /opt/vllm-omni and do not inherit vllm/vllm-openai's `vllm serve` entrypoint, so passing only `<model> --flags` execs the model id as a binary and exits 127. Corrections to claims that source-reading alone got wrong: - /v1/images/edits works, but takes multipart/form-data. A JSON body resets the connection, which reads as a broken endpoint. A data: URL in the `url` form field is additionally capped at 1024 KB per part, which a 512x512 PNG exceeds. - true_cfg_scale defaults to 4.0 when omitted but only applies alongside a negative_prompt, so a plain request behaves as if 1.0 had been sent. - The first-request cost is not CUDA-graph capture: it persists at 1.26x with --enforce-eager and no graphs at all. - Per-component FP8 is serve-reachable via --diffusion-quantization-config; --ignored-layers exists only in text_to_image.py, not in `vllm serve`. - A plain clone lands on main, which does not contain this model. - Without model.docker_image the builder falls back to vllm/vllm-openai:latest. Not measured, and not claimed: throughput (vllm bench serve drives only /v1/completions and /v1/chat/completions, so the t2i task carries a benchmark override saying so), pipeline parallelism, and the GB200 FP8 figures, which stay attributed to the vLLM-Omni contributors. meta.hardware records gb300 as verified and default_hardware points there, so the page opens on the hardware the numbers came from. vram_minimum_gb is 40 from the repo formula ceil(33.1 GB x 1.2), which the measured 34.0 GB sits under. No hardware: entry for any GPU that was not run. Validated with `node scripts/build-recipes-api.mjs`: 191 -> 192 models, no warnings naming this file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Tiezhen WANG <tiezhen@inferact.ai>
80017e5 to
bbcea93
Compare

Adds
models/Qwen/Qwen-Image-2.1.yaml.Qwen-Image-2.1 serves text-to-image and image-conditioned generation through one
pipeline class,
QwenImage21Pipeline: a 7.1B single-stream DiT with block-causalattention and an exact cross-step prefix KV cache, a Qwen3-VL-8B text encoder, and
a 16x RGBA autoencoder.
Draft — two upstream blockers
Qwen/Qwen-Image-2.1returns 401 unauthenticated.Both resolve on their own; this is staged so it is ready when they do.
Verified on one NVIDIA GB300
Built from PR #7759. All at 1024x1024, 40 steps, CFG off, fixed seed,
--vae-use-tiling. Output was checked by decoding the response and asserting PNGmagic bytes, byte length and IHDR dimensions — not by accepting HTTP 200.
img_mlpin BF16prefix_kv_cache_dtype=fp8_vTwo bugs found by running it
Neither is visible from reading the source, and both are reportable upstream:
--revisionis silently ignored.omni_base.py:110callsdownload_weights_from_hf_specific()with norevision=, so the engine alwaysresolves
main. A cache staged by commit sha has norefs/mainand failsoffline with
LocalEntryNotFoundErrorwith every shard present.vllm serveentrypoint. They setWORKDIR /opt/vllm-omni, so a runner passing<model> --flagsexecs the modelid as a binary and exits 127.
Corrections that source-reading alone got wrong
/v1/images/editsworks — it takesmultipart/form-data. A JSON body resetsthe connection, which reads as a broken endpoint. A
data:URL in theurlformfield is additionally capped at 1024 KB per part, which a 512x512 PNG exceeds.
true_cfg_scaledefaults to 4.0 but is inert without anegative_prompt, so aplain request behaves as if 1.0 had been sent. Measured: 853 ms without a negative
prompt against a 1104 ms baseline, and 1800 ms with one.
--enforce-eagerwith no graphs at all.--diffusion-quantization-config;--ignored-layersexists only intext_to_image.py, not invllm serve.main, which does not contain this model.model.docker_imagethe builder substitutesvllm/vllm-openai:latest.Not measured, and not claimed
No throughput figure:
vllm bench servedrives only/v1/completionsand/v1/chat/completions, so nothing in the harness can drive image generation. Thet2itask carries abenchmarkoverride saying so, to stop a text benchmark beingadded later and labelled this model's throughput. Pipeline parallelism is untested.
The GB200 FP8 figures stay attributed to the vLLM-Omni contributors and separate
from the GB300 numbers above.
meta.hardwarerecordsgb300: verifiedwithdefault_hardware: gb300, so the pageopens on the hardware the numbers came from.
vram_minimum_gb: 40from the repoformula
ceil(33.1 GB × 1.2), which the measured 34.0 GB sits under. Nohardware:entry for any GPU that was not run.
Validated with
node scripts/build-recipes-api.mjs: 191 → 192 models, no warningsnaming this file.
🤖 Generated with Claude Code