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

223 lines
8.3 KiB
Python

# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import os
import re
from dataclasses import dataclass, replace
from typing import Any
import torch
from sglang.multimodal_gen.runtime.layers.quantization.configs.nunchaku_config import (
NunchakuConfig,
is_nunchaku_available,
)
from sglang.multimodal_gen.runtime.platforms import current_platform
from sglang.multimodal_gen.runtime.utils.logging_utils import init_logger
from sglang.multimodal_gen.utils import StoreBoolean
logger = init_logger(__name__)
@dataclass
class NunchakuArgsResolution:
"""Normalized runtime settings derived from Nunchaku CLI-facing args."""
transformer_weights_path: str | None = None
nunchaku_config: NunchakuConfig | None = None
@dataclass
class NunchakuSVDQuantArgs:
"""CLI-facing configuration for Nunchaku (SVDQuant) inference.
This is intentionally lightweight and only contains arguments needed to
construct `runtime.layers.quantization.nunchaku_config.NunchakuConfig`.
"""
enable_svdquant: bool = False
transformer_weights_path: str | None = None
quantization_precision: str | None = None # "int4" or "nvfp4"
quantization_rank: int | None = None
quantization_act_unsigned: bool = False
def _infer_from_weights_path(self) -> tuple[bool, str | None, int | None]:
"""Infer whether SVDQuant is enabled and parse precision/rank from filename."""
inferred_precision = None
inferred_rank = None
enable_svdquant = self.enable_svdquant
if not self.transformer_weights_path:
return enable_svdquant, inferred_precision, inferred_rank
filename = os.path.basename(self.transformer_weights_path)
if not enable_svdquant and re.search(r"svdq-(int4|fp4)_r(\d+)", filename):
enable_svdquant = True
if not enable_svdquant:
return enable_svdquant, inferred_precision, inferred_rank
# Expected pattern: svdq-{precision}_r{rank}-...
# e.g., svdq-int4_r32-qwen-image.safetensors
match = re.search(r"svdq-(int4|fp4)_r(\d+)", filename)
if match:
p_str, r_str = match.groups()
inferred_precision = "nvfp4" if p_str == "fp4" else "int4"
inferred_rank = int(r_str)
return enable_svdquant, inferred_precision, inferred_rank
def _normalized(self) -> NunchakuSVDQuantArgs:
enable_svdquant, inferred_precision, inferred_rank = (
self._infer_from_weights_path()
)
normalized = replace(
self,
enable_svdquant=enable_svdquant,
quantization_precision=(
self.quantization_precision or inferred_precision or "int4"
),
quantization_rank=self.quantization_rank or inferred_rank or 32,
)
if self.quantization_precision is None and inferred_precision:
if inferred_precision:
logger.info(
f"inferred --quantization-precision: {normalized.quantization_precision} "
f"from --transformer-weights-path: {self.transformer_weights_path}"
)
if self.quantization_rank is None and inferred_rank:
if inferred_rank:
logger.info(
f"inferred --quantization-rank: {normalized.quantization_rank} "
f"from --transformer-weights-path: {self.transformer_weights_path}"
)
return normalized
def _validate(self) -> None:
# TODO: warn if the served model doesn't support nunchaku
if not self.enable_svdquant:
return
if not current_platform.is_cuda():
raise ValueError(
"Nunchaku SVDQuant is only supported on NVIDIA CUDA GPUs "
"(Ampere SM8x or SM12x)."
)
device_count = torch.cuda.device_count()
unsupported: list[str] = []
for i in range(device_count):
major, minor = torch.cuda.get_device_capability(i)
if major == 9:
unsupported.append(f"cuda:{i} (SM{major}{minor}, Hopper)")
elif major not in (8, 12):
unsupported.append(f"cuda:{i} (SM{major}{minor})")
if unsupported:
raise ValueError(
"Nunchaku SVDQuant is currently only supported on Ampere (SM8x) or SM12x GPUs; "
f"Unsupported devices: {', '.join(unsupported)}. "
"Disable it with --enable-svdquant false."
)
if not self.transformer_weights_path:
raise ValueError(
"--enable-svdquant requires --transformer-weights-path to be set"
)
if not is_nunchaku_available():
raise ValueError(
"Nunchaku is enabled, but not installed. Please refer to https://nunchaku.tech/docs/nunchaku/installation/installation.html for detailed installation methods."
)
if self.quantization_precision not in ("int4", "nvfp4"):
raise ValueError(
f"Invalid --quantization-precision: {self.quantization_precision}. "
"Must be one of: int4, nvfp4"
)
if self.quantization_rank <= 0:
raise ValueError(
f"Invalid --quantization-rank: {self.quantization_rank}. Must be > 0"
)
def resolve_runtime_config(self) -> NunchakuArgsResolution:
normalized = self._normalized()
normalized._validate()
if not normalized.enable_svdquant or not normalized.transformer_weights_path:
return NunchakuArgsResolution(
transformer_weights_path=normalized.transformer_weights_path,
nunchaku_config=None,
)
return NunchakuArgsResolution(
transformer_weights_path=normalized.transformer_weights_path,
nunchaku_config=NunchakuConfig(
precision=normalized.quantization_precision,
rank=normalized.quantization_rank,
act_unsigned=normalized.quantization_act_unsigned,
transformer_weights_path=normalized.transformer_weights_path,
),
)
@staticmethod
def add_cli_args(parser) -> None:
parser.add_argument(
"--enable-svdquant",
action=StoreBoolean,
default=NunchakuSVDQuantArgs.enable_svdquant,
help="Enable Nunchaku SVDQuant (W4A4-style) inference.",
)
parser.add_argument(
"--transformer-weights-path",
type=str,
default=NunchakuSVDQuantArgs.transformer_weights_path,
help=(
"Path to pre-quantized transformer weights. Can be a single .safetensors "
"file, a directory, or a HuggingFace repo ID. Used by Nunchaku (SVDQuant) and quantized single-file checkpoints."
),
)
parser.add_argument(
"--quantization-precision",
type=str,
default=None,
help="Quantization precision: int4 or nvfp4. If not specified, inferred from model path or defaults to int4.",
)
parser.add_argument(
"--quantization-rank",
type=int,
default=None,
help="SVD low-rank dimension (e.g., 32). If not specified, inferred from model path or defaults to 32.",
)
parser.add_argument(
"--quantization-act-unsigned",
action=StoreBoolean,
default=NunchakuSVDQuantArgs.quantization_act_unsigned,
help="Use unsigned activation quantization (if supported).",
)
@classmethod
def from_dict(cls, kwargs: dict[str, Any]) -> NunchakuSVDQuantArgs:
# Map CLI/config keys to dataclass fields (keep backwards compatibility).
path = (
kwargs.get("transformer_weights_path")
or kwargs.get("transformer_quantized_path")
or kwargs.get("quantized_model_path")
)
return cls(
enable_svdquant=bool(kwargs.get("enable_svdquant", cls.enable_svdquant)),
transformer_weights_path=path,
quantization_precision=kwargs.get("quantization_precision"),
quantization_rank=kwargs.get("quantization_rank"),
quantization_act_unsigned=bool(
kwargs.get("quantization_act_unsigned", cls.quantization_act_unsigned)
),
)