From 70fe2e0dd5e69a062fb146d0db35c7ac939f111f Mon Sep 17 00:00:00 2001 From: Mick Date: Sun, 2 Aug 2026 22:32:37 +0800 Subject: [PATCH] [diffusion] model: support minimax-h3 (#33275) Co-authored-by: zhenaozhenfu Co-authored-by: BBuf <1182563586@qq.com> Co-authored-by: andyluo7 Co-authored-by: Zijie Xia Co-authored-by: Claude Fable 5 Co-authored-by: chao-xue <877184285@qq.com> Co-authored-by: Cursor --- .github/workflows/pr-test-multimodal-gen.yml | 49 + .github/workflows/release-docker-dev.yml | 69 +- .../cookbook/diffusion/MiniMax/MiniMax-H3.mdx | 807 ++++++++ docs_new/cookbook/diffusion/intro.mdx | 6 + docs_new/docs.json | 7 + docs_new/docs/sglang-diffusion/api/cli.mdx | 10 +- docs_new/docs/sglang-diffusion/cache_dit.mdx | 7 +- .../sglang-diffusion/compatibility_matrix.mdx | 21 + .../docs/sglang-diffusion/quantization.mdx | 5 + docs_new/scripts/check_cookbook_configs.mjs | 13 +- docs_new/src/snippets/_deployment.jsx | 107 +- docs_new/src/snippets/_playground.jsx | 6 +- .../snippets/configs/MiniMaxAI/minimax-h3.jsx | 618 ++++++ .../jit/csrc/diffusion/qknorm_rope.cuh | 106 +- .../jit/csrc/diffusion/usp_relayout.cuh | 182 ++ .../jit/csrc/elementwise/activation.cuh | 65 +- .../kernels/ops/activation/activation.py | 56 +- .../kernels/ops/diffusion/qknorm_rope.py | 44 +- .../diffusion/triton/indexed_modulation.py | 143 ++ .../ops/diffusion/triton/scale_shift.py | 75 + .../ops/diffusion/triton/ulysses_qkv.py | 94 + .../kernels/ops/diffusion/usp_relayout.py | 83 + python/sglang/multimodal_gen/README.md | 2 +- .../benchmarks/bench_serving.py | 50 +- .../configs/models/dits/__init__.py | 2 + .../configs/models/dits/minimax_h3.py | 65 + .../configs/models/encoders/__init__.py | 6 + .../models/encoders/minimax_h3_qwen3vl.py | 57 + .../configs/models/vaes/__init__.py | 8 + .../configs/models/vaes/minimax_h3_audio.py | 35 + .../models/vaes/minimax_h3_contract.py | 78 + .../configs/models/vaes/minimax_h3_video.py | 68 + .../configs/pipeline_configs/__init__.py | 4 + .../configs/pipeline_configs/base.py | 10 + .../configs/pipeline_configs/minimax_h3.py | 190 ++ .../model_deployment_config.py | 4 + .../configs/sample/minimax_h3.py | 305 +++ .../configs/sample/sampling_params.py | 79 +- python/sglang/multimodal_gen/registry.py | 14 + .../model_padders/minimax_h3.py | 163 ++ .../breakable_cuda_graph/prompt_padding.py | 1 + .../runtime/cache/cache_dit_integration.py | 17 + .../device_communicators/ipc_a2a.py | 9 + .../entrypoints/diffusion_generator.py | 54 +- .../runtime/entrypoints/openai/protocol.py | 3 + .../runtime/entrypoints/openai/utils.py | 6 +- .../runtime/entrypoints/openai/video_api.py | 395 +++- .../runtime/entrypoints/utils.py | 6 +- .../layers/attention/backends/aiter.py | 41 +- .../attention/backends/attention_backend.py | 14 + .../layers/attention/backends/flash_attn.py | 25 + .../runtime/layers/attention/backends/sdpa.py | 31 +- .../multimodal_gen/runtime/layers/usp.py | 47 +- .../component_loaders/component_loader.py | 7 +- .../component_loaders/image_encoder_loader.py | 1 - .../component_loaders/text_encoder_loader.py | 45 +- .../component_loaders/transformer_loader.py | 28 +- .../loader/component_loaders/vae_loader.py | 26 +- .../runtime/loader/fsdp_load.py | 19 +- .../runtime/loader/transformer_load_utils.py | 7 +- .../runtime/loader/weight_utils.py | 8 +- .../runtime/managers/gpu_worker.py | 18 + .../memory_managers/layerwise_offload.py | 27 +- .../runtime/models/dits/minimax_h3.py | 1692 +++++++++++++++++ .../runtime/models/encoders/base.py | 6 +- .../models/encoders/minimax_h3_qwen3vl.py | 193 ++ .../runtime/models/encoders/qwen3vl.py | 84 +- .../scheduling_minimax_h3_euler_ancestral.py | 214 +++ .../runtime/models/vaes/minimax_h3.py | 118 ++ .../vaes/minimax_h3_audio_vae/__init__.py | 5 + .../vaes/minimax_h3_audio_vae/alias_free.py | 177 ++ .../vaes/minimax_h3_audio_vae/audio_vae.py | 307 +++ .../vaes/minimax_h3_audio_vae/bigvgan.py | 255 +++ .../vaes/minimax_h3_video_vae/__init__.py | 5 + .../vaes/minimax_h3_video_vae/attention.py | 174 ++ .../vaes/minimax_h3_video_vae/base_module.py | 281 +++ .../models/vaes/minimax_h3_video_vae/conv.py | 83 + .../models/vaes/minimax_h3_video_vae/flash.py | 190 ++ .../models/vaes/minimax_h3_video_vae/klvae.py | 1297 +++++++++++++ .../models/vaes/minimax_h3_video_vae/norm.py | 283 +++ .../vaes/minimax_h3_video_vae/processor.py | 279 +++ .../vaes/minimax_h3_video_vae/vae_cnn.py | 276 +++ .../vaes/minimax_h3_video_vae/vae_vit.py | 374 ++++ .../vaes/minimax_h3_video_vae/vit_utils.py | 255 +++ .../runtime/pipelines/minimax_h3_pipeline.py | 152 ++ .../pipelines_core/composed_pipeline_base.py | 55 +- .../runtime/pipelines_core/stages/decoding.py | 22 +- .../runtime/pipelines_core/stages/dedup.py | 9 +- .../pipelines_core/stages/denoising.py | 37 +- .../minimax_h3/__init__.py | 21 + .../minimax_h3/canvas.py | 278 +++ .../minimax_h3/condition_noise.py | 194 ++ .../minimax_h3/constants.py | 37 + .../minimax_h3/denoise_loop.py | 519 +++++ .../minimax_h3/keyframe_encoding.py | 139 ++ .../minimax_h3/material_io.py | 913 +++++++++ .../minimax_h3/packed_sequence.py | 502 +++++ .../minimax_h3/packed_tokens.py | 104 + .../minimax_h3/prequeue.py | 346 ++++ .../minimax_h3/presentation.py | 278 +++ .../minimax_h3/reference_encoding.py | 741 ++++++++ .../minimax_h3/release_metadata.py | 221 +++ .../minimax_h3/request_validation.py | 361 ++++ .../minimax_h3/resolved_plan.py | 447 +++++ .../minimax_h3/stages/__init__.py | 2 + .../minimax_h3/stages/audio_encoding.py | 211 ++ .../minimax_h3/stages/decoding.py | 435 +++++ .../minimax_h3/stages/denoising.py | 963 ++++++++++ .../minimax_h3/stages/latent_preparation.py | 177 ++ .../minimax_h3/stages/replica_broadcast.py | 59 + .../minimax_h3/stages/text_encoding.py | 524 +++++ .../minimax_h3/stages/timestep_preparation.py | 183 ++ .../minimax_h3/stages/visual_encoding.py | 358 ++++ .../minimax_h3/task_profiles.py | 289 +++ .../minimax_h3/time_request.py | 59 + .../minimax_h3/video_adapter.py | 545 ++++++ .../runtime/platforms/__init__.py | 21 + .../multimodal_gen/runtime/platforms/aiter.py | 2 + .../runtime/server_args/auto_tune.py | 15 +- .../runtime/server_args/server_args.py | 74 +- .../runtime/utils/hf_diffusers_utils.py | 102 +- .../runtime/warmup_request_builder.py | 3 + .../multimodal_gen/test/server/gpu_cases.py | 68 + .../test/server/test_server_4_gpu_h100.py | 18 + .../test/unit/test_cache_dit_integration.py | 50 +- .../test/unit/test_diffusion_bcg_padding.py | 92 + .../test/unit/test_encoder_world_folding.py | 12 +- .../test/unit/test_fsdp_load.py | 94 + .../test/unit/test_gpu_worker_cpu_threads.py | 42 + .../test/unit/test_hf_diffusers_utils.py | 94 + .../test/unit/test_layerwise_offload.py | 51 + .../test/unit/test_minimax_h3_admission.py | 295 +++ .../test/unit/test_minimax_h3_denoise_loop.py | 195 ++ .../test/unit/test_minimax_h3_dit_contract.py | 288 +++ .../test/unit/test_minimax_h3_media.py | 117 ++ .../unit/test_minimax_h3_packed_sequence.py | 156 ++ .../test_minimax_h3_vae_parallel_modes.py | 51 + .../test/unit/test_multi_output_grouping.py | 10 + .../test/unit/test_platform_detection.py | 42 + .../test/unit/test_sampling_params.py | 13 + .../test/unit/test_server_args.py | 116 +- .../test/unit/test_text_encoder_loader.py | 23 + .../test/unit/test_transformer_quant.py | 41 + .../test/unit/test_video_api_profiling.py | 50 + python/sglang/utils.py | 4 + .../kernels/ops/diffusion/test_qknorm_rope.py | 57 +- .../ops/diffusion/test_usp_relayout.py | 69 + ...st_batch_result_processor_hidden_states.py | 2 +- 148 files changed, 22186 insertions(+), 358 deletions(-) create mode 100644 docs_new/cookbook/diffusion/MiniMax/MiniMax-H3.mdx create mode 100644 docs_new/src/snippets/configs/MiniMaxAI/minimax-h3.jsx create mode 100644 python/sglang/kernels/jit/csrc/diffusion/usp_relayout.cuh create mode 100644 python/sglang/kernels/ops/diffusion/triton/indexed_modulation.py create mode 100644 python/sglang/kernels/ops/diffusion/triton/ulysses_qkv.py create mode 100644 python/sglang/kernels/ops/diffusion/usp_relayout.py create mode 100644 python/sglang/multimodal_gen/configs/models/dits/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/configs/models/encoders/minimax_h3_qwen3vl.py create mode 100644 python/sglang/multimodal_gen/configs/models/vaes/minimax_h3_audio.py create mode 100644 python/sglang/multimodal_gen/configs/models/vaes/minimax_h3_contract.py create mode 100644 python/sglang/multimodal_gen/configs/models/vaes/minimax_h3_video.py create mode 100644 python/sglang/multimodal_gen/configs/pipeline_configs/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/configs/sample/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/runtime/breakable_cuda_graph/model_padders/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/runtime/models/dits/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/runtime/models/encoders/minimax_h3_qwen3vl.py create mode 100644 python/sglang/multimodal_gen/runtime/models/schedulers/scheduling_minimax_h3_euler_ancestral.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_audio_vae/__init__.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_audio_vae/alias_free.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_audio_vae/audio_vae.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_audio_vae/bigvgan.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/__init__.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/attention.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/base_module.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/conv.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/flash.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/klvae.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/norm.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/processor.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/vae_cnn.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/vae_vit.py create mode 100644 python/sglang/multimodal_gen/runtime/models/vaes/minimax_h3_video_vae/vit_utils.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines/minimax_h3_pipeline.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/__init__.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/canvas.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/condition_noise.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/constants.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/denoise_loop.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/keyframe_encoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/material_io.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_sequence.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/packed_tokens.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/prequeue.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/presentation.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/reference_encoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/release_metadata.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/request_validation.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/resolved_plan.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/__init__.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/audio_encoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/decoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/denoising.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/latent_preparation.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/replica_broadcast.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/text_encoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/timestep_preparation.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/visual_encoding.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/task_profiles.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/time_request.py create mode 100644 python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/video_adapter.py create mode 100644 python/sglang/multimodal_gen/test/server/test_server_4_gpu_h100.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_fsdp_load.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_gpu_worker_cpu_threads.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_admission.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_denoise_loop.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_dit_contract.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_media.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_packed_sequence.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_minimax_h3_vae_parallel_modes.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_platform_detection.py create mode 100644 python/sglang/multimodal_gen/test/unit/test_video_api_profiling.py create mode 100644 test/registered/kernels/ops/diffusion/test_usp_relayout.py diff --git a/.github/workflows/pr-test-multimodal-gen.yml b/.github/workflows/pr-test-multimodal-gen.yml index 8cf90602a..c70ba0e12 100644 --- a/.github/workflows/pr-test-multimodal-gen.yml +++ b/.github/workflows/pr-test-multimodal-gen.yml @@ -435,6 +435,55 @@ jobs: - uses: ./.github/actions/upload-cuda-coredumps if: failure() + multimodal-gen-test-4-h100: + # Temporarily disabled while the 4-gpu-h100 runner is unstable + if: ${{ false }} + runs-on: 4-gpu-h100 + timeout-minutes: 90 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.git_ref || github.sha }} + + - uses: ./.github/actions/check-pr-test-health + + - uses: ./.github/actions/check-maintenance + + - name: Download artifacts + if: inputs.sgl_kernel == 'true' + uses: actions/download-artifact@v4 + with: + path: python/sglang/kernels/aot/dist/ + merge-multiple: true + pattern: wheel-python3.10-cuda* + + - name: Install dependencies + timeout-minutes: 20 + run: | + CUSTOM_BUILD_SGL_KERNEL=${{inputs.sgl_kernel}} bash scripts/ci/cuda/ci_install_dependency.sh diffusion + + - name: Run MiniMax-H3 PR smoke test + timeout-minutes: 45 + env: + RUNAI_STREAMER_MEMORY_LIMIT: 0 + SGLANG_TEST_WAIT_SECS: 1800 + SGLANG_DIFFUSION_ARTIFACT_DIR: ${{ github.workspace }}/diffusion-failures + run: | + cd python + python3 sglang/multimodal_gen/test/run_suite.py --suite 4-gpu-h100 + + - name: Upload diffusion failure artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: diffusion-failures-${{ github.job }}-${{ github.run_attempt }} + path: diffusion-failures/ + if-no-files-found: ignore + + - uses: ./.github/actions/upload-cuda-coredumps + if: failure() + multimodal-gen-unit-test: if: | ((github.event_name == 'schedule' || inputs.test_parallel_dispatch == 'true') || (inputs.caller_needs_failure != 'true' && !cancelled())) && diff --git a/.github/workflows/release-docker-dev.yml b/.github/workflows/release-docker-dev.yml index b48126e8c..855903a63 100644 --- a/.github/workflows/release-docker-dev.yml +++ b/.github/workflows/release-docker-dev.yml @@ -15,6 +15,11 @@ on: description: "Docker Hub repo to push to. Use lmsysorg/sglang-staging for testing." required: false default: "lmsysorg/sglang" + build_only: + description: "Build and validate one Linux AMD64 CUDA 13 image locally on the runner without logging in or pushing." + required: false + type: boolean + default: false overlay_dockerfile: description: "Optional extra Dockerfile lines appended after FROM to build a layered image (e.g. 'RUN pip install ...'). Note: this job has no repo checkout, so only FROM + RUN work — you cannot COPY files from this repo. Leave empty to skip overlay." required: false @@ -135,6 +140,7 @@ jobs: build-and-publish: needs: prepare + if: ${{ !inputs.build_only }} uses: ./.github/workflows/_docker-build-and-publish.yml with: docker_target: framework_final @@ -144,9 +150,68 @@ jobs: image_repo: ${{ inputs.image_repo || 'lmsysorg/sglang' }} secrets: inherit + build-only: + needs: prepare + if: ${{ inputs.build_only && github.repository == 'sgl-project/sglang' }} + runs-on: x64-docker-build-node + env: + IMAGE: sglang-diffusion-build-only:${{ github.run_id }}-${{ github.run_attempt }} + SOURCE_DIR: source-${{ github.run_id }}-${{ github.run_attempt }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare.outputs.checkout_ref || github.ref }} + path: ${{ env.SOURCE_DIR }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build CUDA 13 diffusion image locally (no push) + run: | + cd "$SOURCE_DIR" + docker buildx build \ + --target framework_final \ + --platform linux/amd64 \ + --load \ + -t "$IMAGE" \ + -f docker/Dockerfile \ + --build-arg CUDA_VERSION=13.0.1 \ + --build-arg BUILD_TYPE=all \ + --build-arg GRACE_BLACKWELL=0 \ + --build-arg INSTALL_FLASHINFER_JIT_CACHE=1 \ + ${{ needs.prepare.outputs.extra_build_args }} \ + --no-cache \ + . + + - name: Verify diffusion dependencies + run: | + docker run --rm "$IMAGE" python3 -c ' + import importlib + modules = ( + "av", + "cache_dit", + "cv2", + "diffusers", + "imageio_ffmpeg", + "moviepy", + "msgpack", + "sglang.multimodal_gen", + "soundfile", + "trimesh", + ) + for module in modules: + importlib.import_module(module) + print("diffusion dependency smoke check passed") + ' + + - name: Remove local test image + if: always() + run: docker image rm "$IMAGE" || true + cleanup-nightly: needs: build-and-publish - if: ${{ !inputs.tag && !inputs.pr_number }} + if: ${{ !inputs.build_only && !inputs.tag && !inputs.pr_number }} uses: ./.github/workflows/_docker-cleanup-nightly.yml with: tag_prefixes: '["nightly-dev", "nightly-dev-cu12", "nightly-dev-cu13"]' @@ -155,7 +220,7 @@ jobs: build-overlay: needs: [prepare, build-and-publish] - if: ${{ inputs.overlay_dockerfile != '' && github.repository == 'sgl-project/sglang' }} + if: ${{ !inputs.build_only && inputs.overlay_dockerfile != '' && github.repository == 'sgl-project/sglang' }} runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/docs_new/cookbook/diffusion/MiniMax/MiniMax-H3.mdx b/docs_new/cookbook/diffusion/MiniMax/MiniMax-H3.mdx new file mode 100644 index 000000000..e9fad95ca --- /dev/null +++ b/docs_new/cookbook/diffusion/MiniMax/MiniMax-H3.mdx @@ -0,0 +1,807 @@ +--- +title: MiniMax-H3 +description: Run native MiniMax-H3 video-and-audio generation with SGLang Diffusion. +metatags: + description: "Serve MiniMax-H3 with SGLang Diffusion for text-to-video-and-audio, first/last-frame conditioning, video-to-video, and multimodal reference conditioning." +--- + +## 1. Model introduction + +[MiniMax-H3](https://huggingface.co/MiniMaxAI/MiniMax-H3) generates a video and a synchronized stereo audio track in one request. SGLang Diffusion provides a native pipeline for the three public task profiles, split across the released FL2VA (First-and-Last-Frame-to-Video-and-Audio) and Ref2VA (Reference-to-Video-and-Audio) checkpoint partitions: + +| Task | `task` value | Conditioning | +| --- | --- | --- | +| Text to video and audio | `t2va` | Text prompt only | +| First/last frame to video and audio | `fl2va` | First frame, last frame, or both | +| Reference to video and audio | `ref2va` | Image, video, and audio references | + +Video-to-video (V2V) is a supported `ref2va` use case, not a fourth task +value. Run the `Ref2VA` partition and provide a video reference in +`conditions`. + +Use the selected Hub's root model ID: `MiniMaxAI/MiniMax-H3` on Hugging Face +or `MiniMax/MiniMax-H3` on ModelScope. Select the checkpoint variant with +`--model-variant`: `fl2va` serves both `t2va` and `fl2va`, while `ref2va` +serves reference-conditioned requests. SGLang owns the checkpoint-directory +mapping; do not point `--model-path` at a manually downloaded subdirectory. + + +Review the license and usage terms in the MiniMax-H3 model card before production or commercial use. SGLang support does not grant additional model usage rights. + + +## 2. Installation + +Install SGLang with the diffusion dependencies: + +```bash Command +uv pip install "sglang[diffusion]" --prerelease=allow +``` + +For platform-specific setup, see the [SGLang Diffusion installation guide](/docs/sglang-diffusion/installation). + +## 3. Serve MiniMax-H3 + +Use the interactive selector to choose a hardware platform, deployment profile, +one of the two checkpoint partitions, a request mode, and deployment features. +It generates Python and, where available, Docker launch forms. AMD selections +use the Python form until an H3-capable ROCm image is validated. The **$ cURL** +button follows the selected request mode and switches the payload across +text-only, all three first/last-frame signatures, and the image/audio/video +reference combinations listed below. +Set **Outputs per prompt** in the picker’s **Env** panel to generate more than +one output without mixing request sampling controls into the deployment +matrix. + +The Docker form does not assume the base SGLang image contains optional +diffusion dependencies. It installs the platform-specific diffusion extra from +the source bundled in the image before starting the server. Set **Host media +directory** in the **Env** panel for FL2VA, V2V, or Ref2VA; the picker mounts +that directory read-only at `/data/minimax-h3` inside the container. + +Every hardware/topology cell in this picker has completed a real request on +that exact GPU model. Approximate load-time features such as online +quantization are called out separately in the generated command. Sampling +behavior such as Cache-DiT is documented separately below. + +**Deployment Profile** exposes resident and FSDP placement on B200, B300, +H200, and H100. Resident is the latency-oriented default; FSDP reduces DiT +weight residency at the cost of per-block parameter collectives. **Online +Quantization** appears only on B200 and B300. AMD keeps its resident AITER +recipe, while RTX 5090 uses its dedicated layerwise-offload profile. + +import { Deployment } from "/src/snippets/_deployment.jsx"; +import { config } from "/src/snippets/configs/MiniMaxAI/minimax-h3.jsx"; + + + + +The ready-to-run request template lives behind the **$ cURL** button in the +picker above. It regenerates as you change the selection, so the payload it +shows always matches the serve command next to it. + + +The selector uses the verified Hugging Face ID. To use ModelScope through the +same normal `sglang serve` path, prefix the copied command with +`SGLANG_USE_MODELSCOPE=true` and replace the model path with +`MiniMax/MiniMax-H3`; keep its selected variant and topology flags unchanged. + +For a four-card H200 host, keep the full BF16/FP32 model resident by default. +The model fits without FSDP, so this path avoids the per-block parameter +all-gathers of the memory-oriented FSDP profile: + +```bash 4×H200 resident +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 4 \ + --ulysses-degree 4 \ + --performance-mode speed \ + --port 30010 +``` + +For 4×H100 80 GB, balance the large packed activation with resident weight +sharding. TP2 + Ulysses2 was the fastest measured lossless topology while the +Qwen encoder still folds across all four GPUs: + +```bash 4×H100 fastest +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 4 \ + --tp-size 2 \ + --ulysses-degree 2 \ + --performance-mode speed \ + --port 30010 +``` + +Pure Ulysses4 could not keep the full pipeline resident on 80 GB H100s. Use +`--tp-size 4 --ulysses-degree 1` when lower resident memory matters more than +the last few percent of latency. FSDP remains a verified capacity option, but +its per-block weight all-gathers do not make it the H100 speed default: + +```bash 4×H100 FSDP capacity +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 4 \ + --ulysses-degree 4 \ + --performance-mode speed \ + --use-fsdp-inference true \ + --port 30010 +``` + +For a two-card RTX 5090 host, use TP2 and keep 20 DiT blocks +resident. Layerwise placement is lossless: it changes parameter placement and +transfer scheduling, not the BF16/FP32 denoising or VAE math. This is the +fastest measured 32 GB operating point: + +```bash 2×RTX 5090 fastest lossless +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 2 \ + --tp-size 2 \ + --ulysses-degree 1 \ + --performance-mode memory \ + --layerwise-offload-components dit,text_encoder,vae \ + --dit-offload-prefetch-size 1 \ + --dit-layerwise-resident-layers 20 \ + --enable-torch-compile false \ + --port 30010 +``` + +The DiT residency and prefetch knobs apply only to the repeatedly executed DiT +blocks. The text encoder and the video VAE decoder blocks use one-layer +prefetch with zero resident layers. The video VAE encoder stays resident +because its indexed down blocks cannot host executable layerwise hooks; the +roughly 577 MiB audio VAE also stays resident because offloading it only adds +transfer overhead. This exact recipe was validated on +2× RTX 5090 (32 GB each) and a 377 GiB host; use a 384 GiB-class machine. The +latency and memory comparison is collected in the benchmark section below. + +The first launch downloads the model through the selected Hub. If the Hugging +Face repository requires authentication, export a Hugging Face token in the +server environment. + +For MiniMax-H3, `--performance-mode speed` deliberately keeps the DiT eager. The current `torch.compile` path changes the model's numerical output, so it is not enabled implicitly by any recommended lossless preset. An explicit `--enable-torch-compile true` remains available for controlled experiments, but it should not be used to generate consistency ground truth. + +## 4. Generate video and audio + +MiniMax-H3 uses the asynchronous OpenAI-compatible video endpoint. Choose a +generation mode below, submit a job, poll its status, and then download the +completed MP4. + + + + + +MiniMax-H3 supports output durations from 4 through 15 seconds, inclusive. The +following request keeps the verified 5-second profile at a 768-pixel short +edge. MiniMax-H3 resolves the aligned output canvas and frame count from +`target`. + +```bash Command +video_id=$( + curl -sS -X POST http://127.0.0.1:30010/v1/videos \ + -H "Content-Type: application/json" \ + -d '{ + "model": "MiniMaxAI/MiniMax-H3", + "prompt": "At night, while their owner sleeps in a bedroom, three cats march in loudly playing tiny brass instruments, then abruptly file out.", + "seconds": 5, + "task": "t2va", + "conditions": [], + "target": { + "short_edge": 768, + "aspect_ratio": "16:9", + "duration_seconds": 5.0 + }, + "num_outputs_per_prompt": 1, + "num_inference_steps": 50, + "flow_shift": 12.0, + "audio_flow_shift": 3.0, + "seed": 1101 + }' | + jq -r '.id' +) + +while true; do + status=$(curl -sS "http://127.0.0.1:30010/v1/videos/${video_id}" | jq -r '.status') + [ "$status" = "completed" ] && break + [ "$status" = "failed" ] && exit 1 + sleep 1 +done + +curl -sS -L "http://127.0.0.1:30010/v1/videos/${video_id}/content" \ + -o minimax-h3-t2va.mp4 +``` + +The output contract is an MP4 containing H.264 video at 24 fps and one AAC stereo audio stream at 32 kHz. + + + + + +For `fl2va`, provide one or two image conditions with role `keyframe`. The supported frame-index sets are `[0]`, `[-1]`, and `[0, -1]`. + +The following request uses one server-local first frame. Use +`frame_index: -1` for a last frame, or include both entries for first-and-last +conditioning. + +Choose FL2VA when the supplied image should be the actual first or last frame +of the generated clip. Use image-based Ref2VA instead when the image should +guide identity, style, or composition without being preserved as an endpoint; +Ref2VA may recompose or crop the reference. + +```bash Command +curl -sS -X POST http://127.0.0.1:30010/v1/videos \ + -H "Content-Type: application/json" \ + -d '{ + "model": "MiniMaxAI/MiniMax-H3", + "prompt": "The supplied frame continues with calm, natural motion and synchronized ambient sound.", + "seconds": 5, + "task": "fl2va", + "conditions": [ + { + "type": "image", + "uri": "file:///data/minimax-h3/first-frame.png", + "role": "keyframe", + "frame_index": 0 + } + ], + "target": { + "short_edge": 768, + "aspect_ratio": "auto", + "duration_seconds": 5.0 + }, + "num_outputs_per_prompt": 1, + "num_inference_steps": 50, + "flow_shift": 12.0, + "audio_flow_shift": 3.0, + "seed": 2101 + }' +``` + + + + + +V2V uses the reference-conditioning weights. Launch the server with +`--model-variant ref2va`, keep the request `task` set to `ref2va`, and provide a video +reference in `conditions`. There is no separate `v2v` task value. + +Use `type: "video"` when the input may be silent. If the file has a soundtrack, +H3 also uses it as an audio reference. Use `type: "video_audio"` only when both +streams are required; that form rejects an input without audio. The prompt tag +for the visual stream is ` + + + +For `ref2va`, first launch the reference-conditioning capability with +`--model-variant ref2va`, then provide conditions with role `reference`. +Image, video, and audio references can be combined. Material tags in the +prompt use the one-based order for each modality. + +An image condition here is semantic reference material rather than a +pixel-aligned first frame. Use the FL2VA tab when animating a screenshot from +that exact starting composition. + +```bash Command +curl -sS -X POST http://127.0.0.1:30010/v1/videos \ + -H "Content-Type: application/json" \ + -d '{ + "model": "MiniMaxAI/MiniMax-H3", + "prompt": "Use as the visual subject and + + + +Poll and download any conditioned request with the same job-status and +content endpoints used in the T2VA example. Server-local `file://` URIs must +refer to files visible inside the SGLang server environment. + +## 5. Sampling and output controls + +MiniMax-H3 supports more than one output per prompt. The video API accepts +`num_outputs_per_prompt` (or OpenAI-compatible `n`) from 1 through 10. Offline +generation accepts `--num-outputs-per-prompt N`; `--num-outputs N` is the short +alias. A scalar seed is expanded deterministically as `seed + output_index`, so +the outputs do not reuse the same noise. + +Same-prompt fan-out reuses text conditioning. On the verified 2× RTX 5090 +recipe, a 5-step two-output request completed in 155.39 seconds versus 78.11 +seconds for one output, while producing two distinct valid MP4 files. The +independent denoise and decode passes remain sequential on this 32 GB profile +to keep peak memory bounded; the grouped path adds essentially no orchestration +overhead. Use server replicas when lower wall-clock latency for many variants +matters more than per-server memory efficiency. + +For example, set `"num_outputs_per_prompt": 2` in any request above. After the +job completes, download both outputs by selecting each zero-based variant: + +```bash Command +video_id="" +for variant in 0 1; do + curl -sS -L \ + "http://127.0.0.1:30010/v1/videos/${video_id}/content?variant=${variant}" \ + -o "minimax-h3-${variant}.mp4" +done +``` + +### Choose a quality profile + +`quality` is a request-scoped sampling parameter. One resident server can +switch between all four profiles; an approximate request mounts its audited +Cache-DiT policy at the batch boundary, and a later `lossless` request removes +the hooks before denoising. + +Start the validated server once: + +```bash Command +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 4 \ + --tp-size 1 \ + --sp-degree 4 \ + --ulysses-degree 4 \ + --ring-degree 1 \ + --performance-mode speed \ + --use-fsdp-inference false \ + --enable-torch-compile false \ + --port 30010 +``` + +Then choose a request tag: + + + + + +Native denoising with no feature-cache approximation. This is the default. + +```json Request field +{ + "quality": "lossless" +} +``` + + + + + +The least aggressive approximate profile. Use it when output should stay +closest to the same-seed lossless trajectory. + +```json Request field +{ + "quality": "high" +} +``` + + + + + +The balanced profile: substantially lower latency with a larger change from +the same-seed lossless output. + +```json Request field +{ + "quality": "medium" +} +``` + + + + + +The fastest validated profile and the largest visual deviation. Use it for +latency-sensitive previews and high-throughput generation. + +```json Request field +{ + "quality": "low" +} +``` + + + + + +The measured trade-off is: + +| `quality` | Mean inference latency | Speedup | SSIM vs lossless | PSNR vs lossless | Expected trade-off | +| --- | ---: | ---: | ---: | ---: | --- | +| `lossless` | 75.10 s | 1.00× | 1.000 | exact | Native reference path | +| `high` | 53.70 s | 1.40× | 0.931 | 28.16 dB | Smallest same-seed visual change | +| `medium` | 30.23 s | 2.48× | 0.818 | 20.40 dB | Balanced latency and visual deviation | +| `low` | 25.81 s | 2.91× | 0.794 | 19.25 dB | Largest deviation; fastest preview path | + +These numbers use 1344×768, 124-frame, 24 fps T2VA with 50 inference steps, +video flow shift 12, audio flow shift 3, and three fixed prompt/seed pairs on +4×H200. The prompts cover a quiet detailed scene, fast multi-subject action, +and a moving close-up portrait. `inference_time_s` is averaged across the three +prompts; the quiet-scene point is itself the mean of two repeats. + +SSIM and PSNR compare decoded, frame-aligned output with the `lossless` result +for the same prompt and seed. They measure trajectory deviation, not absolute +perceptual quality: an approximate profile can produce a different but still +plausible realization. The profiles also change the joint audio-video denoise +trajectory, while these two metrics cover video only. + +Approximate profiles currently accept only the exact workload and 4×H200 +deployment above; other hardware, task modes, request shapes, step counts, or +flow shifts fail before denoising. Offline generation uses the same profile +name, for example `sglang generate --quality medium`. + + +`quality` selects a model sampling profile and can change generated content. +`output_quality` controls only output-file compression; it is a separate field. + + +For manually tuned Cache-DiT experiments outside that validated profile, omit +the request `quality` field and set the process-wide environment controls +directly. An explicit `quality: lossless` request overrides those controls and +restores native denoising: + +```bash Command +SGLANG_CACHE_DIT_ENABLED=true \ +SGLANG_CACHE_DIT_FN=1 \ +SGLANG_CACHE_DIT_BN=0 \ +SGLANG_CACHE_DIT_WARMUP=4 \ +SGLANG_CACHE_DIT_RDT=0.12 \ +SGLANG_CACHE_DIT_MC=2 \ +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant ref2va \ + --num-gpus 8 \ + --ulysses-degree 8 \ + --performance-mode speed \ + --port 30010 +``` + + +Cache-DiT skips selected block computation and is approximate. It cannot be +combined with FSDP inference or DiT layerwise offload. Breakable CUDA graph +execution takes precedence and leaves Cache-DiT disabled. Tune the cache +thresholds only after comparing both video and audio quality on the target +task profile. A real B200 request has completed, but the named profiles above +remain fail-closed to the audited 4×H200 workload. + + +## 6. Runtime feature recipes + + + + + +The recommended `speed` launch already combines resident components with +Ulysses sequence parallelism. Validation status below applies only to the +listed hardware and topology; it is not inherited by a similar GPU family. + +| Feature | Validation status | Notes | +| --- | --- | --- | +| Ulysses sequence parallelism | Verified: 8× B200, 4× H200, 4× H100, and Ulysses1/2/4/8 on MI300X and MI355X | Use `--ulysses-degree`; Ring is not compatible with H3's packed multi-segment attention. | +| Tensor parallelism | Verified: B200 TP2 + Ulysses4; H100 TP2 + Ulysses2 and TP4 + Ulysses1 | `--tp-size` may be combined with Ulysses when the TP-local head count remains divisible by the Ulysses degree. On 4×H100, TP2 + Ulysses2 is the measured speed default. | +| FSDP inference | Verified: 4× B200 and 4× H100 + Ulysses4 | Preserves H3's mixed BF16/FP32 parameter policy. B200 completed the exact eager comparison; H100 completed consecutive real requests at about 57 GB peak memory per GPU. | +| Resident components | Verified: B200, H200, 4×H100 with TP, and 1/2/4/8× MI300X and MI355X | This is the recommended single-request latency path when the complete workload fits. | +| CPU and layerwise offload | Verified: 2× RTX 5090 TP2 | The measured lossless recipe keeps 20 DiT blocks plus both VAE encoders resident, streams the remaining DiT blocks, text encoder, and video VAE decoder blocks, and leaves the small audio VAE resident. This status applies only to the listed topology. | +| Breakable CUDA graph | Verified: B200 Ref2VA, opt-in | Matching eager output was observed for the captured signature, without a measured speedup. Re-capture for other shapes and reference sets. | +| `torch.compile` | Measured: H200, opt-in | Steady-state benefit was below measurement noise, while startup increased and numerical output changed. Do not use it for consistency ground truth. | + +The verified parallel, placement, and matching-signature BCG paths keep the +BF16/FP32 weights and denoising math. `torch.compile` is the exception called +out above. Always use the eager BF16/FP32 launch when producing CI consistency +ground truth. + +For the validated 1344×768 Ref2VA profile, use a 5504-row text bucket so both +the server warmup and reference-conditioned requests share the captured +signature: + +```bash Command +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant ref2va \ + --num-gpus 8 \ + --ulysses-degree 8 \ + --performance-mode speed \ + --enable-breakable-cuda-graph true \ + --warmup-resolutions 1344x768 \ + --bcg-text-buckets 5504 \ + --port 30010 +``` + +BCG is lossless for a matching captured signature, but capture reserves extra +GPU memory. Re-measure the live H3 text length before reusing this bucket for a +different task profile, reference set, resolution, or prompt template. + + + + + +On the verified 8× B200 topology, quantize the BF16 transformer at server load: + +```bash Command +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant ref2va \ + --num-gpus 8 \ + --ulysses-degree 8 \ + --performance-mode speed \ + --quantization fp8 \ + --port 30010 +``` + +H3 automatically keeps its video/audio patch projections, timestep MLP, and +final video/audio heads in FP32. All other linear layers have stable full +module prefixes, so additional layers can be kept unquantized: + +```bash Command +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant ref2va \ + --num-gpus 8 \ + --ulysses-degree 8 \ + --quantization fp8 \ + --quantization-ignored-layers blocks.0.attn token_refiner \ + --port 30010 +``` + + +Online FP8 is approximate and is not a consistency ground-truth mode. It can +be combined with Cache-DiT, but the two approximations compound. Validate +visual quality, audio quality, memory use, and latency on the target workload. +The picker exposes this option only on the B200 and B300 topologies used for +real H3 validation runs. + + + + + + +## 7. Configuration notes + +- MiniMax-H3 produces the canonical 24 fps output; request duration is expressed through `target.duration_seconds`. +- `target.duration_seconds` must be between 4 and 15 seconds, inclusive. The command picker defaults to the verified 5-second profile. +- Use a 768-pixel short edge for the released quality profile. The aligned output dimensions are derived from `target.aspect_ratio`. +- `flow_shift` controls video diffusion and `audio_flow_shift` controls audio diffusion. +- V2V uses `task: "ref2va"` with a `video` or `video_audio` reference; it is served by the `Ref2VA` partition and is not a separate public task value. +- `conditions[].start_time_seconds` selects a non-negative offset for a video reference. Its visual and audio streams are always sought together. +- Ref2VA condition order is semantic and must match the one-based material tags in the prompt. For Ref2VA, `target.aspect_ratio: "auto"` resolves to the model's 16:9 fallback rather than inheriting a reference asset's geometry. +- The distilled pipeline uses a single denoising branch, so CFG parallelism does not apply. Do not enable it: `--enable-cfg-parallel true` or `--cfg-parallel-size` greater than 1 is rejected instead of duplicating the positive branch. Explicitly disabling CFG, or setting its size to 1, remains a valid no-op. +- The released visual VAE quality recipe uses overlapping tiled decode. SGLang keeps that recipe by default and distributes complete tiles across the decode group; this changes scheduling, not the computation inside each tile. +- H3 rejects `--vae-config.parallel-decode-mode spatial` and `spatial_shard`: validation found output mismatches. Use the default released tiled recipe. +- Keep the default `--encoder-parallel auto`. With the server’s default `batching_max_size` of 1, single-node H100/H200/B200/B300 recipes with peer-to-peer access fold the Qwen text encoder over otherwise idle Ulysses ranks. This is separate from DiT tensor parallelism. A pure-TP recipe already shards the encoder over its TP group and does not add a world fold. +- For throughput-oriented serving, select **DP (batched throughput)**. The picker pairs `--encoder-parallel dp` with an editable `--batching-max-size` greater than 1; compatible requests are distributed across ranks, while every rank keeps a full encoder replica. Encoder DP requires TP1 and DiT DP1, so it is disabled for the H100 TP2 + Ulysses2 and RTX 5090 TP2 recipes. It provides no benefit for a batch of one and is not bitwise-identical to the folded deployment. +- Use explicit **Fold** to prioritize single-request latency and encoder memory on a measured high-bandwidth single-node topology. Use **Replicate** as the compatibility path when folding or encoder DP is unsuitable. +- `--use-fsdp-inference true` shards only the DiT. MiniMax-H3 preserves the original FP32 dtype of its patch, time, and output projections during FSDP all-gather, so this path does not trade numerical correctness for memory. On 4×H100, prefer TP2 + Ulysses2 for speed; use FSDP as an explicit capacity policy rather than assuming it is faster. +- `speed` keeps model components resident, `auto` applies the model-aware 120 GiB residency threshold, and `memory` enables the memory-saving placement policy. Explicit `--layerwise-offload-components` overrides that placement list. DiT residency/prefetch knobs are scoped to the DiT; the text encoder and video VAE decoder use one-layer prefetch and zero residency, while the H3 video VAE encoder stays resident. When `memory` is combined with explicit FSDP, H3 instead keeps the sharded DiT on GPU and layerwise-offloads the text encoder and executable VAE decoder blocks. Use `speed` only after confirming that the complete target workload fits. +- Breakable CUDA graph execution is an explicit opt-in, not part of the recommended `speed` preset. It requires `--enable-breakable-cuda-graph`, every served size in `--warmup-resolutions`, and `--bcg-text-buckets` that cover the live H3 condition sequence. The validated 1344×768 Ref2VA recipe uses 5504; other task profiles and reference sets may need a different value. It preserves eager output for matching captured signatures, but graph capture consumes additional GPU memory and may provide little latency benefit when Ulysses attention and collectives dominate, so benchmark it on the target topology before enabling it. + +## 8. Benchmarks + +The picker exposes resident and FSDP profiles on NVIDIA datacenter GPUs. GPU +counts are properties of the selected recipes, not a claim that every platform +requires that many GPUs. The detailed tables below report performance only for +the configurations with collected measurements: + +| Hardware | Default resident recipe | Other profile or topology | +| --- | --- | --- | +| B300 | 8× Ulysses8 resident | 8× FSDP + Ulysses8; the 8-GPU sweep is not a minimum-GPU claim. | +| B200 | 8× Ulysses8 resident | 4× FSDP + Ulysses4 | +| H200 | 4× Ulysses4 resident | 4× FSDP + Ulysses4 | +| H100 | 4× TP2 + Ulysses2 resident | 4× TP4 + Ulysses1; 4× FSDP + Ulysses4 | +| MI300X / MI355X | 8× Ulysses8 resident | 1×, 2×, and 4× scaling runs | +| RTX 5090 | 2× TP2 + layerwise offload | — | + +### B300 precision and encoder placement + +A 12-configuration sweep on a single 8× B300 host, covering both checkpoint +partitions, both transformer precisions, and all three text-encoder +placements. It answers one question — *how long does one request take, and how +much memory does it need*. + +### What was measured + +**Hardware.** 8× NVIDIA B300 SXM6, single node. + +**Model.** `MiniMaxAI/MiniMax-H3`, both released weight partitions. + +**Serve command.** Exactly the recipe the picker emits for B300, plus the one +or two overlay flags under test: + +```bash Command +sglang serve \ + --model-path MiniMaxAI/MiniMax-H3 \ + --model-variant fl2va \ + --num-gpus 8 \ + --ulysses-degree 8 \ + --performance-mode speed \ + --host 0.0.0.0 \ + --port 30010 +``` + +The swept axes are `--model-variant` (`fl2va` / `ref2va`), `--quantization` +(unset for BF16 / `fp8`), and `--encoder-parallel` (`auto` / `fold` / +`replicate`). Nothing else differs between the 12 servers. + +This is a single-request latency sweep (`batching_max_size: 1`), so encoder DP +is intentionally excluded: it cannot distribute a batch of one. Use the +picker’s **DP (batched throughput)** option for a multi-request throughput +deployment; the table below does not claim a measured H3 DP speedup. + +**Driver.** + +```bash Command +python3 -m sglang.multimodal_gen.benchmarks.bench_serving \ + --host 127.0.0.1 --port 30010 \ + --model MiniMaxAI/MiniMax-H3 \ + --dataset vbench --task text-to-video \ + --num-prompts 1 --max-concurrency 1 \ + --warmup-requests 1 --warmup-inference-steps 50 \ + --extra-body '{"task":"t2va","conditions":[],"target":{"short_edge":768,"aspect_ratio":"16:9","duration_seconds":5.0},"seconds":5,"flow_shift":12.0,"audio_flow_shift":3.0}' +``` + +**Workload** + +| Property | Value | +| --- | --- | +| Output duration | 5.167 s | +| Resolution | 1344×768 | +| Frames | 124 @ 24 fps | +| Denoising steps | 50 | +| `flow_shift` / `audio_flow_shift` | 12.0 / 3.0 | +| Requests in flight | 1 (`--max-concurrency 1`, server at `batching_max_size: 1`) | +| Requests measured | 1 per cell, after 1 warmup request | + +### Results + +| Weights | Precision | Encoder | Load | Warmup | Latency | Peak/GPU | +| --- | --- | --- | ---: | ---: | ---: | ---: | +| FL2VA | BF16 | auto | 118.1 s | 29.65 s | **19.04 s** | 83,578 MB | +| FL2VA | BF16 | fold | 114.0 s | 28.72 s | **19.04 s** | 83,578 MB | +| FL2VA | BF16 | replicate | 116.0 s | 28.33 s | **19.04 s** | 124,158 MB | +| FL2VA | FP8 | auto | 116.0 s | 27.16 s | **18.03 s** | 51,926 MB | +| FL2VA | FP8 | fold | 116.0 s | 25.99 s | **18.04 s** | 51,926 MB | +| FL2VA | FP8 | replicate | 118.0 s | 27.97 s | **18.04 s** | 92,506 MB | +| Ref2VA | BF16 | auto | 114.0 s | 38.69 s | **29.12 s** | 83,968 MB | +| Ref2VA | BF16 | fold | 118.0 s | 36.58 s | **29.13 s** | 83,968 MB | +| Ref2VA | BF16 | replicate | 116.0 s | 35.17 s | **29.13 s** | 124,490 MB | +| Ref2VA | FP8 | auto | 124.0 s | 34.30 s | **27.12 s** | 52,816 MB | +| Ref2VA | FP8 | fold | 112.0 s | 34.44 s | **27.12 s** | 52,816 MB | +| Ref2VA | FP8 | replicate | 116.0 s | 33.42 s | **27.12 s** | 93,396 MB | + +### H100 topology comparison + +The same four-card H100 host completed three lossless placements. TP2 with +Ulysses2 was the fastest; TP4 used the least memory: + +| Topology | Pipeline latency | Peak/GPU | +| --- | ---: | ---: | +| TP2 + Ulysses2 | 13.25 s | 66.04 GB | +| FSDP + Ulysses4 | 13.36 s | 57.01 GB | +| TP4 + Ulysses1 | 13.86 s | 49.80 GB | + +### RTX 5090 capacity run + +The verified two-card RTX 5090 host used TP2 with layerwise offload. The full +50-step, 1344×768, 5-second request completed in 559.67 seconds: 525.05 +seconds of denoising and 33.61 seconds of decoding, with a 26.3 GiB sampled +peak per GPU. + +| DiT settings | 5-step denoise | Inference | Peak/GPU | Result | +| --- | ---: | ---: | ---: | --- | +| prefetch 1, resident 20 | 43.48 s | 78.11 s | 26.3 GiB | Selected recipe | +| prefetch 2, resident 20 | 43.37 s | 78.06 s | 27.5 GiB | No measurable gain | +| Ulysses2, prefetch 2, resident 10 | Did not reach warmup | — | — | Rejected | + +### AMD Instinct task and scaling runs + +The AMD recipes keep the released BF16/FP32 precision policy and use AITER +packed attention. The picker emits the fastest measured topology, 8 GPUs with +Ulysses degree 8. All runs below completed full H.264/AAC decoding and +representative-frame inspection. + +| Hardware | Task | Denoise | Decode | Peak/GPU | +| --- | --- | ---: | ---: | ---: | +| MI355X | T2VA | 55.2907 s | 9.5344 s | 97,444 MB | +| MI355X | FL2VA | 53.7978 s | 9.4477 s | 96,922 MB | +| MI355X | Ref2VA | 41.3812 s | 6.8247 s | 94,518 MB | +| MI300X | T2VA | 167.4878 s | 25.3244 s | 97,272 MB | +| MI300X | FL2VA | 150.2311 s | 12.5684 s | 96,750 MB | +| MI300X | Ref2VA | 107.6232 s | 11.3768 s | 94,268 MB | + +The task matrix used 8 GPUs and 50 denoising steps. The scaling matrix uses +one 1344×768, 209-frame T2VA request and changes only the GPU count and +matching Ulysses degree: + +| Hardware | GPUs | Denoise | Decode | Peak/GPU | +| --- | ---: | ---: | ---: | ---: | +| MI355X | 8 | 55.2907 s | 9.5344 s | 97,444 MB | +| MI355X | 4 | 104.2294 s | 11.1824 s | 103,350 MB | +| MI355X | 2 | 223.0246 s | 15.5330 s | 115,250 MB | +| MI355X | 1 | 288.7968 s | 24.0472 s | 137,676 MB | +| MI300X | 8 | 167.4878 s | 25.3244 s | 97,272 MB | +| MI300X | 4 | 297.3727 s | 26.5067 s | 103,436 MB | +| MI300X | 2 | 585.5401 s | 29.4909 s | 115,010 MB | +| MI300X | 1 | 978.0886 s | 36.0142 s | 137,626 MB | + +For a measured lower-count AMD deployment, set both `--num-gpus` and +`--ulysses-degree` to 4, 2, or 1. AITER packed attention matched segment-wise +BF16 SDPA at cosine similarity `0.9999991655` on MI355X and `0.9999991059` on +MI300X. diff --git a/docs_new/cookbook/diffusion/intro.mdx b/docs_new/cookbook/diffusion/intro.mdx index f207c8999..c9cf90010 100644 --- a/docs_new/cookbook/diffusion/intro.mdx +++ b/docs_new/cookbook/diffusion/intro.mdx @@ -92,6 +92,12 @@ Video models denoise a bounded latent video sequence for each request. Use these href="/cookbook/diffusion/MOVA/MOVA" img="/cards/logos/mova.png" /> + ## Realtime / World Models diff --git a/docs_new/docs.json b/docs_new/docs.json index b86df1f66..e11f8d2be 100644 --- a/docs_new/docs.json +++ b/docs_new/docs.json @@ -1488,6 +1488,13 @@ "cookbook/diffusion/MOVA/MOVA" ] }, + { + "group": "MiniMax", + "tag": "NEW", + "pages": [ + "cookbook/diffusion/MiniMax/MiniMax-H3" + ] + }, { "group": "LingBot World", "pages": [ diff --git a/docs_new/docs/sglang-diffusion/api/cli.mdx b/docs_new/docs/sglang-diffusion/api/cli.mdx index 23c6b7e3d..6c0789947 100644 --- a/docs_new/docs/sglang-diffusion/api/cli.mdx +++ b/docs_new/docs/sglang-diffusion/api/cli.mdx @@ -75,15 +75,17 @@ Use `sglang generate --help` and `sglang serve --help` for the full argument lis ### Model and runtime - `--model-path {MODEL}`: model path or Hugging Face model ID +- `--model-variant {NAME}`: semantic checkpoint variant to load when one model repository contains multiple weight partitions. The pipeline maps this stable name to the repository layout before loading; for example, MiniMax-H3 accepts `fl2va` and `ref2va`. This is a server/load-time choice, unlike a request's `task`. +- `--model-subfolder {PATH}`: advanced direct override for a component subfolder inside the model repository. Prefer `--model-variant` when the pipeline exposes semantic routing. If both are supplied, they must resolve to the same weight partition. - `--lora-path {PATH}` and `--lora-nickname {NAME}`: load a LoRA adapter - `--lora-merge-mode {auto|merge|dynamic}`: choose how LoRA is applied. `auto` statically merges regular weights and uses dynamic LoRA for FSDP-sharded weights to avoid full-gather peaks. - `--num-gpus {N}`: number of GPUs to use -- `--performance-mode {manual|auto|speed|memory}` / `--mode`: preset for latency/throughput and memory defaults. `auto` is the default and keeps safe offload defaults, using FSDP only for validated DiT-offload replacement paths; `speed` also enables `--enable-torch-compile` by default unless you explicitly disable it. Use `manual` to keep performance-related server args under explicit user control. Explicit offload, FSDP, and parallelism flags take precedence in all modes. +- `--performance-mode {manual|auto|speed|memory}` / `--mode`: preset for latency/throughput and memory defaults. `auto` is the default and keeps safe offload defaults, using FSDP only for validated DiT-offload replacement paths; `speed` also enables `--enable-torch-compile` unless the model-specific deployment config opts out or you explicitly disable it. Use `manual` to keep performance-related server args under explicit user control. Explicit offload, FSDP, and parallelism flags take precedence in all modes. - `--tp-size {N}`: tensor parallelism size, mainly for encoders - `--sp-degree {N}`: sequence parallelism size - `--ulysses-degree {N}` and `--ring-degree {N}`: USP parallelism controls - `--enable-cfg-parallel {true|false}`: enable or explicitly disable CFG parallelism -- `--encoder-parallel {auto|fold|dp|replicate}`: how the text/image encoders use the GPUs the DiT replica leaves idle during encoding. `auto` (the default for `generate`) TP-folds an encoder wide enough to pay for the per-layer all-reduce and replicates the rest; `fold` forces the shard whenever the dims allow it; `dp` splits a batched encode across ranks (needs `--batching-max-size > 1` to engage, and is the `serve` default); `replicate` encodes redundantly on every rank. `fold` and `replicate` are bitwise-identical to single-GPU encoding. See [Encoder Parallelism](/docs/sglang-diffusion/encoder_parallel). +- `--encoder-parallel {auto|fold|dp|replicate}`: how the text/image encoders use the GPUs the DiT replica leaves idle during encoding. `auto` (the default for both `generate` and `serve`) TP-folds an encoder wide enough to pay for the per-layer all-reduce, selects DP for a server batch when it can engage, and otherwise replicates; `fold` forces the shard whenever the dims allow it; `dp` splits a batched encode across ranks and needs `--batching-max-size > 1` to engage; `replicate` encodes redundantly on every rank. `fold` and `replicate` are bitwise-identical to single-GPU encoding. See [Encoder Parallelism](/docs/sglang-diffusion/encoder_parallel). - `--warmup-mode {off|request|server}`: control startup warmup for `sglang serve`; `off` skips warmup, `request` primes the request path, and `server` runs a full synthetic server warmup before serving traffic - `--enable-torch-compile {true|false}`: compile native diffusion hot paths. When no warmup mode is configured, this also enables server warmup so first real requests do not pay compile latency. - `--offload-during-compile {true|false}`: when compile warmup is active, temporarily layerwise-offload DiT weights and move resident non-DiT components off-device so `max-autotune` fits on tighter-memory GPUs; the configured serving residency is restored before real traffic. Skipped under existing layerwise offload, Cache-DiT, or FSDP. @@ -102,6 +104,8 @@ Use `sglang generate --help` and `sglang serve --help` for the full argument lis - `--prompt {PROMPT}` and `--negative-prompt {PROMPT}` - `--image-path {PATH} [{PATH} ...]`: input image(s) for image-to-video or image-to-image generation - `--num-inference-steps {STEPS}` and `--seed {SEED}` +- `--num-outputs-per-prompt {N}` / `--num-outputs {N}`: generate multiple outputs for each prompt. A scalar seed expands as `seed + output_index`. +- `--quality {PROFILE}`: select a model-owned request quality/performance profile. Supported names and deployment constraints are model-specific. - `--height {HEIGHT}`, `--width {WIDTH}`, `--num-frames {N}`, `--fps {FPS}` - `--output-path {PATH}`, `--output-file-name {NAME}`, `--save-output`, `--return-frames` @@ -178,7 +182,7 @@ sglang generate \ HTTP server-only arguments are ignored by `sglang generate`. -For diffusers pipelines, Cache-DiT can be enabled with `SGLANG_CACHE_DIT_ENABLED=true` or `--cache-dit-config`. See [Cache-DiT](../cache_dit). +For supported pipelines, Cache-DiT can be enabled with `SGLANG_CACHE_DIT_ENABLED=true` or `--cache-dit-config`. See [Cache-DiT](../cache_dit). For supported image pipelines, breakable CUDA graph can be enabled with `--enable-breakable-cuda-graph`, but you must declare every served resolution in `--warmup-resolutions` so warmup captures matching graph signatures. diff --git a/docs_new/docs/sglang-diffusion/cache_dit.mdx b/docs_new/docs/sglang-diffusion/cache_dit.mdx index d568f1592..843bfacdb 100644 --- a/docs_new/docs/sglang-diffusion/cache_dit.mdx +++ b/docs_new/docs/sglang-diffusion/cache_dit.mdx @@ -547,6 +547,10 @@ SGLang Diffusion x Cache-DiT supports almost all models originally supported in Hunyuan HunyuanVideo + + MiniMax + MiniMax-H3 (T2VA, FL2VA, and Ref2VA) + @@ -562,7 +566,8 @@ SGLang Diffusion x Cache-DiT supports almost all models originally supported in - **SGLang-native pipelines**: Distributed Cache-DiT paths exist for supported pipelines. Hybrid SP+TP configurations add communication and cache coordination overhead, so validate them on the target model and hardware before using them as production defaults. - **SCM minimum steps**: SCM requires >= 8 inference steps to be effective -- **Model support**: Only models registered in Cache-DiT's BlockAdapterRegister are supported +- **Model support**: The model must be registered in Cache-DiT's + `BlockAdapterRegister` or have an SGLang custom block adapter. ## Troubleshooting diff --git a/docs_new/docs/sglang-diffusion/compatibility_matrix.mdx b/docs_new/docs/sglang-diffusion/compatibility_matrix.mdx index 36f977dd0..d73e782c0 100644 --- a/docs_new/docs/sglang-diffusion/compatibility_matrix.mdx +++ b/docs_new/docs/sglang-diffusion/compatibility_matrix.mdx @@ -115,6 +115,12 @@ Rows are grouped when a family shares the same runtime path or optimization supp Video-audio, 360p / 720p; local MOVA detector aliases are also supported. No dedicated optimization listed + + MiniMax-H3 +
MiniMaxAI/MiniMax-H3
+ T2VA / FL2VA / Ref2VA, 768p at 24 fps with synchronized audio + Cache-DiTOnline FP8 + Wan2.1 Fun
weizhou03/Wan2.1-Fun-1.3B-InP-Diffusers
@@ -548,6 +554,21 @@ Optimization columns are abbreviated to keep the matrix readable: ❌ ❌ + + MiniMax-H3 (T2VA / FL2VA / Ref2VA image, audio, video/V2V) + MiniMaxAI/MiniMax-H3 + 768p · 24 fps + ❌ + ❌ + ❌ + ❌ + ❌ + ❌ + ❌ + ❌ + ❌ + ❌ + LTX-2.3 (one/two-stage/TI2V/HQ) Lightricks/LTX-2.3 diff --git a/docs_new/docs/sglang-diffusion/quantization.mdx b/docs_new/docs/sglang-diffusion/quantization.mdx index e2a51680b..ea8171c6b 100644 --- a/docs_new/docs/sglang-diffusion/quantization.mdx +++ b/docs_new/docs/sglang-diffusion/quantization.mdx @@ -134,6 +134,11 @@ sglang generate \ --save-output ``` +MiniMax-H3 supports this path while preserving its required FP32 patch, +timestep, and output projections. See the +[MiniMax-H3 cookbook](/cookbook/diffusion/MiniMax/MiniMax-H3#6-runtime-feature-recipes) +for its distributed serving recipe. + ### MXFP4 Online Quantization MXFP4 provides aggressive 4-bit compression with online quantization. **Note: Requires ROCm and MI350+ (gfx95x) GPU.** diff --git a/docs_new/scripts/check_cookbook_configs.mjs b/docs_new/scripts/check_cookbook_configs.mjs index 8bc5dfc7a..c2d436aed 100755 --- a/docs_new/scripts/check_cookbook_configs.mjs +++ b/docs_new/scripts/check_cookbook_configs.mjs @@ -99,7 +99,10 @@ const selectionSpace = (config) => { const walk = (dir) => readdirSync(dir, { withFileTypes: true }).flatMap((e) => e.isDirectory() ? walk(join(dir, e.name)) - : (e.name.endsWith(".jsx") && !e.name.includes("benchmark") ? [join(dir, e.name)] : [])); + : (e.name.endsWith(".jsx") + && !e.name.includes("benchmark") + && e.name !== "popular-models.jsx" + ? [join(dir, e.name)] : [])); for (const path of walk(CONFIGS)) { const where = relative(join(SNIPPETS, ".."), path); @@ -182,6 +185,14 @@ for (const path of walk(CONFIGS)) { } } } + if (typeof config.curl === "function") { + probe((sel) => { + const out = config.curl(sel, null); + if (typeof out !== "string") { + throw new Error(`curl returned ${typeof out}, expected a string`); + } + }, "curl"); + } } if (failures.length) { diff --git a/docs_new/src/snippets/_deployment.jsx b/docs_new/src/snippets/_deployment.jsx index 2687232c7..37423e511 100644 --- a/docs_new/src/snippets/_deployment.jsx +++ b/docs_new/src/snippets/_deployment.jsx @@ -12,6 +12,7 @@ // vendor picks the selector group: blackwell | hopper | amd. // `multiNodeDockerFlags: string[]` (either source) adds // `docker run` flags the platform's fabric needs +// groupHardware optional — set false to show one flat hardware row // variants/quantizations/strategies/nodesOptions LEGACY 4-dim option lists, // used when `matchDims` is absent (nodesOptions id is // `single` or `multi-N` → --nnodes N) @@ -40,7 +41,9 @@ // whose verification round is open rather than absent. // modelNames HF slug lookup, `hw|variant|quant` then `variant|quant` // placeholders {{KEY}} → {target: 'command'|'curl', label, default?} -// curl cURL template (uses {{MODEL_NAME}} + placeholders) +// curl cURL template (uses {{MODEL_NAME}} + placeholders), or +// `(selection, cell) => template` when the request payload +// depends on a custom match/overlay dimension // benchmarkCommands optional — powers the "⚡ Reproduce" modal (speed + // per-eval accuracy templates) // defaultAccuracy optional — per-variant accuracy merged under cell.accuracy @@ -56,8 +59,14 @@ // dockerImages optional — `docker run` image, keyed by // `hw|quant|strategy` then `hw|quant` then `hw`; // falls back to `lmsysorg/sglang:dev` +// dockerMounts optional — additional `-v` mount specs +// dockerRunCommand optional — command placed after the image and before +// generated server flags; string or `(selection) => string` // runModes optional — command output tabs to show (`python` and/or -// `docker`); defaults to both, in that order +// `docker`), as an array or `(selection) => array`; +// defaults to both, in that order +// showPlaygroundLink optional — false hides the "Open the Playground" footer +// for cookbooks that only expose the deployment matrix // github optional — "Submit verified cell" issue-template overrides // playgroundFeatures optional — consumed by _playground.jsx (see its header) // @@ -689,6 +698,9 @@ export const Deployment = ({ config, benchmarks }) => { const di = config.dockerImages || {}; const image = di[`${sel.hw}|${sel.quant}|${sel.strategy}`] || di[`${sel.hw}|${sel.quant}`] || di[sel.hw] || "lmsysorg/sglang:dev"; + const dockerRunCommand = typeof config.dockerRunCommand === "function" + ? config.dockerRunCommand(sel) + : (config.dockerRunCommand || "sglang serve"); const portFlag = flags.find((x) => x.split(/[\s=]/)[0] === "--port"); const servePort = portFlag ? portFlag.slice("--port".length).trim() : "{{PORT}}"; const vendorOf = (hwId) => { @@ -728,13 +740,14 @@ export const Deployment = ({ config, benchmarks }) => { multinode ? " --network host" : ` -p ${servePort}:${servePort}`, ...(multinode ? fabricFlagsOf(sel.hw).map((f) => " " + f) : []), " -v ~/.cache/huggingface:/root/.cache/huggingface", + ...(config.dockerMounts || []).map((mount) => ` -v ${mount}`), // HF token only for gated checkpoints — configs that declare an HF_TOKEN placeholder. ...(config.placeholders && config.placeholders.HF_TOKEN ? [` --env "HF_TOKEN={{HF_TOKEN}}"`] : []), ...cellEnv.map((e) => ` --env ${e}`), " --ipc=host", ` ${image}`, - " sglang serve", + ` ${dockerRunCommand}`, ...flags.map((f) => " " + f), ]; cmd = dockerLines.join(" \\\n"); @@ -1030,6 +1043,9 @@ export const Deployment = ({ config, benchmarks }) => { .map((hw) => ({ id: hw.id, label: hw.label, subtitle: hw.vram })); if (items.length) groups.push({ label: vendor.toUpperCase(), items }); } + if (config.groupHardware === false) { + return [{ label: null, items: groups.flatMap((group) => group.items) }]; + } return groups; }; @@ -1161,8 +1177,17 @@ export const Deployment = ({ config, benchmarks }) => { const [benchConc, setBenchConc] = useState(null); const [benchAcc, setBenchAcc] = useState(null); const [benchCopied, setBenchCopied] = useState(null); - const runModes = config.runModes || ["python", "docker"]; + const configuredRunModes = typeof config.runModes === "function" + ? config.runModes(sel) + : config.runModes; + const runModes = configuredRunModes || ["python", "docker"]; const [runMode, setRunMode] = useState(runModes[0]); // "python" | "docker" + const hasRunMode = runModes.includes(runMode); + const fallbackRunMode = runModes[0]; + const activeRunMode = hasRunMode ? runMode : fallbackRunMode; + useEffect(() => { + if (!hasRunMode) setRunMode(fallbackRunMode); + }, [hasRunMode, fallbackRunMode]); useEffect(() => { if (modal === "env") setEnvDraft(env); }, [modal, env]); // Live --mamba-full-memory-ratio from the ratio calculator (K3 pages): @@ -1194,7 +1219,7 @@ export const Deployment = ({ config, benchmarks }) => { else flags.push(line); return { ...cell, flags }; })(); - const command = renderCommand(cellWithRatio, sel, env, runMode); + const command = renderCommand(cellWithRatio, sel, env, activeRunMode); // Speculative-decoding hint on the EFFECTIVE flags — speculation can arrive via // the Spec Decode overlay as well as the cell. SGLang resets // --max-running-requests to 48 when spec is on and it's unset; verified for both @@ -1263,7 +1288,9 @@ export const Deployment = ({ config, benchmarks }) => { return out; }; const modelName = resolveModelName(sel); - const curlText = interpolate(config.curl || "", env, modelName); + const curlTemplate = + typeof config.curl === "function" ? config.curl(sel, cell) : config.curl; + const curlText = interpolate(curlTemplate || "", env, modelName); const hwGroups = buildHardwareGroups(); const benchEntry = benchmarks ? findBenchmark(benchmarks, sel) : null; @@ -1385,8 +1412,8 @@ export const Deployment = ({ config, benchmarks }) => {
Hardware Platform
{hwGroups.map((g) => ( -
-
{g.label}
+
+ {g.label &&
{g.label}
}
{g.items.map((item) => renderButton(item, "hw", sel.hw))} {Array.from({ length: maxHwCols - g.items.length }).map((_, i) => ( @@ -1431,13 +1458,13 @@ export const Deployment = ({ config, benchmarks }) => { key={mode} style={{ ...(index === runModes.length - 1 - ? s.runModeChipLast(runMode === mode) - : s.runModeChip(runMode === mode)), + ? s.runModeChipLast(activeRunMode === mode) + : s.runModeChip(activeRunMode === mode)), ...(runModes.length === 1 ? { borderRadius: 7 } : {}), }} onClick={() => setRunMode(mode)} role="tab" - aria-selected={runMode === mode} + aria-selected={activeRunMode === mode} > {mode === "docker" ? "Docker" : "Python"} @@ -1473,38 +1500,40 @@ export const Deployment = ({ config, benchmarks }) => { {/* Playground link — scrollIntoView, not an href, so the hash (which carries the selection) isn't overwritten. */} -
- Need to go beyond the verified matrix? - -
+ Need to go beyond the verified matrix? + +
+ )} {/* cURL modal */} {modal === "curl" && ( diff --git a/docs_new/src/snippets/_playground.jsx b/docs_new/src/snippets/_playground.jsx index 2b994998a..9cd398e9e 100644 --- a/docs_new/src/snippets/_playground.jsx +++ b/docs_new/src/snippets/_playground.jsx @@ -1390,6 +1390,9 @@ export const Playground = ({ config }) => { const di = config.dockerImages || {}; const image = di[`${sel.hw}|${sel.quant}|${sel.strategy}`] || di[`${sel.hw}|${sel.quant}`] || di[sel.hw] || "lmsysorg/sglang:dev"; + const dockerRunCommand = typeof config.dockerRunCommand === "function" + ? config.dockerRunCommand(sel) + : (config.dockerRunCommand || "sglang serve"); const portFlag = f.find((x) => x.split(/[\s=]/)[0] === "--port"); const servePort = portFlag ? portFlag.slice("--port".length).trim() : "{{PORT}}"; // Mirrors `multiNodeDockerFlags` on the _deployment.jsx HARDWARE_CATALOG @@ -1406,11 +1409,12 @@ export const Playground = ({ config }) => { (multinode || pdMode) ? " --network host" : ` -p ${servePort}:${servePort}`, ...(multinode ? fabricFlags.map((x) => " " + x) : []), " -v ~/.cache/huggingface:/root/.cache/huggingface", + ...(config.dockerMounts || []).map((mount) => ` -v ${mount}`), ` --env "HF_TOKEN={{HF_TOKEN}}"`, ...cellEnv.map((e) => ` --env ${e}`), " --ipc=host", ` ${image}`, - " sglang serve", + ` ${dockerRunCommand}`, ...f.map((x) => " " + x), ]; cmd = dockerLines.join(" \\\n"); diff --git a/docs_new/src/snippets/configs/MiniMaxAI/minimax-h3.jsx b/docs_new/src/snippets/configs/MiniMaxAI/minimax-h3.jsx new file mode 100644 index 000000000..fc2579ecd --- /dev/null +++ b/docs_new/src/snippets/configs/MiniMaxAI/minimax-h3.jsx @@ -0,0 +1,618 @@ +// MiniMax-H3 diffusion deployment matrix. Consumed by _deployment.jsx. +// +// The mode, quantization, and encoder choices are deployment overlays because +// they do not change which base hardware topology fits. Request sampling +// controls remain in the generated cURL instead of being mixed into this +// deployment matrix. +// Hardware/profile cells remain deliberately small and carry an honest +// verification state for the exact platform, rather than inheriting a result +// measured on a different GPU. + + +export const config = { + modelName: "MiniMax-H3", + + supportedHardware: [ + "b200", + "b300", + "h200", + "h100", + "mi300x", + "mi355x", + "rtx5090", + ], + hardware: [ + { id: "rtx5090", label: "RTX 5090", vram: "32GB", vendor: "consumer" }, + ], + groupHardware: false, + + matchDims: [ + { + id: "profile", + title: "Deployment Profile", + showWhen: (s) => ["b200", "b300", "h200", "h100"].includes(s.hw), + options: [ + { id: "resident", label: "Resident" }, + { + id: "fsdp", + label: "FSDP sharded", + showWhen: (s) => + ["b200", "b300", "h200", "h100"].includes(s.hw), + }, + { + id: "offload", + label: "Layerwise offload", + showWhen: (s) => s.hw === "rtx5090", + }, + ], + }, + ], + + overlayDims: [ + { + id: "weights", + title: "Checkpoint Weights", + default: "fl2va", + options: [ + { + id: "fl2va", + label: "FL2VA (First-and-Last-Frame-to-Video-and-Audio)", + flags: ["--model-variant fl2va"], + }, + { + id: "ref2va", + label: "Ref2VA (Reference-to-Video-and-Audio)", + flags: ["--model-variant ref2va"], + }, + ], + }, + { + id: "mode", + title: "Request Mode", + default: "t2va", + options: [ + { + id: "t2va", + label: "Text only", + showWhen: (s) => s.weights === "fl2va", + }, + { + id: "i2va", + label: "First frame", + showWhen: (s) => s.weights === "fl2va", + }, + { + id: "l2va", + label: "Last frame", + showWhen: (s) => s.weights === "fl2va", + }, + { + id: "fl2va", + label: "First + last frames", + showWhen: (s) => s.weights === "fl2va", + }, + { + id: "ref_image", + label: "Image reference", + showWhen: (s) => s.weights === "ref2va", + }, + { + id: "ref_image_audio", + label: "Image + audio", + showWhen: (s) => s.weights === "ref2va", + }, + { + id: "v2v", + label: "Video reference", + showWhen: (s) => s.weights === "ref2va", + }, + { + id: "video_audio", + label: "Video + soundtrack", + showWhen: (s) => s.weights === "ref2va", + }, + { + id: "audio_only", + label: "Audio reference", + showWhen: (s) => s.weights === "ref2va", + }, + { + id: "mixed_ref", + label: "Mixed references", + showWhen: (s) => s.weights === "ref2va", + }, + ], + }, + { + id: "quant", + title: "Online Quantization", + default: "bf16", + showWhen: (s) => ["b200", "b300"].includes(s.hw), + options: [ + { id: "bf16", label: "Off — Native BF16/FP32" }, + { + id: "fp8", + label: "FP8 — Approximate", + showWhen: (s) => ["b200", "b300"].includes(s.hw), + disabled: (s) => s.profile !== "resident", + disableReason: + "The documented FP8 operating point keeps the transformer resident; FSDP combinations have not been validated.", + flags: ["--quantization fp8"], + hints: [ + "Online FP8 is approximate. Validate both video and audio quality;", + "verified B200 and B300 runs reduced memory; re-benchmark latency on the target workload.", + ], + }, + ], + }, + { + id: "encoder", + title: "Text Encoder Parallel", + default: "auto", + options: [ + { + id: "auto", + label: "Auto (recommended)", + hints: [ + "Auto uses folding for the single-request recipes below and can", + "select data parallel encoding for a compatible TP1 request batch.", + ], + }, + { + id: "fold", + label: "Fold (single-request)", + flags: ["--encoder-parallel fold"], + hints: [ + "Fold shards the resident Qwen3-VL encoder across the replica and is", + "best suited to single-node GPUs with fast peer-to-peer links.", + ], + }, + { + id: "dp", + label: "DP (batched throughput)", + disabled: (s) => + s.hw === "rtx5090" || + (s.hw === "h100" && s.profile === "resident"), + disableReason: + "Encoder DP requires TP1 and DiT DP1; this verified recipe uses TP2.", + flags: [ + "--encoder-parallel dp", + "--batching-max-size {{BATCHING_MAX_SIZE}}", + ], + hints: [ + "DP distributes a compatible multi-request text batch across ranks;", + "it does not improve a batch of one and replicates encoder weights.", + ], + }, + { + id: "replicate", + label: "Replicate (compatibility)", + flags: ["--encoder-parallel replicate"], + }, + ], + }, + ], + + modelNames: { + default: "MiniMaxAI/MiniMax-H3", + }, + + placeholders: { + HOST_IP: { + target: "command", + label: "Bind host", + default: "0.0.0.0", + }, + PORT: { + target: "command", + label: "Bind port", + default: "30010", + }, + HF_TOKEN: { + target: "command", + label: "HF token (Docker)", + default: "", + }, + MEDIA_DIR: { + target: "command", + label: "Host media directory (Docker)", + default: "/data/minimax-h3", + }, + CURL_HOST: { + target: "curl", + label: "Server host", + default: "localhost", + }, + CURL_PORT: { + target: "curl", + label: "Server port", + default: "30010", + }, + NUM_OUTPUTS: { + target: "curl", + label: "Outputs per prompt (1-10)", + default: "1", + }, + BATCHING_MAX_SIZE: { + target: "command", + label: "Maximum request batch size", + default: "2", + }, + DURATION_SECONDS: { + target: "curl", + label: "Duration (seconds, 4-15)", + default: "5", + }, + FIRST_FRAME: { + target: "curl", + label: "FL2VA first frame URI", + default: "file:///data/minimax-h3/first-frame.png", + }, + LAST_FRAME: { + target: "curl", + label: "FL2VA last frame URI", + default: "file:///data/minimax-h3/last-frame.png", + }, + INPUT_VIDEO: { + target: "curl", + label: "First video URI", + default: "file:///data/minimax-h3/video-1.mp4", + }, + INPUT_VIDEO_START_SECONDS: { + target: "curl", + label: "First video start (seconds)", + default: "0", + }, + SECOND_INPUT_VIDEO: { + target: "curl", + label: "Second video URI (mixed ref)", + default: "file:///data/minimax-h3/video-2.mp4", + }, + SECOND_INPUT_VIDEO_START_SECONDS: { + target: "curl", + label: "Second video start (seconds)", + default: "0", + }, + REFERENCE_IMAGE: { + target: "curl", + label: "First reference image URI", + default: "file:///data/minimax-h3/reference-1.png", + }, + SECOND_REFERENCE_IMAGE: { + target: "curl", + label: "Second reference image URI", + default: "file:///data/minimax-h3/reference-2.png", + }, + REFERENCE_AUDIO: { + target: "curl", + label: "First reference audio URI", + default: "file:///data/minimax-h3/reference-1.mp3", + }, + SECOND_REFERENCE_AUDIO: { + target: "curl", + label: "Second reference audio URI", + default: "file:///data/minimax-h3/reference-2.mp3", + }, + }, + + curl: (s) => { + const request = { + model: "{{MODEL_NAME}}", + prompt: + "Night-vision bedroom footage: while the owner sleeps, three cats burst in playing tiny brass instruments at full volume, freeze, then march out as if nothing happened.", + seconds: "{{DURATION_SECONDS}}", + task: "t2va", + conditions: [], + target: { + short_edge: 768, + aspect_ratio: "16:9", + duration_seconds: "{{DURATION_SECONDS}}", + }, + num_outputs_per_prompt: "{{NUM_OUTPUTS}}", + num_inference_steps: 50, + flow_shift: 12.0, + audio_flow_shift: 3.0, + seed: 1101, + }; + const imageReference = (uri) => ({ + type: "image", + uri, + role: "reference", + }); + const audioReference = (uri) => ({ + type: "audio", + uri, + role: "reference", + }); + const videoReference = (uri, start, type = "video") => ({ + type, + uri, + role: "reference", + start_time_seconds: start, + }); + + if (["i2va", "l2va", "fl2va"].includes(s.mode)) { + request.task = "fl2va"; + request.prompt = + "Continue naturally between the supplied endpoint frame or frames, with synchronized ambient sound."; + request.target.aspect_ratio = "auto"; + request.seed = 2101; + request.conditions = []; + if (s.mode !== "l2va") { + request.conditions.push({ + type: "image", + uri: "{{FIRST_FRAME}}", + role: "keyframe", + frame_index: 0, + }); + } + if (s.mode !== "i2va") { + request.conditions.push({ + type: "image", + uri: "{{LAST_FRAME}}", + role: "keyframe", + frame_index: -1, + }); + } + } else if (s.mode === "ref_image") { + request.task = "ref2va"; + request.prompt = "Use as the visual subject and style reference."; + request.target.aspect_ratio = "auto"; + request.conditions = [imageReference("{{REFERENCE_IMAGE}}")]; + request.seed = 3101; + } else if (s.mode === "ref_image_audio") { + request.task = "ref2va"; + request.prompt = + "Use as the visual subject and