From c3498fb8692eabba309109171ce94e2a5af2c801 Mon Sep 17 00:00:00 2001 From: "Jierui (Jerry) Xu" <132116599+Jerry2423@users.noreply.github.com> Date: Mon, 7 Sep 2026 17:59:23 -0700 Subject: [PATCH] [Model] Add Boogu-Image Turbo pipeline resolution (#6961) Signed-off-by: Jerry Xu --- docs/models/supported_models.md | 1 + recipes/Boogu/Boogu-Image.md | 63 +++++++++--- .../boogu_image/test_boogu_image_registry.py | 96 +++++++++++++++++++ tests/model_tests/diffusion/test_alignment.py | 1 + vllm_omni/diffusion/model_metadata.py | 1 + vllm_omni/diffusion/registry.py | 7 ++ 6 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 tests/diffusion/models/boogu_image/test_boogu_image_registry.py diff --git a/docs/models/supported_models.md b/docs/models/supported_models.md index 9e3a5a9f7..de5d5e346 100644 --- a/docs/models/supported_models.md +++ b/docs/models/supported_models.md @@ -64,6 +64,7 @@ th { | `LongCatImageEditPipeline` | LongCat-Image-Edit | `meituan-longcat/LongCat-Image-Edit` | ✅︎ | ✅︎ | ✅︎ | ✅︎ | — | | `LongCatVideoAvatarPipeline` | LongCat-Video-Avatar-1.5 A2V/AI2V (native single-speaker and multi-speaker AI2V/AVC) | `meituan-longcat/LongCat-Video-Avatar-1.5` | ✅︎ | | | | [Repository](https://github.com/vllm-project/vllm-omni/blob/main/recipes/meituan-longcat/LongCat-Video-Avatar-1.5.md) | | `BooguImagePipeline` | Boogu-Image | `Boogu/Boogu-Image-0.1-Base`, `Boogu/Boogu-Image-0.1-Edit`, `Boogu/Boogu-Image-0.1-Edit-Turbo` | ✅︎ | | | ✅︎ | [Repository](https://github.com/vllm-project/vllm-omni/blob/main/recipes/Boogu/Boogu-Image.md) | +| `BooguImageTurboPipeline` | Boogu-Image Turbo distilled T2I | `Boogu/Boogu-Image-0.1-Turbo` | ✅︎ | | | | [Repository](https://github.com/vllm-project/vllm-omni/blob/main/recipes/Boogu/Boogu-Image.md) | | `StableDiffusionXLPipeline` | Stable-Diffusion-XL | `stabilityai/stable-diffusion-xl-base-1.0` | ✅︎ | ✅︎ | ✅︎ | ✅︎ | — | | `StableDiffusion3Pipeline` | Stable-Diffusion-3 | `stabilityai/stable-diffusion-3.5-medium` | ✅︎ | ✅︎ | | ✅︎ | — | | `CosyVoice3Model` | CosyVoice3 | `FunAudioLLM/Fun-CosyVoice3-0.5B-2512` | ✅︎ | ✅︎ | | ✅︎ | — | diff --git a/recipes/Boogu/Boogu-Image.md b/recipes/Boogu/Boogu-Image.md index ecc2c1d0f..0d832b0ae 100644 --- a/recipes/Boogu/Boogu-Image.md +++ b/recipes/Boogu/Boogu-Image.md @@ -1,12 +1,13 @@ # Boogu-Image > Text-to-image and image-editing online serving -(Boogu-Image-0.1-Base / -Edit / -Edit-Turbo) +(Boogu-Image-0.1-Base / -Turbo / -Edit / -Edit-Turbo) ## Summary - Vendor: Boogu - Model: `Boogu/Boogu-Image-0.1-Base` (text-to-image), + `Boogu/Boogu-Image-0.1-Turbo` (four-step text-to-image), `Boogu/Boogu-Image-0.1-Edit` (image editing), and `Boogu/Boogu-Image-0.1-Edit-Turbo` (four-step image editing) - Task: Text-to-image generation and text-guided image editing (TI2I) @@ -16,8 +17,9 @@ ## When to use this recipe Use this recipe when you want a known-good starting point for serving -`Boogu/Boogu-Image-0.1-Base`, `Boogu/Boogu-Image-0.1-Edit`, or -`Boogu/Boogu-Image-0.1-Edit-Turbo` with vLLM-Omni's native pipeline (no +`Boogu/Boogu-Image-0.1-Base`, `Boogu/Boogu-Image-0.1-Turbo`, +`Boogu/Boogu-Image-0.1-Edit`, or `Boogu/Boogu-Image-0.1-Edit-Turbo` with +vLLM-Omni's native pipeline (no `--diffusion-load-format diffusers`, and the upstream `boogu` package is not required). @@ -25,12 +27,14 @@ Boogu-Image-0.1 is an Apache-2.0 unified image generation and editing model family. The Base text-to-image checkpoint pairs a Qwen3-VL multimodal encoder with a Diffusion Transformer (DiT) and a flow-match Euler scheduler with time-shift. It handles photorealistic generation and Chinese/English text -rendering. The Edit and Edit-Turbo checkpoints use the same native -`BooguImagePipeline` for image editing. +rendering. The Edit checkpoint uses the native `BooguImagePipeline`, while the +distilled Turbo and Edit-Turbo checkpoints run the four-step DMD path through +`BooguImageTurboPipeline`. ## References - Upstream model card: +- Turbo model card: - Edit model card: - Edit-Turbo 1K hotfix: - Project page: @@ -186,6 +190,19 @@ ID passed to `vllm serve`. For example, use corresponding Edit model. Base text-to-image: +## Fast text-to-image (Boogu-Image-0.1-Turbo) + +Turbo is the distilled text-to-image checkpoint. Its `model_index.json` +declares `BooguImageTurboPipeline`, which runs the four-step DMD path instead +of the scheduler-driven path used by Base. + +### Command + +```bash +vllm serve Boogu/Boogu-Image-0.1-Turbo --omni --port 8091 +``` + +### Verification ```bash curl -X POST http://localhost:8091/v1/images/generations \ @@ -230,6 +247,23 @@ curl -X POST http://localhost:8091/v1/images/edits \ checkpoint-declared FP8 configuration. With the regular checkpoints used for online FP8, the MLLM remains in BF16. The VAE and scheduler are outside this quantization routing. + "model": "Boogu/Boogu-Image-0.1-Turbo", + "prompt": "A mountain lake at sunset, photorealistic, cinematic lighting", + "size": "1024x1024", + "seed": 42 + }' | jq -r '.data[0].b64_json' | base64 -d > output-turbo.png +``` + +### Notes + +- **Required settings:** `guidance_scale=1.0` and `guidance_scale_2=1.0`; any + other value is rejected. `num_inference_steps` defaults to 4. All three are + pipeline defaults, so the request above omits them. +- **Resolution:** upstream constrains Turbo to 1K, so `1024x1024` is the + supported working resolution. The shared pipeline still clamps at 2K; larger + sizes are not validated for this checkpoint. +- **Known limitations:** the same single-GPU limitations as Base apply; CPU + offload, Cache-DiT, and multi-GPU parallelism are not yet validated. ## Image editing (Boogu-Image-0.1-Edit) @@ -354,16 +388,18 @@ curl -s http://localhost:8091/v1/chat/completions \ ## Fast image editing (Boogu-Image-0.1-Edit-Turbo) Edit-Turbo is the distilled image-editing checkpoint. Its `model_index.json` -declares `BooguImagePipeline`, so it uses the same native TI2I path as Edit. -The upstream 1K hotfix is recommended for stable results and is pinned below -to avoid silently loading the older checkpoint from the repository's default -revision. +declares `BooguImagePipeline`, so `--model-class-name BooguImageTurboPipeline` +is required to reach the four-step DMD path; without it the checkpoint is +served on the dense Edit path. The upstream 1K hotfix is recommended for +stable results and is pinned below to avoid silently loading the older +checkpoint from the repository's default revision. ### Command ```bash vllm serve Boogu/Boogu-Image-0.1-Edit-Turbo \ --omni \ + --model-class-name BooguImageTurboPipeline \ --revision hotfix-1k-20260708 \ --port 8091 ``` @@ -407,11 +443,10 @@ curl -s http://localhost:8091/v1/chat/completions \ - **Pinned revision:** use `hotfix-1k-20260708`; upstream recommends the 1K hotfix over the 1.5K variant for more stable results. -- **Recommended settings:** `num_inference_steps=4` and - `guidance_scale=1.0`. Edit-Turbo is guidance-distilled, meaning the guidance - behavior is already baked into the distilled checkpoint. A scale of `1.0` - avoids applying additional classifier-free guidance; unlike the regular Edit - checkpoint, it should not be increased to `5.0`. +- **Required settings:** `guidance_scale=1.0` and `guidance_scale_2=1.0`; the + Turbo pipeline rejects any other value, so the `guidance_scale_2=2.0` shown + for the regular Edit checkpoint does not apply here. `num_inference_steps` + defaults to 4. - **Reference images:** the same single-reference and `align_res` behavior as the regular Edit checkpoint applies. - **Known limitations:** the same single-GPU limitations as Base and Edit apply; diff --git a/tests/diffusion/models/boogu_image/test_boogu_image_registry.py b/tests/diffusion/models/boogu_image/test_boogu_image_registry.py new file mode 100644 index 000000000..8048540dc --- /dev/null +++ b/tests/diffusion/models/boogu_image/test_boogu_image_registry.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project + +"""L1 tests for checkpoint-to-pipeline routing of Boogu-Image Turbo.""" + +import json + +import pytest + +pytestmark = [pytest.mark.core_model, pytest.mark.cpu, pytest.mark.diffusion] + + +def test_turbo_registry_entry_loads_the_turbo_class(): + from vllm_omni.diffusion.models.boogu_image import BooguImageTurboPipeline + from vllm_omni.diffusion.registry import DiffusionModelRegistry + + assert DiffusionModelRegistry._try_load_model_cls("BooguImageTurboPipeline") is BooguImageTurboPipeline + + +def test_turbo_entry_disables_request_batching(): + from vllm_omni.diffusion.models.boogu_image import BooguImagePipeline, BooguImageTurboPipeline + + assert BooguImagePipeline.supports_request_batch + assert not BooguImageTurboPipeline.supports_request_batch + + +def test_turbo_process_funcs_resolve_to_the_shared_boogu_helpers(): + from vllm_omni.diffusion.models import boogu_image + from vllm_omni.diffusion.registry import _DIFFUSION_POST_PROCESS_FUNCS, _DIFFUSION_PRE_PROCESS_FUNCS + + module = boogu_image.pipeline_boogu_image + for funcs in (_DIFFUSION_PRE_PROCESS_FUNCS, _DIFFUSION_POST_PROCESS_FUNCS): + name = funcs["BooguImageTurboPipeline"] + assert name == funcs["BooguImagePipeline"] + assert callable(getattr(module, name)) + + +def test_turbo_inherits_the_base_multimodal_metadata(): + from vllm_omni.diffusion.model_metadata import get_diffusion_model_metadata + + metadata = get_diffusion_model_metadata("BooguImageTurboPipeline") + + assert metadata == get_diffusion_model_metadata("BooguImagePipeline") + assert metadata.supports_multimodal_inputs + assert metadata.max_multimodal_image_inputs == 1 + + +def test_turbo_model_index_resolves_and_enriches(tmp_path): + from vllm_omni.diffusion.data import OmniDiffusionConfig, resolve_model_class_name + + (tmp_path / "model_index.json").write_text( + json.dumps({"_class_name": "BooguImageTurboPipeline"}), + encoding="utf-8", + ) + + assert resolve_model_class_name(str(tmp_path)) == "BooguImageTurboPipeline" + + config = OmniDiffusionConfig(model=str(tmp_path)) + config.enrich_config() + + assert config.model_class_name == "BooguImageTurboPipeline" + assert config.supports_multimodal_inputs + assert config.max_multimodal_image_inputs == 1 + + +def test_edit_turbo_override_selects_the_turbo_class(tmp_path): + """Edit-Turbo publishes ``BooguImagePipeline``; ``--model-class-name`` must win.""" + from vllm_omni.diffusion.data import OmniDiffusionConfig + from vllm_omni.diffusion.registry import DiffusionModelRegistry + + (tmp_path / "model_index.json").write_text( + json.dumps({"_class_name": "BooguImagePipeline"}), + encoding="utf-8", + ) + + config = OmniDiffusionConfig(model=str(tmp_path), model_class_name="BooguImageTurboPipeline") + config.enrich_config() + + assert config.model_class_name == "BooguImageTurboPipeline" + assert DiffusionModelRegistry._try_load_model_cls(config.model_class_name)._is_turbo + + +def test_edit_turbo_without_override_keeps_the_base_class(tmp_path): + from vllm_omni.diffusion.data import OmniDiffusionConfig + from vllm_omni.diffusion.registry import DiffusionModelRegistry + + (tmp_path / "model_index.json").write_text( + json.dumps({"_class_name": "BooguImagePipeline"}), + encoding="utf-8", + ) + + config = OmniDiffusionConfig(model=str(tmp_path)) + config.enrich_config() + + assert config.model_class_name == "BooguImagePipeline" + assert not DiffusionModelRegistry._try_load_model_cls(config.model_class_name)._is_turbo diff --git a/tests/model_tests/diffusion/test_alignment.py b/tests/model_tests/diffusion/test_alignment.py index 509f113b7..183ef8659 100644 --- a/tests/model_tests/diffusion/test_alignment.py +++ b/tests/model_tests/diffusion/test_alignment.py @@ -47,6 +47,7 @@ EXCLUDED_MODELS = [ "LongCatVideoAvatarPipeline", "BagelPipeline", "BooguImagePipeline", + "BooguImageTurboPipeline", "LancePipeline", "MingImagePipeline", "InternVLAA1Pipeline", diff --git a/vllm_omni/diffusion/model_metadata.py b/vllm_omni/diffusion/model_metadata.py index 10d495cfd..c91d2ead5 100644 --- a/vllm_omni/diffusion/model_metadata.py +++ b/vllm_omni/diffusion/model_metadata.py @@ -121,6 +121,7 @@ _DIFFUSION_MODEL_METADATA_ALIASES = { "LTX2DistilledOneStagePipeline": "LTX2DistilledPipeline", "LTX2DistilledTwoStagePipeline": "LTX2DistilledPipeline", "LingBotWorldCausalDMDPipeline": "LingBotVideoPipeline", + "BooguImageTurboPipeline": "BooguImagePipeline", } diff --git a/vllm_omni/diffusion/registry.py b/vllm_omni/diffusion/registry.py index 46ddaad1d..39fff7df2 100644 --- a/vllm_omni/diffusion/registry.py +++ b/vllm_omni/diffusion/registry.py @@ -166,6 +166,11 @@ _DIFFUSION_MODELS = { "pipeline_boogu_image", "BooguImagePipeline", ), + "BooguImageTurboPipeline": ( + "boogu_image", + "pipeline_boogu_image", + "BooguImageTurboPipeline", + ), "LancePipeline": ( "lance", "pipeline_lance", @@ -549,6 +554,7 @@ _DIFFUSION_POST_PROCESS_FUNCS = { "ZImagePipeline": "get_post_process_func", "OvisImagePipeline": "get_ovis_image_post_process_func", "BooguImagePipeline": "get_boogu_image_post_process_func", + "BooguImageTurboPipeline": "get_boogu_image_post_process_func", "WanPipeline": "get_wan22_post_process_func", "WanDMDPipeline": "get_wan22_post_process_func", "WanVACEPipeline": "get_wan22_vace_post_process_func", @@ -620,6 +626,7 @@ _DIFFUSION_PRE_PROCESS_FUNCS = { "BagelPipeline": "get_bagel_pre_process_func", "GlmImagePipeline": "get_glm_image_pre_process_func", "BooguImagePipeline": "get_boogu_image_pre_process_func", + "BooguImageTurboPipeline": "get_boogu_image_pre_process_func", "QwenImageEditPipeline": "get_qwen_image_edit_pre_process_func", "QwenImageEditPlusPipeline": "get_qwen_image_edit_plus_pre_process_func", "LongCatImageEditPipeline": "get_longcat_image_edit_pre_process_func",