Files
wehub-resource-sync 94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

363 lines
14 KiB
Python

import argparse
import math
import unittest
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from sglang.multimodal_gen.configs.pipeline_configs.ltx_2 import (
LTX2PipelineConfig,
is_ltx23_native_variant,
sync_ltx23_runtime_vae_markers,
)
from sglang.multimodal_gen.configs.sample.diffusers_generic import (
DiffusersGenericSamplingParams,
)
from sglang.multimodal_gen.configs.sample.flux import (
Flux2KleinSamplingParams,
Flux2SamplingParams,
FluxSamplingParams,
)
from sglang.multimodal_gen.configs.sample.qwenimage import QwenImageSamplingParams
from sglang.multimodal_gen.configs.sample.sampling_params import (
SamplingParams,
_json_safe,
)
from sglang.multimodal_gen.configs.sample.teacache import TeaCacheParams
from sglang.multimodal_gen.configs.sample.wan import (
FastWanT2V480PConfig,
WanI2V_14B_480P_SamplingParam,
WanI2V_14B_720P_SamplingParam,
WanT2V_1_3B_SamplingParams,
WanT2V_14B_SamplingParams,
)
class TestSamplingParamsValidate(unittest.TestCase):
def test_prompt_path_suffix(self):
with self.assertRaisesRegex(ValueError, r"prompt_path"):
SamplingParams(prompt_path="bad.png")
def test_num_outputs_per_prompt_must_be_positive(self):
with self.assertRaisesRegex(ValueError, r"num_outputs_per_prompt"):
SamplingParams(num_outputs_per_prompt=0)
def test_seed_accepts_int_or_non_empty_int_list(self):
self.assertEqual(SamplingParams(seed=7).seed, 7)
self.assertEqual(SamplingParams(seed=[7, 8]).seed, [7, 8])
with self.assertRaisesRegex(ValueError, r"seed list"):
SamplingParams(seed=[])
with self.assertRaisesRegex(ValueError, r"seed"):
SamplingParams(seed=[1, -1])
def test_fps_must_be_positive_int(self):
with self.assertRaisesRegex(ValueError, r"\bfps\b"):
SamplingParams(fps=0)
with self.assertRaisesRegex(ValueError, r"\bfps\b"):
SamplingParams(fps=None) # type: ignore[arg-type]
def test_num_inference_steps_optional_but_if_set_must_be_positive(self):
SamplingParams(num_inference_steps=None)
with self.assertRaisesRegex(ValueError, r"num_inference_steps"):
SamplingParams(num_inference_steps=-1)
def test_guidance_scale_must_be_finite_non_negative_if_set(self):
SamplingParams(guidance_scale=None)
with self.assertRaisesRegex(ValueError, r"guidance_scale"):
SamplingParams(guidance_scale=math.nan)
with self.assertRaisesRegex(ValueError, r"guidance_scale"):
SamplingParams(guidance_scale=-0.1)
def test_guidance_rescale_must_be_finite_non_negative(self):
with self.assertRaisesRegex(ValueError, r"guidance_rescale"):
SamplingParams(guidance_rescale=-1.0)
with self.assertRaisesRegex(ValueError, r"guidance_rescale"):
SamplingParams(guidance_rescale=math.inf)
def test_boundary_ratio_range(self):
SamplingParams(boundary_ratio=None)
with self.assertRaisesRegex(ValueError, r"boundary_ratio"):
SamplingParams(boundary_ratio=1.5)
with self.assertRaisesRegex(ValueError, r"boundary_ratio"):
SamplingParams(boundary_ratio=math.nan)
class TestSamplingParamsSubclass(unittest.TestCase):
def test_flux_defaults_resolution_when_not_provided(self):
params = FluxSamplingParams()
self.assertEqual(params.height, 1024)
self.assertEqual(params.width, 1024)
def test_flux_preserves_user_resolution(self):
params = FluxSamplingParams(height=640, width=768)
self.assertEqual(params.height, 640)
self.assertEqual(params.width, 768)
def test_flux_guidance_defaults_match_model_defaults(self):
self.assertEqual(FluxSamplingParams().guidance_scale, 3.5)
self.assertEqual(Flux2SamplingParams().guidance_scale, 4.0)
self.assertEqual(Flux2KleinSamplingParams().guidance_scale, 1.0)
def test_diffusers_generic_calls_base_post_init(self):
with self.assertRaises(AssertionError):
DiffusersGenericSamplingParams(num_frames=0)
def test_fastwan_480p_default_resolution_is_supported(self):
params = FastWanT2V480PConfig()
self.assertEqual((params.width, params.height), (832, 480))
self.assertIn((params.width, params.height), params.supported_resolutions)
def test_output_file_name_supports_callable_teacache_params(self):
def coefficients_callback(_: TeaCacheParams) -> list[float]:
return [1.0, 2.0, 3.0, 4.0, 5.0]
params = SamplingParams(
prompt="callable teacache",
teacache_params=TeaCacheParams(
coefficients_callback=coefficients_callback,
),
)
params._set_output_file_name()
self.assertTrue(params.output_file_name.endswith(".mp4"))
self.assertIn(
"test_sampling_params.TestSamplingParamsSubclass.test_output_file_name_supports_callable_teacache_params",
_json_safe(coefficients_callback),
)
def test_teacache_callback_takes_precedence_over_static_coefficients(self):
def coefficients_callback(_: TeaCacheParams) -> list[float]:
return [9.0, 8.0, 7.0, 6.0, 5.0]
params = TeaCacheParams(
coefficients=[1.0, 2.0, 3.0, 4.0, 5.0],
coefficients_callback=coefficients_callback,
)
self.assertEqual(params.get_coefficients(), [9.0, 8.0, 7.0, 6.0, 5.0])
def test_wan_teacache_boundaries_match_legacy_behavior(self):
legacy_equivalent_cases = [
(WanT2V_1_3B_SamplingParams().teacache_params, False, (5, 50)),
(WanT2V_1_3B_SamplingParams().teacache_params, True, (10, 100)),
(WanT2V_14B_SamplingParams().teacache_params, False, (1, 49)),
(WanT2V_14B_SamplingParams().teacache_params, True, (2, 98)),
(WanI2V_14B_480P_SamplingParam().teacache_params, False, (5, 50)),
(WanI2V_14B_480P_SamplingParam().teacache_params, True, (10, 100)),
(WanI2V_14B_720P_SamplingParam().teacache_params, False, (5, 50)),
(WanI2V_14B_720P_SamplingParam().teacache_params, True, (10, 100)),
]
for teacache_params, do_cfg, expected in legacy_equivalent_cases:
with self.subTest(
use_ret_steps=teacache_params.use_ret_steps,
do_cfg=do_cfg,
expected=expected,
):
self.assertEqual(
teacache_params.get_skip_boundaries(50, do_cfg),
expected,
)
def test_ltx23_runtime_vae_markers_sync_variant_and_decoder_metadata(self):
arch_config = LTX2PipelineConfig().vae_config.arch_config
self.assertFalse(is_ltx23_native_variant(arch_config))
self.assertEqual(arch_config.video_decoder_variant, "ltx_2")
self.assertEqual(arch_config.condition_encoder_subdir, "")
sync_ltx23_runtime_vae_markers(
arch_config,
SimpleNamespace(
arch_config=SimpleNamespace(
ltx_variant="ltx_2_3",
condition_encoder_subdir="ltx23_image_encoder",
video_decoder_variant="ltx_2_3",
video_decoder_config={"_class_name": "AutoencoderKLLTX2Video"},
)
),
)
self.assertTrue(is_ltx23_native_variant(arch_config))
self.assertEqual(arch_config.condition_encoder_subdir, "ltx23_image_encoder")
self.assertEqual(arch_config.video_decoder_variant, "ltx_2_3")
self.assertEqual(
arch_config.video_decoder_config,
{"_class_name": "AutoencoderKLLTX2Video"},
)
class TestSamplingParamsCliArgs(unittest.TestCase):
def _parse_cli_kwargs(self, argv: list[str]) -> dict:
parser = argparse.ArgumentParser()
SamplingParams.add_cli_args(parser)
args = parser.parse_args(argv)
return SamplingParams.get_cli_args(args)
def _make_qwen_image_params(self, argv: list[str]) -> QwenImageSamplingParams:
return QwenImageSamplingParams(**self._parse_cli_kwargs(argv))
def test_get_cli_args_drops_unset_sampling_params(self):
self.assertEqual(self._parse_cli_kwargs([]), {})
def test_get_cli_args_keeps_explicit_sampling_params(self):
kwargs = self._parse_cli_kwargs(
[
"--guidance-scale",
str(SamplingParams.guidance_scale),
"--negative-prompt",
SamplingParams.negative_prompt,
"--save-output",
]
)
self.assertEqual(kwargs["guidance_scale"], SamplingParams.guidance_scale)
self.assertEqual(kwargs["negative_prompt"], SamplingParams.negative_prompt)
self.assertTrue(kwargs["save_output"])
def test_get_cli_args_accepts_seed_list(self):
self.assertEqual(self._parse_cli_kwargs(["--seed", "7"])["seed"], 7)
self.assertEqual(
self._parse_cli_kwargs(["--seed", "7", "8"])["seed"],
[7, 8],
)
def test_qwen_image_cli_path_preserves_model_defaults(self):
params = self._make_qwen_image_params([])
self.assertEqual(params.negative_prompt, " ")
self.assertEqual(params.guidance_scale, 4.0)
def test_qwen_image_cli_path_allows_explicit_override_to_base_defaults(self):
params = self._make_qwen_image_params(
[
"--guidance-scale",
str(SamplingParams.guidance_scale),
"--negative-prompt",
SamplingParams.negative_prompt,
]
)
self.assertEqual(params.guidance_scale, SamplingParams.guidance_scale)
self.assertEqual(params.negative_prompt, SamplingParams.negative_prompt)
def test_merge_allows_explicit_field_matching_base_default(self):
target = DiffusersGenericSamplingParams()
user = SamplingParams(negative_prompt=SamplingParams.negative_prompt)
target._merge_with_user_params(user, explicit_fields={"negative_prompt"})
self.assertEqual(target.negative_prompt, SamplingParams.negative_prompt)
def test_cli_path_tracks_explicit_width_height_fields(self):
server_args = MagicMock()
server_args.backend = "sglang"
server_args.model_id = None
server_args.pipeline_config = MagicMock()
with patch.object(
SamplingParams,
"from_pretrained",
side_effect=lambda *args, **kwargs: Flux2SamplingParams(),
):
implicit_size = SamplingParams.from_user_sampling_params_args(
"dummy-model",
server_args=server_args,
prompt="p",
image_path="/tmp/in.png",
)
explicit_size = SamplingParams.from_user_sampling_params_args(
"dummy-model",
server_args=server_args,
prompt="p",
image_path="/tmp/in.png",
width=768,
height=512,
)
implicit_fields = set(implicit_size.build_request_extra()["explicit_fields"])
explicit_fields = set(explicit_size.build_request_extra()["explicit_fields"])
self.assertNotIn("width", implicit_fields)
self.assertNotIn("height", implicit_fields)
self.assertIn("width", explicit_fields)
self.assertIn("height", explicit_fields)
def test_cli_path_preserves_diffusers_kwargs_in_request_extra(self):
server_args = MagicMock()
server_args.backend = "sglang"
server_args.model_id = None
server_args.pipeline_config = MagicMock()
diffusers_kwargs = {"camera_to_world_path": "/tmp/camera.npy"}
with patch.object(
SamplingParams,
"from_pretrained",
side_effect=lambda *args, **kwargs: Flux2SamplingParams(),
):
params = SamplingParams.from_user_sampling_params_args(
"dummy-model",
server_args=server_args,
prompt="p",
image_path="/tmp/in.png",
diffusers_kwargs=diffusers_kwargs,
)
self.assertEqual(params.diffusers_kwargs, diffusers_kwargs)
self.assertEqual(
params.build_request_extra()["diffusers_kwargs"],
diffusers_kwargs,
)
def test_dataclasses_replace_preserves_explicit_fields(self):
"""`dataclasses.replace` drops `_explicit_fields`; DiffGenerator must restore it."""
import dataclasses
server_args = MagicMock()
server_args.backend = "sglang"
server_args.model_id = None
server_args.pipeline_config = MagicMock()
with patch.object(
SamplingParams,
"from_pretrained",
side_effect=lambda *args, **kwargs: Flux2SamplingParams(),
):
sampling_params_orig = SamplingParams.from_user_sampling_params_args(
"dummy-model",
server_args=server_args,
prompt="orig",
image_path="/tmp/in.png",
width=768,
height=512,
)
self.assertIn("width", sampling_params_orig._explicit_fields)
self.assertIn("height", sampling_params_orig._explicit_fields)
cloned = dataclasses.replace(
sampling_params_orig,
prompt="new",
output_file_name=None,
image_path="/tmp/in2.png",
)
self.assertFalse(hasattr(cloned, "_explicit_fields"))
# Mirror the restore done in DiffGenerator.generate().
cloned._explicit_fields = getattr(
sampling_params_orig, "_explicit_fields", set()
) | {"prompt", "output_file_name", "image_path"}
explicit = set(cloned.build_request_extra()["explicit_fields"])
self.assertIn("width", explicit)
self.assertIn("height", explicit)
self.assertIn("prompt", explicit)
self.assertIn("image_path", explicit)
if __name__ == "__main__":
unittest.main()