[Model] Add native MAGI-2 Preview diffusion support (#5918)
Signed-off-by: Hongsheng Liu <liuhongsheng4@huawei.com> Signed-off-by: hsliuustc0106 <liuhongsheng4@huawei.com>
This commit is contained in:
1 parent
13c617a140
commit
d4096e01fe
78 files changed
+9896
-459
No files matched your search
@@ -1,5 +1,5 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
||||
"""
|
||||
Unit tests for OpenAI-compatible video generation endpoints.
|
||||
"""
|
||||
@@ -635,6 +635,77 @@ def test_video_generation_bridges_request_fields(generation_request, expected_nu
|
||||
assert sampling.extra_args["duration"] == expected_duration
|
||||
|
||||
|
||||
def test_magi2_i2v_preserves_reference_geometry_for_model_preprocessing(test_client, mocker: MockerFixture):
|
||||
image_bytes = _make_test_image_bytes((48, 32))
|
||||
mocker.patch(
|
||||
"vllm_omni.entrypoints.openai.serving_video._encode_video_bytes",
|
||||
return_value=b"fake-video",
|
||||
)
|
||||
engine = test_client.app.state.openai_serving_video._engine_client
|
||||
engine.model_class_name = "Magi2Pipeline"
|
||||
|
||||
response = test_client.post(
|
||||
"/v1/videos",
|
||||
data={
|
||||
"prompt": "A bear playing with yarn.",
|
||||
"width": "96",
|
||||
"height": "64",
|
||||
},
|
||||
files={"input_reference": ("input.png", image_bytes, "image/png")},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
video_id = response.json()["id"]
|
||||
_wait_for_status(test_client, video_id, VideoGenerationStatus.COMPLETED.value)
|
||||
input_image = engine.captured_prompt["multi_modal_data"]["image"]
|
||||
assert isinstance(input_image, Image.Image)
|
||||
assert input_image.size == (48, 32)
|
||||
|
||||
|
||||
def test_magi2_serving_applies_native_defaults_and_rejects_explicit_frame_mismatch():
|
||||
engine = FakeAsyncOmni()
|
||||
engine.model_class_name = "Magi2Pipeline"
|
||||
handler = OmniOpenAIServingVideo.for_diffusion(
|
||||
diffusion_engine=engine,
|
||||
model_name="sand-ai/MAGI-2-preview",
|
||||
)
|
||||
|
||||
asyncio.run(handler._run_and_extract(VideoGenerationRequest(prompt="A fox walks through snow"), "defaults"))
|
||||
|
||||
sampling = engine.captured_sampling_params_list[0]
|
||||
assert (sampling.width, sampling.height) == (896, 512)
|
||||
assert sampling.num_frames == 125
|
||||
assert sampling.fps == sampling.frame_rate == 12.5
|
||||
assert sampling.num_inference_steps == 100
|
||||
assert "duration" not in sampling.extra_args
|
||||
|
||||
with pytest.raises(HTTPException, match="10-second clips only"):
|
||||
asyncio.run(
|
||||
handler._run_and_extract(
|
||||
VideoGenerationRequest(prompt="A fox walks through snow", seconds="5"),
|
||||
"bad-duration",
|
||||
)
|
||||
)
|
||||
with pytest.raises(HTTPException, match="10-second clips only"):
|
||||
asyncio.run(
|
||||
handler._run_and_extract(
|
||||
VideoGenerationRequest(
|
||||
prompt="A fox walks through snow",
|
||||
extra_params={"duration": 5},
|
||||
),
|
||||
"bad-duration-extra",
|
||||
)
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException, match="requires 125 frames"):
|
||||
asyncio.run(
|
||||
handler._run_and_extract(
|
||||
VideoGenerationRequest(prompt="A fox walks through snow", num_frames=1),
|
||||
"bad-frames",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_i2v_video_generation_with_image_reference_form(test_client, mocker: MockerFixture):
|
||||
mocker.patch(
|
||||
"vllm_omni.entrypoints.openai.serving_video._encode_video_bytes",
|
||||
@@ -1703,6 +1774,11 @@ def test_video_request_validation():
|
||||
assert req.quality is None
|
||||
assert req.generate_sound is False
|
||||
assert req.sound_duration is None
|
||||
assert VideoGenerationRequest(prompt="test", fps=12.5).resolve_video_params().fps == 12.5
|
||||
with pytest.raises(ValueError):
|
||||
VideoGenerationRequest(prompt="test", fps=float("inf"))
|
||||
with pytest.raises(ValueError):
|
||||
VideoGenerationRequest(prompt="test", video_params={"fps": float("nan")})
|
||||
assert VideoGenerationRequest(prompt="test", generate_sound=True, sound_duration=1.5).generate_sound is True
|
||||
with pytest.raises(ValueError):
|
||||
VideoGenerationRequest(prompt="test", size="invalid")
|
||||
@@ -2230,6 +2306,8 @@ def test_sync_sampling_params_pass_through(test_client, mocker: MockerFixture):
|
||||
"/v1/videos/sync",
|
||||
data={
|
||||
"prompt": "param pass",
|
||||
"seconds": "10",
|
||||
"fps": "12.5",
|
||||
"num_inference_steps": "30",
|
||||
"guidance_scale": "6.5",
|
||||
"seed": "42",
|
||||
@@ -2243,6 +2321,10 @@ def test_sync_sampling_params_pass_through(test_client, mocker: MockerFixture):
|
||||
assert captured.guidance_scale == 6.5
|
||||
assert captured.seed == 42
|
||||
assert captured.quality == "high"
|
||||
assert captured.num_frames == 125
|
||||
assert captured.fps == 12.5
|
||||
assert captured.frame_rate == 12.5
|
||||
assert captured.extra_args["duration"] == 10.0
|
||||
|
||||
|
||||
def test_sync_sana_wm_extra_params_payload_passes_to_engine_prompt(test_client, mocker: MockerFixture):
|
||||
|
||||
Reference in new issue
Block a user