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
221 lines
7.6 KiB
Python
221 lines
7.6 KiB
Python
# Adapted from https://github.com/vllm-project/vllm/tree/main/vllm/model_executor/layers/quantization/compressed_tensors
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
|
|
|
import re
|
|
from types import MappingProxyType
|
|
from typing import Iterable, List, Mapping, Optional
|
|
|
|
from compressed_tensors import CompressionFormat
|
|
from torch.nn import Module
|
|
|
|
|
|
def is_activation_quantization_format(format: str) -> bool:
|
|
_ACTIVATION_QUANTIZATION_FORMATS = [
|
|
CompressionFormat.naive_quantized.value,
|
|
CompressionFormat.int_quantized.value,
|
|
CompressionFormat.float_quantized.value,
|
|
CompressionFormat.nvfp4_pack_quantized.value,
|
|
]
|
|
return format in _ACTIVATION_QUANTIZATION_FORMATS
|
|
|
|
|
|
def should_ignore_layer(
|
|
layer_name: Optional[str],
|
|
ignore: Iterable[str] = tuple(),
|
|
fused_mapping: Mapping[str, List[str]] = MappingProxyType({}),
|
|
) -> bool:
|
|
if layer_name is None:
|
|
return False
|
|
|
|
# layer_name = model.layers.0.self_attn.qkv_proj
|
|
# proj_name = qkv_proj
|
|
proj_name = layer_name.split(".")[-1]
|
|
|
|
# Fused layers like gate_up_proj or qkv_proj will not be fused
|
|
# in the safetensors checkpoint. So, we convert the name
|
|
# from the fused version to unfused + check to make sure that
|
|
# each shard of the fused layer has the same scheme.
|
|
if proj_name in fused_mapping and layer_name not in ignore:
|
|
shard_proj_names = fused_mapping[proj_name]
|
|
|
|
# Convert fused_name --> [shard_names]
|
|
shard_names = [
|
|
layer_name.replace(proj_name, shard_proj_name)
|
|
for shard_proj_name in shard_proj_names
|
|
]
|
|
|
|
# Layer should be ignored if shards are ignored.
|
|
should_ignore_layer = None
|
|
for shard_name in shard_names:
|
|
should_ignore_shard = check_equal_or_regex_match(
|
|
layer_name=shard_name, targets=ignore
|
|
)
|
|
|
|
# If shard_idx=0, set layer ignore to match shard.
|
|
if should_ignore_layer is None:
|
|
should_ignore_layer = should_ignore_shard
|
|
|
|
# If shard_idx=1+ confirm scheme matches prior shards.
|
|
elif should_ignore_shard != should_ignore_layer:
|
|
raise ValueError(
|
|
f"Found different quantization schemes for "
|
|
f"{shard_proj_names} in {layer_name}. SGLang "
|
|
"requires all to use the same scheme."
|
|
)
|
|
|
|
# Unfused layers like down_proj and o_proj will match
|
|
# the safetensors checkpoint already.
|
|
else:
|
|
should_ignore_layer = check_equal_or_regex_match(
|
|
layer_name=layer_name, targets=ignore
|
|
)
|
|
|
|
assert should_ignore_layer is not None
|
|
return should_ignore_layer
|
|
|
|
|
|
def check_equal_or_regex_match(layer_name: str, targets: Iterable[str]) -> bool:
|
|
"""
|
|
Checks whether a layer_name is exactly equal or a regex match for
|
|
if target starts with 're:' to any target in list.
|
|
"""
|
|
for target in targets:
|
|
if _is_equal_or_regex_match(layer_name, target, check_contains=True):
|
|
return True
|
|
return False
|
|
|
|
|
|
def find_matched_target(
|
|
layer_name: Optional[str],
|
|
module: Module,
|
|
targets: Iterable[str],
|
|
fused_mapping: Mapping[str, List[str]] = MappingProxyType({}),
|
|
) -> str:
|
|
"""
|
|
Helper function to look up which "target" in the compressed-tensors
|
|
config that a layer corresponds to.
|
|
|
|
Recall that a compressed-tensors configs has a concept of
|
|
config_groups, where each layer can be quantized with with a different
|
|
scheme.
|
|
|
|
targets in each config_group will be a list of either layer names
|
|
(or regexes corresponding to layer names) or names of torch Modules.
|
|
|
|
First, we try to match the layer_name with a target
|
|
Second, we try to match the module's name with a target
|
|
Third, we try to map the layer_name to a list of fused module names.
|
|
*All* component module names must match in order for a match to be
|
|
successful. A successful match returns the first component target
|
|
|
|
:param layer_name: layer name
|
|
:param module: torch.nn.Module
|
|
:param targets: list of targets to match the layer against
|
|
:param fused_mapping: map from fused layer names to its components
|
|
:param fused_strategy: either "all" or "any". If using "all", fused
|
|
layers match if "all" of its components match
|
|
"""
|
|
|
|
if layer_name is None:
|
|
layer_name = ""
|
|
|
|
matched_target = (
|
|
_find_first_match(layer_name, targets)
|
|
or _find_first_match(module.__class__.__name__, targets, True)
|
|
or _match_fused_layer(layer_name, targets, fused_mapping)
|
|
)
|
|
|
|
if matched_target is None:
|
|
raise ValueError(
|
|
f"Unable to find matching target for {layer_name} in the "
|
|
"compressed-tensors config."
|
|
)
|
|
|
|
return matched_target
|
|
|
|
|
|
def _find_first_match(
|
|
value: str, targets: Iterable[str], check_contains: bool = False
|
|
) -> Optional[str]:
|
|
"""
|
|
Returns first element of target that matches value either
|
|
exactly or as a regex after 're:'. If check_contains is set to True,
|
|
additionally checks if the target string is contained within the value.
|
|
|
|
:param value: string to compare the list of targets against
|
|
:param targets: list of targets to match the layer against
|
|
:param check_contains: whether or not to do a substring match
|
|
"""
|
|
|
|
for target in targets:
|
|
if _is_equal_or_regex_match(value, target, check_contains=check_contains):
|
|
return target
|
|
return None
|
|
|
|
|
|
def _is_equal_or_regex_match(
|
|
value: str, target: str, check_contains: bool = False
|
|
) -> bool:
|
|
"""
|
|
Checks whether a value is exactly equal or a regex match for target
|
|
if target starts with 're:'. If check_contains is set to True,
|
|
additionally checks if the target string is contained within the value.
|
|
"""
|
|
|
|
if target.startswith("re:"):
|
|
pattern = target[3:]
|
|
if re.match(pattern, value):
|
|
return True
|
|
elif check_contains:
|
|
if target.lower() in value.lower():
|
|
return True
|
|
elif target == value:
|
|
return True
|
|
return False
|
|
|
|
|
|
def _match_fused_layer(
|
|
layer_name: str,
|
|
target_layers: Iterable[str],
|
|
fused_mapping: Mapping[str, List[str]],
|
|
) -> Optional[str]:
|
|
"""
|
|
Match a fused layer name to its corresponding individual layer in
|
|
target_layers. Returns first value in fused_mapping which matches targets
|
|
|
|
Implements an "all" matching strategy where a fused layer matches iff
|
|
"all" of its components match
|
|
|
|
:param layer_name: layer name
|
|
:param target_layers: list of targets to match the layer against
|
|
:param fused_mapping: map from fused layer names to its components
|
|
|
|
Examples:
|
|
layer_name = "model.layers.0.self_attn.qkv_proj"
|
|
target_layers = ["model.layers.0.self_attn.q_proj",
|
|
"model.layers.0.self_attn.k_proj",
|
|
"model.layers.0.self_attn.v_proj"]
|
|
"""
|
|
# find layer_name in mapping
|
|
fused = next((key for key in fused_mapping if layer_name.endswith(key)), None)
|
|
if fused is None:
|
|
return None
|
|
|
|
# expand path of unfused components
|
|
unfused_paths = [
|
|
layer_name.replace(fused, unfused) for unfused in fused_mapping[fused]
|
|
]
|
|
|
|
# for each unfused component, find a match in targets
|
|
unfused_matches: List[Optional[str]] = []
|
|
for unfused in unfused_paths:
|
|
for target in target_layers:
|
|
if _is_equal_or_regex_match(unfused, target):
|
|
unfused_matches.append(target)
|
|
break
|
|
else:
|
|
unfused_matches.append(None)
|
|
|
|
return unfused_matches[0] if all(unfused_matches) else None
|