diff --git a/.github/workflows/nightly-test-nvidia.yml b/.github/workflows/nightly-test-nvidia.yml index 5ff529fd7..d8eeff7fe 100644 --- a/.github/workflows/nightly-test-nvidia.yml +++ b/.github/workflows/nightly-test-nvidia.yml @@ -202,7 +202,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - ref: ${{ inputs.ref || github.ref }} + ref: ${{ inputs.ref || github.sha }} - name: Install dependencies run: | diff --git a/docs/cookbook/base/benchmarks/diffusion_model_benchmark.mdx b/docs/cookbook/base/benchmarks/diffusion_model_benchmark.mdx index 4c8e7a092..e4fdb6bc2 100644 --- a/docs/cookbook/base/benchmarks/diffusion_model_benchmark.mdx +++ b/docs/cookbook/base/benchmarks/diffusion_model_benchmark.mdx @@ -4,7 +4,7 @@ metatags: description: "Benchmark diffusion model serving throughput and latency with SGLang - supports image and video generation with flexible configurations." --- -`sglang.multimodal_gen.benchmarks.bench_serving` is a command-line tool designed to benchmark the online serving throughput and latency of Diffusion Models. It supports two backends (`sglang-image`, `sglang-video`) and offers flexible configurations for request rates, dataset types, and profiling. +`sglang.multimodal_gen.benchmarks.bench_serving` is a command-line tool designed to benchmark the online serving throughput and latency of diffusion models. It selects the image or video API from the requested task and offers flexible configurations for request rates, dataset types, and profiling. ## 1. Quick Start @@ -15,23 +15,23 @@ Run a benchmark on a local server (port 30000) generating 1 videos/images from t ```bash Command # For text to video: such as Wan2.2-T2V-A14B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task t2v --num-prompts 1 --max-concurrency 1 + --dataset vbench --task text-to-video --num-prompts 1 --max-concurrency 1 # For image to video: such as Wan2.2-I2V-A14B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task i2v --num-prompts 1 --max-concurrency 1 + --dataset vbench --task image-to-video --num-prompts 1 --max-concurrency 1 # For image-text to video: such as Wan2.2-TI2V-5B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task ti2v --num-prompts 1 --max-concurrency 1 + --dataset vbench --task image-to-video --num-prompts 1 --max-concurrency 1 # For text to image: such as Qwen-Image python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-image --dataset vbench --task t2i --num-prompts 1 --max-concurrency 1 + --dataset vbench --task text-to-image --num-prompts 1 --max-concurrency 1 # For image-text to image: such as Qwen-Image-Edit python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-image --dataset vbench --task ti2i --num-prompts 1 --max-concurrency 1 + --dataset vbench --task image-to-image --num-prompts 1 --max-concurrency 1 ``` ### 1.2 Benchmarking in High Concurrency @@ -41,28 +41,28 @@ Run a benchmark on a local server (port 30000) generating 20 videos/images from ```bash Command # For text to video: such as Wan2.2-T2V-A14B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task t2v --num-prompts 20 --max-concurrency 20 + --dataset vbench --task text-to-video --num-prompts 20 --max-concurrency 20 # For image to video: such as Wan2.2-I2V-A14B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task i2v --num-prompts 20 --max-concurrency 20 + --dataset vbench --task image-to-video --num-prompts 20 --max-concurrency 20 # For image-text to video: such as Wan2.2-TI2V-5B-Diffusers python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task ti2v --num-prompts 20 --max-concurrency 20 + --dataset vbench --task image-to-video --num-prompts 20 --max-concurrency 20 # For text to image: such as Qwen-Image python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-image --dataset vbench --task t2i --num-prompts 20 --max-concurrency 20 + --dataset vbench --task text-to-image --num-prompts 20 --max-concurrency 20 # For image-text to image: such as Qwen-Image-Edit python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-image --dataset vbench --task ti2i --num-prompts 20 --max-concurrency 20 + --dataset vbench --task image-to-image --num-prompts 20 --max-concurrency 20 ``` ## 2. Parameter Reference -### 2.1 Connection & Backend Settings +### 2.1 Connection Settings
| `--backend` | -**Required** | -The backend type to use. Choices: `sglang-image`, `sglang-video`. | -||||||||||
| `--base-url` | `None` | @@ -124,8 +119,8 @@ python3 -m sglang.multimodal_gen.benchmarks.bench_serving \|||||||||||
| `--task` | -`t2v`, `i2v`, `ti2v`, `t2i`, `ti2i` | -Defines the generation task: `t2v` (Text-to-Video), `i2v` (Image-to-Video), `ti2v` (Text+Image-to-Video), `t2i` (Text-to-image), `ti2i` (Text+Image-to-Image). | +`text-to-video`, `image-to-video`, `text-to-image`, `image-to-image`, `video-to-video` | +Defines the generation task when it cannot be inferred from the model metadata. | ||||||||
| `--dataset` | diff --git a/docs/cookbook/diffusion/FLUX/FLUX.mdx b/docs/cookbook/diffusion/FLUX/FLUX.mdx index a38345f6a..24bc85a0d 100644 --- a/docs/cookbook/diffusion/FLUX/FLUX.mdx +++ b/docs/cookbook/diffusion/FLUX/FLUX.mdx @@ -230,17 +230,16 @@ Test Environment: ```shell Command python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-video --dataset vbench --task t2v --num-prompts 1 --max-concurrency 1 + --dataset vbench --task text-to-image --num-prompts 1 --max-concurrency 1 ``` **Result**: ```text Output ================= Serving Benchmark Result ================= - Backend: sglang-image Model: black-forest-labs/FLUX.1-dev Dataset: vbench - Task: t2v + Task: text-to-image -------------------------------------------------- Benchmark duration (s): 50.97 Request rate: inf @@ -317,17 +316,16 @@ Test Environment: ```shell Command python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ - --backend sglang-image --dataset vbench --task t2v --num-prompts 20 --max-concurrency 20 + --dataset vbench --task text-to-image --num-prompts 20 --max-concurrency 20 ``` **Result** : ```text Output ================= Serving Benchmark Result ================= - Backend: sglang-image Model: black-forest-labs/FLUX.1-dev Dataset: vbench - Task: t2v + Task: text-to-image -------------------------------------------------- Benchmark duration (s): 111.79 Request rate: inf diff --git a/docs/cookbook/diffusion/LTX/LTX2 & LTX2.3.mdx b/docs/cookbook/diffusion/LTX/LTX2 & LTX2.3.mdx index a9801bb8a..35b9bd804 100644 --- a/docs/cookbook/diffusion/LTX/LTX2 & LTX2.3.mdx +++ b/docs/cookbook/diffusion/LTX/LTX2 & LTX2.3.mdx @@ -67,8 +67,6 @@ For two-stage pipelines, `--ltx2-two-stage-device-mode` controls transformer res | `resident` | Best latency on high-VRAM GPUs because both DiTs can stay resident. | | `original` | Closest to the original two-stage switching semantics. | -`snapshot` is kept only as a deprecated compatibility alias for `original` and may be removed after two release cycles; use `original` or `resident` in new configs. - Other deployment flags: - `--lora-path`: Preload a community LoRA adapter. diff --git a/docs/cookbook/diffusion/LingBot-Video/LingBot-Video-MoE.mdx b/docs/cookbook/diffusion/LingBot-Video/LingBot-Video-MoE.mdx new file mode 100644 index 000000000..f34043b6a --- /dev/null +++ b/docs/cookbook/diffusion/LingBot-Video/LingBot-Video-MoE.mdx @@ -0,0 +1,147 @@ +--- +title: LingBot Video MoE +description: Serve the native LingBot Video MoE 30B-A3B text-to-video model with SGLang Diffusion. +metatags: + description: "Run robbyant/lingbot-video-moe-30b-a3b text-to-video generation with SGLang Diffusion." +--- + +import { DiffusionModelTags } from '/src/snippets/diffusion/model-tags.jsx'; + +T2V, 480p | No dedicated optimization listed | ||||||||||
| LingBot Video MoE | +robbyant/lingbot-video-moe-30b-a3b |
+ T2V, 480p | +No dedicated optimization listed | +|||||||||
| Wan2.2 | Wan-AI/Wan2.2-TI2V-5B-DiffusersWan-AI/Wan2.2-T2V-A14B-Diffusersnvidia/Wan2.2-T2V-A14B-Diffusers-NVFP4Wan-AI/Wan2.2-I2V-A14B-Diffusers |
@@ -285,6 +291,21 @@ Optimization columns are abbreviated to keep the matrix readable:
❌ | ❌ | |||||||||
| LingBot Video MoE 30B-A3B | +robbyant/lingbot-video-moe-30b-a3b |
+ 480p | +❌ | +❌ | +❌ | +❌ | +❌ | +❌ | +❌ | +❌ | +❌ | +❌ | +
| FastWan2.2 TI2V 5B | FastVideo/FastWan2.2-TI2V-5B-FullAttn-DiffusersFastVideo/FastWan2.2-TI2V-5B-Diffusers |
@@ -678,7 +699,6 @@ Optimization columns are abbreviated to keep the matrix readable:
- `original` keeps official two-stage semantics without the premerged stage-2 transformer path.
- `resident` usually provides the best latency/throughput but uses much more VRAM.
- Default is auto: `resident` on H200/high-memory CUDA GPUs, otherwise `original`.
- - Deprecated compatibility: `snapshot` is accepted as an alias for `original` and may be removed after two release cycles.
5. Cosmos3 ships in two sizes — `nvidia/Cosmos3-Nano` (16B) and
`nvidia/Cosmos3-Super` (64B). Both share the same pipeline; the only
difference is transformer depth and width, picked up from
diff --git a/python/sglang/multimodal_gen/README.md b/python/sglang/multimodal_gen/README.md
index 8602dfa05..05ad5cf35 100644
--- a/python/sglang/multimodal_gen/README.md
+++ b/python/sglang/multimodal_gen/README.md
@@ -9,7 +9,7 @@ SGLang diffusion features an end-to-end unified pipeline for accelerating diffus
## Key Features
SGLang Diffusion has the following features:
- - Broad model support: Wan, FastWan, FLUX, Qwen-Image, Z-Image, Ideogram 4, Krea-2, Cosmos3, LTX-2/LTX-2.3, MiniMax-H3, LingBot World, SANA-WM, JoyEcho, MOVA, GLM-Image, ERNIE-Image, Hunyuan3D, and more
+ - Broad model support: Wan, FastWan, FLUX, Qwen-Image, Z-Image, Ideogram 4, Krea-2, Cosmos3, LTX-2/LTX-2.3, MiniMax-H3, LingBot Video MoE, LingBot World, SANA-Video/SANA-WM, JoyEcho, MOVA, GLM-Image, ERNIE-Image, Hunyuan3D, and more
- Fast inference speed: empowered by optimized `sgl-kernel` kernels, scheduler/runtime improvements, caching acceleration, and native diffusion hot-path optimizations
- Ease of use: OpenAI-compatible api, CLI, and python sdk support
- Multi-platform support:
diff --git a/python/sglang/multimodal_gen/benchmarks/bench_serving.py b/python/sglang/multimodal_gen/benchmarks/bench_serving.py
index d50f98bdf..dca9a4c28 100644
--- a/python/sglang/multimodal_gen/benchmarks/bench_serving.py
+++ b/python/sglang/multimodal_gen/benchmarks/bench_serving.py
@@ -728,12 +728,6 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Benchmark serving for diffusion models."
)
- parser.add_argument(
- "--backend",
- type=str,
- default=None,
- help="DEPRECATED: --task is deprecated and will be ignored. The task will be inferred from --model.",
- )
parser.add_argument(
"--base-url",
type=str,
diff --git a/python/sglang/multimodal_gen/runtime/entrypoints/utils.py b/python/sglang/multimodal_gen/runtime/entrypoints/utils.py
index 3eee51ed1..e964b91a1 100644
--- a/python/sglang/multimodal_gen/runtime/entrypoints/utils.py
+++ b/python/sglang/multimodal_gen/runtime/entrypoints/utils.py
@@ -639,11 +639,12 @@ def _try_save_cuda_video_direct(
stderr=stderr_file.read(),
)
return True
- except Exception as e:
- logger.warning(
- "Direct CUDA video save failed; falling back to imageio: %s",
- str(e),
+ except Exception:
+ logger.warning_once(
+ "Direct CUDA video save failed; falling back to imageio. "
+ "Enable debug logging for exception details."
)
+ logger.debug("Direct CUDA video save failure", exc_info=True)
return False
finally:
if tmp_wav_path:
@@ -725,11 +726,12 @@ def _try_save_cuda_videos_direct(
try:
with ThreadPoolExecutor(max_workers=_MAX_PARALLEL_CUDA_VIDEO_SAVES) as pool:
return list(pool.map(save_one, range(len(samples))))
- except Exception as exc:
- logger.warning(
- "Parallel CUDA video save failed; falling back to serial output: %s",
- str(exc),
+ except Exception:
+ logger.warning_once(
+ "Parallel CUDA video save failed; falling back to serial output. "
+ "Enable debug logging for exception details."
)
+ logger.debug("Parallel CUDA video save failure", exc_info=True)
return None
diff --git a/python/sglang/multimodal_gen/runtime/platforms/cuda.py b/python/sglang/multimodal_gen/runtime/platforms/cuda.py
index 5b89fb765..1c4bc869f 100644
--- a/python/sglang/multimodal_gen/runtime/platforms/cuda.py
+++ b/python/sglang/multimodal_gen/runtime/platforms/cuda.py
@@ -151,8 +151,7 @@ class _SageAttentionBackendResolver(_CudaAttentionBackendResolver):
def resolve(cls, platform) -> str | AttentionBackendEnum:
try:
from sageattention import sageattn # noqa: F401
- except ImportError as e:
- logger.info(e)
+ except ImportError:
logger.info(
"Sage Attention backend is not installed (To install it, run `pip install git+https://github.com/thu-ml/SageAttention.git@d9704247a5139ab4c03bf7fc6b35cc0e2cbb5ea4 --no-build-isolation`). Falling back to Flash Attention."
)
@@ -176,8 +175,7 @@ class _SageAttentionBackendResolver(_CudaAttentionBackendResolver):
)
return "sglang.multimodal_gen.runtime.layers.attention.backends.sage_attn.SageAttentionBackend"
- except ImportError as e:
- logger.info(e)
+ except ImportError:
logger.info(
"Sage Attention backend failed to import. Falling back to Flash Attention."
)
@@ -195,8 +193,7 @@ class _SageAttention3BackendResolver(_CudaAttentionBackendResolver):
)
return "sglang.multimodal_gen.runtime.layers.attention.backends.sage_attn3.SageAttention3Backend"
- except ImportError as e:
- logger.info(e)
+ except ImportError:
logger.info(
"Sage Attention 3 backend is not installed (To install it, see https://github.com/thu-ml/SageAttention/tree/main/sageattention3_blackwell#installation). Falling back to Torch SDPA."
)
diff --git a/python/sglang/multimodal_gen/runtime/server_args/server_args.py b/python/sglang/multimodal_gen/runtime/server_args/server_args.py
index 8fa6e1f35..043572260 100644
--- a/python/sglang/multimodal_gen/runtime/server_args/server_args.py
+++ b/python/sglang/multimodal_gen/runtime/server_args/server_args.py
@@ -86,7 +86,7 @@ from sglang.multimodal_gen.utils import (
logger = init_logger(__name__)
LTX2_TWO_STAGE_DEVICE_MODES = ("original", "resident")
-LTX2_TWO_STAGE_DEVICE_MODE_CHOICES = (*LTX2_TWO_STAGE_DEVICE_MODES, "snapshot")
+LTX2_TWO_STAGE_DEVICE_MODE_CHOICES = LTX2_TWO_STAGE_DEVICE_MODES
LTX2_TWO_STAGE_PIPELINE_NAMES = ("LTX2TwoStagePipeline", "LTX2TwoStageHQPipeline")
# H200-class GPUs (>=130 GiB total) can usually keep both LTX2 DiTs resident.
LTX2_RESIDENT_AUTO_ENABLE_MEM_GB = 130
@@ -100,15 +100,7 @@ RING_CAPABLE_ATTENTION_BACKENDS = ("fa", "sage_attn")
def _normalize_ltx2_two_stage_device_mode(mode: str | None) -> str | None:
if mode is None:
return None
- mode = mode.lower()
- if mode == "snapshot":
- logger.warning(
- "ltx2_two_stage_device_mode=snapshot is deprecated and is treated "
- "as original. Please use ltx2_two_stage_device_mode=original or "
- "resident instead. This alias may be removed after two release cycles."
- )
- return "original"
- return mode
+ return mode.lower()
def is_ltx2_two_stage_pipeline_name(pipeline_class_name: str | None) -> bool:
@@ -2211,8 +2203,6 @@ class ServerArgs(DisaggServerArgsMixin):
"LTX-2.3 two-stage device residency mode: "
"'original' keeps official two-stage semantics without premerged stage2, "
"'resident' keeps both transformers resident on GPU. "
- "'snapshot' is deprecated, treated as 'original', and may be "
- "removed after two release cycles. "
"Default is auto: resident on H200/high-memory CUDA GPUs, otherwise original."
),
)
diff --git a/python/sglang/multimodal_gen/test/unit/test_server_args.py b/python/sglang/multimodal_gen/test/unit/test_server_args.py
index 659cb0734..8a5ec7804 100644
--- a/python/sglang/multimodal_gen/test/unit/test_server_args.py
+++ b/python/sglang/multimodal_gen/test/unit/test_server_args.py
@@ -2001,24 +2001,19 @@ class TestOffloadDefaults(unittest.TestCase):
["text_encoder", "image_encoder", "vae"],
)
- def test_ltx23_snapshot_device_mode_is_deprecated_alias_for_original(self):
- args = self._from_dict_with_pipeline_config(
- LTX2PipelineConfig(),
- memory_gb=140,
- available_memory_gb=134,
- kwargs={
- "model_path": "Lightricks/LTX-2.3",
- "num_gpus": 2,
- "pipeline_class_name": "LTX2TwoStagePipeline",
- "ltx2_two_stage_device_mode": "snapshot",
- },
- )
-
- self.assertEqual(args.ltx2_two_stage_device_mode, "original")
- self.assertEqual(
- args.layerwise_offload_components,
- ["text_encoder", "image_encoder", "vae"],
- )
+ def test_ltx23_snapshot_device_mode_is_rejected(self):
+ with self.assertRaisesRegex(ValueError, "Expected one of"):
+ self._from_dict_with_pipeline_config(
+ LTX2PipelineConfig(),
+ memory_gb=140,
+ available_memory_gb=134,
+ kwargs={
+ "model_path": "Lightricks/LTX-2.3",
+ "num_gpus": 2,
+ "pipeline_class_name": "LTX2TwoStagePipeline",
+ "ltx2_two_stage_device_mode": "snapshot",
+ },
+ )
def test_explicit_layerwise_components_preserved_in_ltx23_resident(self):
args = self._from_dict_with_pipeline_config(
@@ -2425,7 +2420,7 @@ class TestOffloadDefaults(unittest.TestCase):
self.assertFalse(server_args.use_fsdp_inference)
self.assertFalse(server_args.enable_cfg_parallel)
- def test_ltx23_snapshot_device_mode_cli_alias_is_accepted(self):
+ def test_ltx23_snapshot_device_mode_cli_is_rejected(self):
parser = FlexibleArgumentParser()
ServerArgs.add_cli_args(parser)
argv = [
@@ -2437,36 +2432,8 @@ class TestOffloadDefaults(unittest.TestCase):
"snapshot",
]
- with (
- patch.object(sys, "argv", ["sglang"] + argv),
- patch.object(
- PipelineConfig, "from_kwargs", return_value=LTX2PipelineConfig()
- ),
- patch(
- "sglang.multimodal_gen.runtime.platforms.current_platform.is_cpu",
- return_value=False,
- ),
- patch(
- "sglang.multimodal_gen.runtime.platforms.current_platform.is_mps",
- return_value=False,
- ),
- patch(
- "sglang.multimodal_gen.runtime.platforms.current_platform.is_cuda",
- return_value=True,
- ),
- patch(
- "sglang.multimodal_gen.runtime.platforms.current_platform.get_device_total_memory",
- return_value=140 * 1024**3,
- ),
- patch(
- "sglang.multimodal_gen.runtime.platforms.current_platform.get_available_gpu_memory",
- return_value=134,
- ),
- ):
- args, unknown_args = parser.parse_known_args(argv)
- server_args = ServerArgs.from_cli_args(args, unknown_args)
-
- self.assertEqual(server_args.ltx2_two_stage_device_mode, "original")
+ with self.assertRaises(SystemExit):
+ parser.parse_known_args(argv)
class TestKVGatherDegree(unittest.TestCase):
diff --git a/scripts/ci/utils/diffusion/run_comparison.py b/scripts/ci/utils/diffusion/run_comparison.py
index 62c64c963..86d765130 100644
--- a/scripts/ci/utils/diffusion/run_comparison.py
+++ b/scripts/ci/utils/diffusion/run_comparison.py
@@ -868,6 +868,20 @@ def _install_framework(fw_name: str, dry_run: bool = False) -> bool:
return True
+def _get_checkout_commit_sha() -> str:
+ fallback = os.environ.get("GITHUB_SHA", "unknown")
+ try:
+ result = subprocess.run(
+ ["git", "rev-parse", "HEAD"],
+ check=True,
+ capture_output=True,
+ text=True,
+ )
+ except (OSError, subprocess.CalledProcessError):
+ return fallback
+ return result.stdout.strip() or fallback
+
+
def run_comparison(
config: dict,
case_ids: list[str] | None = None,
@@ -882,7 +896,7 @@ def run_comparison(
Each non-sglang framework is installed right before its cases run.
"""
timestamp = datetime.now(timezone.utc).isoformat()
- commit_sha = os.environ.get("GITHUB_SHA", "unknown")
+ commit_sha = _get_checkout_commit_sha()
run_id = os.environ.get("GITHUB_RUN_ID", "local")
log_dir = Path("comparison-logs")