Files
vllm-omni/tests/examples/offline_inference/test_text_to_video_prompts.py
T

156 lines
5.1 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
from __future__ import annotations
import functools
import importlib.util
import sys
from types import SimpleNamespace
import pytest
import torch
from tests.examples.helpers import EXAMPLES
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
@functools.cache
def _load_text_to_video():
path = EXAMPLES / "offline_inference" / "text_to_video" / "text_to_video.py"
spec = importlib.util.spec_from_file_location("text_to_video_example", path)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@pytest.mark.parametrize(
("arguments", "expected"),
[
(["--quantization", "mxfp4"], {"quantization": "mxfp4"}),
(
["--quantization-config", '{"method":"mxfp4","w4a8_fallback_steps":[0,2]}'],
{"quantization_config": {"method": "mxfp4", "w4a8_fallback_steps": [0, 2]}},
),
],
)
def test_quantization_cli_reaches_omni(arguments, expected, monkeypatch):
mod = _load_text_to_video()
captured = {}
class StopBeforeModelLoadError(Exception):
pass
def capture_omni(**kwargs):
captured.update(kwargs)
raise StopBeforeModelLoadError
monkeypatch.setattr(sys, "argv", ["text_to_video.py", "--model", "Wan-AI/Wan2.2-T2V-A14B-Diffusers", *arguments])
monkeypatch.setattr(mod, "current_omni_platform", SimpleNamespace(device_type="cpu"))
monkeypatch.setattr(mod, "Omni", capture_omni)
with pytest.raises(StopBeforeModelLoadError):
mod.main()
assert {key: captured[key] for key in ("quantization", "quantization_config") if key in captured} == expected
def test_quantization_cli_options_are_mutually_exclusive(monkeypatch):
mod = _load_text_to_video()
monkeypatch.setattr(
sys,
"argv",
["text_to_video.py", "--quantization", "mxfp4", "--quantization-config", '{"method":"mxfp4"}'],
)
with pytest.raises(SystemExit) as exc:
mod.parse_args()
assert exc.value.code == 2
@pytest.mark.parametrize(
("negative_prompt", "expected_negative_prompt"),
[(None, None), ("", ""), ("blurry", "blurry")],
)
def test_text_to_video_builds_canonical_prompt(
negative_prompt: str | None,
expected_negative_prompt: str | None,
) -> None:
mod = _load_text_to_video()
result = mod.build_text_to_video_prompt("a robot waves", negative_prompt)
assert result["prompt"] == "a robot waves"
assert result["modalities"] == ["video"]
if expected_negative_prompt is None:
assert "negative_prompt" not in result
else:
assert result["negative_prompt"] == expected_negative_prompt
@pytest.mark.parametrize(
("model", "model_class_name", "preset_name"),
[
("Efficient-Large-Model/SANA-Video_2B_480p_diffusers", None, "sana_480p"),
("Efficient-Large-Model/SANA-Video_2B_720p_diffusers", None, "sana_720p"),
("/models/custom-checkpoint", "SanaVideoPipeline", "sana_480p"),
("robbyant/lingbot-video-dense-1.3b", None, "lingbot"),
("/models/custom-checkpoint", "LingBotVideoPipeline", "lingbot"),
("Lightricks/LTX-2", "LTX2DistilledPipeline", "ltx2_distilled"),
("BestWishYsh/Helios-Distilled", None, "helios"),
("/models/cosmos-edge", "Cosmos3EdgeVFMTransformer", "cosmos3_edge"),
("/models/vace", "WanVACEPipeline", "vace"),
],
)
def test_detect_preset_is_scoped_to_model_family(
model: str,
model_class_name: str | None,
preset_name: str,
) -> None:
mod = _load_text_to_video()
assert mod._detect_preset(model, model_class_name) is mod._MODEL_PRESETS[preset_name]
def test_lingbot_preset_matches_lingbot_defaults() -> None:
mod = _load_text_to_video()
assert mod._MODEL_PRESETS["lingbot"] == {
"model_class_name": "LingBotVideoPipeline",
"height": 192,
"width": 320,
"num_frames": 9,
"num_inference_steps": 2,
"guidance_scale": 3.0,
"fps": 24,
"flow_shift": 3.0,
"output": "lingbot_video_output.mp4",
}
def test_normalize_float_tensor_preserves_zero_to_one_frames() -> None:
mod = _load_text_to_video()
frames = torch.tensor([0.0, 0.25, 1.0, 1.5])
assert torch.equal(mod._normalize_float_tensor(frames, "zero_to_one"), torch.tensor([0.0, 0.25, 1.0, 1.0]))
def test_normalize_float_tensor_maps_negative_one_to_one_frames() -> None:
mod = _load_text_to_video()
frames = torch.tensor([-1.5, -1.0, 0.0, 1.0, 1.5])
assert torch.equal(
mod._normalize_float_tensor(frames, "negative_one_to_one"),
torch.tensor([0.0, 0.0, 0.5, 1.0, 1.0]),
)
def test_normalize_float_tensor_uses_one_contract_for_ambiguous_frames() -> None:
mod = _load_text_to_video()
frames = [torch.tensor([0.0, 0.5, 1.0]), torch.tensor([-1.0, 0.0, 1.0])]
normalized = [mod._normalize_float_tensor(frame, "negative_one_to_one") for frame in frames]
assert torch.equal(normalized[0], torch.tensor([0.5, 0.75, 1.0]))
assert torch.equal(normalized[1], torch.tensor([0.0, 0.5, 1.0]))