From f3a761a4c4998347ee2e616e06f40fa6089a0c8d Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Wed, 15 Apr 2026 15:22:34 +0800 Subject: [PATCH 01/11] [Test] Add L4 complete diffusion feature test for LTX-2 model Signed-off-by: Songrui625 --- tests/conftest.py | 7 ++ .../e2e/online_serving/test_ltx2_expansion.py | 117 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tests/e2e/online_serving/test_ltx2_expansion.py diff --git a/tests/conftest.py b/tests/conftest.py index 098fd8d970c..e123c8fee43 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -77,6 +77,7 @@ class OmniServerParams(NamedTuple): use_stage_cli: bool = False init_timeout: int | None = None stage_init_timeout: int | None = None # None defers to the server's own default (300 s) + model_class_name: str | None = None def assert_image_diffusion_response( @@ -1437,6 +1438,7 @@ def __init__( port: int | None = None, env_dict: dict[str, str] | None = None, use_omni: bool = True, + model_class_name: str | None = None, ) -> None: _run_pre_test_cleanup(enable_force=True) _run_post_test_cleanup(enable_force=True) @@ -1446,6 +1448,7 @@ def __init__( self.env_dict = env_dict self.use_omni = use_omni self.proc: subprocess.Popen | None = None + self.model_class_name = model_class_name self.host = "127.0.0.1" if port is None: self.port = get_open_port() @@ -1796,6 +1799,8 @@ def omni_server(request: pytest.FixtureRequest, run_level: str, model_prefix: st server_args = [*server_args, "--init-timeout", str(params.init_timeout)] else: server_args = [*server_args, "--init-timeout", "900"] + if params.model_class_name: + server_args = [*server_args, "--model-class-name", params.model_class_name] if params.use_stage_cli: if not params.use_omni: raise ValueError("omni_server with use_stage_cli=True requires use_omni=True") @@ -1823,6 +1828,7 @@ def omni_server(request: pytest.FixtureRequest, run_level: str, model_prefix: st port=port, env_dict=params.env_dict, use_omni=params.use_omni, + model_class_name=params.model_class_name, ) if port else OmniServer( @@ -1830,6 +1836,7 @@ def omni_server(request: pytest.FixtureRequest, run_level: str, model_prefix: st server_args, env_dict=params.env_dict, use_omni=params.use_omni, + model_class_name=params.model_class_name, ) ) as server: print("OmniServer started successfully") diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py new file mode 100644 index 00000000000..cfaae19f43c --- /dev/null +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -0,0 +1,117 @@ +""" +Comprehensive tests of diffusion features that are available in online serving mode +and are supported by the LTX2 model. +- Lightricks/LTX-2 +- rootonchair/LTX-2-19b-distilled + +Coverage: +- Cache-DiT +- CFG-Parallel +- Ulysses-SP +- Ring-Attn + +assert_diffusion_response validates successful generation +""" + +import os + +import pytest + +from tests.conftest import ( + OmniServer, + OmniServerParams, + OpenAIClientHandler, + generate_synthetic_image, +) +from tests.utils import hardware_marks + +PROMPT = "Two anthropomorphic cats in comfy boxing gear and bright gloves fight intensely on a spotlighted stage." +NEGATIVE_PROMPT = "shaky, glitchy, low quality, worst quality, deformed, distorted, disfigured, motion smear, motion artifacts, fused fingers, bad anatomy, weird hand, ugly, transition, static." +SINGLE_CARD_FEATURE_MARKS = hardware_marks(res={"cuda": "H100"}) +PARALLEL_FEATURE_MARKS = hardware_marks(res={"cuda": "H100"}, num_cards=2) + +LTX2_MODELS = [ + ("Lightricks/LTX-2", "LTX2Pipeline"), + ("Lightricks/LTX-2", "LTX2ImageToVideoPipeline"), + ("rootonchair/LTX-2-19b-distilled", "LTX2TwoStagesPipeline"), + ("rootonchair/LTX-2-19b-distilled", "LTX2ImageToVideoTwoStagesPipeline"), +] + +PARALLEL_CONFIGS = [ + ("cfg_parallel", ["--cfg-parallel-size", "2"]), + ("ulysses_sp", ["--usp", "2"]), + ("ring_atten", ["--ring", "2"]), +] + + +def _get_ltx2_feature_cases(): + cases = [] + + # Single-card: Cache-DiT (applies to all models) + for model_path, model_cls_name in LTX2_MODELS: + cases.append( + pytest.param( + OmniServerParams( + model=model_path, + model_class_name=model_cls_name, + server_args=["--cache-backend", "cache_dit"], + ), + id=f"{model_cls_name}_cache_dit", + marks=SINGLE_CARD_FEATURE_MARKS, + ) + ) + + # Multi-card features + for model_path, model_cls_name in LTX2_MODELS: + for feat_id, server_args in PARALLEL_CONFIGS: + cases.append( + pytest.param( + OmniServerParams( + model=model_path, + model_class_name=model_cls_name, + server_args=server_args.extend(["--model-class-name", model_cls_name]), + ), + id=f"{model_cls_name}_{feat_id}", + marks=PARALLEL_FEATURE_MARKS, + ) + ) + + return cases + + +@pytest.mark.advanced_model +@pytest.mark.diffusion +@pytest.mark.parametrize( + "omni_server", + _get_ltx2_feature_cases(), + indirect=True, +) +def test_ltx2_diffusion_features( + omni_server: OmniServer, + openai_client: OpenAIClientHandler, +): + model_path = omni_server.model + model_name = os.path.basename(os.path.normpath(model_path)) + model_class_name = omni_server.model_class_name + is_distilled_model = model_name == "LTX-2-19b-distilled" + is_i2v = "ImageToVideo" in model_class_name + + form_data = { + "prompt": PROMPT, + "negative_prompt": NEGATIVE_PROMPT, + "height": 768, + "width": 512, + "num_inference_steps": 2, + "guidance_scale": 1.0 if is_distilled_model else 4.0, + "seed": 42, + } + + request_config = { + "model": model_path, + "form_data": form_data, + } + + if is_i2v: + request_config["image_reference"] = f"data:image/jpeg;base64,{generate_synthetic_image(512, 512)['base64']}" + + openai_client.send_video_diffusion_request(request_config) From 14a6755854fad59fc342026b3737c86e0b653c9b Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Wed, 15 Apr 2026 15:29:18 +0800 Subject: [PATCH 02/11] Fix incorrect expected_weight and expected_height for LTX-2 two-stages pipeline in L4 tests Signed-off-by: Songrui625 --- tests/conftest.py | 7 +++++++ tests/e2e/online_serving/test_ltx2_expansion.py | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index e123c8fee43..351ec56d9e4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -149,6 +149,13 @@ def assert_video_diffusion_response( expected_width = _maybe_int(form_data.get("width")) expected_height = _maybe_int(form_data.get("height")) expected_fps = _maybe_int(form_data.get("fps")) + # check for LTX-2 two-stages pipeline + model_class_name = request_config.get("model_class_name", None) + if model_class_name is not None and ( + model_class_name == "LTX2TwoStagesPipeline" or model_class_name == "LTX2ImageToVideoTwoStagesPipeline" + ): + expected_height *= 2 + expected_width *= 2 for vid_bytes in response.videos: assert_video_valid( diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py index cfaae19f43c..00c9af1bb90 100644 --- a/tests/e2e/online_serving/test_ltx2_expansion.py +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -109,9 +109,10 @@ def test_ltx2_diffusion_features( request_config = { "model": model_path, "form_data": form_data, + "model_class_name": model_class_name, # use for validate diffusion response for two-stages pipeline } if is_i2v: - request_config["image_reference"] = f"data:image/jpeg;base64,{generate_synthetic_image(512, 512)['base64']}" + request_config["image_reference"] = f"data:image/jpeg;base64,{generate_synthetic_image(758, 512)['base64']}" openai_client.send_video_diffusion_request(request_config) From f0756914d0a8e563cc492345fdb9e056ebf01c27 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Mon, 20 Apr 2026 12:08:33 +0800 Subject: [PATCH 03/11] Add layerwise offload feature test Signed-off-by: Songrui625 --- tests/e2e/online_serving/test_ltx2_expansion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py index 00c9af1bb90..0f39a105974 100644 --- a/tests/e2e/online_serving/test_ltx2_expansion.py +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -54,7 +54,7 @@ def _get_ltx2_feature_cases(): OmniServerParams( model=model_path, model_class_name=model_cls_name, - server_args=["--cache-backend", "cache_dit"], + server_args=["--cache-backend", "cache_dit", "--enable-layerwise-offload"], ), id=f"{model_cls_name}_cache_dit", marks=SINGLE_CARD_FEATURE_MARKS, From 9cd2c19a95510fa43e3c110fea7ac0dd3fa3b8c4 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 14:27:20 +0800 Subject: [PATCH 04/11] Add argument 'model_class_name' to speficy pipeline to run Signed-off-by: Songrui625 --- tests/helpers/runtime.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/helpers/runtime.py b/tests/helpers/runtime.py index 190cb66b4af..f0caa11ba74 100644 --- a/tests/helpers/runtime.py +++ b/tests/helpers/runtime.py @@ -118,6 +118,7 @@ class OmniServerParams(NamedTuple): use_stage_cli: bool = False init_timeout: int | None = None stage_init_timeout: int | None = None # None: fixture supplies default (600 s) + model_class_name: str | None = None class OmniServer: @@ -131,6 +132,7 @@ def __init__( port: int | None = None, env_dict: dict[str, str] | None = None, use_omni: bool = True, + model_class_name: str | None = None, ) -> None: run_forced_gpu_cleanup_round() cleanup_dist_env_and_memory() @@ -138,6 +140,7 @@ def __init__( self.serve_args = serve_args self.env_dict = env_dict self.use_omni = use_omni + self.model_class_name = model_class_name self.proc: subprocess.Popen | None = None self.host = "127.0.0.1" self.port = get_open_port() if port is None else port @@ -161,6 +164,8 @@ def _start_server(self) -> None: ] if self.use_omni: cmd.append("--omni") + if self.model_class_name: + cmd.append(f"--model-class-name {self.model_class_name}") cmd += self.serve_args print(f"Launching OmniServer with: {' '.join(cmd)}") From 6fe275232cce7e08009eb0b27558c7f93c3cd236 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 14:32:39 +0800 Subject: [PATCH 05/11] Fix import Signed-off-by: Songrui625 --- tests/e2e/online_serving/test_ltx2_expansion.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py index 0f39a105974..7e1938fc0b6 100644 --- a/tests/e2e/online_serving/test_ltx2_expansion.py +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -17,13 +17,15 @@ import pytest -from tests.conftest import ( +from tests.helpers.mark import hardware_marks +from tests.helpers.media import ( + generate_synthetic_image, +) +from tests.helpers.runtime import ( OmniServer, OmniServerParams, OpenAIClientHandler, - generate_synthetic_image, ) -from tests.utils import hardware_marks PROMPT = "Two anthropomorphic cats in comfy boxing gear and bright gloves fight intensely on a spotlighted stage." NEGATIVE_PROMPT = "shaky, glitchy, low quality, worst quality, deformed, distorted, disfigured, motion smear, motion artifacts, fused fingers, bad anatomy, weird hand, ugly, transition, static." From 82688f94cf5fdcffb4a777197eacb4a06e66cbbc Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 14:50:16 +0800 Subject: [PATCH 06/11] Fix missing passed argument model_class_name Signed-off-by: Songrui625 --- tests/e2e/online_serving/test_ltx2_expansion.py | 2 +- tests/helpers/fixtures/runtime.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py index 7e1938fc0b6..c91f5ebbf4a 100644 --- a/tests/e2e/online_serving/test_ltx2_expansion.py +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -71,7 +71,7 @@ def _get_ltx2_feature_cases(): OmniServerParams( model=model_path, model_class_name=model_cls_name, - server_args=server_args.extend(["--model-class-name", model_cls_name]), + server_args=server_args, ), id=f"{model_cls_name}_{feat_id}", marks=PARALLEL_FEATURE_MARKS, diff --git a/tests/helpers/fixtures/runtime.py b/tests/helpers/fixtures/runtime.py index 4cae13cd6eb..d9c55d3de75 100644 --- a/tests/helpers/fixtures/runtime.py +++ b/tests/helpers/fixtures/runtime.py @@ -90,6 +90,7 @@ def omni_server(request: pytest.FixtureRequest, run_level: str, model_prefix: st port=port, env_dict=params.env_dict, use_omni=params.use_omni, + model_class_name=params.model_class_name, ) if port else OmniServer( @@ -97,6 +98,7 @@ def omni_server(request: pytest.FixtureRequest, run_level: str, model_prefix: st server_args, env_dict=params.env_dict, use_omni=params.use_omni, + model_class_name=params.model_class_name, ) ) as server: print("OmniServer started successfully") From e058452cc3a1ddefa3a90ced753d8540a9614c53 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 14:54:54 +0800 Subject: [PATCH 07/11] Fix incorrect expected_weight and expected_height for LTX-2 two-stage pipeline Signed-off-by: Songrui625 --- tests/helpers/assertions.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/helpers/assertions.py b/tests/helpers/assertions.py index 604b76b62ec..ad4332f775a 100644 --- a/tests/helpers/assertions.py +++ b/tests/helpers/assertions.py @@ -97,6 +97,12 @@ def assert_video_diffusion_response( expected_width = _maybe_int(form_data.get("width")) expected_height = _maybe_int(form_data.get("height")) expected_fps = _maybe_int(form_data.get("fps")) + model_class_name = request_config.get("model_class_name", None) + if model_class_name is not None and ( + model_class_name == "LTX2TwoStagesPipeline" or model_class_name == "LTX2ImageToVideoTwoStagesPipeline" + ): + expected_height *= 2 + expected_width *= 2 for vid_bytes in response.videos: assert_video_valid( From a2a752ac794951db697b81b8459499079fefdcc4 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 15:07:19 +0800 Subject: [PATCH 08/11] Fix mistake server_args for cmd args Signed-off-by: Songrui625 --- tests/helpers/runtime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/helpers/runtime.py b/tests/helpers/runtime.py index f0caa11ba74..c5a821ab348 100644 --- a/tests/helpers/runtime.py +++ b/tests/helpers/runtime.py @@ -165,7 +165,7 @@ def _start_server(self) -> None: if self.use_omni: cmd.append("--omni") if self.model_class_name: - cmd.append(f"--model-class-name {self.model_class_name}") + self.server_args.append(f"--model-class-name {self.model_class_name}") cmd += self.serve_args print(f"Launching OmniServer with: {' '.join(cmd)}") From 6e1efc4f9fa4785dc92284ef579cf07868505b06 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 15:08:35 +0800 Subject: [PATCH 09/11] Fix typo Signed-off-by: Songrui625 --- tests/helpers/runtime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/helpers/runtime.py b/tests/helpers/runtime.py index c5a821ab348..0dd4ad22d4e 100644 --- a/tests/helpers/runtime.py +++ b/tests/helpers/runtime.py @@ -165,7 +165,7 @@ def _start_server(self) -> None: if self.use_omni: cmd.append("--omni") if self.model_class_name: - self.server_args.append(f"--model-class-name {self.model_class_name}") + self.serve_args.append(f"--model-class-name {self.model_class_name}") cmd += self.serve_args print(f"Launching OmniServer with: {' '.join(cmd)}") From 7107adb71ed040431d07ab359637038993272225 Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 15:28:50 +0800 Subject: [PATCH 10/11] Fix incorrect passed argument list Signed-off-by: Songrui625 --- tests/helpers/runtime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/helpers/runtime.py b/tests/helpers/runtime.py index 0dd4ad22d4e..a65c9f12ca2 100644 --- a/tests/helpers/runtime.py +++ b/tests/helpers/runtime.py @@ -165,7 +165,7 @@ def _start_server(self) -> None: if self.use_omni: cmd.append("--omni") if self.model_class_name: - self.serve_args.append(f"--model-class-name {self.model_class_name}") + self.serve_args.extend(["--model-class-name", self.model_class_name]) cmd += self.serve_args print(f"Launching OmniServer with: {' '.join(cmd)}") From 6317e001b25d97e1bb28c3c99dac6006dd9b36ca Mon Sep 17 00:00:00 2001 From: Songrui625 Date: Thu, 23 Apr 2026 15:35:28 +0800 Subject: [PATCH 11/11] Add hsdp test Signed-off-by: Songrui625 --- tests/e2e/online_serving/test_ltx2_expansion.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/online_serving/test_ltx2_expansion.py b/tests/e2e/online_serving/test_ltx2_expansion.py index c91f5ebbf4a..8a020acab58 100644 --- a/tests/e2e/online_serving/test_ltx2_expansion.py +++ b/tests/e2e/online_serving/test_ltx2_expansion.py @@ -43,6 +43,7 @@ ("cfg_parallel", ["--cfg-parallel-size", "2"]), ("ulysses_sp", ["--usp", "2"]), ("ring_atten", ["--ring", "2"]), + ("hsdp", ["--use-hsdp", "--hsdp-shard-size", "2"]), ]