Files
wehub-resource-sync eec33d25b2
pre-commit / pre-commit (push) Failing after 1s
Build Wheel / build (3.11) (push) Failing after 1s
Build Wheel / build (3.12) (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 12:29:08 +08:00

517 lines
16 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
from __future__ import annotations
import pytest
from PIL import Image
from vllm_omni.diffusion.utils.param_utils import apply_declared_extra_args
from vllm_omni.inputs.data import OmniDiffusionSamplingParams
from vllm_omni.model_extras import (
build_image_to_image_prompt,
build_image_to_video_prompt,
build_text_to_image_prompt,
get_extra_body_params,
get_extra_output_params,
should_init_extra_args_for_non_diffusion_stages,
)
@pytest.mark.core_model
@pytest.mark.cpu
def test_bagel_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("BagelPipeline") == frozenset(
{
"cfg_text_scale",
"cfg_img_scale",
"cfg_interval",
"cfg_renorm_type",
"cfg_renorm_min",
"negative_prompt",
"think",
"max_think_tokens",
"do_sample",
"text_temperature",
"timestep_shift",
}
)
assert get_extra_output_params("BagelPipeline") == frozenset({"text_output", "think_text"})
assert should_init_extra_args_for_non_diffusion_stages("BagelPipeline") is True
@pytest.mark.core_model
@pytest.mark.cpu
def test_sensenova_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("SenseNovaU1Pipeline") == frozenset(
{
"think",
"cfg_scale",
"cfg_norm",
"timestep_shift",
"t_eps",
"img_cfg_scale",
"max_tokens",
}
)
assert get_extra_output_params("SenseNovaU1Pipeline") == frozenset({"think_text"})
assert should_init_extra_args_for_non_diffusion_stages("SenseNovaU1Pipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_cosmos3_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("Cosmos3OmniDiffusersPipeline") == frozenset(
{
"flow_shift",
"max_sequence_length",
"use_resolution_template",
"use_duration_template",
"use_system_prompt",
"system_prompt",
"negative_prompt",
"guardrails",
"condition_frame_indexes_vision",
"condition_video_keep",
"generate_sound",
"sound_gen",
"sound_duration",
"audio_duration",
"action_mode",
"action",
"domain_name",
"domain_id",
"raw_action_dim",
"action_chunk_size",
"action_space",
"action_fps",
"image_height",
"image_width",
"history_length",
"conditioning_fps",
"resolution",
"image_size",
"use_state",
"observation",
"robot_obs",
"deterministic_seed",
"session_id",
}
)
assert get_extra_output_params("Cosmos3OmniDiffusersPipeline") == frozenset(
{
"action",
"raw_action_dim",
"domain_id",
"action_mode",
}
)
assert should_init_extra_args_for_non_diffusion_stages("Cosmos3OmniDiffusersPipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_magi_human_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("MagiHumanPipeline") == frozenset(
{
"seconds",
"audio_path",
"image_path",
"sr_height",
"sr_width",
"sr_num_inference_steps",
}
)
assert get_extra_output_params("MagiHumanPipeline") == frozenset()
assert should_init_extra_args_for_non_diffusion_stages("MagiHumanPipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_ming_flash_omni_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("MingImagePipeline") == frozenset(
{
"height",
"width",
"steps",
"cfg",
"seed",
"byte5_text",
"negative_prompt",
}
)
assert get_extra_output_params("MingImagePipeline") == frozenset()
assert should_init_extra_args_for_non_diffusion_stages("MingImagePipeline") is True
@pytest.mark.core_model
@pytest.mark.cpu
def test_ming_flash_omni_declared_extra_args_route_into_sampling_params() -> None:
params = OmniDiffusionSamplingParams()
declared = get_extra_body_params("MingImagePipeline")
apply_declared_extra_args(
params,
declared,
{
"steps": 6,
"cfg": 1.5,
"byte5_text": ["理解与生成统一"],
"negative_prompt": "ugly, blurry",
"unknown": "ignored",
},
)
assert params.extra_args == {
"steps": 6,
"cfg": 1.5,
"byte5_text": ["理解与生成统一"],
"negative_prompt": "ugly, blurry",
}
@pytest.mark.core_model
@pytest.mark.cpu
def test_ming_flash_omni_text_to_image_prompt_builder() -> None:
assert build_text_to_image_prompt(
"MingImagePipeline",
prompt="Please draw a cute cat.",
negative_prompt="ugly, blurry",
height=512,
width=768,
) == {
"prompt": "Please draw a cute cat.",
"modalities": ["image"],
"mm_processor_kwargs": {
"modalities": ["image"],
"target_h": 512,
"target_w": 768,
},
"negative_prompt": "ugly, blurry",
}
# target_h/w are omitted when height/width are not supplied so the
# pipeline's 1024x1024 default still applies.
assert build_text_to_image_prompt(
"MingImagePipeline",
prompt="Draw a poster.",
negative_prompt=None,
) == {
"prompt": "Draw a poster.",
"modalities": ["image"],
"mm_processor_kwargs": {"modalities": ["image"]},
}
@pytest.mark.core_model
@pytest.mark.cpu
def test_ming_flash_omni_image_to_image_prompt_builder() -> None:
dummy_image = Image.new("RGB", (64, 64))
result = build_image_to_image_prompt(
"MingImagePipeline",
prompt="Change the background to a sandy beach at sunset.",
negative_prompt=None,
input_image=dummy_image,
height=256,
width=256,
)
assert result["modalities"] == ["img2img"]
assert result["multi_modal_data"]["img2img"] is dummy_image
assert result["mm_processor_kwargs"] == {
"modalities": ["img2img"],
"target_h": 256,
"target_w": 256,
}
assert "negative_prompt" not in result
@pytest.mark.core_model
@pytest.mark.cpu
def test_cosmos3_text_to_image_prompt_builder_selects_image_modality() -> None:
assert build_text_to_image_prompt(
"Cosmos3OmniDiffusersPipeline",
prompt="a red sports car at golden hour",
negative_prompt="blurry, distorted",
height=1024,
width=1024,
) == {
"prompt": "a red sports car at golden hour",
"modalities": ["image"],
"negative_prompt": "blurry, distorted",
}
assert build_text_to_image_prompt(
"Cosmos3OmniDiffusersPipeline",
prompt="a red sports car",
negative_prompt=None,
) == {"prompt": "a red sports car", "modalities": ["image"]}
@pytest.mark.core_model
@pytest.mark.cpu
def test_audiox_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("AudioXPipeline") == frozenset(
{
"audiox_task",
"seconds_start",
"seconds_total",
"sigma_min",
"sigma_max",
"cfg_rescale",
"video_path",
"audio_path",
}
)
assert get_extra_output_params("AudioXPipeline") == frozenset({"audiox_task"})
assert should_init_extra_args_for_non_diffusion_stages("AudioXPipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_audiox_declared_extra_args_route_into_sampling_params() -> None:
params = OmniDiffusionSamplingParams()
declared = get_extra_body_params("AudioXPipeline")
apply_declared_extra_args(
params,
declared,
{
"audiox_task": "t2a",
"seconds_total": 10.0,
"sigma_min": 0.03,
"unknown": "ignored",
},
)
assert params.extra_args == {
"audiox_task": "t2a",
"seconds_total": 10.0,
"sigma_min": 0.03,
}
@pytest.mark.core_model
@pytest.mark.cpu
def test_helios_extra_registry_declares_request_and_response_params() -> None:
expected_body = frozenset(
{
"is_enable_stage2",
"pyramid_num_stages",
"pyramid_num_inference_steps_list",
"is_amplify_first_chunk",
"is_skip_first_chunk",
"use_cfg_zero_star",
"use_zero_init",
"zero_steps",
"image",
"video",
"add_noise_to_image_latents",
"image_noise_sigma_min",
"image_noise_sigma_max",
"add_noise_to_video_latents",
"video_noise_sigma_min",
"video_noise_sigma_max",
}
)
# Both the base and pyramid class names resolve to the same declaration.
for cls in ("HeliosPipeline", "HeliosPyramidPipeline"):
assert get_extra_body_params(cls) == expected_body
assert get_extra_output_params(cls) == frozenset()
assert should_init_extra_args_for_non_diffusion_stages(cls) is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_vace_extra_registry_has_no_pipeline_params() -> None:
assert get_extra_body_params("WanVACEPipeline") == frozenset()
assert get_extra_output_params("WanVACEPipeline") == frozenset()
assert should_init_extra_args_for_non_diffusion_stages("WanVACEPipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_unknown_pipeline_has_empty_extra_registry() -> None:
assert get_extra_body_params("UnknownPipeline") == frozenset()
assert get_extra_output_params("UnknownPipeline") == frozenset()
assert should_init_extra_args_for_non_diffusion_stages("UnknownPipeline") is False
@pytest.mark.core_model
@pytest.mark.cpu
def test_bagel_text_to_image_prompt_builder() -> None:
assert build_text_to_image_prompt(
"BagelPipeline",
prompt="a cat",
negative_prompt="blurry",
height=512,
width=768,
) == {
"prompt": "<|im_start|>a cat<|im_end|>",
"modalities": ["image"],
"mm_processor_kwargs": {
"target_h": 512,
"target_w": 768,
"modalities": ["image"],
},
"negative_prompt": "blurry",
}
@pytest.mark.core_model
@pytest.mark.cpu
def test_bagel_image_to_image_prompt_builder() -> None:
dummy_image = Image.new("RGB", (64, 64))
result = build_image_to_image_prompt(
"BagelPipeline",
prompt="paint it",
negative_prompt="ugly",
input_image=dummy_image,
height=256,
width=256,
)
assert result["prompt"] == "<|fim_middle|><|im_start|>paint it<|im_end|>"
assert result["modalities"] == ["img2img"]
assert result["multi_modal_data"]["img2img"] is dummy_image
assert result["mm_processor_kwargs"]["target_h"] == 256
assert result["mm_processor_kwargs"]["target_w"] == 256
assert result["negative_prompt"] == "ugly"
@pytest.mark.core_model
@pytest.mark.cpu
def test_unknown_pipeline_uses_default_text_to_image_prompt() -> None:
assert build_text_to_image_prompt(
"UnknownPipeline",
prompt="a cat",
negative_prompt=None,
height=512,
width=512,
) == {"prompt": "a cat"}
@pytest.mark.core_model
@pytest.mark.cpu
def test_unknown_pipeline_uses_default_image_to_image_prompt() -> None:
dummy_image = Image.new("RGB", (64, 64))
result = build_image_to_image_prompt(
"UnknownPipeline",
prompt="edit",
negative_prompt=None,
input_image=dummy_image,
)
assert result == {
"prompt": "edit",
"multi_modal_data": {"image": dummy_image},
}
def _build_vace_prompt(media_inputs: dict[str, object], *, num_frames: int = 5) -> dict:
return build_image_to_video_prompt(
"WanVACEPipeline",
prompt="a bird flying",
negative_prompt=None,
media_inputs=media_inputs,
height=16,
width=320,
num_frames=num_frames,
)
@pytest.mark.core_model
@pytest.mark.cpu
@pytest.mark.parametrize(
"media_inputs",
[
{"image": Image.new("RGB", (320, 16), "red")},
{"last_image": Image.new("RGB", (320, 16), "blue")},
{
"image": Image.new("RGB", (320, 16), "red"),
"last_image": Image.new("RGB", (320, 16), "blue"),
},
{"image": Image.new("RGB", (320, 16), "red"), "mask": Image.new("L", (320, 16), 0)},
{"reference_images": [Image.new("RGB", (64, 64), "red")]},
],
ids=["i2v", "v2lf", "flf2v", "inpaint", "r2v"],
)
def test_vace_image_to_video_prompt_builder(media_inputs: dict[str, object]) -> None:
result = _build_vace_prompt(media_inputs)
mmd = result["multi_modal_data"]
if "reference_images" in mmd:
assert mmd["reference_images"] is media_inputs["reference_images"]
else:
assert len(mmd["video"]) == len(mmd["mask"]) == 5
@pytest.mark.core_model
@pytest.mark.cpu
@pytest.mark.parametrize(
("media_inputs", "message"),
[
({}, "requires a conditioning media input"),
({"mask": Image.new("L", (320, 16))}, "mask input requires an image"),
({"control_image": Image.new("RGB", (320, 16))}, "Unsupported VACE media input"),
],
)
def test_vace_rejects_invalid_media_combinations(media_inputs: dict[str, object], message: str) -> None:
with pytest.raises(ValueError, match=message):
_build_vace_prompt(media_inputs)
@pytest.mark.core_model
@pytest.mark.cpu
def test_declared_extra_args_apply_to_existing_sampling_params() -> None:
params = OmniDiffusionSamplingParams(extra_args={"existing": 1})
declared_extra_params: frozenset[str] = frozenset({"cfg_text_scale", "think"})
apply_declared_extra_args(
params,
declared_extra_params,
{
"cfg_text_scale": 4.0,
"think": False,
"unknown": "ignored",
},
)
assert params.extra_args == {
"existing": 1,
"cfg_text_scale": 4.0,
"think": False,
}
@pytest.mark.core_model
@pytest.mark.cpu
def test_mammothmoda2_extra_registry_declares_request_and_response_params() -> None:
assert get_extra_body_params("MammothModa2DiTPipeline") == frozenset(
{
"text_guidance_scale",
"cfg_range",
"num_inference_steps",
}
)
assert get_extra_output_params("MammothModa2DiTPipeline") == frozenset()
assert should_init_extra_args_for_non_diffusion_stages("MammothModa2DiTPipeline") is True
@pytest.mark.core_model
@pytest.mark.cpu
def test_mammothmoda2_text_to_image_prompt_builder() -> None:
# Image dims are converted to the AR grid (width/16 x height/16); the negative
# prompt is ignored (MammothModa2 t2i uses CFG, not an explicit negative path).
assert build_text_to_image_prompt(
"MammothModa2DiTPipeline",
prompt="a cat",
negative_prompt="blurry",
height=512,
width=768,
) == {
"prompt": (
"<|im_start|>system\nYou are a helpful image generator.<|im_end|>\n"
"<|im_start|>user\na cat<|im_end|>\n"
"<|im_start|>assistant\n"
"<|image start|>48*32<|image token|>"
),
"additional_information": {
"omni_task": ["t2i"],
"ar_width": [48],
"ar_height": [32],
"image_height": [512],
"image_width": [768],
},
}