Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- lib/python3.12/site-packages/sglang/srt/configs/__init__.py +13 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/chatglm.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/dbrx.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/deepseekvl2.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/device_config.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/exaone.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/janus_pro.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/load_config.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/model_config.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/__pycache__/utils.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/configs/chatglm.py +78 -0
- lib/python3.12/site-packages/sglang/srt/configs/dbrx.py +279 -0
- lib/python3.12/site-packages/sglang/srt/configs/deepseekvl2.py +676 -0
- lib/python3.12/site-packages/sglang/srt/configs/device_config.py +17 -0
- lib/python3.12/site-packages/sglang/srt/configs/exaone.py +195 -0
- lib/python3.12/site-packages/sglang/srt/configs/janus_pro.py +628 -0
- lib/python3.12/site-packages/sglang/srt/configs/load_config.py +89 -0
- lib/python3.12/site-packages/sglang/srt/configs/model_config.py +558 -0
- lib/python3.12/site-packages/sglang/srt/configs/utils.py +25 -0
- lib/python3.12/site-packages/sglang/srt/connector/__init__.py +51 -0
- lib/python3.12/site-packages/sglang/srt/connector/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/__pycache__/base_connector.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/__pycache__/redis.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/__pycache__/s3.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/__pycache__/utils.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/base_connector.py +112 -0
- lib/python3.12/site-packages/sglang/srt/connector/redis.py +85 -0
- lib/python3.12/site-packages/sglang/srt/connector/s3.py +122 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/__init__.py +31 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/safe_serde.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/serde.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/safe_serde.py +29 -0
- lib/python3.12/site-packages/sglang/srt/connector/serde/serde.py +43 -0
- lib/python3.12/site-packages/sglang/srt/connector/utils.py +35 -0
- lib/python3.12/site-packages/sglang/srt/layers/activation.py +172 -0
- lib/python3.12/site-packages/sglang/srt/layers/dp_attention.py +260 -0
- lib/python3.12/site-packages/sglang/srt/layers/elementwise.py +424 -0
- lib/python3.12/site-packages/sglang/srt/layers/layernorm.py +183 -0
- lib/python3.12/site-packages/sglang/srt/layers/linear.py +1307 -0
- lib/python3.12/site-packages/sglang/srt/layers/logits_processor.py +586 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_native.py +139 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/__init__.py +40 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=14336,device_name=NVIDIA_A100-SXM4-80GB,dtype=int8_w8a16.json +146 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=14336,device_name=NVIDIA_A100-SXM4-80GB.json +146 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=7168,device_name=NVIDIA_A100-SXM4-80GB,dtype=int8_w8a16.json +218 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=7168,device_name=NVIDIA_A100-SXM4-80GB.json +218 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=128,N=192,device_name=NVIDIA_H20.json +146 -0
- lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=128,N=384,device_name=NVIDIA_H20.json +146 -0
lib/python3.12/site-packages/sglang/srt/configs/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sglang.srt.configs.chatglm import ChatGLMConfig
|
| 2 |
+
from sglang.srt.configs.dbrx import DbrxConfig
|
| 3 |
+
from sglang.srt.configs.deepseekvl2 import DeepseekVL2Config
|
| 4 |
+
from sglang.srt.configs.exaone import ExaoneConfig
|
| 5 |
+
from sglang.srt.configs.janus_pro import MultiModalityConfig
|
| 6 |
+
|
| 7 |
+
__all__ = [
|
| 8 |
+
"ExaoneConfig",
|
| 9 |
+
"ChatGLMConfig",
|
| 10 |
+
"DbrxConfig",
|
| 11 |
+
"DeepseekVL2Config",
|
| 12 |
+
"MultiModalityConfig",
|
| 13 |
+
]
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (583 Bytes). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/chatglm.cpython-312.pyc
ADDED
|
Binary file (2.26 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/dbrx.cpython-312.pyc
ADDED
|
Binary file (11.5 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/deepseekvl2.cpython-312.pyc
ADDED
|
Binary file (24.8 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/device_config.cpython-312.pyc
ADDED
|
Binary file (1.07 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/exaone.cpython-312.pyc
ADDED
|
Binary file (10 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/janus_pro.cpython-312.pyc
ADDED
|
Binary file (25.1 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/load_config.cpython-312.pyc
ADDED
|
Binary file (4.3 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/model_config.cpython-312.pyc
ADDED
|
Binary file (19.8 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/__pycache__/utils.cpython-312.pyc
ADDED
|
Binary file (1.1 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/configs/chatglm.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Adapted from
|
| 2 |
+
# https://github.com/THUDM/ChatGLM2-6B
|
| 3 |
+
# https://github.com/vllm-project/vllm/blob/main/vllm/transformers_utils/configs/chatglm.py
|
| 4 |
+
|
| 5 |
+
# ChatGLM2 and ChatGLM3 share the same config.
|
| 6 |
+
# ChatGLM4 is officially supported by Huggingface
|
| 7 |
+
# transformers >= 4.46.0 is required
|
| 8 |
+
# https://huggingface.co/docs/transformers/en/model_doc/glm
|
| 9 |
+
from transformers import PretrainedConfig
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class ChatGLMConfig(PretrainedConfig):
|
| 13 |
+
model_type = "chatglm"
|
| 14 |
+
attribute_map = {
|
| 15 |
+
"num_hidden_layers": "num_layers",
|
| 16 |
+
"n_head_kv": "multi_query_group_num",
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
def __init__(
|
| 20 |
+
self,
|
| 21 |
+
num_layers=28,
|
| 22 |
+
padded_vocab_size=65024,
|
| 23 |
+
hidden_size=4096,
|
| 24 |
+
ffn_hidden_size=13696,
|
| 25 |
+
kv_channels=128,
|
| 26 |
+
num_attention_heads=32,
|
| 27 |
+
seq_length=2048,
|
| 28 |
+
hidden_dropout=0.0,
|
| 29 |
+
attention_dropout=0.0,
|
| 30 |
+
layernorm_epsilon=1e-5,
|
| 31 |
+
rmsnorm=True,
|
| 32 |
+
apply_residual_connection_post_layernorm=False,
|
| 33 |
+
post_layer_norm=True,
|
| 34 |
+
add_bias_linear=False,
|
| 35 |
+
add_qkv_bias=False,
|
| 36 |
+
interleaved_qkv=False,
|
| 37 |
+
bias_dropout_fusion=True,
|
| 38 |
+
multi_query_attention=False,
|
| 39 |
+
multi_query_group_num=1,
|
| 40 |
+
apply_query_key_layer_scaling=True,
|
| 41 |
+
attention_softmax_in_fp32=True,
|
| 42 |
+
fp32_residual_connection=False,
|
| 43 |
+
quantization_bit=0,
|
| 44 |
+
pre_seq_len=None,
|
| 45 |
+
prefix_projection=False,
|
| 46 |
+
**kwargs
|
| 47 |
+
):
|
| 48 |
+
self.num_layers = num_layers
|
| 49 |
+
self.vocab_size = padded_vocab_size
|
| 50 |
+
self.padded_vocab_size = padded_vocab_size
|
| 51 |
+
self.hidden_size = hidden_size
|
| 52 |
+
self.ffn_hidden_size = ffn_hidden_size
|
| 53 |
+
self.kv_channels = kv_channels
|
| 54 |
+
self.num_attention_heads = num_attention_heads
|
| 55 |
+
self.seq_length = seq_length
|
| 56 |
+
# It is to be compatible with long lora.
|
| 57 |
+
self.max_position_embeddings = seq_length
|
| 58 |
+
self.hidden_dropout = hidden_dropout
|
| 59 |
+
self.attention_dropout = attention_dropout
|
| 60 |
+
self.layernorm_epsilon = layernorm_epsilon
|
| 61 |
+
self.rmsnorm = rmsnorm
|
| 62 |
+
self.apply_residual_connection_post_layernorm = (
|
| 63 |
+
apply_residual_connection_post_layernorm
|
| 64 |
+
)
|
| 65 |
+
self.post_layer_norm = post_layer_norm
|
| 66 |
+
self.add_bias_linear = add_bias_linear
|
| 67 |
+
self.add_qkv_bias = add_qkv_bias
|
| 68 |
+
self.bias_dropout_fusion = bias_dropout_fusion
|
| 69 |
+
self.multi_query_attention = multi_query_attention
|
| 70 |
+
self.multi_query_group_num = multi_query_group_num
|
| 71 |
+
self.apply_query_key_layer_scaling = apply_query_key_layer_scaling
|
| 72 |
+
self.attention_softmax_in_fp32 = attention_softmax_in_fp32
|
| 73 |
+
self.fp32_residual_connection = fp32_residual_connection
|
| 74 |
+
self.quantization_bit = quantization_bit
|
| 75 |
+
self.pre_seq_len = pre_seq_len
|
| 76 |
+
self.prefix_projection = prefix_projection
|
| 77 |
+
self.interleaved_qkv = interleaved_qkv
|
| 78 |
+
super().__init__(**kwargs)
|
lib/python3.12/site-packages/sglang/srt/configs/dbrx.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Adapted from
|
| 2 |
+
# https://huggingface.co/databricks/dbrx-base/blob/main/configuration_dbrx.py
|
| 3 |
+
# https://github.com/vllm-project/vllm/blob/main/vllm/transformers_utils/configs/dbrx.py
|
| 4 |
+
"""Dbrx configuration."""
|
| 5 |
+
|
| 6 |
+
from typing import Any, Optional
|
| 7 |
+
|
| 8 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 9 |
+
from transformers.utils import logging
|
| 10 |
+
|
| 11 |
+
logger = logging.get_logger(__name__)
|
| 12 |
+
|
| 13 |
+
DBRX_PRETRAINED_CONFIG_ARCHIVE_MAP = {} # type: ignore
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class DbrxAttentionConfig(PretrainedConfig):
|
| 17 |
+
"""Configuration class for Dbrx Attention.
|
| 18 |
+
|
| 19 |
+
[`DbrxAttention`] class. It is used to instantiate attention layers
|
| 20 |
+
according to the specified arguments, defining the layers architecture.
|
| 21 |
+
|
| 22 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 23 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
attn_pdrop (`float`, *optional*, defaults to 0.0):
|
| 27 |
+
The dropout probability for the attention layers.
|
| 28 |
+
clip_qkv (`float`, *optional*, defaults to None):
|
| 29 |
+
If not `None`, clip the queries, keys, and values in the attention layer to this value.
|
| 30 |
+
kv_n_heads (Optional[int]): For grouped_query_attention only, allow user to specify number of kv heads.
|
| 31 |
+
rope_theta (float): The base frequency for rope.
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
def __init__(
|
| 35 |
+
self,
|
| 36 |
+
attn_pdrop: float = 0,
|
| 37 |
+
clip_qkv: Optional[float] = None,
|
| 38 |
+
kv_n_heads: int = 1,
|
| 39 |
+
rope_theta: float = 10000.0,
|
| 40 |
+
**kwargs: Any,
|
| 41 |
+
):
|
| 42 |
+
super().__init__(**kwargs)
|
| 43 |
+
self.attn_pdrop = attn_pdrop
|
| 44 |
+
self.clip_qkv = clip_qkv
|
| 45 |
+
self.kv_n_heads = kv_n_heads
|
| 46 |
+
self.rope_theta = rope_theta
|
| 47 |
+
|
| 48 |
+
for k in ["model_type"]:
|
| 49 |
+
if k in kwargs:
|
| 50 |
+
kwargs.pop(k)
|
| 51 |
+
if len(kwargs) != 0:
|
| 52 |
+
raise ValueError(f"Found unknown {kwargs=}")
|
| 53 |
+
|
| 54 |
+
@classmethod
|
| 55 |
+
def from_pretrained(
|
| 56 |
+
cls, pretrained_model_name_or_path: str, **kwargs: Any
|
| 57 |
+
) -> "PretrainedConfig":
|
| 58 |
+
cls._set_token_in_kwargs(kwargs)
|
| 59 |
+
|
| 60 |
+
config_dict, kwargs = cls.get_config_dict(
|
| 61 |
+
pretrained_model_name_or_path, **kwargs
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
if config_dict.get("model_type") == "dbrx":
|
| 65 |
+
config_dict = config_dict["attn_config"]
|
| 66 |
+
|
| 67 |
+
if (
|
| 68 |
+
"model_type" in config_dict
|
| 69 |
+
and hasattr(cls, "model_type")
|
| 70 |
+
and config_dict["model_type"] != cls.model_type
|
| 71 |
+
):
|
| 72 |
+
logger.warning(
|
| 73 |
+
"You are using a model of type %s to instantiate a model of "
|
| 74 |
+
"type %s. This is not supported for all configurations of "
|
| 75 |
+
"models and can yield errors.",
|
| 76 |
+
config_dict["model_type"],
|
| 77 |
+
cls.model_type,
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
return cls.from_dict(config_dict, **kwargs)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class DbrxFFNConfig(PretrainedConfig):
|
| 84 |
+
"""Configuration class for Dbrx FFN.
|
| 85 |
+
|
| 86 |
+
[`DbrxFFN`] class. It is used to instantiate feedforward layers according to
|
| 87 |
+
the specified arguments, defining the layers architecture.
|
| 88 |
+
|
| 89 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 90 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
ffn_act_fn (dict, optional): A dict specifying activation function for the FFN.
|
| 94 |
+
The dict should have a key 'name' with the value being the name of
|
| 95 |
+
the activation function along with any additional keyword arguments.
|
| 96 |
+
ffn_hidden_size (int, optional): The hidden size of the feedforward network.
|
| 97 |
+
moe_num_experts (int, optional): The number of experts in the mixture of experts layer.
|
| 98 |
+
moe_top_k (int, optional): The number of experts to use in the mixture of experts layer.
|
| 99 |
+
moe_jitter_eps (float, optional): The jitter epsilon for the mixture of experts layer.
|
| 100 |
+
moe_loss_weight (float, optional): The loss weight for the mixture of experts layer.
|
| 101 |
+
moe_normalize_expert_weights (float, optional): The normalization factor for the expert weights.
|
| 102 |
+
uniform_expert_assignment (bool, optional): Whether to use uniform expert assignment.
|
| 103 |
+
This should only be used for benchmarking purposes.
|
| 104 |
+
"""
|
| 105 |
+
|
| 106 |
+
def __init__(
|
| 107 |
+
self,
|
| 108 |
+
ffn_act_fn: Optional[dict] = None,
|
| 109 |
+
ffn_hidden_size: int = 3584,
|
| 110 |
+
moe_num_experts: int = 4,
|
| 111 |
+
moe_top_k: int = 1,
|
| 112 |
+
moe_jitter_eps: Optional[float] = None,
|
| 113 |
+
moe_loss_weight: float = 0.01,
|
| 114 |
+
moe_normalize_expert_weights: Optional[float] = 1,
|
| 115 |
+
uniform_expert_assignment: bool = False,
|
| 116 |
+
**kwargs: Any,
|
| 117 |
+
):
|
| 118 |
+
super().__init__()
|
| 119 |
+
if ffn_act_fn is None:
|
| 120 |
+
ffn_act_fn = {"name": "silu"}
|
| 121 |
+
self.ffn_act_fn = ffn_act_fn
|
| 122 |
+
self.ffn_hidden_size = ffn_hidden_size
|
| 123 |
+
self.moe_num_experts = moe_num_experts
|
| 124 |
+
self.moe_top_k = moe_top_k
|
| 125 |
+
self.moe_jitter_eps = moe_jitter_eps
|
| 126 |
+
self.moe_loss_weight = moe_loss_weight
|
| 127 |
+
self.moe_normalize_expert_weights = moe_normalize_expert_weights
|
| 128 |
+
self.uniform_expert_assignment = uniform_expert_assignment
|
| 129 |
+
|
| 130 |
+
for k in ["model_type"]:
|
| 131 |
+
if k in kwargs:
|
| 132 |
+
kwargs.pop(k)
|
| 133 |
+
if len(kwargs) != 0:
|
| 134 |
+
raise ValueError(f"Found unknown {kwargs=}")
|
| 135 |
+
|
| 136 |
+
@classmethod
|
| 137 |
+
def from_pretrained(
|
| 138 |
+
cls, pretrained_model_name_or_path: str, **kwargs: Any
|
| 139 |
+
) -> "PretrainedConfig":
|
| 140 |
+
cls._set_token_in_kwargs(kwargs)
|
| 141 |
+
|
| 142 |
+
config_dict, kwargs = cls.get_config_dict(
|
| 143 |
+
pretrained_model_name_or_path, **kwargs
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
if config_dict.get("model_type") == "dbrx":
|
| 147 |
+
config_dict = config_dict["ffn_config"]
|
| 148 |
+
|
| 149 |
+
if (
|
| 150 |
+
"model_type" in config_dict
|
| 151 |
+
and hasattr(cls, "model_type")
|
| 152 |
+
and config_dict["model_type"] != cls.model_type
|
| 153 |
+
):
|
| 154 |
+
logger.warning(
|
| 155 |
+
"You are using a model of type %s to instantiate a model of "
|
| 156 |
+
"type %s. This is not supported for all "
|
| 157 |
+
"configurations of models and can yield errors.",
|
| 158 |
+
config_dict["model_type"],
|
| 159 |
+
cls.model_type,
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
return cls.from_dict(config_dict, **kwargs)
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
class DbrxConfig(PretrainedConfig):
|
| 166 |
+
"""Configuration class for Dbrx.
|
| 167 |
+
|
| 168 |
+
[`DbrxModel`]. It is used to instantiate a Dbrx model according to the
|
| 169 |
+
specified arguments, defining the model architecture.
|
| 170 |
+
|
| 171 |
+
Configuration objects inherit from [`PretrainedConfig`] and can be used to control the model outputs. Read the
|
| 172 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
Args:
|
| 176 |
+
d_model (`int`, *optional*, defaults to 6144):
|
| 177 |
+
Dimensionality of the embeddings and hidden states.
|
| 178 |
+
n_heads (`int`, *optional*, defaults to 48):
|
| 179 |
+
Number of attention heads for each attention layer in the Transformer encoder.
|
| 180 |
+
n_layers (`int`, *optional*, defaults to 40):
|
| 181 |
+
Number of hidden layers in the Transformer encoder.
|
| 182 |
+
max_seq_len (`int`, *optional*, defaults to 32768):
|
| 183 |
+
The maximum sequence length of the model.
|
| 184 |
+
vocab_size (`int`, *optional*, defaults to 100352):
|
| 185 |
+
Vocabulary size of the Dbrx model. Defines the maximum number of different tokens that can be represented by
|
| 186 |
+
the `inputs_ids` passed when calling [`DbrxModel`].
|
| 187 |
+
resid_pdrop (`float`, *optional*, defaults to 0.0):
|
| 188 |
+
The dropout probability applied to the attention output before combining with residual.
|
| 189 |
+
emb_pdrop (`float`, *optional*, defaults to 0.0):
|
| 190 |
+
The dropout probability for the embedding layer.
|
| 191 |
+
attn_config (`dict`, *optional*):
|
| 192 |
+
A dictionary used to configure the model's attention module.
|
| 193 |
+
ffn_config (`dict`, *optional*):
|
| 194 |
+
A dictionary used to configure the model's FFN module.
|
| 195 |
+
use_cache (`bool`, *optional*, defaults to `False`):
|
| 196 |
+
Whether or not the model should return the last key/values attentions (not used by all models).
|
| 197 |
+
initializer_range (`float`, *optional*, defaults to 0.02):
|
| 198 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 199 |
+
output_router_logits (`bool`, *optional*, defaults to `False`):
|
| 200 |
+
Whether or not the router logits should be returned by the model. Enabling this will also
|
| 201 |
+
allow the model to output the auxiliary loss. See [here]() for more details
|
| 202 |
+
router_aux_loss_coef (`float`, *optional*, defaults to 0.001):
|
| 203 |
+
The aux loss factor for the total loss.
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
Example:
|
| 207 |
+
```python
|
| 208 |
+
>>> from transformers import DbrxConfig, DbrxModel
|
| 209 |
+
|
| 210 |
+
>>> # Initializing a Dbrx configuration
|
| 211 |
+
>>> configuration = DbrxConfig()
|
| 212 |
+
|
| 213 |
+
>>> # Initializing a model (with random weights) from the configuration
|
| 214 |
+
>>> model = DbrxModel(configuration)
|
| 215 |
+
|
| 216 |
+
>>> # Accessing the model configuration
|
| 217 |
+
>>> configuration = model.config
|
| 218 |
+
```
|
| 219 |
+
"""
|
| 220 |
+
|
| 221 |
+
model_type = "dbrx"
|
| 222 |
+
attribute_map = {
|
| 223 |
+
"num_attention_heads": "n_heads",
|
| 224 |
+
"hidden_size": "d_model",
|
| 225 |
+
"num_hidden_layers": "n_layers",
|
| 226 |
+
"max_position_embeddings": "max_seq_len",
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
def __init__(
|
| 230 |
+
self,
|
| 231 |
+
d_model: int = 2048,
|
| 232 |
+
n_heads: int = 16,
|
| 233 |
+
n_layers: int = 24,
|
| 234 |
+
max_seq_len: int = 2048,
|
| 235 |
+
vocab_size: int = 32000,
|
| 236 |
+
resid_pdrop: float = 0.0,
|
| 237 |
+
emb_pdrop: float = 0.0,
|
| 238 |
+
attn_config: Optional[DbrxAttentionConfig] = None,
|
| 239 |
+
ffn_config: Optional[DbrxFFNConfig] = None,
|
| 240 |
+
use_cache: bool = True,
|
| 241 |
+
initializer_range: float = 0.02,
|
| 242 |
+
output_router_logits: bool = False,
|
| 243 |
+
router_aux_loss_coef: float = 0.05,
|
| 244 |
+
**kwargs: Any,
|
| 245 |
+
):
|
| 246 |
+
if attn_config is None:
|
| 247 |
+
self.attn_config = DbrxAttentionConfig()
|
| 248 |
+
elif isinstance(attn_config, dict):
|
| 249 |
+
self.attn_config = DbrxAttentionConfig(**attn_config)
|
| 250 |
+
else:
|
| 251 |
+
self.attn_config = attn_config
|
| 252 |
+
|
| 253 |
+
if ffn_config is None:
|
| 254 |
+
self.ffn_config = DbrxFFNConfig()
|
| 255 |
+
elif isinstance(ffn_config, dict):
|
| 256 |
+
self.ffn_config = DbrxFFNConfig(**ffn_config)
|
| 257 |
+
else:
|
| 258 |
+
self.ffn_config = ffn_config
|
| 259 |
+
|
| 260 |
+
self.d_model = d_model
|
| 261 |
+
self.n_heads = n_heads
|
| 262 |
+
self.n_layers = n_layers
|
| 263 |
+
self.max_seq_len = max_seq_len
|
| 264 |
+
self.vocab_size = vocab_size
|
| 265 |
+
self.resid_pdrop = resid_pdrop
|
| 266 |
+
self.emb_pdrop = emb_pdrop
|
| 267 |
+
self.use_cache = use_cache
|
| 268 |
+
self.initializer_range = initializer_range
|
| 269 |
+
self.output_router_logits = output_router_logits
|
| 270 |
+
self.router_aux_loss_coef = router_aux_loss_coef
|
| 271 |
+
|
| 272 |
+
tie_word_embeddings = kwargs.pop("tie_word_embeddings", False)
|
| 273 |
+
if tie_word_embeddings:
|
| 274 |
+
raise ValueError("tie_word_embeddings is not supported for Dbrx models.")
|
| 275 |
+
|
| 276 |
+
super().__init__(
|
| 277 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 278 |
+
**kwargs,
|
| 279 |
+
)
|
lib/python3.12/site-packages/sglang/srt/configs/deepseekvl2.py
ADDED
|
@@ -0,0 +1,676 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import os
|
| 3 |
+
from dataclasses import dataclass
|
| 4 |
+
from typing import Dict, List, Optional, Tuple
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
from PIL import Image, ImageOps
|
| 8 |
+
from transformers import (
|
| 9 |
+
AutoProcessor,
|
| 10 |
+
LlamaTokenizerFast,
|
| 11 |
+
PretrainedConfig,
|
| 12 |
+
ProcessorMixin,
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def select_best_resolution(image_size, candidate_resolutions):
|
| 17 |
+
# used for cropping
|
| 18 |
+
original_width, original_height = image_size
|
| 19 |
+
best_fit = None
|
| 20 |
+
max_effective_resolution = 0
|
| 21 |
+
min_wasted_resolution = float("inf")
|
| 22 |
+
|
| 23 |
+
for width, height in candidate_resolutions:
|
| 24 |
+
scale = min(width / original_width, height / original_height)
|
| 25 |
+
downscaled_width, downscaled_height = int(original_width * scale), int(
|
| 26 |
+
original_height * scale
|
| 27 |
+
)
|
| 28 |
+
effective_resolution = min(
|
| 29 |
+
downscaled_width * downscaled_height, original_width * original_height
|
| 30 |
+
)
|
| 31 |
+
wasted_resolution = (width * height) - effective_resolution
|
| 32 |
+
|
| 33 |
+
if effective_resolution > max_effective_resolution or (
|
| 34 |
+
effective_resolution == max_effective_resolution
|
| 35 |
+
and wasted_resolution < min_wasted_resolution
|
| 36 |
+
):
|
| 37 |
+
max_effective_resolution = effective_resolution
|
| 38 |
+
min_wasted_resolution = wasted_resolution
|
| 39 |
+
best_fit = (width, height)
|
| 40 |
+
|
| 41 |
+
return best_fit
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class DictOutput(object):
|
| 45 |
+
def keys(self):
|
| 46 |
+
return self.__dict__.keys()
|
| 47 |
+
|
| 48 |
+
def __getitem__(self, item):
|
| 49 |
+
return self.__dict__[item]
|
| 50 |
+
|
| 51 |
+
def __setitem__(self, key, value):
|
| 52 |
+
self.__dict__[key] = value
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
@dataclass
|
| 56 |
+
class VLChatProcessorOutput(DictOutput):
|
| 57 |
+
input_ids: torch.LongTensor
|
| 58 |
+
target_ids: torch.LongTensor
|
| 59 |
+
images: torch.Tensor
|
| 60 |
+
images_seq_mask: torch.BoolTensor
|
| 61 |
+
images_spatial_crop: torch.LongTensor
|
| 62 |
+
|
| 63 |
+
def __len__(self):
|
| 64 |
+
return len(self.input_ids)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class ImageTransform(object):
|
| 68 |
+
def __init__(
|
| 69 |
+
self,
|
| 70 |
+
mean: Optional[Tuple[float, float, float]] = (0.5, 0.5, 0.5),
|
| 71 |
+
std: Optional[Tuple[float, float, float]] = (0.5, 0.5, 0.5),
|
| 72 |
+
normalize: bool = True,
|
| 73 |
+
):
|
| 74 |
+
self.mean = mean
|
| 75 |
+
self.std = std
|
| 76 |
+
self.normalize = normalize
|
| 77 |
+
|
| 78 |
+
# only load torchvision.transforms when needed
|
| 79 |
+
try:
|
| 80 |
+
import torchvision.transforms as T
|
| 81 |
+
|
| 82 |
+
# FIXME: add version check for gguf
|
| 83 |
+
except ImportError as err:
|
| 84 |
+
raise ImportError(
|
| 85 |
+
"Please install torchvision via `pip install torchvision` to use Deepseek-VL2."
|
| 86 |
+
) from err
|
| 87 |
+
|
| 88 |
+
transform_pipelines = [T.ToTensor()]
|
| 89 |
+
|
| 90 |
+
if normalize:
|
| 91 |
+
transform_pipelines.append(T.Normalize(mean, std))
|
| 92 |
+
|
| 93 |
+
self.transform = T.Compose(transform_pipelines)
|
| 94 |
+
|
| 95 |
+
def __call__(self, pil_img: Image.Image):
|
| 96 |
+
x = self.transform(pil_img)
|
| 97 |
+
return x
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
class DeepseekVLV2Processor(ProcessorMixin):
|
| 101 |
+
tokenizer_class = ("LlamaTokenizer", "LlamaTokenizerFast")
|
| 102 |
+
attributes = ["tokenizer"]
|
| 103 |
+
|
| 104 |
+
def __init__(
|
| 105 |
+
self,
|
| 106 |
+
tokenizer: LlamaTokenizerFast,
|
| 107 |
+
candidate_resolutions: Tuple[Tuple[int, int]],
|
| 108 |
+
patch_size: int,
|
| 109 |
+
downsample_ratio: int,
|
| 110 |
+
image_mean: Tuple[float, float, float] = (0.5, 0.5, 0.5),
|
| 111 |
+
image_std: Tuple[float, float, float] = (0.5, 0.5, 0.5),
|
| 112 |
+
normalize: bool = True,
|
| 113 |
+
image_token: str = "<image>",
|
| 114 |
+
pad_token: str = "<|▁pad▁|>",
|
| 115 |
+
add_special_token: bool = False,
|
| 116 |
+
sft_format: str = "deepseek",
|
| 117 |
+
mask_prompt: bool = True,
|
| 118 |
+
ignore_id: int = -100,
|
| 119 |
+
**kwargs,
|
| 120 |
+
):
|
| 121 |
+
|
| 122 |
+
self.candidate_resolutions = candidate_resolutions
|
| 123 |
+
self.image_size = candidate_resolutions[0][0]
|
| 124 |
+
self.patch_size = patch_size
|
| 125 |
+
self.image_mean = image_mean
|
| 126 |
+
self.image_std = image_std
|
| 127 |
+
self.normalize = normalize
|
| 128 |
+
self.downsample_ratio = downsample_ratio
|
| 129 |
+
|
| 130 |
+
self.image_transform = ImageTransform(
|
| 131 |
+
mean=image_mean, std=image_std, normalize=normalize
|
| 132 |
+
)
|
| 133 |
+
self.tokenizer = tokenizer
|
| 134 |
+
# must set this,padding side with make a difference in batch inference
|
| 135 |
+
self.tokenizer.padding_side = "left"
|
| 136 |
+
|
| 137 |
+
# add the pad_token as special token to use 'tokenizer.pad_token' and 'tokenizer.pad_token_id'
|
| 138 |
+
if tokenizer.pad_token is None:
|
| 139 |
+
self.tokenizer.add_special_tokens({"pad_token": pad_token})
|
| 140 |
+
|
| 141 |
+
# add image token
|
| 142 |
+
image_token_id = self.tokenizer.vocab.get(image_token)
|
| 143 |
+
if image_token_id is None:
|
| 144 |
+
special_tokens = [image_token]
|
| 145 |
+
special_tokens_dict = {"additional_special_tokens": special_tokens}
|
| 146 |
+
self.tokenizer.add_special_tokens(special_tokens_dict)
|
| 147 |
+
self.image_token_id = self.tokenizer.vocab.get(image_token)
|
| 148 |
+
|
| 149 |
+
# add five special tokens for grounding-related tasks
|
| 150 |
+
# <|ref|>, <|/ref|>, <|det|>, <|/det|>, <|grounding|>
|
| 151 |
+
special_tokens = ["<|ref|>", "<|/ref|>", "<|det|>", "<|/det|>", "<|grounding|>"]
|
| 152 |
+
special_tokens_dict = {"additional_special_tokens": special_tokens}
|
| 153 |
+
self.tokenizer.add_special_tokens(special_tokens_dict)
|
| 154 |
+
|
| 155 |
+
# add special tokens for SFT data
|
| 156 |
+
special_tokens = ["<|User|>", "<|Assistant|>"]
|
| 157 |
+
special_tokens_dict = {"additional_special_tokens": special_tokens}
|
| 158 |
+
self.tokenizer.add_special_tokens(special_tokens_dict)
|
| 159 |
+
|
| 160 |
+
self.image_token = image_token
|
| 161 |
+
self.pad_token = pad_token
|
| 162 |
+
self.add_special_token = add_special_token
|
| 163 |
+
self.sft_format = sft_format
|
| 164 |
+
self.mask_prompt = mask_prompt
|
| 165 |
+
self.ignore_id = ignore_id
|
| 166 |
+
|
| 167 |
+
super().__init__(
|
| 168 |
+
tokenizer,
|
| 169 |
+
**kwargs,
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
def format_messages_v2(self, messages, pil_images, max_req_input_len=-1):
|
| 173 |
+
"""play the role of format_messages_v2 and get_images_info in the last version"""
|
| 174 |
+
tokenized_data = []
|
| 175 |
+
masked_tokenized_data = [] # labels
|
| 176 |
+
images_list = []
|
| 177 |
+
images_seq_mask = []
|
| 178 |
+
images_spatial_crop = []
|
| 179 |
+
|
| 180 |
+
image_index = 0
|
| 181 |
+
image_token_cnt = messages.count(self.image_token)
|
| 182 |
+
tokenized_str, images, seq_mask, spatial_crop = self.tokenize_with_images(
|
| 183 |
+
messages,
|
| 184 |
+
pil_images[image_index : image_index + image_token_cnt],
|
| 185 |
+
bos=True,
|
| 186 |
+
eos=True,
|
| 187 |
+
cropping=len(pil_images) <= 2,
|
| 188 |
+
max_req_input_len=max_req_input_len,
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
image_index = image_token_cnt
|
| 192 |
+
tokenized_data += tokenized_str
|
| 193 |
+
if self.mask_prompt:
|
| 194 |
+
masked_tokenized_data += [self.ignore_id] * len(tokenized_str)
|
| 195 |
+
else:
|
| 196 |
+
masked_tokenized_data += tokenized_str
|
| 197 |
+
images_list += images
|
| 198 |
+
images_seq_mask += seq_mask
|
| 199 |
+
images_spatial_crop += spatial_crop
|
| 200 |
+
|
| 201 |
+
assert len(tokenized_data) == len(
|
| 202 |
+
images_seq_mask
|
| 203 |
+
), f"format_messages_v2: tokenized_str's length {len(tokenized_str)} is not equal to imags_seq_mask's length {len(images_seq_mask)}"
|
| 204 |
+
|
| 205 |
+
return (
|
| 206 |
+
tokenized_data,
|
| 207 |
+
masked_tokenized_data,
|
| 208 |
+
images_list,
|
| 209 |
+
images_seq_mask,
|
| 210 |
+
images_spatial_crop,
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
@property
|
| 214 |
+
def bos_id(self):
|
| 215 |
+
return self.tokenizer.bos_token_id
|
| 216 |
+
|
| 217 |
+
@property
|
| 218 |
+
def eos_id(self):
|
| 219 |
+
return self.tokenizer.eos_token_id
|
| 220 |
+
|
| 221 |
+
@property
|
| 222 |
+
def pad_id(self):
|
| 223 |
+
return self.tokenizer.pad_token_id
|
| 224 |
+
|
| 225 |
+
def encode(self, text: str, bos: bool = True, eos: bool = False):
|
| 226 |
+
t = self.tokenizer.encode(text, add_special_tokens=False)
|
| 227 |
+
|
| 228 |
+
if bos:
|
| 229 |
+
t = [self.bos_id] + t
|
| 230 |
+
if eos:
|
| 231 |
+
t = t + [self.eos_id]
|
| 232 |
+
|
| 233 |
+
return t
|
| 234 |
+
|
| 235 |
+
def decode(self, t: List[int], **kwargs) -> str:
|
| 236 |
+
return self.tokenizer.decode(t, **kwargs)
|
| 237 |
+
|
| 238 |
+
def process_one(
|
| 239 |
+
self,
|
| 240 |
+
prompt: str = None,
|
| 241 |
+
conversations: List[Dict[str, str]] = None,
|
| 242 |
+
images: List[Image.Image] = None,
|
| 243 |
+
apply_sft_format: bool = False,
|
| 244 |
+
inference_mode: bool = True,
|
| 245 |
+
system_prompt: str = "",
|
| 246 |
+
max_req_input_len: int = -1,
|
| 247 |
+
**kwargs,
|
| 248 |
+
):
|
| 249 |
+
"""
|
| 250 |
+
|
| 251 |
+
Args:
|
| 252 |
+
prompt (str): the formatted prompt;
|
| 253 |
+
conversations (List[Dict]): conversations with a list of messages;
|
| 254 |
+
images (List[ImageType]): the list of images;
|
| 255 |
+
apply_sft_format (bool): if prompt is not None, then apply the SFT format to prompt;
|
| 256 |
+
if conversations is not None, then it will always apply the SFT format to conversations;
|
| 257 |
+
inference_mode (bool): if True, then remove the last eos token;
|
| 258 |
+
system_prompt (str): the system prompt;
|
| 259 |
+
**kwargs:
|
| 260 |
+
|
| 261 |
+
Returns:
|
| 262 |
+
outputs (BaseProcessorOutput): the output of the processor,
|
| 263 |
+
- input_ids (torch.LongTensor): [N + image tokens]
|
| 264 |
+
- target_ids (torch.LongTensor): [N + image tokens]
|
| 265 |
+
- images (torch.FloatTensor): [n_images, 3, H, W]
|
| 266 |
+
- image_id (int): the id of the image token
|
| 267 |
+
- num_image_tokens (List[int]): the number of image tokens
|
| 268 |
+
"""
|
| 269 |
+
|
| 270 |
+
assert (
|
| 271 |
+
prompt is None or conversations is None
|
| 272 |
+
), "prompt and conversations cannot be used at the same time."
|
| 273 |
+
|
| 274 |
+
(
|
| 275 |
+
tokenized_str,
|
| 276 |
+
masked_tokenized_str,
|
| 277 |
+
images_list,
|
| 278 |
+
images_seq_mask,
|
| 279 |
+
images_spatial_crop,
|
| 280 |
+
) = self.format_messages_v2(conversations, images, max_req_input_len)
|
| 281 |
+
|
| 282 |
+
assert (
|
| 283 |
+
len(tokenized_str) == len(images_seq_mask) == len(masked_tokenized_str)
|
| 284 |
+
), (
|
| 285 |
+
f"tokenized_str's length {len(tokenized_str)}, input_ids' length {len(masked_tokenized_str)}, "
|
| 286 |
+
f"imags_seq_mask's length {len(images_seq_mask)}, are not equal"
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
input_ids = torch.LongTensor(tokenized_str)
|
| 290 |
+
target_ids = torch.LongTensor(masked_tokenized_str)
|
| 291 |
+
images_seq_mask = torch.tensor(images_seq_mask, dtype=torch.bool)
|
| 292 |
+
|
| 293 |
+
# set input_ids < 0 | input_ids == self.image_token_id as ignore_id
|
| 294 |
+
target_ids[(input_ids < 0) | (input_ids == self.image_token_id)] = (
|
| 295 |
+
self.ignore_id
|
| 296 |
+
)
|
| 297 |
+
input_ids[input_ids < 0] = self.pad_id
|
| 298 |
+
|
| 299 |
+
if inference_mode:
|
| 300 |
+
assert input_ids[-1] == self.eos_id
|
| 301 |
+
input_ids = input_ids[:-1]
|
| 302 |
+
target_ids = target_ids[:-1]
|
| 303 |
+
images_seq_mask = images_seq_mask[:-1]
|
| 304 |
+
|
| 305 |
+
if len(images_list) == 0:
|
| 306 |
+
images = torch.zeros((1, 3, self.image_size, self.image_size))
|
| 307 |
+
images_spatial_crop = torch.zeros((1, 2), dtype=torch.long)
|
| 308 |
+
else:
|
| 309 |
+
images = torch.stack(images_list, dim=0)
|
| 310 |
+
images_spatial_crop = torch.tensor(images_spatial_crop, dtype=torch.long)
|
| 311 |
+
|
| 312 |
+
prepare = VLChatProcessorOutput(
|
| 313 |
+
input_ids=input_ids,
|
| 314 |
+
target_ids=target_ids,
|
| 315 |
+
images=images,
|
| 316 |
+
images_seq_mask=images_seq_mask,
|
| 317 |
+
images_spatial_crop=images_spatial_crop,
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
return prepare
|
| 321 |
+
|
| 322 |
+
def __call__(
|
| 323 |
+
self,
|
| 324 |
+
*,
|
| 325 |
+
prompt: str = None,
|
| 326 |
+
conversations: List[Dict[str, str]] = None,
|
| 327 |
+
images: List[Image.Image] = None,
|
| 328 |
+
apply_sft_format: bool = False,
|
| 329 |
+
inference_mode: bool = True,
|
| 330 |
+
system_prompt: str = "",
|
| 331 |
+
max_req_input_len: int = -1,
|
| 332 |
+
**kwargs,
|
| 333 |
+
):
|
| 334 |
+
prepare = self.process_one(
|
| 335 |
+
prompt=prompt,
|
| 336 |
+
conversations=conversations,
|
| 337 |
+
images=images,
|
| 338 |
+
apply_sft_format=apply_sft_format,
|
| 339 |
+
inference_mode=inference_mode,
|
| 340 |
+
system_prompt=system_prompt,
|
| 341 |
+
max_req_input_len=max_req_input_len,
|
| 342 |
+
)
|
| 343 |
+
|
| 344 |
+
return prepare
|
| 345 |
+
|
| 346 |
+
def find_all_indices(self, messages, target_value):
|
| 347 |
+
indices = []
|
| 348 |
+
for index, item in enumerate(messages):
|
| 349 |
+
if item == target_value:
|
| 350 |
+
indices.append(index)
|
| 351 |
+
return indices
|
| 352 |
+
|
| 353 |
+
def tokenize_with_images(
|
| 354 |
+
self,
|
| 355 |
+
conversation: str,
|
| 356 |
+
images: List[Image.Image],
|
| 357 |
+
bos: bool = True,
|
| 358 |
+
eos: bool = True,
|
| 359 |
+
cropping: bool = True,
|
| 360 |
+
max_req_input_len: int = -1,
|
| 361 |
+
):
|
| 362 |
+
"""Tokenize text with <image> tags."""
|
| 363 |
+
images_list, images_seq_mask, images_spatial_crop = [], [], []
|
| 364 |
+
text_splits = conversation.split(self.image_token)
|
| 365 |
+
tokenized_str = []
|
| 366 |
+
for text_sep, image in zip(text_splits, images):
|
| 367 |
+
"""encode text_sep"""
|
| 368 |
+
tokenized_sep = self.encode(text_sep, bos=False, eos=False)
|
| 369 |
+
tokenized_str += tokenized_sep
|
| 370 |
+
images_seq_mask += [False] * len(tokenized_sep)
|
| 371 |
+
|
| 372 |
+
"""select best resolution for anyres"""
|
| 373 |
+
if cropping:
|
| 374 |
+
best_width, best_height = select_best_resolution(
|
| 375 |
+
image.size, self.candidate_resolutions
|
| 376 |
+
)
|
| 377 |
+
else:
|
| 378 |
+
best_width, best_height = self.image_size, self.image_size
|
| 379 |
+
# print(image.size, (best_width, best_height)) # check the select_best_resolutions func
|
| 380 |
+
|
| 381 |
+
"""process the global view"""
|
| 382 |
+
global_view = ImageOps.pad(
|
| 383 |
+
image,
|
| 384 |
+
(self.image_size, self.image_size),
|
| 385 |
+
color=tuple(int(x * 255) for x in self.image_transform.mean),
|
| 386 |
+
)
|
| 387 |
+
images_list.append(self.image_transform(global_view))
|
| 388 |
+
|
| 389 |
+
"""process the local views"""
|
| 390 |
+
local_view = ImageOps.pad(
|
| 391 |
+
image,
|
| 392 |
+
(best_width, best_height),
|
| 393 |
+
color=tuple(int(x * 255) for x in self.image_transform.mean),
|
| 394 |
+
)
|
| 395 |
+
for i in range(0, best_height, self.image_size):
|
| 396 |
+
for j in range(0, best_width, self.image_size):
|
| 397 |
+
images_list.append(
|
| 398 |
+
self.image_transform(
|
| 399 |
+
local_view.crop(
|
| 400 |
+
(j, i, j + self.image_size, i + self.image_size)
|
| 401 |
+
)
|
| 402 |
+
)
|
| 403 |
+
)
|
| 404 |
+
|
| 405 |
+
"""record height / width crop num"""
|
| 406 |
+
num_width_tiles, num_height_tiles = (
|
| 407 |
+
best_width // self.image_size,
|
| 408 |
+
best_height // self.image_size,
|
| 409 |
+
)
|
| 410 |
+
images_spatial_crop.append([num_width_tiles, num_height_tiles])
|
| 411 |
+
|
| 412 |
+
"""add image tokens"""
|
| 413 |
+
h = w = math.ceil(
|
| 414 |
+
(self.image_size // self.patch_size) / self.downsample_ratio
|
| 415 |
+
)
|
| 416 |
+
# global views tokens h * (w + 1), 1 is for line seperator
|
| 417 |
+
tokenized_image = [self.image_token_id] * h * (w + 1)
|
| 418 |
+
# add a seperator between global and local views
|
| 419 |
+
tokenized_image += [self.image_token_id]
|
| 420 |
+
# local views tokens, (num_height_tiles * h) * (num_width_tiles * w + 1)
|
| 421 |
+
tokenized_image += (
|
| 422 |
+
[self.image_token_id]
|
| 423 |
+
* (num_height_tiles * h)
|
| 424 |
+
* (num_width_tiles * w + 1)
|
| 425 |
+
)
|
| 426 |
+
|
| 427 |
+
tokenized_str += tokenized_image
|
| 428 |
+
images_seq_mask += [True] * len(tokenized_image)
|
| 429 |
+
# print(width_crop_num, height_crop_num, len(tokenized_image)) # test the correctness of the number of image-related tokens
|
| 430 |
+
|
| 431 |
+
"""process the last text split"""
|
| 432 |
+
tokenized_sep = self.encode(text_splits[-1], bos=False, eos=False)
|
| 433 |
+
# deal with video, limit with request len
|
| 434 |
+
if max_req_input_len > -1:
|
| 435 |
+
if max_req_input_len < len(tokenized_sep) + len(tokenized_str) - 1:
|
| 436 |
+
rest = max_req_input_len - len(tokenized_sep) - 1 - 1024
|
| 437 |
+
tokenized_str = tokenized_str[:rest]
|
| 438 |
+
images_seq_mask = images_seq_mask[:rest]
|
| 439 |
+
tokenized_str += tokenized_sep
|
| 440 |
+
images_seq_mask += [False] * len(tokenized_sep)
|
| 441 |
+
|
| 442 |
+
"""add the bos and eos tokens"""
|
| 443 |
+
if bos:
|
| 444 |
+
tokenized_str = [self.bos_id] + tokenized_str
|
| 445 |
+
images_seq_mask = [False] + images_seq_mask
|
| 446 |
+
if eos:
|
| 447 |
+
tokenized_str = tokenized_str + [self.eos_id]
|
| 448 |
+
images_seq_mask = images_seq_mask + [False]
|
| 449 |
+
|
| 450 |
+
assert len(tokenized_str) == len(
|
| 451 |
+
images_seq_mask
|
| 452 |
+
), f"tokenize_with_images func: tokenized_str's length {len(tokenized_str)} is not equal to imags_seq_mask's length {len(images_seq_mask)}"
|
| 453 |
+
|
| 454 |
+
return tokenized_str, images_list, images_seq_mask, images_spatial_crop
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
class DeepseekVL2VisionEncoderConfig(PretrainedConfig):
|
| 458 |
+
model_type: str = "vision"
|
| 459 |
+
|
| 460 |
+
model_name: str = "siglip_large_patch16_384"
|
| 461 |
+
image_size: int = 384
|
| 462 |
+
patch_size: int = 16
|
| 463 |
+
width: int = 1024
|
| 464 |
+
layers: int = 24
|
| 465 |
+
heads: int = 16
|
| 466 |
+
mlp_ratio: int = 4
|
| 467 |
+
global_pool: str = "map"
|
| 468 |
+
ignore_head: bool = True
|
| 469 |
+
class_token: bool = False
|
| 470 |
+
num_classes: int = 0
|
| 471 |
+
use_checkpoint: bool = False
|
| 472 |
+
weight_init: str = "skip"
|
| 473 |
+
deterministic: bool = False
|
| 474 |
+
num_recomputing_layers: int = 0
|
| 475 |
+
|
| 476 |
+
def __init__(
|
| 477 |
+
self,
|
| 478 |
+
model_name: str = "siglip_large_patch16_384",
|
| 479 |
+
image_size: int = 384,
|
| 480 |
+
patch_size: int = 16,
|
| 481 |
+
width: int = 1024,
|
| 482 |
+
layers: int = 24,
|
| 483 |
+
heads: int = 16,
|
| 484 |
+
mlp_ratio: int = 4,
|
| 485 |
+
global_pool: str = "map",
|
| 486 |
+
ignore_head: bool = True,
|
| 487 |
+
class_token: bool = False,
|
| 488 |
+
num_classes: int = 0,
|
| 489 |
+
use_checkpoint: bool = False,
|
| 490 |
+
**kwargs,
|
| 491 |
+
):
|
| 492 |
+
self.model_name = model_name
|
| 493 |
+
self.image_size = image_size
|
| 494 |
+
self.patch_size = patch_size
|
| 495 |
+
self.width = width
|
| 496 |
+
self.layers = layers
|
| 497 |
+
self.heads = heads
|
| 498 |
+
self.mlp_ratio = mlp_ratio
|
| 499 |
+
self.global_pool = global_pool
|
| 500 |
+
self.ignore_head = ignore_head
|
| 501 |
+
self.class_token = class_token
|
| 502 |
+
self.num_classes = num_classes
|
| 503 |
+
self.use_checkpoint = use_checkpoint
|
| 504 |
+
|
| 505 |
+
super().__init__(**kwargs)
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
class DeepseekVL2MlpProjectorConfig(PretrainedConfig):
|
| 509 |
+
model_type = "mlp_projector"
|
| 510 |
+
projector_type: str = "downsample_mlp_gelu"
|
| 511 |
+
input_dim: int = 1152
|
| 512 |
+
n_embed: int = 2048
|
| 513 |
+
depth: int = 2
|
| 514 |
+
mlp_ratio: int = 1
|
| 515 |
+
downsample_ratio: int = 2
|
| 516 |
+
token_pooling: bool = False
|
| 517 |
+
|
| 518 |
+
def __init__(
|
| 519 |
+
self,
|
| 520 |
+
projector_type: str = "downsample_mlp_gelu",
|
| 521 |
+
input_dim: int = 1152,
|
| 522 |
+
n_embed: int = 2048,
|
| 523 |
+
depth: int = 2,
|
| 524 |
+
mlp_ratio: int = 1,
|
| 525 |
+
downsample_ratio: int = 2,
|
| 526 |
+
**kwargs,
|
| 527 |
+
):
|
| 528 |
+
self.projector_type = projector_type
|
| 529 |
+
self.input_dim = input_dim
|
| 530 |
+
self.n_embed = n_embed
|
| 531 |
+
self.depth = depth
|
| 532 |
+
self.mlp_ratio = mlp_ratio
|
| 533 |
+
self.downsample_ratio = downsample_ratio
|
| 534 |
+
|
| 535 |
+
super().__init__(**kwargs)
|
| 536 |
+
|
| 537 |
+
|
| 538 |
+
class DeepseekV2Config(PretrainedConfig):
|
| 539 |
+
|
| 540 |
+
model_type = "deepseek_v2"
|
| 541 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 542 |
+
|
| 543 |
+
def __init__(
|
| 544 |
+
self,
|
| 545 |
+
vocab_size=102400,
|
| 546 |
+
hidden_size=4096,
|
| 547 |
+
intermediate_size=11008,
|
| 548 |
+
moe_intermediate_size=1407,
|
| 549 |
+
num_hidden_layers=30,
|
| 550 |
+
num_attention_heads=32,
|
| 551 |
+
num_key_value_heads=32,
|
| 552 |
+
n_shared_experts=None,
|
| 553 |
+
n_routed_experts=None,
|
| 554 |
+
ep_size=1,
|
| 555 |
+
routed_scaling_factor=1.0,
|
| 556 |
+
kv_lora_rank=512,
|
| 557 |
+
q_lora_rank=1536,
|
| 558 |
+
qk_rope_head_dim=64,
|
| 559 |
+
v_head_dim=128,
|
| 560 |
+
qk_nope_head_dim=128,
|
| 561 |
+
topk_method="gready",
|
| 562 |
+
n_group=None,
|
| 563 |
+
topk_group=None,
|
| 564 |
+
num_experts_per_tok=None,
|
| 565 |
+
moe_layer_freq=1,
|
| 566 |
+
first_k_dense_replace=0,
|
| 567 |
+
norm_topk_prob=False,
|
| 568 |
+
scoring_func="softmax",
|
| 569 |
+
aux_loss_alpha=0.001,
|
| 570 |
+
seq_aux=True,
|
| 571 |
+
hidden_act="silu",
|
| 572 |
+
max_position_embeddings=2048,
|
| 573 |
+
initializer_range=0.02,
|
| 574 |
+
rms_norm_eps=1e-6,
|
| 575 |
+
use_cache=True,
|
| 576 |
+
pad_token_id=None,
|
| 577 |
+
bos_token_id=100000,
|
| 578 |
+
eos_token_id=100001,
|
| 579 |
+
pretraining_tp=1,
|
| 580 |
+
tie_word_embeddings=False,
|
| 581 |
+
rope_theta=10000.0,
|
| 582 |
+
rope_scaling=None,
|
| 583 |
+
attention_bias=False,
|
| 584 |
+
attention_dropout=0.0,
|
| 585 |
+
use_mla=True,
|
| 586 |
+
**kwargs,
|
| 587 |
+
):
|
| 588 |
+
self.vocab_size = vocab_size
|
| 589 |
+
self.max_position_embeddings = max_position_embeddings
|
| 590 |
+
self.hidden_size = hidden_size
|
| 591 |
+
self.intermediate_size = intermediate_size
|
| 592 |
+
self.moe_intermediate_size = moe_intermediate_size
|
| 593 |
+
self.num_hidden_layers = num_hidden_layers
|
| 594 |
+
self.num_attention_heads = num_attention_heads
|
| 595 |
+
self.n_shared_experts = n_shared_experts
|
| 596 |
+
self.n_routed_experts = n_routed_experts
|
| 597 |
+
self.ep_size = ep_size
|
| 598 |
+
self.routed_scaling_factor = routed_scaling_factor
|
| 599 |
+
self.kv_lora_rank = kv_lora_rank
|
| 600 |
+
self.q_lora_rank = q_lora_rank
|
| 601 |
+
self.qk_rope_head_dim = qk_rope_head_dim
|
| 602 |
+
self.v_head_dim = v_head_dim
|
| 603 |
+
self.qk_nope_head_dim = qk_nope_head_dim
|
| 604 |
+
self.topk_method = topk_method
|
| 605 |
+
self.n_group = n_group
|
| 606 |
+
self.topk_group = topk_group
|
| 607 |
+
self.num_experts_per_tok = num_experts_per_tok
|
| 608 |
+
self.moe_layer_freq = moe_layer_freq
|
| 609 |
+
self.first_k_dense_replace = first_k_dense_replace
|
| 610 |
+
self.norm_topk_prob = norm_topk_prob
|
| 611 |
+
self.scoring_func = scoring_func
|
| 612 |
+
self.aux_loss_alpha = aux_loss_alpha
|
| 613 |
+
self.seq_aux = seq_aux
|
| 614 |
+
# for backward compatibility
|
| 615 |
+
if num_key_value_heads is None:
|
| 616 |
+
num_key_value_heads = num_attention_heads
|
| 617 |
+
|
| 618 |
+
self.num_key_value_heads = num_key_value_heads
|
| 619 |
+
self.hidden_act = hidden_act
|
| 620 |
+
self.initializer_range = initializer_range
|
| 621 |
+
self.rms_norm_eps = float(rms_norm_eps)
|
| 622 |
+
self.pretraining_tp = pretraining_tp
|
| 623 |
+
self.use_cache = use_cache
|
| 624 |
+
self.rope_theta = rope_theta
|
| 625 |
+
self.rope_scaling = rope_scaling
|
| 626 |
+
self.attention_bias = attention_bias
|
| 627 |
+
self.attention_dropout = attention_dropout
|
| 628 |
+
self.use_mla = use_mla
|
| 629 |
+
|
| 630 |
+
super().__init__(
|
| 631 |
+
pad_token_id=pad_token_id,
|
| 632 |
+
bos_token_id=bos_token_id,
|
| 633 |
+
eos_token_id=eos_token_id,
|
| 634 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 635 |
+
**kwargs,
|
| 636 |
+
)
|
| 637 |
+
|
| 638 |
+
|
| 639 |
+
class DeepseekVL2Config(PretrainedConfig):
|
| 640 |
+
model_type = "deepseek_vl_v2"
|
| 641 |
+
vision_config: DeepseekVL2VisionEncoderConfig
|
| 642 |
+
projector_config: DeepseekVL2MlpProjectorConfig
|
| 643 |
+
language_config: DeepseekV2Config
|
| 644 |
+
|
| 645 |
+
tile_tag: str = "2D"
|
| 646 |
+
global_view_pos: str = "head"
|
| 647 |
+
candidate_resolutions: Tuple[Tuple[int, int]] = ((384, 384),)
|
| 648 |
+
|
| 649 |
+
def __init__(
|
| 650 |
+
self,
|
| 651 |
+
tile_tag: str = "tile_tag",
|
| 652 |
+
global_view_pos: str = "head",
|
| 653 |
+
candidate_resolutions: Tuple[Tuple[int, int]] = ((384, 384),),
|
| 654 |
+
**kwargs,
|
| 655 |
+
):
|
| 656 |
+
super().__init__(**kwargs)
|
| 657 |
+
|
| 658 |
+
vision_config = kwargs.get("vision_config", {})
|
| 659 |
+
self.vision_config = DeepseekVL2VisionEncoderConfig(**vision_config)
|
| 660 |
+
|
| 661 |
+
projector_config = kwargs.get("projector_config", {})
|
| 662 |
+
self.projector_config = DeepseekVL2MlpProjectorConfig(**projector_config)
|
| 663 |
+
|
| 664 |
+
language_config = kwargs.get("language_config", {})
|
| 665 |
+
if isinstance(language_config, DeepseekV2Config):
|
| 666 |
+
self.language_config = language_config
|
| 667 |
+
else:
|
| 668 |
+
self.language_config = DeepseekV2Config(**language_config)
|
| 669 |
+
|
| 670 |
+
self.tile_tag = tile_tag
|
| 671 |
+
self.global_view_pos = global_view_pos
|
| 672 |
+
self.candidate_resolutions = candidate_resolutions
|
| 673 |
+
self.architectures = ["DeepseekVL2ForCausalLM"]
|
| 674 |
+
|
| 675 |
+
|
| 676 |
+
AutoProcessor.register(DeepseekVL2Config, DeepseekVLV2Processor)
|
lib/python3.12/site-packages/sglang/srt/configs/device_config.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
from typing import Optional
|
| 3 |
+
|
| 4 |
+
import torch
|
| 5 |
+
|
| 6 |
+
logger = logging.getLogger(__name__)
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class DeviceConfig:
|
| 10 |
+
device: Optional[torch.device]
|
| 11 |
+
|
| 12 |
+
def __init__(self, device: str = "cuda") -> None:
|
| 13 |
+
if device in ["cuda", "xpu", "hpu", "cpu"]:
|
| 14 |
+
self.device_type = device
|
| 15 |
+
else:
|
| 16 |
+
raise RuntimeError(f"Not supported device type: {device}")
|
| 17 |
+
self.device = torch.device(self.device_type)
|
lib/python3.12/site-packages/sglang/srt/configs/exaone.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding=utf-8
|
| 2 |
+
# Copyright 2024 The LG AI Research EXAONE Lab. All rights reserved.
|
| 3 |
+
# Copyright 2024 The LG CNS AI Engineering Team.
|
| 4 |
+
# Copyright 2023-2024 SGLang Team.
|
| 5 |
+
#
|
| 6 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
# you may not use this file except in compliance with the License.
|
| 8 |
+
# You may obtain a copy of the License at
|
| 9 |
+
#
|
| 10 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
#
|
| 12 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
# See the License for the specific language governing permissions and
|
| 16 |
+
# limitations under the License.
|
| 17 |
+
""" EXAONE model configuration """
|
| 18 |
+
from typing import Any, Dict
|
| 19 |
+
|
| 20 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 21 |
+
from transformers.utils import logging
|
| 22 |
+
|
| 23 |
+
logger = logging.get_logger(__name__)
|
| 24 |
+
|
| 25 |
+
EXAONE_PRETRAINED_CONFIG_ARCHIVE_MAP: Dict[str, Any] = {}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
# ruff: noqa: E501
|
| 29 |
+
class ExaoneConfig(PretrainedConfig):
|
| 30 |
+
r"""
|
| 31 |
+
This is the configuration class to store the configuration of a :class:`~transformers.ExaoneModel`. It is used to
|
| 32 |
+
instantiate a EXAONE model according to the specified arguments, defining the model architecture. Instantiating a
|
| 33 |
+
configuration with the defaults will yield a similar configuration to that of the Exaone
|
| 34 |
+
|
| 35 |
+
Configuration objects inherit from :class:`~transformers.PretrainedConfig` and can be used to control the model
|
| 36 |
+
outputs. Read the documentation from :class:`~transformers.PretrainedConfig` for more information.
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
Args:
|
| 40 |
+
vocab_size (:obj:`int`, `optional`, defaults to 102400):
|
| 41 |
+
Vocabulary size of the EXAONE model. Defines the number of different tokens that can be represented by the
|
| 42 |
+
:obj:`inputs_ids` passed when calling :class:`~transformers.ExaoneModel`. Vocabulary size of the model.
|
| 43 |
+
Defines the different tokens that can be represented by the `inputs_ids` passed to the forward method of
|
| 44 |
+
:class:`~transformers.EXAONEModel`.
|
| 45 |
+
max_position_embeddings (:obj:`int`, `optional`, defaults to 2048):
|
| 46 |
+
The maximum sequence length that this model might ever be used with. Typically set this to something large
|
| 47 |
+
just in case (e.g., 512 or 1024 or 2048).
|
| 48 |
+
hidden_size (:obj:`int`, `optional`, defaults to 2048):
|
| 49 |
+
Dimensionality of the encoder layers and the pooler layer.
|
| 50 |
+
num_layers (:obj:`int`, `optional`, defaults to 32):
|
| 51 |
+
Number of hidden layers in the Transformer encoder.
|
| 52 |
+
num_attention_heads (:obj:`int`, `optional`, defaults to 32):
|
| 53 |
+
Number of attention heads for each attention layer in the Transformer decoder.
|
| 54 |
+
num_key_value_heads (:obj:`int`, `optional`):
|
| 55 |
+
This is the number of key_value heads that should be used to implement Grouped Query Attention. If
|
| 56 |
+
`num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
|
| 57 |
+
`num_key_value_heads=1 the model will use Multi Query Attention (MQA) otherwise GQA is used. When
|
| 58 |
+
converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
|
| 59 |
+
by meanpooling all the original heads within that group. For more details checkout [this
|
| 60 |
+
paper](https://arxiv.org/pdf/2305.13245.pdf). If it is not specified, will default to
|
| 61 |
+
`num_attention_heads`.
|
| 62 |
+
intermediate_size (:obj:`int`, `optional`, defaults to `hidden_size * 4`):
|
| 63 |
+
Dimensionality of the "intermediate" (i.e., feed-forward) layer in the Transformer encoder.
|
| 64 |
+
activation_function (:obj:`str` or :obj:`function`, `optional`, defaults to :obj:`"silu"`):
|
| 65 |
+
The non-linear activation function (function or string) in the decoder.
|
| 66 |
+
rope_theta (:obj:`float`, `optional`, defaults to 10000.0):
|
| 67 |
+
The base period of the RoPE embeddings.
|
| 68 |
+
rope_scaling (:obj:`Dict`, `optional`):
|
| 69 |
+
Dictionary containing the scaling configuration for the RoPE embeddings. NOTE: if you apply new rope type
|
| 70 |
+
and you expect the model to work on longer `max_position_embeddings`, we recommend you to update this value
|
| 71 |
+
accordingly.
|
| 72 |
+
Expected contents:
|
| 73 |
+
`rope_type` (:obj:`str`):
|
| 74 |
+
The sub-variant of RoPE to use. Can be one of ['default', 'linear', 'dynamic', 'yarn', 'longrope',
|
| 75 |
+
'llama3'], with 'default' being the original RoPE implementation.
|
| 76 |
+
`factor` (:obj:`float`, `optional`):
|
| 77 |
+
Used with all rope types except 'default'. The scaling factor to apply to the RoPE embeddings. In
|
| 78 |
+
most scaling types, a `factor` of x will enable the model to handle sequences of length x *
|
| 79 |
+
original maximum pre-trained length.
|
| 80 |
+
`original_max_position_embeddings` (:obj:`int`, `optional`):
|
| 81 |
+
Used with 'dynamic', 'longrope' and 'llama3'. The original max position embeddings used during
|
| 82 |
+
pretraining.
|
| 83 |
+
`attention_factor` (:obj:`float`, `optional`):
|
| 84 |
+
Used with 'yarn' and 'longrope'. The scaling factor to be applied on the attention
|
| 85 |
+
computation. If unspecified, it defaults to value recommended by the implementation, using the
|
| 86 |
+
`factor` field to infer the suggested value.
|
| 87 |
+
`beta_fast` (:obj:`float`, `optional`):
|
| 88 |
+
Only used with 'yarn'. Parameter to set the boundary for extrapolation (only) in the linear
|
| 89 |
+
ramp function. If unspecified, it defaults to 32.
|
| 90 |
+
`beta_slow` (:obj:`float`, `optional`):
|
| 91 |
+
Only used with 'yarn'. Parameter to set the boundary for interpolation (only) in the linear
|
| 92 |
+
ramp function. If unspecified, it defaults to 1.
|
| 93 |
+
`short_factor` (:obj:`List[float]`, `optional`):
|
| 94 |
+
Only used with 'longrope'. The scaling factor to be applied to short contexts (<
|
| 95 |
+
`original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
|
| 96 |
+
size divided by the number of attention heads divided by 2
|
| 97 |
+
`long_factor` (:obj:`List[float]`, `optional`):
|
| 98 |
+
Only used with 'longrope'. The scaling factor to be applied to long contexts (<
|
| 99 |
+
`original_max_position_embeddings`). Must be a list of numbers with the same length as the hidden
|
| 100 |
+
size divided by the number of attention heads divided by 2
|
| 101 |
+
`low_freq_factor` (:obj:`float`, `optional`):
|
| 102 |
+
Only used with 'llama3'. Scaling factor applied to low frequency components of the RoPE
|
| 103 |
+
`high_freq_factor` (:obj:`float`, `optional`):
|
| 104 |
+
Only used with 'llama3'. Scaling factor applied to high frequency components of the RoPE
|
| 105 |
+
embed_dropout (:obj:`float`, `optional`, defaults to 0.0):
|
| 106 |
+
The dropout probabilitiy for all fully connected layers in the embeddings, encoder, and pooler.
|
| 107 |
+
attention_dropout (:obj:`float`, `optional`, defaults to 0.0):
|
| 108 |
+
The dropout ratio for the attention probabilities.
|
| 109 |
+
layer_norm_epsilon (:obj:`float`, `optional`, defaults to 1e-5):
|
| 110 |
+
The epsilon used by the layer normalization layers.
|
| 111 |
+
initializer_range (:obj:`float`, `optional`, defaults to 0.02):
|
| 112 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 113 |
+
use_cache (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
| 114 |
+
Whether or not the model should return the last key/values attentions (not used by all models). Only
|
| 115 |
+
relevant if ``configs.is_decoder=True``.
|
| 116 |
+
bos_token_id (:obj:`int`, `optional`, defaults to 0):
|
| 117 |
+
Beginning of stream token id.
|
| 118 |
+
eos_token_id (:obj:`int`, `optional`, defaults to 2):
|
| 119 |
+
End of stream token id.
|
| 120 |
+
tie_word_embeddings (:obj:`bool`, `optional`, defaults to :obj:`True`):
|
| 121 |
+
Whether to tie weight embeddings
|
| 122 |
+
gradient_checkpointing (:obj:`bool`, `optional`, defaults to :obj:`False`):
|
| 123 |
+
If True, use gradient checkpointing to save memory at the expense of slower backward pass.
|
| 124 |
+
|
| 125 |
+
Example::
|
| 126 |
+
|
| 127 |
+
>>> from transformers import EXAONEModel, ExaoneConfig
|
| 128 |
+
|
| 129 |
+
>>> # Initializing a EXAONE configuration
|
| 130 |
+
>>> configuration = ExaoneConfig()
|
| 131 |
+
|
| 132 |
+
>>> # Initializing a model from configuration
|
| 133 |
+
>>> model = EXAONEModel(configuration)
|
| 134 |
+
|
| 135 |
+
>>> # Accessing the model configuration
|
| 136 |
+
>>> configuration = model.configs
|
| 137 |
+
"""
|
| 138 |
+
|
| 139 |
+
model_type = "exaone"
|
| 140 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 141 |
+
attribute_map = {"num_hidden_layers": "num_layers"}
|
| 142 |
+
|
| 143 |
+
def __init__(
|
| 144 |
+
self,
|
| 145 |
+
vocab_size=102400,
|
| 146 |
+
max_position_embeddings=2048,
|
| 147 |
+
hidden_size=2048,
|
| 148 |
+
num_layers=32,
|
| 149 |
+
num_attention_heads=32,
|
| 150 |
+
num_key_value_heads=None,
|
| 151 |
+
intermediate_size=None,
|
| 152 |
+
activation_function="silu",
|
| 153 |
+
rope_theta=10000.0,
|
| 154 |
+
rope_scaling=None,
|
| 155 |
+
embed_dropout=0.0,
|
| 156 |
+
attention_dropout=0.0,
|
| 157 |
+
layer_norm_epsilon=1e-5,
|
| 158 |
+
initializer_range=0.02,
|
| 159 |
+
use_cache=True,
|
| 160 |
+
bos_token_id=0,
|
| 161 |
+
eos_token_id=2,
|
| 162 |
+
tie_word_embeddings=True,
|
| 163 |
+
**kwargs
|
| 164 |
+
):
|
| 165 |
+
self.vocab_size = vocab_size
|
| 166 |
+
self.max_position_embeddings = max_position_embeddings
|
| 167 |
+
self.hidden_size = hidden_size
|
| 168 |
+
self.num_layers = num_layers
|
| 169 |
+
self.num_attention_heads = num_attention_heads
|
| 170 |
+
self.num_hidden_layers = num_layers
|
| 171 |
+
if num_key_value_heads is None:
|
| 172 |
+
num_key_value_heads = num_attention_heads
|
| 173 |
+
self.num_key_value_heads = num_key_value_heads
|
| 174 |
+
if intermediate_size:
|
| 175 |
+
self.intermediate_size = intermediate_size
|
| 176 |
+
else:
|
| 177 |
+
self.intermediate_size = hidden_size * 4
|
| 178 |
+
self.activation_function = activation_function
|
| 179 |
+
self.embed_dropout = embed_dropout
|
| 180 |
+
self.attention_dropout = attention_dropout
|
| 181 |
+
self.layer_norm_epsilon = layer_norm_epsilon
|
| 182 |
+
self.initializer_range = initializer_range
|
| 183 |
+
self.use_cache = use_cache
|
| 184 |
+
self.rope_theta = rope_theta
|
| 185 |
+
self.rope_scaling = rope_scaling
|
| 186 |
+
|
| 187 |
+
self.bos_token_id = bos_token_id
|
| 188 |
+
self.eos_token_id = eos_token_id
|
| 189 |
+
|
| 190 |
+
super().__init__(
|
| 191 |
+
bos_token_id=bos_token_id,
|
| 192 |
+
eos_token_id=eos_token_id,
|
| 193 |
+
tie_word_embeddings=tie_word_embeddings,
|
| 194 |
+
**kwargs
|
| 195 |
+
)
|
lib/python3.12/site-packages/sglang/srt/configs/janus_pro.py
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Adapted from:
|
| 2 |
+
# https://github.com/deepseek-ai/Janus/tree/main/janus/models
|
| 3 |
+
|
| 4 |
+
from dataclasses import dataclass
|
| 5 |
+
from typing import Dict, List, Tuple, Union
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import PIL
|
| 9 |
+
import torch
|
| 10 |
+
from PIL.Image import Image
|
| 11 |
+
from transformers import (
|
| 12 |
+
BaseImageProcessor,
|
| 13 |
+
BatchFeature,
|
| 14 |
+
LlamaConfig,
|
| 15 |
+
LlamaTokenizerFast,
|
| 16 |
+
PretrainedConfig,
|
| 17 |
+
ProcessorMixin,
|
| 18 |
+
)
|
| 19 |
+
from transformers.image_utils import to_numpy_array
|
| 20 |
+
|
| 21 |
+
from sglang.srt.configs.utils import register_image_processor, register_processor
|
| 22 |
+
from sglang.srt.mm_utils import expand2square
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class DictToObject(dict):
|
| 26 |
+
def __init__(self, dictionary):
|
| 27 |
+
super(self).__init__(dictionary)
|
| 28 |
+
|
| 29 |
+
for key, value in dictionary.items():
|
| 30 |
+
if isinstance(value, dict):
|
| 31 |
+
value = DictToObject(value)
|
| 32 |
+
setattr(self, key, value)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class VisionConfig(PretrainedConfig):
|
| 36 |
+
model_type = "vision"
|
| 37 |
+
cls: str = ""
|
| 38 |
+
params = {}
|
| 39 |
+
|
| 40 |
+
def __init__(self, **kwargs):
|
| 41 |
+
super().__init__(**kwargs)
|
| 42 |
+
|
| 43 |
+
self.cls = kwargs.get("cls", "")
|
| 44 |
+
if not isinstance(self.cls, str):
|
| 45 |
+
self.cls = self.cls.__name__
|
| 46 |
+
|
| 47 |
+
self.params = kwargs.get("params", {})
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class GenAlignerConfig(PretrainedConfig):
|
| 51 |
+
model_type = "gen_aligner"
|
| 52 |
+
cls: str = ""
|
| 53 |
+
params = {}
|
| 54 |
+
|
| 55 |
+
def __init__(self, **kwargs):
|
| 56 |
+
super().__init__(**kwargs)
|
| 57 |
+
|
| 58 |
+
self.cls = kwargs.get("cls", "")
|
| 59 |
+
if not isinstance(self.cls, str):
|
| 60 |
+
self.cls = self.cls.__name__
|
| 61 |
+
|
| 62 |
+
self.params = kwargs.get("params", {})
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
class GenHeadConfig(PretrainedConfig):
|
| 66 |
+
model_type = "gen_head"
|
| 67 |
+
cls: str = ""
|
| 68 |
+
params = {}
|
| 69 |
+
|
| 70 |
+
def __init__(self, **kwargs):
|
| 71 |
+
super().__init__(**kwargs)
|
| 72 |
+
|
| 73 |
+
self.cls = kwargs.get("cls", "")
|
| 74 |
+
if not isinstance(self.cls, str):
|
| 75 |
+
self.cls = self.cls.__name__
|
| 76 |
+
|
| 77 |
+
self.params = kwargs.get("params", {})
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
class AlignerConfig(PretrainedConfig):
|
| 81 |
+
model_type = "aligner"
|
| 82 |
+
cls: str = ""
|
| 83 |
+
params = {}
|
| 84 |
+
|
| 85 |
+
def __init__(self, **kwargs):
|
| 86 |
+
super().__init__(**kwargs)
|
| 87 |
+
|
| 88 |
+
self.cls = kwargs.get("cls", "")
|
| 89 |
+
if not isinstance(self.cls, str):
|
| 90 |
+
self.cls = self.cls.__name__
|
| 91 |
+
|
| 92 |
+
self.params = kwargs.get("params", {})
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class GenVisionConfig(PretrainedConfig):
|
| 96 |
+
model_type = "gen_vision"
|
| 97 |
+
cls: str = ""
|
| 98 |
+
params = {}
|
| 99 |
+
|
| 100 |
+
def __init__(self, **kwargs):
|
| 101 |
+
super().__init__(**kwargs)
|
| 102 |
+
|
| 103 |
+
self.cls = kwargs.get("cls", "")
|
| 104 |
+
if not isinstance(self.cls, str):
|
| 105 |
+
self.cls = self.cls.__name__
|
| 106 |
+
|
| 107 |
+
self.params = kwargs.get("params", {})
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
@dataclass
|
| 111 |
+
class SigLIPVisionCfg:
|
| 112 |
+
width: int = 1152
|
| 113 |
+
layers: Union[Tuple[int, int, int, int], int] = 27
|
| 114 |
+
heads: int = 16
|
| 115 |
+
patch_size: int = 14
|
| 116 |
+
image_size: Union[Tuple[int, int], int] = 336
|
| 117 |
+
global_pool: str = "map"
|
| 118 |
+
mlp_ratio: float = 3.7362
|
| 119 |
+
class_token: bool = False
|
| 120 |
+
num_classes: int = 0
|
| 121 |
+
use_checkpoint: bool = False
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
class MultiModalityConfig(PretrainedConfig):
|
| 125 |
+
model_type = "multi_modality"
|
| 126 |
+
vision_config: VisionConfig
|
| 127 |
+
aligner_config: AlignerConfig
|
| 128 |
+
|
| 129 |
+
gen_vision_config: GenVisionConfig
|
| 130 |
+
gen_aligner_config: GenAlignerConfig
|
| 131 |
+
gen_head_config: GenHeadConfig
|
| 132 |
+
|
| 133 |
+
language_config: LlamaConfig
|
| 134 |
+
|
| 135 |
+
def __init__(self, **kwargs):
|
| 136 |
+
super().__init__(**kwargs)
|
| 137 |
+
vision_config = kwargs.get("vision_config", {})
|
| 138 |
+
self.vision_config = VisionConfig(**vision_config)
|
| 139 |
+
|
| 140 |
+
aligner_config = kwargs.get("aligner_config", {})
|
| 141 |
+
self.aligner_config = AlignerConfig(**aligner_config)
|
| 142 |
+
|
| 143 |
+
gen_vision_config = kwargs.get("gen_vision_config", {})
|
| 144 |
+
self.gen_vision_config = GenVisionConfig(**gen_vision_config)
|
| 145 |
+
|
| 146 |
+
gen_aligner_config = kwargs.get("gen_aligner_config", {})
|
| 147 |
+
self.gen_aligner_config = GenAlignerConfig(**gen_aligner_config)
|
| 148 |
+
|
| 149 |
+
gen_head_config = kwargs.get("gen_head_config", {})
|
| 150 |
+
self.gen_head_config = GenHeadConfig(**gen_head_config)
|
| 151 |
+
|
| 152 |
+
language_config = kwargs.get("language_config", {})
|
| 153 |
+
if isinstance(language_config, LlamaConfig):
|
| 154 |
+
self.language_config = language_config
|
| 155 |
+
else:
|
| 156 |
+
self.language_config = LlamaConfig(**language_config)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
class VLMImageProcessor(BaseImageProcessor):
|
| 160 |
+
model_input_names = ["pixel_values"]
|
| 161 |
+
|
| 162 |
+
def __init__(
|
| 163 |
+
self,
|
| 164 |
+
image_size: int,
|
| 165 |
+
min_size: int = 14,
|
| 166 |
+
image_mean: Union[Tuple[float, float, float], List[float]] = (
|
| 167 |
+
0.48145466,
|
| 168 |
+
0.4578275,
|
| 169 |
+
0.40821073,
|
| 170 |
+
),
|
| 171 |
+
image_std: Union[Tuple[float, float, float], List[float]] = (
|
| 172 |
+
0.26862954,
|
| 173 |
+
0.26130258,
|
| 174 |
+
0.27577711,
|
| 175 |
+
),
|
| 176 |
+
rescale_factor: float = 1.0 / 255.0,
|
| 177 |
+
do_normalize: bool = True,
|
| 178 |
+
**kwargs,
|
| 179 |
+
):
|
| 180 |
+
super().__init__(**kwargs)
|
| 181 |
+
|
| 182 |
+
self.image_size = image_size
|
| 183 |
+
self.rescale_factor = rescale_factor
|
| 184 |
+
self.image_mean = image_mean
|
| 185 |
+
self.image_std = image_std
|
| 186 |
+
self.min_size = min_size
|
| 187 |
+
self.do_normalize = do_normalize
|
| 188 |
+
|
| 189 |
+
if image_mean is None:
|
| 190 |
+
self.background_color = (127, 127, 127)
|
| 191 |
+
else:
|
| 192 |
+
self.background_color = tuple([int(x * 255) for x in image_mean])
|
| 193 |
+
|
| 194 |
+
def resize(self, pil_img: Image) -> np.ndarray:
|
| 195 |
+
"""
|
| 196 |
+
|
| 197 |
+
Args:
|
| 198 |
+
pil_img (PIL.Image): [H, W, 3] in PIL.Image in RGB
|
| 199 |
+
|
| 200 |
+
Returns:
|
| 201 |
+
x (np.ndarray): [3, self.image_size, self.image_size]
|
| 202 |
+
"""
|
| 203 |
+
|
| 204 |
+
width, height = pil_img.size
|
| 205 |
+
max_size = max(width, height)
|
| 206 |
+
|
| 207 |
+
size = [
|
| 208 |
+
max(int(height / max_size * self.image_size), self.min_size),
|
| 209 |
+
max(int(width / max_size * self.image_size), self.min_size),
|
| 210 |
+
]
|
| 211 |
+
|
| 212 |
+
if width <= 0 or height <= 0 or size[0] <= 0 or size[1] <= 0:
|
| 213 |
+
# print(f"orig size = {pil_img.size}, new size = {size}")
|
| 214 |
+
raise ValueError("Invalid size!")
|
| 215 |
+
|
| 216 |
+
def resize(
|
| 217 |
+
pil_img, size, interpolation=PIL.Image.Resampling.BICUBIC, antialias=True
|
| 218 |
+
):
|
| 219 |
+
if isinstance(size, int):
|
| 220 |
+
w, h = pil_img.size
|
| 221 |
+
if (w <= h and w == size) or (h <= w and h == size):
|
| 222 |
+
return pil_img
|
| 223 |
+
if w < h:
|
| 224 |
+
ow = size
|
| 225 |
+
oh = int(size * h / w)
|
| 226 |
+
else:
|
| 227 |
+
oh = size
|
| 228 |
+
ow = int(size * w / h)
|
| 229 |
+
size = (ow, oh)
|
| 230 |
+
else:
|
| 231 |
+
size = (size[1], size[0])
|
| 232 |
+
|
| 233 |
+
return pil_img.resize(
|
| 234 |
+
size, resample=interpolation, reducing_gap=None if antialias else 3.0
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
pil_img = resize(
|
| 238 |
+
pil_img, size, interpolation=PIL.Image.Resampling.BICUBIC, antialias=True
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
pil_img = expand2square(pil_img, self.background_color)
|
| 242 |
+
x = to_numpy_array(pil_img)
|
| 243 |
+
|
| 244 |
+
# [H, W, 3] -> [3, H, W]
|
| 245 |
+
x = np.transpose(x, (2, 0, 1))
|
| 246 |
+
|
| 247 |
+
return x
|
| 248 |
+
|
| 249 |
+
def preprocess(self, images, return_tensors: str = "pt", **kwargs) -> BatchFeature:
|
| 250 |
+
# resize and pad to [self.image_size, self.image_size]
|
| 251 |
+
# then convert from [H, W, 3] to [3, H, W]
|
| 252 |
+
if not isinstance(images, list):
|
| 253 |
+
images = [images]
|
| 254 |
+
images: List[np.ndarray] = [self.resize(image) for image in images]
|
| 255 |
+
images = [image[:3, ...] for image in images]
|
| 256 |
+
|
| 257 |
+
# rescale from [0, 255] -> [0, 1]
|
| 258 |
+
images = [
|
| 259 |
+
self.rescale(
|
| 260 |
+
image=image,
|
| 261 |
+
scale=self.rescale_factor,
|
| 262 |
+
input_data_format="channels_first",
|
| 263 |
+
)
|
| 264 |
+
for image in images
|
| 265 |
+
]
|
| 266 |
+
|
| 267 |
+
# normalize
|
| 268 |
+
if self.do_normalize:
|
| 269 |
+
images = [
|
| 270 |
+
self.normalize(
|
| 271 |
+
image=image,
|
| 272 |
+
mean=self.image_mean,
|
| 273 |
+
std=self.image_std,
|
| 274 |
+
input_data_format="channels_first",
|
| 275 |
+
)
|
| 276 |
+
for image in images
|
| 277 |
+
]
|
| 278 |
+
data = {"pixel_values": images}
|
| 279 |
+
return BatchFeature(data=data, tensor_type=return_tensors)
|
| 280 |
+
|
| 281 |
+
@property
|
| 282 |
+
def default_shape(self):
|
| 283 |
+
return [3, self.image_size, self.image_size]
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
class DictOutput(object):
|
| 287 |
+
def keys(self):
|
| 288 |
+
return self.__dict__.keys()
|
| 289 |
+
|
| 290 |
+
def __getitem__(self, item):
|
| 291 |
+
return self.__dict__[item]
|
| 292 |
+
|
| 293 |
+
def __setitem__(self, key, value):
|
| 294 |
+
self.__dict__[key] = value
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
@dataclass
|
| 298 |
+
class VLChatProcessorOutput(DictOutput):
|
| 299 |
+
sft_format: str
|
| 300 |
+
input_ids: torch.Tensor
|
| 301 |
+
pixel_values: torch.Tensor
|
| 302 |
+
num_image_tokens: torch.IntTensor
|
| 303 |
+
|
| 304 |
+
def __len__(self):
|
| 305 |
+
return len(self.input_ids)
|
| 306 |
+
|
| 307 |
+
|
| 308 |
+
@dataclass
|
| 309 |
+
class BatchedVLChatProcessorOutput(DictOutput):
|
| 310 |
+
sft_format: List[str]
|
| 311 |
+
input_ids: torch.Tensor
|
| 312 |
+
pixel_values: torch.Tensor
|
| 313 |
+
attention_mask: torch.Tensor
|
| 314 |
+
images_seq_mask: torch.BoolTensor
|
| 315 |
+
images_emb_mask: torch.BoolTensor
|
| 316 |
+
|
| 317 |
+
|
| 318 |
+
# FIXME: had to place Official Processor here, since image_processor module would not be imported in all threads,
|
| 319 |
+
# hence AutoProcessor registration would not be affective in some cases
|
| 320 |
+
class VLChatProcessor(ProcessorMixin):
|
| 321 |
+
image_processor_class = "AutoImageProcessor"
|
| 322 |
+
tokenizer_class = ("LlamaTokenizer", "LlamaTokenizerFast")
|
| 323 |
+
|
| 324 |
+
attributes = ["image_processor", "tokenizer"]
|
| 325 |
+
|
| 326 |
+
def __init__(
|
| 327 |
+
self,
|
| 328 |
+
image_processor: VLMImageProcessor,
|
| 329 |
+
tokenizer: LlamaTokenizerFast,
|
| 330 |
+
image_tag: str = "<image_placeholder>",
|
| 331 |
+
image_start_tag: str = "<begin_of_image>",
|
| 332 |
+
image_end_tag: str = "<end_of_image>",
|
| 333 |
+
pad_tag: str = "<|▁pad▁|>",
|
| 334 |
+
num_image_tokens: int = 576,
|
| 335 |
+
add_special_token: bool = False,
|
| 336 |
+
sft_format: str = "deepseek",
|
| 337 |
+
mask_prompt: bool = True,
|
| 338 |
+
ignore_id: int = -100,
|
| 339 |
+
**kwargs,
|
| 340 |
+
):
|
| 341 |
+
self.image_processor = image_processor
|
| 342 |
+
self.tokenizer = tokenizer
|
| 343 |
+
|
| 344 |
+
image_id = self.tokenizer.vocab.get(image_tag)
|
| 345 |
+
if image_id is None:
|
| 346 |
+
special_tokens = [image_tag]
|
| 347 |
+
special_tokens_dict = {"additional_special_tokens": special_tokens}
|
| 348 |
+
self.tokenizer.add_special_tokens(special_tokens_dict)
|
| 349 |
+
# print(f"Add image tag = {image_tag} to the tokenizer")
|
| 350 |
+
|
| 351 |
+
self.image_tag = image_tag
|
| 352 |
+
self.image_start_tag = image_start_tag
|
| 353 |
+
self.image_end_tag = image_end_tag
|
| 354 |
+
self.pad_tag = pad_tag
|
| 355 |
+
|
| 356 |
+
self.num_image_tokens = num_image_tokens
|
| 357 |
+
self.add_special_token = add_special_token
|
| 358 |
+
self.sft_format = sft_format
|
| 359 |
+
self.ignore_id = ignore_id
|
| 360 |
+
|
| 361 |
+
super().__init__(
|
| 362 |
+
image_processor,
|
| 363 |
+
tokenizer,
|
| 364 |
+
**kwargs,
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
@property
|
| 368 |
+
def image_token(self):
|
| 369 |
+
return self.image_tag
|
| 370 |
+
|
| 371 |
+
@property
|
| 372 |
+
def image_id(self) -> int:
|
| 373 |
+
image_id = self.tokenizer.vocab.get(self.image_tag)
|
| 374 |
+
return image_id
|
| 375 |
+
|
| 376 |
+
@property
|
| 377 |
+
def image_start_id(self):
|
| 378 |
+
image_start_id = self.tokenizer.vocab.get(self.image_start_tag)
|
| 379 |
+
return image_start_id
|
| 380 |
+
|
| 381 |
+
@property
|
| 382 |
+
def image_end_id(self):
|
| 383 |
+
image_end_id = self.tokenizer.vocab.get(self.image_end_tag)
|
| 384 |
+
return image_end_id
|
| 385 |
+
|
| 386 |
+
@property
|
| 387 |
+
def image_start_token(self):
|
| 388 |
+
return self.image_start_tag
|
| 389 |
+
|
| 390 |
+
@property
|
| 391 |
+
def image_end_token(self):
|
| 392 |
+
return self.image_end_tag
|
| 393 |
+
|
| 394 |
+
@property
|
| 395 |
+
def pad_id(self):
|
| 396 |
+
pad_id = self.tokenizer.vocab.get(self.pad_tag)
|
| 397 |
+
return pad_id
|
| 398 |
+
|
| 399 |
+
def add_image_token(
|
| 400 |
+
self,
|
| 401 |
+
image_indices: List[int],
|
| 402 |
+
input_ids: torch.LongTensor,
|
| 403 |
+
):
|
| 404 |
+
"""
|
| 405 |
+
|
| 406 |
+
Args:
|
| 407 |
+
image_indices (List[int]): [index_0, index_1, ..., index_j]
|
| 408 |
+
input_ids (torch.LongTensor): [N]
|
| 409 |
+
|
| 410 |
+
Returns:
|
| 411 |
+
input_ids (torch.LongTensor): [N + image tokens]
|
| 412 |
+
num_image_tokens (torch.IntTensor): [n_images]
|
| 413 |
+
"""
|
| 414 |
+
|
| 415 |
+
input_slices = []
|
| 416 |
+
|
| 417 |
+
start = 0
|
| 418 |
+
for index in image_indices:
|
| 419 |
+
if self.add_special_token:
|
| 420 |
+
end = index + 1
|
| 421 |
+
else:
|
| 422 |
+
end = index
|
| 423 |
+
|
| 424 |
+
# original text tokens
|
| 425 |
+
input_slices.append(input_ids[start:end])
|
| 426 |
+
|
| 427 |
+
# add boi, image tokens, eoi and set the mask as False
|
| 428 |
+
input_slices.append(self.image_start_id * torch.ones((1), dtype=torch.long))
|
| 429 |
+
input_slices.append(
|
| 430 |
+
self.image_id * torch.ones((self.num_image_tokens,), dtype=torch.long)
|
| 431 |
+
)
|
| 432 |
+
input_slices.append(self.image_end_id * torch.ones((1), dtype=torch.long))
|
| 433 |
+
start = index + 1
|
| 434 |
+
|
| 435 |
+
# the left part
|
| 436 |
+
input_slices.append(input_ids[start:])
|
| 437 |
+
|
| 438 |
+
# concat all slices
|
| 439 |
+
input_ids = torch.cat(input_slices, dim=0)
|
| 440 |
+
num_image_tokens = torch.IntTensor([self.num_image_tokens] * len(image_indices))
|
| 441 |
+
|
| 442 |
+
return input_ids, num_image_tokens
|
| 443 |
+
|
| 444 |
+
def process_one(
|
| 445 |
+
self,
|
| 446 |
+
prompt: str = None,
|
| 447 |
+
images: List[Image] = None,
|
| 448 |
+
**kwargs,
|
| 449 |
+
):
|
| 450 |
+
"""
|
| 451 |
+
|
| 452 |
+
Args:
|
| 453 |
+
prompt (str): the formatted prompt;
|
| 454 |
+
images (List[ImageType]): the list of images;
|
| 455 |
+
**kwargs:
|
| 456 |
+
|
| 457 |
+
Returns:
|
| 458 |
+
outputs (BaseProcessorOutput): the output of the processor,
|
| 459 |
+
- input_ids (torch.LongTensor): [N + image tokens]
|
| 460 |
+
- target_ids (torch.LongTensor): [N + image tokens]
|
| 461 |
+
- images (torch.FloatTensor): [n_images, 3, H, W]
|
| 462 |
+
- image_id (int): the id of the image token
|
| 463 |
+
- num_image_tokens (List[int]): the number of image tokens
|
| 464 |
+
"""
|
| 465 |
+
|
| 466 |
+
sft_format = prompt
|
| 467 |
+
# tokenize
|
| 468 |
+
input_ids = self.tokenizer.encode(sft_format)
|
| 469 |
+
input_ids = torch.LongTensor(input_ids)
|
| 470 |
+
|
| 471 |
+
# add image tokens to the input_ids
|
| 472 |
+
image_token_mask: torch.Tensor = (input_ids == self.image_id).to(torch.bool)
|
| 473 |
+
image_indices = image_token_mask.nonzero()
|
| 474 |
+
input_ids, num_image_tokens = self.add_image_token(
|
| 475 |
+
image_indices=image_indices,
|
| 476 |
+
input_ids=input_ids,
|
| 477 |
+
)
|
| 478 |
+
|
| 479 |
+
# load images
|
| 480 |
+
images_outputs = self.image_processor(images, return_tensors="pt")
|
| 481 |
+
|
| 482 |
+
prepare = VLChatProcessorOutput(
|
| 483 |
+
sft_format=sft_format,
|
| 484 |
+
input_ids=input_ids,
|
| 485 |
+
pixel_values=images_outputs.pixel_values,
|
| 486 |
+
num_image_tokens=num_image_tokens,
|
| 487 |
+
)
|
| 488 |
+
|
| 489 |
+
return prepare
|
| 490 |
+
|
| 491 |
+
def __call__(
|
| 492 |
+
self,
|
| 493 |
+
*,
|
| 494 |
+
prompt: str = None,
|
| 495 |
+
conversations: List[Dict[str, str]] = None,
|
| 496 |
+
images: List[Image] = None,
|
| 497 |
+
force_batchify: bool = True,
|
| 498 |
+
**kwargs,
|
| 499 |
+
):
|
| 500 |
+
"""
|
| 501 |
+
|
| 502 |
+
Args:
|
| 503 |
+
prompt (str): the formatted prompt;
|
| 504 |
+
conversations (List[Dict]): conversations with a list of messages;
|
| 505 |
+
images (List[ImageType]): the list of images;
|
| 506 |
+
force_batchify (bool): force batchify the inputs;
|
| 507 |
+
**kwargs:
|
| 508 |
+
|
| 509 |
+
Returns:
|
| 510 |
+
outputs (BaseProcessorOutput): the output of the processor,
|
| 511 |
+
- input_ids (torch.LongTensor): [N + image tokens]
|
| 512 |
+
- images (torch.FloatTensor): [n_images, 3, H, W]
|
| 513 |
+
- image_id (int): the id of the image token
|
| 514 |
+
- num_image_tokens (List[int]): the number of image tokens
|
| 515 |
+
"""
|
| 516 |
+
|
| 517 |
+
prepare = self.process_one(
|
| 518 |
+
prompt=prompt, conversations=conversations, images=images
|
| 519 |
+
)
|
| 520 |
+
|
| 521 |
+
if force_batchify:
|
| 522 |
+
prepare = self.batchify([prepare])
|
| 523 |
+
|
| 524 |
+
return prepare
|
| 525 |
+
|
| 526 |
+
def batchify(
|
| 527 |
+
self, prepare_list: List[VLChatProcessorOutput]
|
| 528 |
+
) -> BatchedVLChatProcessorOutput:
|
| 529 |
+
"""
|
| 530 |
+
Preprocesses the inputs for multimodal inference.
|
| 531 |
+
|
| 532 |
+
Args:
|
| 533 |
+
prepare_list (List[VLChatProcessorOutput]): A list of VLChatProcessorOutput.
|
| 534 |
+
|
| 535 |
+
Returns:
|
| 536 |
+
BatchedVLChatProcessorOutput: A dictionary of the inputs to use for multimodal inference.
|
| 537 |
+
"""
|
| 538 |
+
|
| 539 |
+
batch_size = len(prepare_list)
|
| 540 |
+
sft_format = []
|
| 541 |
+
n_images = []
|
| 542 |
+
seq_lens = []
|
| 543 |
+
for prepare in prepare_list:
|
| 544 |
+
n_images.append(len(prepare.num_image_tokens))
|
| 545 |
+
seq_lens.append(len(prepare))
|
| 546 |
+
|
| 547 |
+
input_token_max_len = max(seq_lens)
|
| 548 |
+
max_n_images = max(1, max(n_images))
|
| 549 |
+
|
| 550 |
+
batched_input_ids = torch.full(
|
| 551 |
+
(batch_size, input_token_max_len), self.pad_id
|
| 552 |
+
).long() # FIXME
|
| 553 |
+
batched_attention_mask = torch.zeros((batch_size, input_token_max_len)).long()
|
| 554 |
+
batched_pixel_values = torch.zeros(
|
| 555 |
+
(batch_size, max_n_images, *self.image_processor.default_shape)
|
| 556 |
+
).float()
|
| 557 |
+
batched_images_seq_mask = torch.zeros((batch_size, input_token_max_len)).bool()
|
| 558 |
+
batched_images_emb_mask = torch.zeros(
|
| 559 |
+
(batch_size, max_n_images, self.num_image_tokens)
|
| 560 |
+
).bool()
|
| 561 |
+
|
| 562 |
+
for i, prepare in enumerate(prepare_list):
|
| 563 |
+
input_ids = prepare.input_ids
|
| 564 |
+
seq_len = len(prepare)
|
| 565 |
+
n_image = len(prepare.num_image_tokens)
|
| 566 |
+
# left-padding
|
| 567 |
+
batched_attention_mask[i, -seq_len:] = 1
|
| 568 |
+
batched_input_ids[i, -seq_len:] = torch.LongTensor(input_ids)
|
| 569 |
+
batched_images_seq_mask[i, -seq_len:] = input_ids == self.image_id
|
| 570 |
+
|
| 571 |
+
if n_image > 0:
|
| 572 |
+
batched_pixel_values[i, :n_image] = prepare.pixel_values
|
| 573 |
+
for j, n_image_tokens in enumerate(prepare.num_image_tokens):
|
| 574 |
+
batched_images_emb_mask[i, j, :n_image_tokens] = True
|
| 575 |
+
|
| 576 |
+
sft_format.append(prepare.sft_format)
|
| 577 |
+
|
| 578 |
+
batched_prepares = BatchedVLChatProcessorOutput(
|
| 579 |
+
input_ids=batched_input_ids,
|
| 580 |
+
attention_mask=batched_attention_mask,
|
| 581 |
+
pixel_values=batched_pixel_values,
|
| 582 |
+
images_seq_mask=batched_images_seq_mask,
|
| 583 |
+
images_emb_mask=batched_images_emb_mask,
|
| 584 |
+
sft_format=sft_format,
|
| 585 |
+
)
|
| 586 |
+
|
| 587 |
+
return batched_prepares
|
| 588 |
+
|
| 589 |
+
|
| 590 |
+
class VLMImageProcessorConfig(PretrainedConfig):
|
| 591 |
+
model_type = "deepseek_vlm"
|
| 592 |
+
image_size: int
|
| 593 |
+
min_size: int
|
| 594 |
+
image_mean: Union[Tuple[float, float, float], List[float]]
|
| 595 |
+
image_std: Union[Tuple[float, float, float], List[float]]
|
| 596 |
+
rescale_factor: float
|
| 597 |
+
do_normalize: bool
|
| 598 |
+
|
| 599 |
+
def __init__(
|
| 600 |
+
self,
|
| 601 |
+
image_size: int,
|
| 602 |
+
min_size: int = 14,
|
| 603 |
+
image_mean: Union[Tuple[float, float, float], List[float]] = (
|
| 604 |
+
0.48145466,
|
| 605 |
+
0.4578275,
|
| 606 |
+
0.40821073,
|
| 607 |
+
),
|
| 608 |
+
image_std: Union[Tuple[float, float, float], List[float]] = (
|
| 609 |
+
0.26862954,
|
| 610 |
+
0.26130258,
|
| 611 |
+
0.27577711,
|
| 612 |
+
),
|
| 613 |
+
rescale_factor: float = 1.0 / 255.0,
|
| 614 |
+
do_normalize: bool = True,
|
| 615 |
+
**kwargs,
|
| 616 |
+
):
|
| 617 |
+
self.image_size = image_size
|
| 618 |
+
self.min_size = min_size
|
| 619 |
+
self.image_mean = image_mean
|
| 620 |
+
self.image_std = image_std
|
| 621 |
+
self.rescale_factor = rescale_factor
|
| 622 |
+
self.do_normalize = do_normalize
|
| 623 |
+
|
| 624 |
+
super().__init__(**kwargs)
|
| 625 |
+
|
| 626 |
+
|
| 627 |
+
register_processor(MultiModalityConfig, VLChatProcessor)
|
| 628 |
+
register_image_processor(MultiModalityConfig, VLMImageProcessor)
|
lib/python3.12/site-packages/sglang/srt/configs/load_config.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/config.py
|
| 2 |
+
import enum
|
| 3 |
+
import json
|
| 4 |
+
import logging
|
| 5 |
+
from dataclasses import dataclass, field
|
| 6 |
+
from typing import List, Optional, Union
|
| 7 |
+
|
| 8 |
+
from sglang.srt.utils import is_hip
|
| 9 |
+
|
| 10 |
+
logger = logging.getLogger(__name__)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class LoadFormat(str, enum.Enum):
|
| 14 |
+
AUTO = "auto"
|
| 15 |
+
PT = "pt"
|
| 16 |
+
SAFETENSORS = "safetensors"
|
| 17 |
+
NPCACHE = "npcache"
|
| 18 |
+
DUMMY = "dummy"
|
| 19 |
+
SHARDED_STATE = "sharded_state"
|
| 20 |
+
GGUF = "gguf"
|
| 21 |
+
BITSANDBYTES = "bitsandbytes"
|
| 22 |
+
MISTRAL = "mistral"
|
| 23 |
+
LAYERED = "layered"
|
| 24 |
+
JAX = "jax"
|
| 25 |
+
REMOTE = "remote"
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@dataclass
|
| 29 |
+
class LoadConfig:
|
| 30 |
+
"""
|
| 31 |
+
download_dir: Directory to download and load the weights, default to the
|
| 32 |
+
default cache directory of huggingface.
|
| 33 |
+
load_format: The format of the model weights to load:
|
| 34 |
+
"auto" will try to load the weights in the safetensors format and
|
| 35 |
+
fall back to the pytorch bin format if safetensors format is
|
| 36 |
+
not available.
|
| 37 |
+
"pt" will load the weights in the pytorch bin format.
|
| 38 |
+
"safetensors" will load the weights in the safetensors format.
|
| 39 |
+
"npcache" will load the weights in pytorch format and store
|
| 40 |
+
a numpy cache to speed up the loading.
|
| 41 |
+
"dummy" will initialize the weights with random values, which is
|
| 42 |
+
mainly for profiling.
|
| 43 |
+
"bitsandbytes" will load nf4 type weights.
|
| 44 |
+
ignore_patterns: The list of patterns to ignore when loading the model.
|
| 45 |
+
Default to "original/**/*" to avoid repeated loading of llama's
|
| 46 |
+
checkpoints.
|
| 47 |
+
decryption_key_file: If set, decrypts the output files with a password read
|
| 48 |
+
from this file (after PBKDF2).
|
| 49 |
+
"""
|
| 50 |
+
|
| 51 |
+
load_format: Union[str, LoadFormat] = LoadFormat.AUTO
|
| 52 |
+
download_dir: Optional[str] = None
|
| 53 |
+
model_loader_extra_config: Optional[Union[str, dict]] = field(default_factory=dict)
|
| 54 |
+
ignore_patterns: Optional[Union[List[str], str]] = None
|
| 55 |
+
decryption_key_file: Optional[str] = None
|
| 56 |
+
|
| 57 |
+
def __post_init__(self):
|
| 58 |
+
model_loader_extra_config = self.model_loader_extra_config or {}
|
| 59 |
+
if isinstance(model_loader_extra_config, str):
|
| 60 |
+
self.model_loader_extra_config = json.loads(model_loader_extra_config)
|
| 61 |
+
self._verify_load_format()
|
| 62 |
+
|
| 63 |
+
if self.ignore_patterns is not None and len(self.ignore_patterns) > 0:
|
| 64 |
+
logger.info(
|
| 65 |
+
"Ignoring the following patterns when downloading weights: %s",
|
| 66 |
+
self.ignore_patterns,
|
| 67 |
+
)
|
| 68 |
+
else:
|
| 69 |
+
self.ignore_patterns = ["original/**/*"]
|
| 70 |
+
|
| 71 |
+
def _verify_load_format(self) -> None:
|
| 72 |
+
if not isinstance(self.load_format, str):
|
| 73 |
+
return
|
| 74 |
+
|
| 75 |
+
load_format = self.load_format.lower()
|
| 76 |
+
self.load_format = LoadFormat(load_format)
|
| 77 |
+
|
| 78 |
+
rocm_not_supported_load_format: List[str] = []
|
| 79 |
+
if is_hip() and load_format in rocm_not_supported_load_format:
|
| 80 |
+
rocm_supported_load_format = [
|
| 81 |
+
f
|
| 82 |
+
for f in LoadFormat.__members__
|
| 83 |
+
if (f not in rocm_not_supported_load_format)
|
| 84 |
+
]
|
| 85 |
+
raise ValueError(
|
| 86 |
+
f"load format '{load_format}' is not supported in ROCm. "
|
| 87 |
+
f"Supported load formats are "
|
| 88 |
+
f"{rocm_supported_load_format}"
|
| 89 |
+
)
|
lib/python3.12/site-packages/sglang/srt/configs/model_config.py
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023-2024 SGLang Team
|
| 2 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 3 |
+
# you may not use this file except in compliance with the License.
|
| 4 |
+
# You may obtain a copy of the License at
|
| 5 |
+
#
|
| 6 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 7 |
+
#
|
| 8 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 9 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 10 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 11 |
+
# See the License for the specific language governing permissions and
|
| 12 |
+
# limitations under the License.
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
|
| 15 |
+
import json
|
| 16 |
+
import logging
|
| 17 |
+
import math
|
| 18 |
+
import os
|
| 19 |
+
from enum import IntEnum, auto
|
| 20 |
+
from typing import List, Optional, Set, Union
|
| 21 |
+
|
| 22 |
+
import torch
|
| 23 |
+
from transformers import PretrainedConfig
|
| 24 |
+
|
| 25 |
+
from sglang.srt.hf_transformers_utils import get_config, get_context_length
|
| 26 |
+
from sglang.srt.layers.quantization import QUANTIZATION_METHODS
|
| 27 |
+
from sglang.srt.utils import get_bool_env_var, is_hip
|
| 28 |
+
|
| 29 |
+
logger = logging.getLogger(__name__)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class AttentionArch(IntEnum):
|
| 33 |
+
MLA = auto()
|
| 34 |
+
MHA = auto()
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class ModelConfig:
|
| 38 |
+
def __init__(
|
| 39 |
+
self,
|
| 40 |
+
model_path: str,
|
| 41 |
+
trust_remote_code: bool = True,
|
| 42 |
+
revision: Optional[str] = None,
|
| 43 |
+
context_length: Optional[int] = None,
|
| 44 |
+
model_override_args: Optional[str] = None,
|
| 45 |
+
is_embedding: Optional[bool] = None,
|
| 46 |
+
enable_multimodal: Optional[bool] = None,
|
| 47 |
+
dtype: str = "auto",
|
| 48 |
+
quantization: Optional[str] = None,
|
| 49 |
+
override_config_file: Optional[str] = None,
|
| 50 |
+
) -> None:
|
| 51 |
+
|
| 52 |
+
self.model_path = model_path
|
| 53 |
+
self.revision = revision
|
| 54 |
+
self.quantization = quantization
|
| 55 |
+
|
| 56 |
+
# Parse args
|
| 57 |
+
self.maybe_pull_model_tokenizer_from_remote()
|
| 58 |
+
self.model_override_args = json.loads(model_override_args)
|
| 59 |
+
kwargs = {}
|
| 60 |
+
if override_config_file and override_config_file.strip():
|
| 61 |
+
kwargs["_configuration_file"] = override_config_file.strip()
|
| 62 |
+
|
| 63 |
+
self.hf_config = get_config(
|
| 64 |
+
self.model_path,
|
| 65 |
+
trust_remote_code=trust_remote_code,
|
| 66 |
+
revision=revision,
|
| 67 |
+
model_override_args=self.model_override_args,
|
| 68 |
+
**kwargs,
|
| 69 |
+
)
|
| 70 |
+
self.hf_text_config = get_hf_text_config(self.hf_config)
|
| 71 |
+
self.attention_chunk_size = getattr(
|
| 72 |
+
self.hf_text_config, "attention_chunk_size", None
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
if enable_multimodal is None:
|
| 76 |
+
mm_disabled_models = [
|
| 77 |
+
"Gemma3ForConditionalGeneration",
|
| 78 |
+
"Llama4ForConditionalGeneration",
|
| 79 |
+
]
|
| 80 |
+
if self.hf_config.architectures[0] in mm_disabled_models:
|
| 81 |
+
enable_multimodal = False
|
| 82 |
+
logger.info(
|
| 83 |
+
f"Multimodal is disabled for {self.hf_config.model_type}. To enable it, set --enable-multimodal."
|
| 84 |
+
)
|
| 85 |
+
else:
|
| 86 |
+
enable_multimodal = True
|
| 87 |
+
|
| 88 |
+
# Check model type
|
| 89 |
+
self.is_generation = is_generation_model(
|
| 90 |
+
self.hf_config.architectures, is_embedding
|
| 91 |
+
)
|
| 92 |
+
self.is_multimodal = enable_multimodal and is_multimodal_model(
|
| 93 |
+
self.hf_config.architectures
|
| 94 |
+
)
|
| 95 |
+
self.is_multimodal_gen = enable_multimodal and is_multimodal_gen_model(
|
| 96 |
+
self.hf_config.architectures
|
| 97 |
+
)
|
| 98 |
+
self.is_image_gen = enable_multimodal and is_image_gen_model(
|
| 99 |
+
self.hf_config.architectures
|
| 100 |
+
)
|
| 101 |
+
self.is_audio_model = enable_multimodal and is_audio_model(
|
| 102 |
+
self.hf_config.architectures
|
| 103 |
+
)
|
| 104 |
+
self.is_encoder_decoder = is_encoder_decoder_model(self.hf_config.architectures)
|
| 105 |
+
self.dtype = _get_and_verify_dtype(self.hf_text_config, dtype)
|
| 106 |
+
|
| 107 |
+
# Derive context length
|
| 108 |
+
derived_context_len = get_context_length(self.hf_text_config)
|
| 109 |
+
if context_length is not None:
|
| 110 |
+
if context_length > derived_context_len:
|
| 111 |
+
if get_bool_env_var(
|
| 112 |
+
"SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN", default="True"
|
| 113 |
+
):
|
| 114 |
+
logger.warning(
|
| 115 |
+
f"Warning: User-specified context_length ({context_length}) is greater than the derived context_length ({derived_context_len}). "
|
| 116 |
+
f"This may lead to incorrect model outputs or CUDA errors."
|
| 117 |
+
)
|
| 118 |
+
self.context_len = context_length
|
| 119 |
+
else:
|
| 120 |
+
raise ValueError(
|
| 121 |
+
f"User-specified context_length ({context_length}) is greater than the derived context_length ({derived_context_len}). "
|
| 122 |
+
f"This may lead to incorrect model outputs or CUDA errors. Note that the derived context_length may differ from max_position_embeddings in the model's config. "
|
| 123 |
+
f"To allow overriding this maximum, set the env var SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1"
|
| 124 |
+
)
|
| 125 |
+
else:
|
| 126 |
+
self.context_len = context_length
|
| 127 |
+
else:
|
| 128 |
+
self.context_len = derived_context_len
|
| 129 |
+
|
| 130 |
+
# Unify the config keys for hf_text_config
|
| 131 |
+
self.head_dim = getattr(
|
| 132 |
+
self.hf_text_config,
|
| 133 |
+
"head_dim",
|
| 134 |
+
self.hf_text_config.hidden_size // self.hf_text_config.num_attention_heads,
|
| 135 |
+
)
|
| 136 |
+
|
| 137 |
+
# FIXME: temporary special judge for MLA architecture
|
| 138 |
+
if (
|
| 139 |
+
"DeepseekV2ForCausalLM" in self.hf_config.architectures
|
| 140 |
+
or "DeepseekV3ForCausalLM" in self.hf_config.architectures
|
| 141 |
+
or "DeepseekV3ForCausalLMNextN" in self.hf_config.architectures
|
| 142 |
+
):
|
| 143 |
+
self.head_dim = 256
|
| 144 |
+
self.attention_arch = AttentionArch.MLA
|
| 145 |
+
self.kv_lora_rank = self.hf_config.kv_lora_rank
|
| 146 |
+
self.qk_nope_head_dim = self.hf_config.qk_nope_head_dim
|
| 147 |
+
self.qk_rope_head_dim = self.hf_config.qk_rope_head_dim
|
| 148 |
+
self.v_head_dim = self.hf_config.v_head_dim
|
| 149 |
+
|
| 150 |
+
# Handle rope scaling with yarn
|
| 151 |
+
self.scaling = 1 / math.sqrt(self.qk_nope_head_dim + self.qk_rope_head_dim)
|
| 152 |
+
if self.hf_config.rope_scaling:
|
| 153 |
+
mscale_all_dim = self.hf_config.rope_scaling.get(
|
| 154 |
+
"mscale_all_dim", False
|
| 155 |
+
)
|
| 156 |
+
scaling_factor = self.hf_config.rope_scaling["factor"]
|
| 157 |
+
mscale = yarn_get_mscale(scaling_factor, float(mscale_all_dim))
|
| 158 |
+
self.scaling = self.scaling * mscale * mscale
|
| 159 |
+
|
| 160 |
+
elif "MiniCPM3ForCausalLM" in self.hf_config.architectures:
|
| 161 |
+
self.head_dim = 128
|
| 162 |
+
self.attention_arch = AttentionArch.MLA
|
| 163 |
+
self.kv_lora_rank = self.hf_config.kv_lora_rank
|
| 164 |
+
self.qk_rope_head_dim = self.hf_config.qk_rope_head_dim
|
| 165 |
+
elif "DeepseekVL2ForCausalLM" in self.hf_config.architectures and getattr(
|
| 166 |
+
self.hf_text_config, "use_mla", True
|
| 167 |
+
):
|
| 168 |
+
self.head_dim = 256
|
| 169 |
+
self.attention_arch = AttentionArch.MLA
|
| 170 |
+
self.kv_lora_rank = self.hf_text_config.kv_lora_rank
|
| 171 |
+
self.qk_rope_head_dim = self.hf_text_config.qk_rope_head_dim
|
| 172 |
+
else:
|
| 173 |
+
self.attention_arch = AttentionArch.MHA
|
| 174 |
+
|
| 175 |
+
self.num_attention_heads = self.hf_text_config.num_attention_heads
|
| 176 |
+
self.num_key_value_heads = getattr(
|
| 177 |
+
self.hf_text_config, "num_key_value_heads", None
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
# for Dbrx and MPT models
|
| 181 |
+
if self.hf_config.model_type in ["dbrx", "mpt"]:
|
| 182 |
+
self.num_key_value_heads = getattr(
|
| 183 |
+
self.hf_config.attn_config, "kv_n_heads", None
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
if self.num_key_value_heads is None:
|
| 187 |
+
self.num_key_value_heads = self.num_attention_heads
|
| 188 |
+
self.hidden_size = self.hf_text_config.hidden_size
|
| 189 |
+
self.num_hidden_layers = self.hf_text_config.num_hidden_layers
|
| 190 |
+
self.vocab_size = self.hf_text_config.vocab_size
|
| 191 |
+
|
| 192 |
+
# Verify quantization
|
| 193 |
+
self._verify_quantization()
|
| 194 |
+
|
| 195 |
+
# Cache attributes
|
| 196 |
+
self.hf_eos_token_id = self.get_hf_eos_token_id()
|
| 197 |
+
self.image_token_id = getattr(self.hf_config, "image_token_id", None)
|
| 198 |
+
|
| 199 |
+
# adapted from https://github.com/vllm-project/vllm/blob/main/vllm/config.py#L289
|
| 200 |
+
def get_total_num_kv_heads(self) -> int:
|
| 201 |
+
"""Returns the total number of KV heads."""
|
| 202 |
+
# For GPTBigCode & Falcon:
|
| 203 |
+
# NOTE: for falcon, when new_decoder_architecture is True, the
|
| 204 |
+
# multi_query flag is ignored and we use n_head_kv for the number of
|
| 205 |
+
# KV heads.
|
| 206 |
+
falcon_model_types = ["falcon", "RefinedWeb", "RefinedWebModel"]
|
| 207 |
+
new_decoder_arch_falcon = (
|
| 208 |
+
self.hf_config.model_type in falcon_model_types
|
| 209 |
+
and getattr(self.hf_config, "new_decoder_architecture", False)
|
| 210 |
+
)
|
| 211 |
+
if not new_decoder_arch_falcon and getattr(
|
| 212 |
+
self.hf_text_config, "multi_query", False
|
| 213 |
+
):
|
| 214 |
+
# Multi-query attention, only one KV head.
|
| 215 |
+
# Currently, tensor parallelism is not supported in this case.
|
| 216 |
+
return 1
|
| 217 |
+
|
| 218 |
+
# For DBRX and MPT
|
| 219 |
+
if self.hf_config.model_type in ["mpt"]:
|
| 220 |
+
if "kv_n_heads" in self.hf_config.attn_config:
|
| 221 |
+
return self.hf_config.attn_config["kv_n_heads"]
|
| 222 |
+
return self.hf_config.num_attention_heads
|
| 223 |
+
if self.hf_config.model_type in ["dbrx"]:
|
| 224 |
+
return getattr(
|
| 225 |
+
self.hf_config.attn_config,
|
| 226 |
+
"kv_n_heads",
|
| 227 |
+
self.hf_config.num_attention_heads,
|
| 228 |
+
)
|
| 229 |
+
|
| 230 |
+
attributes = [
|
| 231 |
+
# For Falcon:
|
| 232 |
+
"n_head_kv",
|
| 233 |
+
"num_kv_heads",
|
| 234 |
+
# For LLaMA-2:
|
| 235 |
+
"num_key_value_heads",
|
| 236 |
+
# For ChatGLM:
|
| 237 |
+
"multi_query_group_num",
|
| 238 |
+
]
|
| 239 |
+
for attr in attributes:
|
| 240 |
+
num_kv_heads = getattr(self.hf_text_config, attr, None)
|
| 241 |
+
if num_kv_heads is not None:
|
| 242 |
+
return num_kv_heads
|
| 243 |
+
|
| 244 |
+
# For non-grouped-query attention models, the number of KV heads is
|
| 245 |
+
# equal to the number of attention heads.
|
| 246 |
+
return self.hf_text_config.num_attention_heads
|
| 247 |
+
|
| 248 |
+
def get_num_kv_heads(self, tensor_parallel_size) -> int:
|
| 249 |
+
"""Returns the number of KV heads per GPU."""
|
| 250 |
+
total_num_kv_heads = self.get_total_num_kv_heads()
|
| 251 |
+
# If tensor parallelism is used, we divide the number of KV heads by
|
| 252 |
+
# the tensor parallel size. We will replicate the KV heads in the
|
| 253 |
+
# case where the number of KV heads is smaller than the tensor
|
| 254 |
+
# parallel size so each GPU has at least one KV head.
|
| 255 |
+
return max(1, total_num_kv_heads // tensor_parallel_size)
|
| 256 |
+
|
| 257 |
+
# adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/config.py
|
| 258 |
+
def _parse_quant_hf_config(self):
|
| 259 |
+
quant_cfg = getattr(self.hf_config, "quantization_config", None)
|
| 260 |
+
if quant_cfg is None:
|
| 261 |
+
# compressed-tensors uses a "compression_config" key
|
| 262 |
+
quant_cfg = getattr(self.hf_config, "compression_config", None)
|
| 263 |
+
if quant_cfg is None:
|
| 264 |
+
# check if is modelopt model -- modelopt doesn't have corresponding field
|
| 265 |
+
# in hf `config.json` but has a standalone `hf_quant_config.json` in the root directory
|
| 266 |
+
# example: https://huggingface.co/nvidia/Llama-3.1-8B-Instruct-FP8/tree/main
|
| 267 |
+
is_local = os.path.exists(self.model_path)
|
| 268 |
+
modelopt_quant_config = {"quant_method": "modelopt"}
|
| 269 |
+
if not is_local:
|
| 270 |
+
from huggingface_hub import HfApi
|
| 271 |
+
|
| 272 |
+
hf_api = HfApi()
|
| 273 |
+
if hf_api.file_exists(self.model_path, "hf_quant_config.json"):
|
| 274 |
+
quant_cfg = modelopt_quant_config
|
| 275 |
+
elif os.path.exists(os.path.join(self.model_path, "hf_quant_config.json")):
|
| 276 |
+
quant_cfg = modelopt_quant_config
|
| 277 |
+
return quant_cfg
|
| 278 |
+
|
| 279 |
+
# adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/config.py
|
| 280 |
+
def _verify_quantization(self) -> None:
|
| 281 |
+
supported_quantization = [*QUANTIZATION_METHODS]
|
| 282 |
+
rocm_supported_quantization = [
|
| 283 |
+
"awq",
|
| 284 |
+
"gptq",
|
| 285 |
+
"fp8",
|
| 286 |
+
"compressed_tensors",
|
| 287 |
+
"compressed-tensors",
|
| 288 |
+
"fbgemm_fp8",
|
| 289 |
+
"w8a8_fp8",
|
| 290 |
+
]
|
| 291 |
+
optimized_quantization_methods = [
|
| 292 |
+
"fp8",
|
| 293 |
+
"marlin",
|
| 294 |
+
"modelopt",
|
| 295 |
+
"gptq_marlin_24",
|
| 296 |
+
"gptq_marlin",
|
| 297 |
+
"awq_marlin",
|
| 298 |
+
"fbgemm_fp8",
|
| 299 |
+
"compressed_tensors",
|
| 300 |
+
"compressed-tensors",
|
| 301 |
+
"experts_int8",
|
| 302 |
+
"w8a8_int8",
|
| 303 |
+
"w8a8_fp8",
|
| 304 |
+
"moe_wna16",
|
| 305 |
+
]
|
| 306 |
+
compatible_quantization_methods = {
|
| 307 |
+
"modelopt_fp4": ["modelopt"],
|
| 308 |
+
"w8a8_int8": ["compressed-tensors", "compressed_tensors"],
|
| 309 |
+
"w8a8_fp8": ["compressed-tensors", "compressed_tensors"],
|
| 310 |
+
}
|
| 311 |
+
if self.quantization is not None:
|
| 312 |
+
self.quantization = self.quantization.lower()
|
| 313 |
+
|
| 314 |
+
# Parse quantization method from the HF model config, if available.
|
| 315 |
+
quant_cfg = self._parse_quant_hf_config()
|
| 316 |
+
|
| 317 |
+
if quant_cfg is not None:
|
| 318 |
+
quant_method = quant_cfg.get("quant_method", "").lower()
|
| 319 |
+
|
| 320 |
+
# Detect which checkpoint is it
|
| 321 |
+
for _, method in QUANTIZATION_METHODS.items():
|
| 322 |
+
quantization_override = method.override_quantization_method(
|
| 323 |
+
quant_cfg, self.quantization
|
| 324 |
+
)
|
| 325 |
+
if quantization_override:
|
| 326 |
+
quant_method = quantization_override
|
| 327 |
+
self.quantization = quantization_override
|
| 328 |
+
break
|
| 329 |
+
|
| 330 |
+
# Verify quantization configurations.
|
| 331 |
+
if self.quantization is None:
|
| 332 |
+
self.quantization = quant_method
|
| 333 |
+
elif self.quantization != quant_method:
|
| 334 |
+
if (
|
| 335 |
+
self.quantization not in compatible_quantization_methods
|
| 336 |
+
or quant_method
|
| 337 |
+
not in compatible_quantization_methods[self.quantization]
|
| 338 |
+
):
|
| 339 |
+
raise ValueError(
|
| 340 |
+
"Quantization method specified in the model config "
|
| 341 |
+
f"({quant_method}) does not match the quantization "
|
| 342 |
+
f"method specified in the `quantization` argument "
|
| 343 |
+
f"({self.quantization})."
|
| 344 |
+
)
|
| 345 |
+
|
| 346 |
+
if self.quantization is not None:
|
| 347 |
+
if self.quantization not in supported_quantization:
|
| 348 |
+
raise ValueError(
|
| 349 |
+
f"Unknown quantization method: {self.quantization}. Must "
|
| 350 |
+
f"be one of {supported_quantization}."
|
| 351 |
+
)
|
| 352 |
+
if is_hip() and self.quantization not in rocm_supported_quantization:
|
| 353 |
+
raise ValueError(
|
| 354 |
+
f"{self.quantization} quantization is currently not "
|
| 355 |
+
f"supported in ROCm."
|
| 356 |
+
)
|
| 357 |
+
if self.quantization not in optimized_quantization_methods:
|
| 358 |
+
logger.warning(
|
| 359 |
+
"%s quantization is not fully "
|
| 360 |
+
"optimized yet. The speed can be slower than "
|
| 361 |
+
"non-quantized models.",
|
| 362 |
+
self.quantization,
|
| 363 |
+
)
|
| 364 |
+
|
| 365 |
+
def get_hf_eos_token_id(self) -> Optional[Set[int]]:
|
| 366 |
+
eos_ids = getattr(self.hf_config, "eos_token_id", None)
|
| 367 |
+
if eos_ids:
|
| 368 |
+
# it can be either int or list of int
|
| 369 |
+
eos_ids = {eos_ids} if isinstance(eos_ids, int) else set(eos_ids)
|
| 370 |
+
return eos_ids
|
| 371 |
+
|
| 372 |
+
def maybe_pull_model_tokenizer_from_remote(self) -> None:
|
| 373 |
+
"""
|
| 374 |
+
Pull the model config files to a temporary
|
| 375 |
+
directory in case of remote.
|
| 376 |
+
|
| 377 |
+
Args:
|
| 378 |
+
model: The model name or path.
|
| 379 |
+
|
| 380 |
+
"""
|
| 381 |
+
from sglang.srt.connector import create_remote_connector
|
| 382 |
+
from sglang.srt.utils import is_remote_url
|
| 383 |
+
|
| 384 |
+
if is_remote_url(self.model_path):
|
| 385 |
+
logger.info("Pulling model configs from remote...")
|
| 386 |
+
# BaseConnector implements __del__() to clean up the local dir.
|
| 387 |
+
# Since config files need to exist all the time, so we DO NOT use
|
| 388 |
+
# with statement to avoid closing the client.
|
| 389 |
+
client = create_remote_connector(self.model_path)
|
| 390 |
+
if is_remote_url(self.model_path):
|
| 391 |
+
client.pull_files(allow_pattern=["*config.json"])
|
| 392 |
+
self.model_weights = self.model_path
|
| 393 |
+
self.model_path = client.get_local_dir()
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
def get_hf_text_config(config: PretrainedConfig):
|
| 397 |
+
"""Get the "sub" config relevant to llm for multi modal models.
|
| 398 |
+
No op for pure text models.
|
| 399 |
+
"""
|
| 400 |
+
class_name = config.architectures[0]
|
| 401 |
+
if class_name.startswith("Llava") and class_name.endswith("ForCausalLM"):
|
| 402 |
+
# We support non-hf version of llava models, so we do not want to
|
| 403 |
+
# read the wrong values from the unused default text_config.
|
| 404 |
+
# NOTE(HandH1998): We set `torch_dtype` of config to `torch.float16` for the weights, as
|
| 405 |
+
# `torch.float16` is default used for image features in `python/sglang/srt/models/llava.py`.
|
| 406 |
+
setattr(config, "torch_dtype", torch.float16)
|
| 407 |
+
return config
|
| 408 |
+
|
| 409 |
+
if hasattr(config, "text_config"):
|
| 410 |
+
# The code operates under the assumption that text_config should have
|
| 411 |
+
# `num_attention_heads` (among others). Assert here to fail early
|
| 412 |
+
# if transformers config doesn't align with this assumption.
|
| 413 |
+
assert hasattr(config.text_config, "num_attention_heads")
|
| 414 |
+
return config.text_config
|
| 415 |
+
if hasattr(config, "language_config"):
|
| 416 |
+
return config.language_config
|
| 417 |
+
else:
|
| 418 |
+
return config
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
# adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/config.py
|
| 422 |
+
_STR_DTYPE_TO_TORCH_DTYPE = {
|
| 423 |
+
"half": torch.float16,
|
| 424 |
+
"float16": torch.float16,
|
| 425 |
+
"float": torch.float32,
|
| 426 |
+
"float32": torch.float32,
|
| 427 |
+
"bfloat16": torch.bfloat16,
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
|
| 431 |
+
# adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/config.py
|
| 432 |
+
def _get_and_verify_dtype(
|
| 433 |
+
config: PretrainedConfig,
|
| 434 |
+
dtype: Union[str, torch.dtype],
|
| 435 |
+
) -> torch.dtype:
|
| 436 |
+
# NOTE: getattr(config, "torch_dtype", torch.float32) is not correct
|
| 437 |
+
# because config.torch_dtype can be None.
|
| 438 |
+
config_dtype = getattr(config, "torch_dtype", None)
|
| 439 |
+
if config_dtype is None:
|
| 440 |
+
config_dtype = torch.float32
|
| 441 |
+
|
| 442 |
+
if isinstance(dtype, str):
|
| 443 |
+
dtype = dtype.lower()
|
| 444 |
+
if dtype == "auto":
|
| 445 |
+
if config_dtype == torch.float32:
|
| 446 |
+
if config.model_type.startswith("gemma"):
|
| 447 |
+
if config.model_type == "gemma":
|
| 448 |
+
gemma_version = ""
|
| 449 |
+
else:
|
| 450 |
+
gemma_version = config.model_type[5]
|
| 451 |
+
logger.info(
|
| 452 |
+
f"For Gemma {gemma_version}, we downcast float32 to bfloat16 instead "
|
| 453 |
+
"of float16 by default. Please specify `dtype` if you "
|
| 454 |
+
"want to use float16."
|
| 455 |
+
)
|
| 456 |
+
torch_dtype = torch.bfloat16
|
| 457 |
+
else:
|
| 458 |
+
# Following the common practice, we use float16 for float32
|
| 459 |
+
# models.
|
| 460 |
+
torch_dtype = torch.float16
|
| 461 |
+
else:
|
| 462 |
+
torch_dtype = config_dtype
|
| 463 |
+
else:
|
| 464 |
+
if dtype not in _STR_DTYPE_TO_TORCH_DTYPE:
|
| 465 |
+
raise ValueError(f"Unknown dtype: {dtype}")
|
| 466 |
+
torch_dtype = _STR_DTYPE_TO_TORCH_DTYPE[dtype]
|
| 467 |
+
elif isinstance(dtype, torch.dtype):
|
| 468 |
+
torch_dtype = dtype
|
| 469 |
+
else:
|
| 470 |
+
raise ValueError(f"Unknown dtype: {dtype}")
|
| 471 |
+
|
| 472 |
+
# Verify the dtype.
|
| 473 |
+
if torch_dtype != config_dtype:
|
| 474 |
+
if torch_dtype == torch.float32:
|
| 475 |
+
# Upcasting to float32 is allowed.
|
| 476 |
+
logger.info("Upcasting %s to %s.", config_dtype, torch_dtype)
|
| 477 |
+
pass
|
| 478 |
+
elif config_dtype == torch.float32:
|
| 479 |
+
# Downcasting from float32 to float16 or bfloat16 is allowed.
|
| 480 |
+
logger.info("Downcasting %s to %s.", config_dtype, torch_dtype)
|
| 481 |
+
pass
|
| 482 |
+
else:
|
| 483 |
+
# Casting between float16 and bfloat16 is allowed with a warning.
|
| 484 |
+
logger.warning("Casting %s to %s.", config_dtype, torch_dtype)
|
| 485 |
+
|
| 486 |
+
return torch_dtype
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
def is_generation_model(model_architectures: List[str], is_embedding: bool = False):
|
| 490 |
+
# We have two ways to determine whether a model is a generative model.
|
| 491 |
+
# 1. Check the model architecture
|
| 492 |
+
# 2. check the `is_embedding` server args
|
| 493 |
+
|
| 494 |
+
if (
|
| 495 |
+
"LlamaEmbeddingModel" in model_architectures
|
| 496 |
+
or "MistralModel" in model_architectures
|
| 497 |
+
or "LlamaForSequenceClassification" in model_architectures
|
| 498 |
+
or "LlamaForSequenceClassificationWithNormal_Weights" in model_architectures
|
| 499 |
+
or "InternLM2ForRewardModel" in model_architectures
|
| 500 |
+
or "Qwen2ForRewardModel" in model_architectures
|
| 501 |
+
or "Qwen2ForSequenceClassification" in model_architectures
|
| 502 |
+
or "CLIPModel" in model_architectures
|
| 503 |
+
):
|
| 504 |
+
return False
|
| 505 |
+
else:
|
| 506 |
+
return not is_embedding
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
multimodal_model_archs = [
|
| 510 |
+
"DeepseekVL2ForCausalLM",
|
| 511 |
+
"Gemma3ForConditionalGeneration",
|
| 512 |
+
"Grok1VForCausalLM",
|
| 513 |
+
"Grok1AForCausalLM",
|
| 514 |
+
"LlavaLlamaForCausalLM",
|
| 515 |
+
"Llama4ForConditionalGeneration",
|
| 516 |
+
"LlavaMistralForCausalLM",
|
| 517 |
+
"LlavaQwenForCausalLM",
|
| 518 |
+
"LlavaVidForCausalLM",
|
| 519 |
+
"MiniCPMO",
|
| 520 |
+
"MiniCPMV",
|
| 521 |
+
"MultiModalityCausalLM",
|
| 522 |
+
"MllamaForConditionalGeneration",
|
| 523 |
+
"Qwen2VLForConditionalGeneration",
|
| 524 |
+
"Qwen2_5_VLForConditionalGeneration",
|
| 525 |
+
"CLIPModel",
|
| 526 |
+
]
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
def is_multimodal_model(model_architectures: List[str]):
|
| 530 |
+
if any(
|
| 531 |
+
multi_model_arch in model_architectures
|
| 532 |
+
for multi_model_arch in multimodal_model_archs
|
| 533 |
+
):
|
| 534 |
+
return True
|
| 535 |
+
else:
|
| 536 |
+
return False
|
| 537 |
+
|
| 538 |
+
|
| 539 |
+
def is_multimodal_gen_model(model_architectures: List[str]):
|
| 540 |
+
return False
|
| 541 |
+
|
| 542 |
+
|
| 543 |
+
def is_image_gen_model(model_architectures: List[str]):
|
| 544 |
+
return False
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
def is_audio_model(model_architectures: List[str]):
|
| 548 |
+
return False
|
| 549 |
+
|
| 550 |
+
|
| 551 |
+
def is_encoder_decoder_model(model_architectures: List[str]):
|
| 552 |
+
return "MllamaForConditionalGeneration" in model_architectures
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
def yarn_get_mscale(scale: float = 1, mscale: float = 1) -> float:
|
| 556 |
+
if scale <= 1:
|
| 557 |
+
return 1.0
|
| 558 |
+
return 0.1 * mscale * math.log(scale) + 1.0
|
lib/python3.12/site-packages/sglang/srt/configs/utils.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Type
|
| 2 |
+
|
| 3 |
+
from transformers import (
|
| 4 |
+
AutoImageProcessor,
|
| 5 |
+
AutoProcessor,
|
| 6 |
+
BaseImageProcessor,
|
| 7 |
+
PretrainedConfig,
|
| 8 |
+
ProcessorMixin,
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def register_image_processor(
|
| 13 |
+
config: Type[PretrainedConfig], image_processor: Type[BaseImageProcessor]
|
| 14 |
+
):
|
| 15 |
+
"""
|
| 16 |
+
register customized hf image processor while removing hf impl
|
| 17 |
+
"""
|
| 18 |
+
AutoImageProcessor.register(config, None, image_processor, None, exist_ok=True)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def register_processor(config: Type[PretrainedConfig], processor: Type[ProcessorMixin]):
|
| 22 |
+
"""
|
| 23 |
+
register customized hf processor while removing hf impl
|
| 24 |
+
"""
|
| 25 |
+
AutoProcessor.register(config, processor, exist_ok=True)
|
lib/python3.12/site-packages/sglang/srt/connector/__init__.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import enum
|
| 4 |
+
import logging
|
| 5 |
+
|
| 6 |
+
from sglang.srt.connector.base_connector import (
|
| 7 |
+
BaseConnector,
|
| 8 |
+
BaseFileConnector,
|
| 9 |
+
BaseKVConnector,
|
| 10 |
+
)
|
| 11 |
+
from sglang.srt.connector.redis import RedisConnector
|
| 12 |
+
from sglang.srt.connector.s3 import S3Connector
|
| 13 |
+
from sglang.srt.utils import parse_connector_type
|
| 14 |
+
|
| 15 |
+
logger = logging.getLogger(__name__)
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class ConnectorType(str, enum.Enum):
|
| 19 |
+
FS = "filesystem"
|
| 20 |
+
KV = "KV"
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def create_remote_connector(url, device="cpu") -> BaseConnector:
|
| 24 |
+
connector_type = parse_connector_type(url)
|
| 25 |
+
if connector_type == "redis":
|
| 26 |
+
return RedisConnector(url)
|
| 27 |
+
elif connector_type == "s3":
|
| 28 |
+
return S3Connector(url)
|
| 29 |
+
else:
|
| 30 |
+
raise ValueError(f"Invalid connector type: {url}")
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def get_connector_type(client: BaseConnector) -> ConnectorType:
|
| 34 |
+
if isinstance(client, BaseKVConnector):
|
| 35 |
+
return ConnectorType.KV
|
| 36 |
+
if isinstance(client, BaseFileConnector):
|
| 37 |
+
return ConnectorType.FS
|
| 38 |
+
|
| 39 |
+
raise ValueError(f"Invalid connector type: {client}")
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
__all__ = [
|
| 43 |
+
"BaseConnector",
|
| 44 |
+
"BaseFileConnector",
|
| 45 |
+
"BaseKVConnector",
|
| 46 |
+
"RedisConnector",
|
| 47 |
+
"S3Connector",
|
| 48 |
+
"ConnectorType",
|
| 49 |
+
"create_remote_connector",
|
| 50 |
+
"get_connector_type",
|
| 51 |
+
]
|
lib/python3.12/site-packages/sglang/srt/connector/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (1.79 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/__pycache__/base_connector.cpython-312.pyc
ADDED
|
Binary file (5.7 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/__pycache__/redis.cpython-312.pyc
ADDED
|
Binary file (4.92 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/__pycache__/s3.cpython-312.pyc
ADDED
|
Binary file (6.16 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/__pycache__/utils.cpython-312.pyc
ADDED
|
Binary file (1.9 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/base_connector.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import shutil
|
| 5 |
+
import signal
|
| 6 |
+
import tempfile
|
| 7 |
+
from abc import ABC, abstractmethod
|
| 8 |
+
from typing import Generator, List, Optional, Tuple
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class BaseConnector(ABC):
|
| 14 |
+
"""
|
| 15 |
+
For fs connector such as s3:
|
| 16 |
+
<connector_type>://<path>/<filename>
|
| 17 |
+
|
| 18 |
+
For kv connector such as redis:
|
| 19 |
+
<connector_type>://<host>:<port>/<model_name>/keys/<key>
|
| 20 |
+
<connector_type://<host>:<port>/<model_name>/files/<filename>
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
def __init__(self, url: str, device: torch.device = "cpu"):
|
| 24 |
+
self.url = url
|
| 25 |
+
self.device = device
|
| 26 |
+
self.closed = False
|
| 27 |
+
self.local_dir = tempfile.mkdtemp()
|
| 28 |
+
for sig in (signal.SIGINT, signal.SIGTERM):
|
| 29 |
+
existing_handler = signal.getsignal(sig)
|
| 30 |
+
signal.signal(sig, self._close_by_signal(existing_handler))
|
| 31 |
+
|
| 32 |
+
def get_local_dir(self):
|
| 33 |
+
return self.local_dir
|
| 34 |
+
|
| 35 |
+
@abstractmethod
|
| 36 |
+
def weight_iterator(
|
| 37 |
+
self, rank: int = 0
|
| 38 |
+
) -> Generator[Tuple[str, torch.Tensor], None, None]:
|
| 39 |
+
raise NotImplementedError()
|
| 40 |
+
|
| 41 |
+
@abstractmethod
|
| 42 |
+
def pull_files(
|
| 43 |
+
self,
|
| 44 |
+
allow_pattern: Optional[List[str]] = None,
|
| 45 |
+
ignore_pattern: Optional[List[str]] = None,
|
| 46 |
+
) -> None:
|
| 47 |
+
raise NotImplementedError()
|
| 48 |
+
|
| 49 |
+
def close(self):
|
| 50 |
+
if self.closed:
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
self.closed = True
|
| 54 |
+
if os.path.exists(self.local_dir):
|
| 55 |
+
shutil.rmtree(self.local_dir)
|
| 56 |
+
|
| 57 |
+
def __enter__(self):
|
| 58 |
+
return self
|
| 59 |
+
|
| 60 |
+
def __exit__(self, exc_type, exc_value, traceback):
|
| 61 |
+
self.close()
|
| 62 |
+
|
| 63 |
+
def __del__(self):
|
| 64 |
+
self.close()
|
| 65 |
+
|
| 66 |
+
def _close_by_signal(self, existing_handler=None):
|
| 67 |
+
|
| 68 |
+
def new_handler(signum, frame):
|
| 69 |
+
self.close()
|
| 70 |
+
if existing_handler:
|
| 71 |
+
existing_handler(signum, frame)
|
| 72 |
+
|
| 73 |
+
return new_handler
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class BaseKVConnector(BaseConnector):
|
| 77 |
+
|
| 78 |
+
@abstractmethod
|
| 79 |
+
def get(self, key: str) -> Optional[torch.Tensor]:
|
| 80 |
+
raise NotImplementedError()
|
| 81 |
+
|
| 82 |
+
@abstractmethod
|
| 83 |
+
def getstr(self, key: str) -> Optional[str]:
|
| 84 |
+
raise NotImplementedError()
|
| 85 |
+
|
| 86 |
+
@abstractmethod
|
| 87 |
+
def set(self, key: str, obj: torch.Tensor) -> None:
|
| 88 |
+
raise NotImplementedError()
|
| 89 |
+
|
| 90 |
+
@abstractmethod
|
| 91 |
+
def setstr(self, key: str, obj: str) -> None:
|
| 92 |
+
raise NotImplementedError()
|
| 93 |
+
|
| 94 |
+
@abstractmethod
|
| 95 |
+
def list(self, prefix: str) -> List[str]:
|
| 96 |
+
raise NotImplementedError()
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
class BaseFileConnector(BaseConnector):
|
| 100 |
+
"""
|
| 101 |
+
List full file names from remote fs path and filter by allow pattern.
|
| 102 |
+
|
| 103 |
+
Args:
|
| 104 |
+
allow_pattern: A list of patterns of which files to pull.
|
| 105 |
+
|
| 106 |
+
Returns:
|
| 107 |
+
list[str]: List of full paths allowed by the pattern
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
@abstractmethod
|
| 111 |
+
def glob(self, allow_pattern: str) -> List[str]:
|
| 112 |
+
raise NotImplementedError()
|
lib/python3.12/site-packages/sglang/srt/connector/redis.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import logging
|
| 4 |
+
from typing import Generator, List, Optional, Tuple
|
| 5 |
+
from urllib.parse import urlparse
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
|
| 9 |
+
from sglang.srt.connector import BaseKVConnector
|
| 10 |
+
from sglang.srt.connector.serde import create_serde
|
| 11 |
+
from sglang.srt.connector.utils import pull_files_from_db
|
| 12 |
+
|
| 13 |
+
logger = logging.getLogger(__name__)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class RedisConnector(BaseKVConnector):
|
| 17 |
+
|
| 18 |
+
def __init__(self, url: str, device: torch.device = "cpu"):
|
| 19 |
+
import redis
|
| 20 |
+
|
| 21 |
+
super().__init__(url, device)
|
| 22 |
+
parsed_url = urlparse(url)
|
| 23 |
+
self.connection = redis.Redis(host=parsed_url.hostname, port=parsed_url.port)
|
| 24 |
+
self.model_name = parsed_url.path.lstrip("/")
|
| 25 |
+
# TODO: more serde options
|
| 26 |
+
self.s, self.d = create_serde("safe")
|
| 27 |
+
|
| 28 |
+
def get(self, key: str) -> Optional[torch.Tensor]:
|
| 29 |
+
val = self.connection.get(key)
|
| 30 |
+
|
| 31 |
+
if val is None:
|
| 32 |
+
logger.error("Key %s not found", key)
|
| 33 |
+
return None
|
| 34 |
+
|
| 35 |
+
return self.d.from_bytes(val)
|
| 36 |
+
|
| 37 |
+
def getstr(self, key: str) -> Optional[str]:
|
| 38 |
+
val = self.connection.get(key)
|
| 39 |
+
if val is None:
|
| 40 |
+
logger.error("Key %s not found", key)
|
| 41 |
+
return None
|
| 42 |
+
|
| 43 |
+
return val.decode("utf-8")
|
| 44 |
+
|
| 45 |
+
def set(self, key: str, tensor: torch.Tensor) -> None:
|
| 46 |
+
assert tensor is not None
|
| 47 |
+
self.connection.set(key, self.s.to_bytes(tensor))
|
| 48 |
+
|
| 49 |
+
def setstr(self, key: str, obj: str) -> None:
|
| 50 |
+
self.connection.set(key, obj)
|
| 51 |
+
|
| 52 |
+
def list(self, prefix: str) -> List[str]:
|
| 53 |
+
cursor = 0
|
| 54 |
+
all_keys: List[bytes] = []
|
| 55 |
+
|
| 56 |
+
while True:
|
| 57 |
+
ret: Tuple[int, List[bytes]] = self.connection.scan(
|
| 58 |
+
cursor=cursor, match=f"{prefix}*"
|
| 59 |
+
) # type: ignore
|
| 60 |
+
cursor, keys = ret
|
| 61 |
+
all_keys.extend(keys)
|
| 62 |
+
if cursor == 0:
|
| 63 |
+
break
|
| 64 |
+
|
| 65 |
+
return [key.decode("utf-8") for key in all_keys]
|
| 66 |
+
|
| 67 |
+
def weight_iterator(
|
| 68 |
+
self, rank: int = 0
|
| 69 |
+
) -> Generator[Tuple[str, bytes], None, None]:
|
| 70 |
+
keys = self.list(f"{self.model_name}/keys/rank_{rank}/")
|
| 71 |
+
for key in keys:
|
| 72 |
+
val = self.get(key)
|
| 73 |
+
key = key.removeprefix(f"{self.model_name}/keys/rank_{rank}/")
|
| 74 |
+
yield key, val
|
| 75 |
+
|
| 76 |
+
def pull_files(
|
| 77 |
+
self,
|
| 78 |
+
allow_pattern: Optional[List[str]] = None,
|
| 79 |
+
ignore_pattern: Optional[List[str]] = None,
|
| 80 |
+
) -> None:
|
| 81 |
+
pull_files_from_db(self, self.model_name, allow_pattern, ignore_pattern)
|
| 82 |
+
|
| 83 |
+
def close(self):
|
| 84 |
+
self.connection.close()
|
| 85 |
+
super().close()
|
lib/python3.12/site-packages/sglang/srt/connector/s3.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import fnmatch
|
| 4 |
+
import os
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
from typing import Generator, Optional, Tuple
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
|
| 10 |
+
from sglang.srt.connector import BaseFileConnector
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def _filter_allow(paths: list[str], patterns: list[str]) -> list[str]:
|
| 14 |
+
return [
|
| 15 |
+
path
|
| 16 |
+
for path in paths
|
| 17 |
+
if any(fnmatch.fnmatch(path, pattern) for pattern in patterns)
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def _filter_ignore(paths: list[str], patterns: list[str]) -> list[str]:
|
| 22 |
+
return [
|
| 23 |
+
path
|
| 24 |
+
for path in paths
|
| 25 |
+
if not any(fnmatch.fnmatch(path, pattern) for pattern in patterns)
|
| 26 |
+
]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def list_files(
|
| 30 |
+
s3,
|
| 31 |
+
path: str,
|
| 32 |
+
allow_pattern: Optional[list[str]] = None,
|
| 33 |
+
ignore_pattern: Optional[list[str]] = None,
|
| 34 |
+
) -> tuple[str, str, list[str]]:
|
| 35 |
+
"""
|
| 36 |
+
List files from S3 path and filter by pattern.
|
| 37 |
+
|
| 38 |
+
Args:
|
| 39 |
+
s3: S3 client to use.
|
| 40 |
+
path: The S3 path to list from.
|
| 41 |
+
allow_pattern: A list of patterns of which files to pull.
|
| 42 |
+
ignore_pattern: A list of patterns of which files not to pull.
|
| 43 |
+
|
| 44 |
+
Returns:
|
| 45 |
+
tuple[str, str, list[str]]: A tuple where:
|
| 46 |
+
- The first element is the bucket name
|
| 47 |
+
- The second element is string represent the bucket
|
| 48 |
+
and the prefix as a dir like string
|
| 49 |
+
- The third element is a list of files allowed or
|
| 50 |
+
disallowed by pattern
|
| 51 |
+
"""
|
| 52 |
+
parts = path.removeprefix("s3://").split("/")
|
| 53 |
+
prefix = "/".join(parts[1:])
|
| 54 |
+
bucket_name = parts[0]
|
| 55 |
+
|
| 56 |
+
objects = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
|
| 57 |
+
paths = [obj["Key"] for obj in objects.get("Contents", [])]
|
| 58 |
+
|
| 59 |
+
paths = _filter_ignore(paths, ["*/"])
|
| 60 |
+
if allow_pattern is not None:
|
| 61 |
+
paths = _filter_allow(paths, allow_pattern)
|
| 62 |
+
|
| 63 |
+
if ignore_pattern is not None:
|
| 64 |
+
paths = _filter_ignore(paths, ignore_pattern)
|
| 65 |
+
|
| 66 |
+
return bucket_name, prefix, paths
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
class S3Connector(BaseFileConnector):
|
| 70 |
+
|
| 71 |
+
def __init__(self, url: str) -> None:
|
| 72 |
+
import boto3
|
| 73 |
+
|
| 74 |
+
super().__init__(url)
|
| 75 |
+
self.client = boto3.client("s3")
|
| 76 |
+
|
| 77 |
+
def glob(self, allow_pattern: Optional[list[str]] = None) -> list[str]:
|
| 78 |
+
bucket_name, _, paths = list_files(
|
| 79 |
+
self.client, path=self.url, allow_pattern=allow_pattern
|
| 80 |
+
)
|
| 81 |
+
return [f"s3://{bucket_name}/{path}" for path in paths]
|
| 82 |
+
|
| 83 |
+
def pull_files(
|
| 84 |
+
self,
|
| 85 |
+
allow_pattern: Optional[list[str]] = None,
|
| 86 |
+
ignore_pattern: Optional[list[str]] = None,
|
| 87 |
+
) -> None:
|
| 88 |
+
"""
|
| 89 |
+
Pull files from S3 storage into the temporary directory.
|
| 90 |
+
|
| 91 |
+
Args:
|
| 92 |
+
s3_model_path: The S3 path of the model.
|
| 93 |
+
allow_pattern: A list of patterns of which files to pull.
|
| 94 |
+
ignore_pattern: A list of patterns of which files not to pull.
|
| 95 |
+
|
| 96 |
+
"""
|
| 97 |
+
bucket_name, base_dir, files = list_files(
|
| 98 |
+
self.client, self.url, allow_pattern, ignore_pattern
|
| 99 |
+
)
|
| 100 |
+
if len(files) == 0:
|
| 101 |
+
return
|
| 102 |
+
|
| 103 |
+
for file in files:
|
| 104 |
+
destination_file = os.path.join(self.local_dir, file.removeprefix(base_dir))
|
| 105 |
+
local_dir = Path(destination_file).parent
|
| 106 |
+
os.makedirs(local_dir, exist_ok=True)
|
| 107 |
+
self.client.download_file(bucket_name, file, destination_file)
|
| 108 |
+
|
| 109 |
+
def weight_iterator(
|
| 110 |
+
self, rank: int = 0
|
| 111 |
+
) -> Generator[Tuple[str, torch.Tensor], None, None]:
|
| 112 |
+
from sglang.srt.model_loader.weight_utils import (
|
| 113 |
+
runai_safetensors_weights_iterator,
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
# only support safetensor files now
|
| 117 |
+
hf_weights_files = self.glob(allow_pattern=["*.safetensors"])
|
| 118 |
+
return runai_safetensors_weights_iterator(hf_weights_files)
|
| 119 |
+
|
| 120 |
+
def close(self):
|
| 121 |
+
self.client.close()
|
| 122 |
+
super().close()
|
lib/python3.12/site-packages/sglang/srt/connector/serde/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
# inspired by LMCache
|
| 4 |
+
from typing import Optional, Tuple
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
|
| 8 |
+
from sglang.srt.connector.serde.safe_serde import SafeDeserializer, SafeSerializer
|
| 9 |
+
from sglang.srt.connector.serde.serde import Deserializer, Serializer
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def create_serde(serde_type: str) -> Tuple[Serializer, Deserializer]:
|
| 13 |
+
s: Optional[Serializer] = None
|
| 14 |
+
d: Optional[Deserializer] = None
|
| 15 |
+
|
| 16 |
+
if serde_type == "safe":
|
| 17 |
+
s = SafeSerializer()
|
| 18 |
+
d = SafeDeserializer(torch.uint8)
|
| 19 |
+
else:
|
| 20 |
+
raise ValueError(f"Unknown serde type: {serde_type}")
|
| 21 |
+
|
| 22 |
+
return s, d
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
__all__ = [
|
| 26 |
+
"Serializer",
|
| 27 |
+
"Deserializer",
|
| 28 |
+
"SafeSerializer",
|
| 29 |
+
"SafeDeserializer",
|
| 30 |
+
"create_serde",
|
| 31 |
+
]
|
lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (966 Bytes). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/safe_serde.cpython-312.pyc
ADDED
|
Binary file (2.2 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/serde/__pycache__/serde.cpython-312.pyc
ADDED
|
Binary file (1.88 kB). View file
|
|
|
lib/python3.12/site-packages/sglang/srt/connector/serde/safe_serde.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
from typing import Union
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from safetensors.torch import load, save
|
| 7 |
+
|
| 8 |
+
from sglang.srt.connector.serde.serde import Deserializer, Serializer
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class SafeSerializer(Serializer):
|
| 12 |
+
|
| 13 |
+
def __init__(self):
|
| 14 |
+
super().__init__()
|
| 15 |
+
|
| 16 |
+
def to_bytes(self, t: torch.Tensor) -> bytes:
|
| 17 |
+
return save({"tensor_bytes": t.cpu().contiguous()})
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class SafeDeserializer(Deserializer):
|
| 21 |
+
|
| 22 |
+
def __init__(self, dtype):
|
| 23 |
+
super().__init__(dtype)
|
| 24 |
+
|
| 25 |
+
def from_bytes_normal(self, b: Union[bytearray, bytes]) -> torch.Tensor:
|
| 26 |
+
return load(bytes(b))["tensor_bytes"].to(dtype=self.dtype)
|
| 27 |
+
|
| 28 |
+
def from_bytes(self, b: Union[bytearray, bytes]) -> torch.Tensor:
|
| 29 |
+
return self.from_bytes_normal(b)
|
lib/python3.12/site-packages/sglang/srt/connector/serde/serde.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import abc
|
| 4 |
+
from abc import ABC, abstractmethod
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Serializer(ABC):
|
| 10 |
+
|
| 11 |
+
@abstractmethod
|
| 12 |
+
def to_bytes(self, t: torch.Tensor) -> bytes:
|
| 13 |
+
"""
|
| 14 |
+
Serialize a pytorch tensor to bytes. The serialized bytes should contain
|
| 15 |
+
both the data and the metadata (shape, dtype, etc.) of the tensor.
|
| 16 |
+
|
| 17 |
+
Input:
|
| 18 |
+
t: the input pytorch tensor, can be on any device, in any shape,
|
| 19 |
+
with any dtype
|
| 20 |
+
|
| 21 |
+
Returns:
|
| 22 |
+
bytes: the serialized bytes
|
| 23 |
+
"""
|
| 24 |
+
raise NotImplementedError
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class Deserializer(metaclass=abc.ABCMeta):
|
| 28 |
+
|
| 29 |
+
def __init__(self, dtype):
|
| 30 |
+
self.dtype = dtype
|
| 31 |
+
|
| 32 |
+
@abstractmethod
|
| 33 |
+
def from_bytes(self, bs: bytes) -> torch.Tensor:
|
| 34 |
+
"""
|
| 35 |
+
Deserialize a pytorch tensor from bytes.
|
| 36 |
+
|
| 37 |
+
Input:
|
| 38 |
+
bytes: a stream of bytes
|
| 39 |
+
|
| 40 |
+
Output:
|
| 41 |
+
torch.Tensor: the deserialized pytorch tensor
|
| 42 |
+
"""
|
| 43 |
+
raise NotImplementedError
|
lib/python3.12/site-packages/sglang/srt/connector/utils.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from typing import Optional
|
| 6 |
+
from urllib.parse import urlparse
|
| 7 |
+
|
| 8 |
+
from sglang.srt.connector import BaseConnector
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def parse_model_name(url: str) -> str:
|
| 12 |
+
"""
|
| 13 |
+
Parse the model name from the url.
|
| 14 |
+
Only used for db connector
|
| 15 |
+
"""
|
| 16 |
+
parsed_url = urlparse(url)
|
| 17 |
+
return parsed_url.path.lstrip("/")
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def pull_files_from_db(
|
| 21 |
+
connector: BaseConnector,
|
| 22 |
+
model_name: str,
|
| 23 |
+
allow_pattern: Optional[list[str]] = None,
|
| 24 |
+
ignore_pattern: Optional[list[str]] = None,
|
| 25 |
+
) -> None:
|
| 26 |
+
prefix = f"{model_name}/files/"
|
| 27 |
+
local_dir = connector.get_local_dir()
|
| 28 |
+
files = connector.list(prefix)
|
| 29 |
+
|
| 30 |
+
for file in files:
|
| 31 |
+
destination_file = os.path.join(local_dir, file.removeprefix(prefix))
|
| 32 |
+
local_dir = Path(destination_file).parent
|
| 33 |
+
os.makedirs(local_dir, exist_ok=True)
|
| 34 |
+
with open(destination_file, "wb") as f:
|
| 35 |
+
f.write(connector.getstr(file).encode("utf-8"))
|
lib/python3.12/site-packages/sglang/srt/layers/activation.py
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023-2024 SGLang Team
|
| 2 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 3 |
+
# you may not use this file except in compliance with the License.
|
| 4 |
+
# You may obtain a copy of the License at
|
| 5 |
+
#
|
| 6 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 7 |
+
#
|
| 8 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 9 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 10 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 11 |
+
# See the License for the specific language governing permissions and
|
| 12 |
+
# limitations under the License.
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
"""Fused operators for activation layers."""
|
| 15 |
+
|
| 16 |
+
import logging
|
| 17 |
+
import math
|
| 18 |
+
from typing import Optional
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
import torch.nn as nn
|
| 22 |
+
import torch.nn.functional as F
|
| 23 |
+
|
| 24 |
+
from sglang.srt.custom_op import CustomOp
|
| 25 |
+
from sglang.srt.distributed import (
|
| 26 |
+
divide,
|
| 27 |
+
get_tensor_model_parallel_rank,
|
| 28 |
+
get_tensor_model_parallel_world_size,
|
| 29 |
+
)
|
| 30 |
+
from sglang.srt.layers.quantization.base_config import QuantizationConfig
|
| 31 |
+
from sglang.srt.utils import is_cuda, set_weight_attrs
|
| 32 |
+
|
| 33 |
+
_is_cuda = is_cuda()
|
| 34 |
+
|
| 35 |
+
if _is_cuda:
|
| 36 |
+
from sgl_kernel import gelu_and_mul, gelu_tanh_and_mul, silu_and_mul
|
| 37 |
+
|
| 38 |
+
logger = logging.getLogger(__name__)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class SiluAndMul(CustomOp):
|
| 42 |
+
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
|
| 43 |
+
d = x.shape[-1] // 2
|
| 44 |
+
return F.silu(x[..., :d]) * x[..., d:]
|
| 45 |
+
|
| 46 |
+
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
|
| 47 |
+
d = x.shape[-1] // 2
|
| 48 |
+
output_shape = x.shape[:-1] + (d,)
|
| 49 |
+
out = torch.empty(output_shape, dtype=x.dtype, device=x.device)
|
| 50 |
+
silu_and_mul(x, out)
|
| 51 |
+
return out
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class GeluAndMul(CustomOp):
|
| 55 |
+
def __init__(self, approximate="tanh"):
|
| 56 |
+
super().__init__()
|
| 57 |
+
self.approximate = approximate
|
| 58 |
+
|
| 59 |
+
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
|
| 60 |
+
d = x.shape[-1] // 2
|
| 61 |
+
return F.gelu(x[..., :d], approximate=self.approximate) * x[..., d:]
|
| 62 |
+
|
| 63 |
+
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
|
| 64 |
+
d = x.shape[-1] // 2
|
| 65 |
+
output_shape = x.shape[:-1] + (d,)
|
| 66 |
+
out = torch.empty(output_shape, dtype=x.dtype, device=x.device)
|
| 67 |
+
if self.approximate == "tanh":
|
| 68 |
+
gelu_tanh_and_mul(x, out)
|
| 69 |
+
elif self.approximate == "none":
|
| 70 |
+
gelu_and_mul(x, out)
|
| 71 |
+
else:
|
| 72 |
+
raise RuntimeError("GeluAndMul only support tanh or none")
|
| 73 |
+
return out
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class NewGELU(CustomOp):
|
| 77 |
+
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
|
| 78 |
+
c = math.sqrt(2.0 / math.pi)
|
| 79 |
+
return 0.5 * x * (1.0 + torch.tanh(c * (x + 0.044715 * torch.pow(x, 3.0))))
|
| 80 |
+
|
| 81 |
+
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
|
| 82 |
+
# TODO: Implement the CUDA kernel for NewGELU in sgl-kernel
|
| 83 |
+
return self.forward_native(x)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
class QuickGELU(CustomOp):
|
| 87 |
+
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
|
| 88 |
+
return x * torch.sigmoid(1.702 * x)
|
| 89 |
+
|
| 90 |
+
def forward_cuda(self, x: torch.Tensor) -> torch.Tensor:
|
| 91 |
+
# TODO(zhyncs): Implement the CUDA kernel for QuickGELU in sgl-kernel
|
| 92 |
+
return self.forward_native(x)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class ScaledActivation(nn.Module):
|
| 96 |
+
"""An activation function with post-scale parameters.
|
| 97 |
+
|
| 98 |
+
This is used for some quantization methods like AWQ.
|
| 99 |
+
"""
|
| 100 |
+
|
| 101 |
+
def __init__(
|
| 102 |
+
self,
|
| 103 |
+
act_module: nn.Module,
|
| 104 |
+
intermediate_size: int,
|
| 105 |
+
input_is_parallel: bool = True,
|
| 106 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 107 |
+
):
|
| 108 |
+
super().__init__()
|
| 109 |
+
self.act = act_module
|
| 110 |
+
self.input_is_parallel = input_is_parallel
|
| 111 |
+
if input_is_parallel:
|
| 112 |
+
tp_size = get_tensor_model_parallel_world_size()
|
| 113 |
+
intermediate_size_per_partition = divide(intermediate_size, tp_size)
|
| 114 |
+
else:
|
| 115 |
+
intermediate_size_per_partition = intermediate_size
|
| 116 |
+
if params_dtype is None:
|
| 117 |
+
params_dtype = torch.get_default_dtype()
|
| 118 |
+
self.scales = nn.Parameter(
|
| 119 |
+
torch.empty(intermediate_size_per_partition, dtype=params_dtype)
|
| 120 |
+
)
|
| 121 |
+
set_weight_attrs(self.scales, {"weight_loader": self.weight_loader})
|
| 122 |
+
|
| 123 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 124 |
+
return self.act(x) / self.scales
|
| 125 |
+
|
| 126 |
+
def weight_loader(self, param: nn.Parameter, loaded_weight: torch.Tensor):
|
| 127 |
+
param_data = param.data
|
| 128 |
+
if self.input_is_parallel:
|
| 129 |
+
tp_rank = get_tensor_model_parallel_rank()
|
| 130 |
+
shard_size = param_data.shape[0]
|
| 131 |
+
start_idx = tp_rank * shard_size
|
| 132 |
+
loaded_weight = loaded_weight.narrow(0, start_idx, shard_size)
|
| 133 |
+
assert param_data.shape == loaded_weight.shape
|
| 134 |
+
param_data.copy_(loaded_weight)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
_ACTIVATION_REGISTRY = {
|
| 138 |
+
"gelu": nn.GELU(),
|
| 139 |
+
"gelu_pytorch_tanh": nn.GELU(approximate="tanh"),
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def get_act_fn(
|
| 144 |
+
act_fn_name: str,
|
| 145 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 146 |
+
intermediate_size: Optional[int] = None,
|
| 147 |
+
input_is_parallel: bool = True,
|
| 148 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 149 |
+
) -> nn.Module:
|
| 150 |
+
"""Get an activation function by name."""
|
| 151 |
+
act_fn_name = act_fn_name.lower()
|
| 152 |
+
if act_fn_name not in _ACTIVATION_REGISTRY:
|
| 153 |
+
raise ValueError(f"Activation function {act_fn_name!r} is not supported.")
|
| 154 |
+
|
| 155 |
+
act_fn = _ACTIVATION_REGISTRY[act_fn_name]
|
| 156 |
+
if quant_config is not None and act_fn_name in quant_config.get_scaled_act_names():
|
| 157 |
+
if intermediate_size is None:
|
| 158 |
+
raise ValueError(
|
| 159 |
+
"intermediate_size must be specified for scaled "
|
| 160 |
+
"activation functions."
|
| 161 |
+
)
|
| 162 |
+
return ScaledActivation(
|
| 163 |
+
act_fn, intermediate_size, input_is_parallel, params_dtype
|
| 164 |
+
)
|
| 165 |
+
return act_fn
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
if not _is_cuda:
|
| 169 |
+
logger.info(
|
| 170 |
+
"sgl-kernel is not available on Non-NV platforms. Fallback to other kernel libraries."
|
| 171 |
+
)
|
| 172 |
+
from vllm.model_executor.layers.activation import GeluAndMul, SiluAndMul
|
lib/python3.12/site-packages/sglang/srt/layers/dp_attention.py
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import functools
|
| 4 |
+
import logging
|
| 5 |
+
from contextlib import contextmanager
|
| 6 |
+
from typing import TYPE_CHECKING, List
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import triton
|
| 10 |
+
import triton.language as tl
|
| 11 |
+
|
| 12 |
+
from sglang.srt.distributed import (
|
| 13 |
+
GroupCoordinator,
|
| 14 |
+
get_tensor_model_parallel_world_size,
|
| 15 |
+
get_tp_group,
|
| 16 |
+
tensor_model_parallel_all_reduce,
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
logger = logging.getLogger(__name__)
|
| 20 |
+
|
| 21 |
+
if TYPE_CHECKING:
|
| 22 |
+
from sglang.srt.model_executor.forward_batch_info import ForwardBatch
|
| 23 |
+
|
| 24 |
+
_ATTN_TP_GROUP = None
|
| 25 |
+
_ATTN_TP_RANK = None
|
| 26 |
+
_ATTN_TP_SIZE = None
|
| 27 |
+
_DP_RANK = None
|
| 28 |
+
_DP_SIZE = None
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def compute_dp_attention_world_info(enable_dp_attention, tp_rank, tp_size, dp_size):
|
| 32 |
+
if not enable_dp_attention:
|
| 33 |
+
return tp_rank, tp_size, 0
|
| 34 |
+
|
| 35 |
+
attn_tp_size = tp_size // dp_size
|
| 36 |
+
dp_rank = tp_rank // attn_tp_size
|
| 37 |
+
attn_tp_rank = tp_rank % attn_tp_size
|
| 38 |
+
return attn_tp_rank, attn_tp_size, dp_rank
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def initialize_dp_attention(
|
| 42 |
+
enable_dp_attention: bool,
|
| 43 |
+
tp_rank: int,
|
| 44 |
+
tp_size: int,
|
| 45 |
+
dp_size: int,
|
| 46 |
+
):
|
| 47 |
+
global _ATTN_TP_GROUP, _ATTN_TP_RANK, _ATTN_TP_SIZE, _DP_RANK, _DP_SIZE
|
| 48 |
+
|
| 49 |
+
from sglang.srt.layers.sampler import SYNC_TOKEN_IDS_ACROSS_TP
|
| 50 |
+
|
| 51 |
+
_ATTN_TP_RANK, _ATTN_TP_SIZE, _DP_RANK = compute_dp_attention_world_info(
|
| 52 |
+
enable_dp_attention, tp_rank, tp_size, dp_size
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
if enable_dp_attention:
|
| 56 |
+
_DP_SIZE = dp_size
|
| 57 |
+
else:
|
| 58 |
+
_DP_SIZE = 1
|
| 59 |
+
|
| 60 |
+
tp_group = get_tp_group()
|
| 61 |
+
_ATTN_TP_GROUP = GroupCoordinator(
|
| 62 |
+
[
|
| 63 |
+
list(range(head, head + _ATTN_TP_SIZE))
|
| 64 |
+
for head in range(0, tp_size, _ATTN_TP_SIZE)
|
| 65 |
+
],
|
| 66 |
+
tp_group.local_rank,
|
| 67 |
+
torch.distributed.get_backend(tp_group.device_group),
|
| 68 |
+
SYNC_TOKEN_IDS_ACROSS_TP,
|
| 69 |
+
False,
|
| 70 |
+
False,
|
| 71 |
+
False,
|
| 72 |
+
False,
|
| 73 |
+
group_name="attention_tp",
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def get_attention_tp_group():
|
| 78 |
+
assert _ATTN_TP_GROUP is not None, "dp attention not initialized!"
|
| 79 |
+
return _ATTN_TP_GROUP
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def get_attention_tp_rank():
|
| 83 |
+
assert _ATTN_TP_RANK is not None, "dp attention not initialized!"
|
| 84 |
+
return _ATTN_TP_RANK
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def get_attention_tp_size():
|
| 88 |
+
assert _ATTN_TP_SIZE is not None, "dp attention not initialized!"
|
| 89 |
+
return _ATTN_TP_SIZE
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def get_attention_dp_rank():
|
| 93 |
+
assert _DP_RANK is not None, "dp attention not initialized!"
|
| 94 |
+
return _DP_RANK
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def get_attention_dp_size():
|
| 98 |
+
assert _DP_SIZE is not None, "dp attention not initialized!"
|
| 99 |
+
return _DP_SIZE
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
@contextmanager
|
| 103 |
+
def disable_dp_size():
|
| 104 |
+
"""Patch the tp group temporarily until this function ends.
|
| 105 |
+
|
| 106 |
+
This method is for draft workers of speculative decoding to run draft model
|
| 107 |
+
with different tp degree from that of target model workers.
|
| 108 |
+
|
| 109 |
+
Args:
|
| 110 |
+
tp_group (GroupCoordinator): the tp group coordinator
|
| 111 |
+
"""
|
| 112 |
+
global _DP_SIZE
|
| 113 |
+
assert _DP_SIZE is not None, "dp attention not initialized!"
|
| 114 |
+
|
| 115 |
+
old_dp_size = _DP_SIZE
|
| 116 |
+
_DP_SIZE = 1
|
| 117 |
+
try:
|
| 118 |
+
yield
|
| 119 |
+
finally:
|
| 120 |
+
_DP_SIZE = old_dp_size
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def get_dp_local_info(forward_batch: ForwardBatch):
|
| 124 |
+
dp_rank = get_attention_dp_rank()
|
| 125 |
+
|
| 126 |
+
if forward_batch.dp_local_start_pos is None:
|
| 127 |
+
cumtokens = torch.cumsum(forward_batch.global_num_tokens_gpu, dim=0)
|
| 128 |
+
if dp_rank == 0:
|
| 129 |
+
local_start_pos = torch.zeros_like(cumtokens[0])
|
| 130 |
+
else:
|
| 131 |
+
local_start_pos = cumtokens[dp_rank - 1]
|
| 132 |
+
local_num_tokens = forward_batch.global_num_tokens_gpu[dp_rank]
|
| 133 |
+
|
| 134 |
+
forward_batch.dp_local_start_pos = local_start_pos
|
| 135 |
+
forward_batch.dp_local_num_tokens = local_num_tokens
|
| 136 |
+
|
| 137 |
+
return forward_batch.dp_local_start_pos, forward_batch.dp_local_num_tokens
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
@triton.jit
|
| 141 |
+
def memcpy_triton_kernel(
|
| 142 |
+
dst_ptr,
|
| 143 |
+
src_ptr,
|
| 144 |
+
offset_ptr,
|
| 145 |
+
sz_ptr,
|
| 146 |
+
offset_src: tl.constexpr,
|
| 147 |
+
chunk_size, # multiplied for offset and sz
|
| 148 |
+
BLOCK_SIZE: tl.constexpr,
|
| 149 |
+
):
|
| 150 |
+
pid = tl.program_id(axis=0).to(tl.int64)
|
| 151 |
+
offset = tl.load(offset_ptr).to(tl.int64) * chunk_size
|
| 152 |
+
sz = tl.load(sz_ptr).to(tl.int64) * chunk_size
|
| 153 |
+
|
| 154 |
+
start_index = pid * BLOCK_SIZE
|
| 155 |
+
offs = tl.arange(0, BLOCK_SIZE)
|
| 156 |
+
mask = start_index + offs < sz
|
| 157 |
+
|
| 158 |
+
if offset_src:
|
| 159 |
+
data = tl.load(src_ptr + offset + start_index + offs, mask=mask)
|
| 160 |
+
tl.store(dst_ptr + start_index + offs, data, mask=mask)
|
| 161 |
+
else:
|
| 162 |
+
data = tl.load(src_ptr + start_index + offs, mask=mask)
|
| 163 |
+
tl.store(dst_ptr + offset + start_index + offs, data, mask=mask)
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def prod(x):
|
| 167 |
+
return functools.reduce(lambda a, b: a * b, x, 1)
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def memcpy_triton(dst, src, dim, offset, sz, offset_src):
|
| 171 |
+
max_size = min(src.numel(), dst.numel())
|
| 172 |
+
assert dim == 0, "dim != 0 unsupported"
|
| 173 |
+
assert src.shape[1:] == dst.shape[1:], "src and dst must have same shape"
|
| 174 |
+
chunk_size = prod(src.shape[1:])
|
| 175 |
+
BLOCK_SIZE = 8192
|
| 176 |
+
grid = (triton.cdiv(max_size, BLOCK_SIZE),)
|
| 177 |
+
|
| 178 |
+
memcpy_triton_kernel[grid](dst, src, offset, sz, offset_src, chunk_size, BLOCK_SIZE)
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
def _dp_gather(
|
| 182 |
+
global_tokens: torch.Tensor,
|
| 183 |
+
local_tokens: torch.Tensor,
|
| 184 |
+
forward_batch: ForwardBatch,
|
| 185 |
+
is_partial: bool,
|
| 186 |
+
):
|
| 187 |
+
local_start_pos, local_num_tokens = get_dp_local_info(forward_batch)
|
| 188 |
+
|
| 189 |
+
global_tokens.fill_(0)
|
| 190 |
+
assert local_tokens.is_contiguous()
|
| 191 |
+
assert global_tokens.is_contiguous()
|
| 192 |
+
|
| 193 |
+
if local_tokens.shape[0] > 0 and (is_partial or get_attention_tp_rank() == 0):
|
| 194 |
+
assert (
|
| 195 |
+
local_tokens.untyped_storage() is not global_tokens.untyped_storage()
|
| 196 |
+
), "aliasing between global_tokens and local_tokens not allowed"
|
| 197 |
+
memcpy_triton(
|
| 198 |
+
global_tokens, local_tokens, 0, local_start_pos, local_num_tokens, False
|
| 199 |
+
)
|
| 200 |
+
|
| 201 |
+
# Input IDs are in int 32. We should use inplace_all_reduce for local case becaues of custom all reduce.
|
| 202 |
+
NUM_GPUS_PER_NODE = 8
|
| 203 |
+
if (
|
| 204 |
+
not local_tokens.dtype.is_floating_point
|
| 205 |
+
and get_tensor_model_parallel_world_size() <= NUM_GPUS_PER_NODE
|
| 206 |
+
):
|
| 207 |
+
torch.ops.sglang.inplace_all_reduce(
|
| 208 |
+
global_tokens, group_name=get_tp_group().unique_name
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
else:
|
| 212 |
+
global_tokens[:] = tensor_model_parallel_all_reduce(global_tokens)
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def dp_gather_partial(
|
| 216 |
+
global_tokens: torch.Tensor,
|
| 217 |
+
local_tokens: torch.Tensor,
|
| 218 |
+
forward_batch: ForwardBatch,
|
| 219 |
+
):
|
| 220 |
+
_dp_gather(global_tokens, local_tokens, forward_batch, is_partial=True)
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def dp_gather_replicate(
|
| 224 |
+
global_tokens: torch.Tensor,
|
| 225 |
+
local_tokens: torch.Tensor,
|
| 226 |
+
forward_batch: ForwardBatch,
|
| 227 |
+
):
|
| 228 |
+
_dp_gather(global_tokens, local_tokens, forward_batch, is_partial=False)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
def dp_scatter(
|
| 232 |
+
local_tokens: torch.Tensor, # output
|
| 233 |
+
global_tokens: torch.Tensor, # input
|
| 234 |
+
forward_batch: ForwardBatch,
|
| 235 |
+
):
|
| 236 |
+
# local_num_tokens is not necessarily the same as local_tokens.shape[0],
|
| 237 |
+
# since local_tokens may be padded for cuda graph
|
| 238 |
+
local_start_pos, local_num_tokens = get_dp_local_info(forward_batch)
|
| 239 |
+
|
| 240 |
+
local_tokens.fill_(0)
|
| 241 |
+
assert local_tokens.is_contiguous()
|
| 242 |
+
assert global_tokens.is_contiguous()
|
| 243 |
+
if local_tokens.shape[0] > 0:
|
| 244 |
+
assert (
|
| 245 |
+
local_tokens.untyped_storage() is not global_tokens.untyped_storage()
|
| 246 |
+
), "aliasing between local_tokens and global_tokens not allowed"
|
| 247 |
+
memcpy_triton(
|
| 248 |
+
local_tokens, global_tokens, 0, local_start_pos, local_num_tokens, True
|
| 249 |
+
)
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
def tp_reduce_scatter(
|
| 253 |
+
output: torch.Tensor,
|
| 254 |
+
input_list: List[torch.Tensor],
|
| 255 |
+
):
|
| 256 |
+
return get_attention_tp_group().reduce_scatter(output, input_list)
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def tp_all_gather(output_list: List[torch.Tensor], input_: torch.Tensor):
|
| 260 |
+
return get_attention_tp_group().all_gather(input_, tensor_list=output_list)
|
lib/python3.12/site-packages/sglang/srt/layers/elementwise.py
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Tuple
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
import triton
|
| 5 |
+
import triton.language as tl
|
| 6 |
+
|
| 7 |
+
from sglang.srt.utils import is_hip
|
| 8 |
+
|
| 9 |
+
_is_hip = is_hip()
|
| 10 |
+
|
| 11 |
+
fused_softcap_autotune = triton.autotune(
|
| 12 |
+
configs=[
|
| 13 |
+
triton.Config(kwargs={"BLOCK_SIZE": 128}, num_warps=4),
|
| 14 |
+
triton.Config(kwargs={"BLOCK_SIZE": 128}, num_warps=8),
|
| 15 |
+
triton.Config(kwargs={"BLOCK_SIZE": 128}, num_warps=16),
|
| 16 |
+
triton.Config(kwargs={"BLOCK_SIZE": 256}, num_warps=4),
|
| 17 |
+
triton.Config(kwargs={"BLOCK_SIZE": 256}, num_warps=8),
|
| 18 |
+
triton.Config(kwargs={"BLOCK_SIZE": 512}, num_warps=4),
|
| 19 |
+
triton.Config(kwargs={"BLOCK_SIZE": 512}, num_warps=8),
|
| 20 |
+
triton.Config(kwargs={"BLOCK_SIZE": 512}, num_warps=16),
|
| 21 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=4),
|
| 22 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=8),
|
| 23 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=16),
|
| 24 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=32),
|
| 25 |
+
triton.Config(kwargs={"BLOCK_SIZE": 2048}, num_warps=32),
|
| 26 |
+
triton.Config(kwargs={"BLOCK_SIZE": 4096}, num_warps=32),
|
| 27 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=32),
|
| 28 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=32),
|
| 29 |
+
triton.Config(kwargs={"BLOCK_SIZE": 32768}, num_warps=32),
|
| 30 |
+
],
|
| 31 |
+
key=["n_ele"],
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
@triton.jit
|
| 36 |
+
def fused_softcap_kernel(
|
| 37 |
+
output_ptr,
|
| 38 |
+
input_ptr,
|
| 39 |
+
n_ele,
|
| 40 |
+
softcap_const: tl.constexpr,
|
| 41 |
+
BLOCK_SIZE: tl.constexpr,
|
| 42 |
+
):
|
| 43 |
+
pid = tl.program_id(axis=0)
|
| 44 |
+
block_start = pid * BLOCK_SIZE
|
| 45 |
+
offsets = block_start + tl.arange(0, BLOCK_SIZE)
|
| 46 |
+
mask = offsets < n_ele
|
| 47 |
+
x = tl.load(input_ptr + offsets, mask=mask)
|
| 48 |
+
fx = x.to(tl.float32)
|
| 49 |
+
fxs = fx / softcap_const
|
| 50 |
+
exped = tl.exp(2 * fxs)
|
| 51 |
+
top = exped - 1
|
| 52 |
+
bottom = exped + 1
|
| 53 |
+
output = top / bottom * softcap_const
|
| 54 |
+
tl.store(output_ptr + offsets, output, mask=mask)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
fused_softcap_kernel_autotuned = fused_softcap_autotune(fused_softcap_kernel)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def fused_softcap(x, softcap_const, autotune=False):
|
| 61 |
+
output = torch.empty_like(x, dtype=torch.float32)
|
| 62 |
+
n_elements = output.numel()
|
| 63 |
+
if autotune:
|
| 64 |
+
grid = lambda meta: (triton.cdiv(n_elements, meta["BLOCK_SIZE"]),)
|
| 65 |
+
fused_softcap_kernel_autotuned[grid](output, x, n_elements, softcap_const)
|
| 66 |
+
else:
|
| 67 |
+
fused_softcap_kernel[(triton.cdiv(n_elements, 128),)](
|
| 68 |
+
output, x, n_elements, softcap_const, BLOCK_SIZE=128, num_warps=8
|
| 69 |
+
)
|
| 70 |
+
return output
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
# cast to float + softcap
|
| 74 |
+
class Softcap:
|
| 75 |
+
def __init__(self, softcap_const: float):
|
| 76 |
+
self.softcap_const = softcap_const
|
| 77 |
+
|
| 78 |
+
def __call__(self, *args, **kwargs):
|
| 79 |
+
return self.forward(*args, **kwargs)
|
| 80 |
+
|
| 81 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 82 |
+
if x.is_cuda:
|
| 83 |
+
return self.forward_cuda(x)
|
| 84 |
+
else:
|
| 85 |
+
return self.forward_native(x)
|
| 86 |
+
|
| 87 |
+
def forward_native(self, x: torch.Tensor) -> torch.Tensor:
|
| 88 |
+
return torch.tanh(x.float() / self.softcap_const) * self.softcap_const
|
| 89 |
+
|
| 90 |
+
def forward_cuda(self, x: torch.Tensor, autotune=False) -> torch.Tensor:
|
| 91 |
+
return fused_softcap(x, self.softcap_const, autotune=autotune)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
rmsnorm_autotune = triton.autotune(
|
| 95 |
+
configs=[
|
| 96 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=4, num_stages=1),
|
| 97 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=8, num_stages=1),
|
| 98 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=16, num_stages=1),
|
| 99 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=4),
|
| 100 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=8),
|
| 101 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=16),
|
| 102 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=4, num_stages=4),
|
| 103 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=8, num_stages=4),
|
| 104 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=16, num_stages=4),
|
| 105 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=8, num_stages=8),
|
| 106 |
+
triton.Config(kwargs={"BLOCK_SIZE": 1024}, num_warps=16, num_stages=8),
|
| 107 |
+
triton.Config(kwargs={"BLOCK_SIZE": 2048}, num_warps=8),
|
| 108 |
+
triton.Config(kwargs={"BLOCK_SIZE": 2048}, num_warps=16),
|
| 109 |
+
triton.Config(kwargs={"BLOCK_SIZE": 2048}, num_warps=8, num_stages=4),
|
| 110 |
+
triton.Config(kwargs={"BLOCK_SIZE": 2048}, num_warps=16, num_stages=4),
|
| 111 |
+
triton.Config(kwargs={"BLOCK_SIZE": 4096}, num_warps=8),
|
| 112 |
+
triton.Config(kwargs={"BLOCK_SIZE": 4096}, num_warps=16),
|
| 113 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=8),
|
| 114 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=16),
|
| 115 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=32),
|
| 116 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=8, num_stages=1),
|
| 117 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=16, num_stages=1),
|
| 118 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=32, num_stages=1),
|
| 119 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=8, num_stages=4),
|
| 120 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=16, num_stages=4),
|
| 121 |
+
triton.Config(kwargs={"BLOCK_SIZE": 8192}, num_warps=32, num_stages=4),
|
| 122 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=8),
|
| 123 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=16),
|
| 124 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=32),
|
| 125 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=8, num_stages=1),
|
| 126 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=16, num_stages=1),
|
| 127 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=32, num_stages=1),
|
| 128 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=8, num_stages=4),
|
| 129 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=16, num_stages=4),
|
| 130 |
+
triton.Config(kwargs={"BLOCK_SIZE": 16384}, num_warps=32, num_stages=4),
|
| 131 |
+
],
|
| 132 |
+
key=["hidden_dim"],
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
@triton.jit
|
| 137 |
+
def fused_dual_residual_rmsnorm_kernel(
|
| 138 |
+
output_ptr,
|
| 139 |
+
mid_ptr,
|
| 140 |
+
activ_ptr,
|
| 141 |
+
residual_ptr,
|
| 142 |
+
weight1_ptr,
|
| 143 |
+
weight2_ptr,
|
| 144 |
+
eps: tl.constexpr,
|
| 145 |
+
hidden_dim: tl.constexpr,
|
| 146 |
+
BLOCK_SIZE: tl.constexpr,
|
| 147 |
+
):
|
| 148 |
+
pid = tl.program_id(axis=0)
|
| 149 |
+
input_start = pid * hidden_dim
|
| 150 |
+
|
| 151 |
+
offsets = tl.arange(0, BLOCK_SIZE)
|
| 152 |
+
mask = offsets < hidden_dim
|
| 153 |
+
|
| 154 |
+
a_ = tl.load(activ_ptr + input_start + offsets, mask=mask, other=0.0)
|
| 155 |
+
a = a_.to(tl.float32)
|
| 156 |
+
rms = tl.sqrt(tl.sum(a * a, axis=0) / hidden_dim + eps)
|
| 157 |
+
|
| 158 |
+
r = tl.load(residual_ptr + input_start + offsets, mask=mask, other=0.0)
|
| 159 |
+
w1_ = tl.load(weight1_ptr + offsets, mask=mask, other=0.0)
|
| 160 |
+
w1 = w1_.to(tl.float32)
|
| 161 |
+
|
| 162 |
+
a2r = r + (a / rms * w1).to(r.dtype)
|
| 163 |
+
tl.store(
|
| 164 |
+
mid_ptr + input_start + offsets,
|
| 165 |
+
a2r,
|
| 166 |
+
mask=mask,
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
a2r = a2r.to(tl.float32)
|
| 170 |
+
rms2 = tl.sqrt(tl.sum(a2r * a2r, axis=0) / hidden_dim + eps)
|
| 171 |
+
|
| 172 |
+
w2_ = tl.load(weight2_ptr + offsets, mask=mask, other=0.0)
|
| 173 |
+
w2 = w2_.to(tl.float32)
|
| 174 |
+
|
| 175 |
+
tl.store(
|
| 176 |
+
output_ptr + input_start + offsets,
|
| 177 |
+
a2r / rms2 * w2, # implicitly casts to output dtype here
|
| 178 |
+
mask=mask,
|
| 179 |
+
)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
fused_dual_residual_rmsnorm_kernel_autotune = rmsnorm_autotune(
|
| 183 |
+
fused_dual_residual_rmsnorm_kernel
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def fused_dual_residual_rmsnorm(x, residual, weight1, weight2, eps, autotune=False):
|
| 188 |
+
assert len(x.shape) == 2
|
| 189 |
+
assert x.shape == residual.shape and x.dtype == residual.dtype
|
| 190 |
+
output, mid = torch.empty_like(x), torch.empty_like(x)
|
| 191 |
+
bs, hidden_dim = x.shape
|
| 192 |
+
|
| 193 |
+
min_num_warps = 16 if _is_hip else 32
|
| 194 |
+
|
| 195 |
+
if autotune:
|
| 196 |
+
fused_dual_residual_rmsnorm_kernel_autotune[(bs,)](
|
| 197 |
+
output, mid, x, residual, weight1, weight2, eps=eps, hidden_dim=hidden_dim
|
| 198 |
+
)
|
| 199 |
+
else:
|
| 200 |
+
config = {
|
| 201 |
+
"BLOCK_SIZE": triton.next_power_of_2(hidden_dim),
|
| 202 |
+
"num_warps": max(
|
| 203 |
+
min(
|
| 204 |
+
triton.next_power_of_2(triton.cdiv(hidden_dim, 256)), min_num_warps
|
| 205 |
+
),
|
| 206 |
+
4,
|
| 207 |
+
),
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
fused_dual_residual_rmsnorm_kernel[(bs,)](
|
| 211 |
+
output,
|
| 212 |
+
mid,
|
| 213 |
+
x,
|
| 214 |
+
residual,
|
| 215 |
+
weight1,
|
| 216 |
+
weight2,
|
| 217 |
+
eps=eps,
|
| 218 |
+
hidden_dim=hidden_dim,
|
| 219 |
+
**config,
|
| 220 |
+
)
|
| 221 |
+
|
| 222 |
+
return output, mid
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
@triton.jit
|
| 226 |
+
def fused_rmsnorm_kernel(
|
| 227 |
+
output_ptr,
|
| 228 |
+
activ_ptr,
|
| 229 |
+
weight_ptr,
|
| 230 |
+
eps: tl.constexpr,
|
| 231 |
+
hidden_dim: tl.constexpr,
|
| 232 |
+
BLOCK_SIZE: tl.constexpr,
|
| 233 |
+
):
|
| 234 |
+
pid = tl.program_id(axis=0)
|
| 235 |
+
input_start = pid * hidden_dim
|
| 236 |
+
|
| 237 |
+
offsets = tl.arange(0, BLOCK_SIZE)
|
| 238 |
+
mask = offsets < hidden_dim
|
| 239 |
+
|
| 240 |
+
a_ = tl.load(activ_ptr + input_start + offsets, mask=mask, other=0.0)
|
| 241 |
+
a = a_.to(tl.float32)
|
| 242 |
+
rms = tl.sqrt(tl.sum(a * a, axis=0) / hidden_dim + eps)
|
| 243 |
+
|
| 244 |
+
w1_ = tl.load(weight_ptr + offsets, mask=mask, other=0.0)
|
| 245 |
+
w1 = w1_.to(tl.float32)
|
| 246 |
+
|
| 247 |
+
a_rms = a / rms * w1
|
| 248 |
+
|
| 249 |
+
tl.store(
|
| 250 |
+
output_ptr + input_start + offsets,
|
| 251 |
+
a_rms, # implicitly casts to output dtype here
|
| 252 |
+
mask=mask,
|
| 253 |
+
)
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
def fused_rmsnorm(x, weight, eps, autotune=False, inplace=False):
|
| 257 |
+
assert len(x.shape) == 2
|
| 258 |
+
if inplace:
|
| 259 |
+
output = x
|
| 260 |
+
else:
|
| 261 |
+
output = torch.empty_like(x)
|
| 262 |
+
bs, hidden_dim = x.shape
|
| 263 |
+
|
| 264 |
+
min_num_warps = 16 if _is_hip else 32
|
| 265 |
+
|
| 266 |
+
config = {
|
| 267 |
+
"BLOCK_SIZE": triton.next_power_of_2(hidden_dim),
|
| 268 |
+
"num_warps": max(
|
| 269 |
+
min(triton.next_power_of_2(triton.cdiv(hidden_dim, 256)), min_num_warps), 4
|
| 270 |
+
),
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
fused_rmsnorm_kernel[(bs,)](
|
| 274 |
+
output, x, weight, eps=eps, hidden_dim=hidden_dim, **config
|
| 275 |
+
)
|
| 276 |
+
return output
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
class FusedDualResidualRMSNorm:
|
| 280 |
+
"""
|
| 281 |
+
Fused implementation of
|
| 282 |
+
y = RMSNorm2(RMSNorm1(x) + residual))
|
| 283 |
+
"""
|
| 284 |
+
|
| 285 |
+
def __init__(self, rmsnorm1, rmsnorm2) -> None: # the one after rmsnorm1
|
| 286 |
+
self.rmsnorm1 = rmsnorm1
|
| 287 |
+
self.rmsnorm2 = rmsnorm2
|
| 288 |
+
self.variance_epsilon = self.rmsnorm1.variance_epsilon
|
| 289 |
+
assert self.rmsnorm1.variance_epsilon == self.rmsnorm2.variance_epsilon
|
| 290 |
+
assert self.rmsnorm1.weight.shape == self.rmsnorm2.weight.shape
|
| 291 |
+
|
| 292 |
+
def __call__(self, *args, **kwargs):
|
| 293 |
+
return self.forward(*args, **kwargs)
|
| 294 |
+
|
| 295 |
+
def forward(
|
| 296 |
+
self, x: torch.Tensor, residual: torch.Tensor
|
| 297 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 298 |
+
if x.is_cuda:
|
| 299 |
+
return self.forward_cuda(x, residual)
|
| 300 |
+
else:
|
| 301 |
+
return self.forward_flashinfer(x, residual)
|
| 302 |
+
|
| 303 |
+
def forward_cuda(
|
| 304 |
+
self, x: torch.Tensor, residual: torch.Tensor, autotune=False
|
| 305 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 306 |
+
return fused_dual_residual_rmsnorm(
|
| 307 |
+
x,
|
| 308 |
+
residual,
|
| 309 |
+
self.rmsnorm1.weight,
|
| 310 |
+
self.rmsnorm2.weight,
|
| 311 |
+
self.variance_epsilon,
|
| 312 |
+
autotune=autotune,
|
| 313 |
+
)
|
| 314 |
+
|
| 315 |
+
def forward_flashinfer(
|
| 316 |
+
self,
|
| 317 |
+
x: torch.Tensor,
|
| 318 |
+
residual: torch.Tensor,
|
| 319 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 320 |
+
normed1 = self.rmsnorm1(x)
|
| 321 |
+
residual = normed1 + residual
|
| 322 |
+
return self.rmsnorm2(residual), residual
|
| 323 |
+
|
| 324 |
+
def forward_native(
|
| 325 |
+
self,
|
| 326 |
+
x: torch.Tensor,
|
| 327 |
+
residual: torch.Tensor,
|
| 328 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 329 |
+
normed1 = self.rmsnorm1.forward_native(x)
|
| 330 |
+
residual = normed1 + residual
|
| 331 |
+
return self.rmsnorm2.forward_native(residual), residual
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
# gelu on first half of vector
|
| 335 |
+
@triton.jit
|
| 336 |
+
def gelu_and_mul_kernel(
|
| 337 |
+
out_hidden_states_ptr, # (bs, hidden_dim)
|
| 338 |
+
out_scales_ptr, # (bs,)
|
| 339 |
+
hidden_states_ptr, # (bs, hidden_dim * 2)
|
| 340 |
+
quant_max: tl.constexpr,
|
| 341 |
+
static_scale: tl.constexpr,
|
| 342 |
+
hidden_dim: tl.constexpr, # the output hidden_dim
|
| 343 |
+
BLOCK_SIZE: tl.constexpr,
|
| 344 |
+
):
|
| 345 |
+
pid = tl.program_id(axis=0)
|
| 346 |
+
|
| 347 |
+
input_start = pid * hidden_dim * 2
|
| 348 |
+
output_start = pid * hidden_dim
|
| 349 |
+
|
| 350 |
+
input1_offs = tl.arange(0, BLOCK_SIZE)
|
| 351 |
+
mask = tl.arange(0, BLOCK_SIZE) < hidden_dim # shared for input1, input3, output
|
| 352 |
+
input3_offs = hidden_dim + tl.arange(0, BLOCK_SIZE)
|
| 353 |
+
output_offs = tl.arange(0, BLOCK_SIZE)
|
| 354 |
+
|
| 355 |
+
x1 = tl.load(
|
| 356 |
+
hidden_states_ptr + input_start + input1_offs, mask=mask, other=0.0
|
| 357 |
+
).to(tl.float32)
|
| 358 |
+
x3 = tl.load(
|
| 359 |
+
hidden_states_ptr + input_start + input3_offs, mask=mask, other=0.0
|
| 360 |
+
).to(tl.float32)
|
| 361 |
+
|
| 362 |
+
# gelu
|
| 363 |
+
# cast down before mul to better match training?
|
| 364 |
+
gelu_x1 = 0.5 * (1.0 + tl.erf(x1 * 0.7071067811865475)) * x1
|
| 365 |
+
out = x3 * gelu_x1.to(hidden_states_ptr.dtype.element_ty)
|
| 366 |
+
|
| 367 |
+
if quant_max is not None:
|
| 368 |
+
raise NotImplementedError()
|
| 369 |
+
|
| 370 |
+
tl.store(out_hidden_states_ptr + output_start + output_offs, out, mask=mask)
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def gelu_and_mul_triton(
|
| 374 |
+
hidden_states,
|
| 375 |
+
scales=None,
|
| 376 |
+
quantize=None, # dtype to quantize to
|
| 377 |
+
out=None,
|
| 378 |
+
):
|
| 379 |
+
bs, in_hidden_dim = hidden_states.shape
|
| 380 |
+
hidden_dim = in_hidden_dim // 2
|
| 381 |
+
|
| 382 |
+
if out is None:
|
| 383 |
+
out_hidden_states = torch.empty(
|
| 384 |
+
(bs, hidden_dim),
|
| 385 |
+
dtype=quantize or hidden_states.dtype,
|
| 386 |
+
device=hidden_states.device,
|
| 387 |
+
)
|
| 388 |
+
else:
|
| 389 |
+
assert out.shape == (bs, hidden_dim)
|
| 390 |
+
assert out.dtype == (quantize or hidden_states.dtype)
|
| 391 |
+
out_hidden_states = out
|
| 392 |
+
out_scales = None
|
| 393 |
+
static_scale = False
|
| 394 |
+
if quantize is not None:
|
| 395 |
+
if scales is None:
|
| 396 |
+
out_scales = torch.empty(
|
| 397 |
+
(bs,), dtype=torch.float32, device=hidden_states.device
|
| 398 |
+
)
|
| 399 |
+
else:
|
| 400 |
+
out_scales = scales
|
| 401 |
+
static_scale = True
|
| 402 |
+
|
| 403 |
+
config = {
|
| 404 |
+
# 8 ele per thread (not tuned)
|
| 405 |
+
"num_warps": max(
|
| 406 |
+
min(triton.next_power_of_2(triton.cdiv(hidden_dim, 8 * 32)), 32), 4
|
| 407 |
+
),
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
gelu_and_mul_kernel[(bs,)](
|
| 411 |
+
out_hidden_states,
|
| 412 |
+
out_scales,
|
| 413 |
+
hidden_states,
|
| 414 |
+
quant_max=torch.finfo(quantize).max if quantize is not None else None,
|
| 415 |
+
static_scale=static_scale,
|
| 416 |
+
hidden_dim=hidden_dim,
|
| 417 |
+
BLOCK_SIZE=triton.next_power_of_2(hidden_dim),
|
| 418 |
+
**config,
|
| 419 |
+
)
|
| 420 |
+
|
| 421 |
+
if quantize is not None:
|
| 422 |
+
return out_hidden_states, out_scales
|
| 423 |
+
else:
|
| 424 |
+
return out_hidden_states, None
|
lib/python3.12/site-packages/sglang/srt/layers/layernorm.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023-2024 SGLang Team
|
| 2 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 3 |
+
# you may not use this file except in compliance with the License.
|
| 4 |
+
# You may obtain a copy of the License at
|
| 5 |
+
#
|
| 6 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 7 |
+
#
|
| 8 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 9 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 10 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 11 |
+
# See the License for the specific language governing permissions and
|
| 12 |
+
# limitations under the License.
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
"""Fused operators for normalization layers."""
|
| 15 |
+
|
| 16 |
+
import logging
|
| 17 |
+
from typing import Optional, Tuple, Union
|
| 18 |
+
|
| 19 |
+
import torch
|
| 20 |
+
import torch.nn as nn
|
| 21 |
+
|
| 22 |
+
from sglang.srt.custom_op import CustomOp
|
| 23 |
+
from sglang.srt.utils import is_cuda, is_hip
|
| 24 |
+
|
| 25 |
+
_is_cuda = is_cuda()
|
| 26 |
+
_is_hip = is_hip()
|
| 27 |
+
|
| 28 |
+
if _is_cuda:
|
| 29 |
+
from sgl_kernel import (
|
| 30 |
+
fused_add_rmsnorm,
|
| 31 |
+
gemma_fused_add_rmsnorm,
|
| 32 |
+
gemma_rmsnorm,
|
| 33 |
+
rmsnorm,
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
if _is_hip:
|
| 37 |
+
from vllm._custom_ops import fused_add_rms_norm, rms_norm
|
| 38 |
+
|
| 39 |
+
logger = logging.getLogger(__name__)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class RMSNorm(CustomOp):
|
| 43 |
+
def __init__(
|
| 44 |
+
self,
|
| 45 |
+
hidden_size: int,
|
| 46 |
+
eps: float = 1e-6,
|
| 47 |
+
) -> None:
|
| 48 |
+
super().__init__()
|
| 49 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 50 |
+
self.variance_epsilon = eps
|
| 51 |
+
|
| 52 |
+
def forward(self, *args, **kwargs):
|
| 53 |
+
if torch.compiler.is_compiling():
|
| 54 |
+
return self.forward_native(*args, **kwargs)
|
| 55 |
+
if _is_cuda:
|
| 56 |
+
return self.forward_cuda(*args, **kwargs)
|
| 57 |
+
elif _is_hip:
|
| 58 |
+
return self.forward_hip(*args, **kwargs)
|
| 59 |
+
else:
|
| 60 |
+
return self.forward_native(*args, **kwargs)
|
| 61 |
+
|
| 62 |
+
def forward_cuda(
|
| 63 |
+
self,
|
| 64 |
+
x: torch.Tensor,
|
| 65 |
+
residual: Optional[torch.Tensor] = None,
|
| 66 |
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
| 67 |
+
if residual is not None:
|
| 68 |
+
fused_add_rmsnorm(x, residual, self.weight.data, self.variance_epsilon)
|
| 69 |
+
return x, residual
|
| 70 |
+
out = rmsnorm(x, self.weight.data, self.variance_epsilon)
|
| 71 |
+
return out
|
| 72 |
+
|
| 73 |
+
def forward_hip(
|
| 74 |
+
self,
|
| 75 |
+
x: torch.Tensor,
|
| 76 |
+
residual: Optional[torch.Tensor] = None,
|
| 77 |
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
| 78 |
+
if not x.is_contiguous():
|
| 79 |
+
# NOTE: Romove this if aiter kernel supports discontinuous input
|
| 80 |
+
x = x.contiguous()
|
| 81 |
+
if residual is not None:
|
| 82 |
+
fused_add_rms_norm(x, residual, self.weight.data, self.variance_epsilon)
|
| 83 |
+
return x, residual
|
| 84 |
+
out = torch.empty_like(x)
|
| 85 |
+
rms_norm(out, x, self.weight.data, self.variance_epsilon)
|
| 86 |
+
return out
|
| 87 |
+
|
| 88 |
+
def forward_native(
|
| 89 |
+
self,
|
| 90 |
+
x: torch.Tensor,
|
| 91 |
+
residual: Optional[torch.Tensor] = None,
|
| 92 |
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
| 93 |
+
if not x.is_contiguous():
|
| 94 |
+
x = x.contiguous()
|
| 95 |
+
orig_dtype = x.dtype
|
| 96 |
+
x = x.to(torch.float32)
|
| 97 |
+
if residual is not None:
|
| 98 |
+
x = x + residual.to(torch.float32)
|
| 99 |
+
residual = x.to(orig_dtype)
|
| 100 |
+
|
| 101 |
+
variance = x.pow(2).mean(dim=-1, keepdim=True)
|
| 102 |
+
x = x * torch.rsqrt(variance + self.variance_epsilon)
|
| 103 |
+
x = (x * self.weight).to(orig_dtype)
|
| 104 |
+
if residual is None:
|
| 105 |
+
return x
|
| 106 |
+
else:
|
| 107 |
+
return x, residual
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
class GemmaRMSNorm(CustomOp):
|
| 111 |
+
def __init__(
|
| 112 |
+
self,
|
| 113 |
+
hidden_size: int,
|
| 114 |
+
eps: float = 1e-6,
|
| 115 |
+
) -> None:
|
| 116 |
+
super().__init__()
|
| 117 |
+
self.weight = nn.Parameter(torch.zeros(hidden_size))
|
| 118 |
+
self.variance_epsilon = eps
|
| 119 |
+
|
| 120 |
+
def forward(self, *args, **kwargs):
|
| 121 |
+
if torch.compiler.is_compiling():
|
| 122 |
+
return self.forward_native(*args, **kwargs)
|
| 123 |
+
if _is_cuda:
|
| 124 |
+
return self.forward_cuda(*args, **kwargs)
|
| 125 |
+
else:
|
| 126 |
+
return self.forward_native(*args, **kwargs)
|
| 127 |
+
|
| 128 |
+
def forward_native(
|
| 129 |
+
self,
|
| 130 |
+
x: torch.Tensor,
|
| 131 |
+
residual: Optional[torch.Tensor] = None,
|
| 132 |
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
| 133 |
+
orig_dtype = x.dtype
|
| 134 |
+
if residual is not None:
|
| 135 |
+
x = x + residual
|
| 136 |
+
residual = x
|
| 137 |
+
|
| 138 |
+
x = x.float()
|
| 139 |
+
variance = x.pow(2).mean(dim=-1, keepdim=True)
|
| 140 |
+
x = x * torch.rsqrt(variance + self.variance_epsilon)
|
| 141 |
+
x = x * (1.0 + self.weight.float())
|
| 142 |
+
x = x.to(orig_dtype)
|
| 143 |
+
return x if residual is None else (x, residual)
|
| 144 |
+
|
| 145 |
+
def forward_cuda(
|
| 146 |
+
self,
|
| 147 |
+
x: torch.Tensor,
|
| 148 |
+
residual: Optional[torch.Tensor] = None,
|
| 149 |
+
) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]:
|
| 150 |
+
if residual is not None:
|
| 151 |
+
gemma_fused_add_rmsnorm(
|
| 152 |
+
x, residual, self.weight.data, self.variance_epsilon
|
| 153 |
+
)
|
| 154 |
+
return x, residual
|
| 155 |
+
out = gemma_rmsnorm(x, self.weight.data, self.variance_epsilon)
|
| 156 |
+
return out
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
class Gemma3RMSNorm(nn.Module):
|
| 160 |
+
def __init__(self, dim: int, eps: float = 1e-6):
|
| 161 |
+
super().__init__()
|
| 162 |
+
self.eps = eps
|
| 163 |
+
self.weight = nn.Parameter(torch.zeros(dim))
|
| 164 |
+
|
| 165 |
+
def _norm(self, x):
|
| 166 |
+
return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
|
| 167 |
+
|
| 168 |
+
def forward(self, x):
|
| 169 |
+
output = self._norm(x.float())
|
| 170 |
+
# Llama does x.to(float16) * w whilst Gemma3 is (x * w).to(float16)
|
| 171 |
+
# See https://github.com/huggingface/transformers/pull/29402
|
| 172 |
+
output = output * (1.0 + self.weight.float())
|
| 173 |
+
return output.type_as(x)
|
| 174 |
+
|
| 175 |
+
def extra_repr(self):
|
| 176 |
+
return f"{tuple(self.weight.shape)}, eps={self.eps}"
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
if not (_is_cuda or _is_hip):
|
| 180 |
+
logger.info(
|
| 181 |
+
"sgl-kernel layernorm implementation is not available on current platform. Fallback to other kernel libraries."
|
| 182 |
+
)
|
| 183 |
+
from vllm.model_executor.layers.layernorm import GemmaRMSNorm, RMSNorm
|
lib/python3.12/site-packages/sglang/srt/layers/linear.py
ADDED
|
@@ -0,0 +1,1307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Adapted from https://github.com/vllm-project/vllm/blob/v0.6.4.post1/vllm/model_executor/layers/linear.py"""
|
| 2 |
+
|
| 3 |
+
import itertools
|
| 4 |
+
import logging
|
| 5 |
+
from abc import abstractmethod
|
| 6 |
+
from typing import Dict, List, Optional, Tuple
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from torch.nn.parameter import Parameter, UninitializedParameter
|
| 11 |
+
|
| 12 |
+
from sglang.srt.distributed import (
|
| 13 |
+
divide,
|
| 14 |
+
get_tensor_model_parallel_rank,
|
| 15 |
+
get_tensor_model_parallel_world_size,
|
| 16 |
+
split_tensor_along_last_dim,
|
| 17 |
+
tensor_model_parallel_all_gather,
|
| 18 |
+
tensor_model_parallel_all_reduce,
|
| 19 |
+
)
|
| 20 |
+
from sglang.srt.layers.parameter import (
|
| 21 |
+
BasevLLMParameter,
|
| 22 |
+
BlockQuantScaleParameter,
|
| 23 |
+
PackedColumnParameter,
|
| 24 |
+
PackedvLLMParameter,
|
| 25 |
+
PerTensorScaleParameter,
|
| 26 |
+
RowvLLMParameter,
|
| 27 |
+
_ColumnvLLMParameter,
|
| 28 |
+
)
|
| 29 |
+
from sglang.srt.layers.quantization.base_config import (
|
| 30 |
+
QuantizationConfig,
|
| 31 |
+
QuantizeMethodBase,
|
| 32 |
+
)
|
| 33 |
+
from sglang.srt.utils import set_weight_attrs
|
| 34 |
+
|
| 35 |
+
logger = logging.getLogger(__name__)
|
| 36 |
+
|
| 37 |
+
WEIGHT_LOADER_V2_SUPPORTED = [
|
| 38 |
+
"CompressedTensorsLinearMethod",
|
| 39 |
+
"AWQMarlinLinearMethod",
|
| 40 |
+
"AWQLinearMethod",
|
| 41 |
+
"GPTQMarlinLinearMethod",
|
| 42 |
+
"Fp8LinearMethod",
|
| 43 |
+
"BlockInt8LinearMethod",
|
| 44 |
+
"MarlinLinearMethod",
|
| 45 |
+
"QQQLinearMethod",
|
| 46 |
+
"GPTQMarlin24LinearMethod",
|
| 47 |
+
"TPUInt8LinearMethod",
|
| 48 |
+
"GPTQLinearMethod",
|
| 49 |
+
"FBGEMMFp8LinearMethod",
|
| 50 |
+
"ModelOptFp8LinearMethod",
|
| 51 |
+
"ModelOptFp4LinearMethod",
|
| 52 |
+
"IPEXAWQLinearMethod",
|
| 53 |
+
]
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def adjust_marlin_shard(param, shard_size, shard_offset):
|
| 57 |
+
marlin_tile_size = getattr(param, "marlin_tile_size", None)
|
| 58 |
+
if marlin_tile_size is None:
|
| 59 |
+
return shard_size, shard_offset
|
| 60 |
+
|
| 61 |
+
return shard_size * marlin_tile_size, shard_offset * marlin_tile_size
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def adjust_bitsandbytes_4bit_shard(
|
| 65 |
+
param: Parameter, shard_offsets: Dict[str, Tuple[int, int]], loaded_shard_id: str
|
| 66 |
+
) -> Tuple[int, int]:
|
| 67 |
+
"""Adjust the quantization offsets and sizes for BitsAndBytes sharding."""
|
| 68 |
+
|
| 69 |
+
total, _ = shard_offsets["total"]
|
| 70 |
+
orig_offset, orig_size = shard_offsets[loaded_shard_id]
|
| 71 |
+
|
| 72 |
+
quantized_total = param.data.shape[0]
|
| 73 |
+
quantized_offset = orig_offset * quantized_total // total
|
| 74 |
+
quantized_size = orig_size * quantized_total // total
|
| 75 |
+
|
| 76 |
+
return quantized_size, quantized_offset
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def adjust_scalar_to_fused_array(param, loaded_weight, shard_id):
|
| 80 |
+
"""For fused modules (QKV and MLP) we have an array of length
|
| 81 |
+
N that holds 1 scale for each "logical" matrix. So the param
|
| 82 |
+
is an array of length N. The loaded_weight corresponds to
|
| 83 |
+
one of the shards on disk. Here, we slice the param based on
|
| 84 |
+
the shard_id for loading.
|
| 85 |
+
"""
|
| 86 |
+
qkv_idxs = {"q": 0, "k": 1, "v": 2}
|
| 87 |
+
|
| 88 |
+
if isinstance(shard_id, str):
|
| 89 |
+
shard_id = qkv_idxs[shard_id]
|
| 90 |
+
elif not isinstance(shard_id, int):
|
| 91 |
+
raise ValueError(f"Unknown Shard Id {shard_id}")
|
| 92 |
+
|
| 93 |
+
# AutoFP8 scales do not have a shape
|
| 94 |
+
# compressed-tensors scales do have a shape
|
| 95 |
+
if len(loaded_weight.shape) != 0:
|
| 96 |
+
assert loaded_weight.shape[0] == 1
|
| 97 |
+
loaded_weight = loaded_weight[0]
|
| 98 |
+
|
| 99 |
+
return param[shard_id], loaded_weight
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
class LinearMethodBase(QuantizeMethodBase):
|
| 103 |
+
"""Base class for different (maybe quantized) linear methods."""
|
| 104 |
+
|
| 105 |
+
@abstractmethod
|
| 106 |
+
def create_weights(
|
| 107 |
+
self,
|
| 108 |
+
layer: torch.nn.Module,
|
| 109 |
+
input_size_per_partition: int,
|
| 110 |
+
output_partition_sizes: List[int],
|
| 111 |
+
input_size: int,
|
| 112 |
+
output_size: int,
|
| 113 |
+
params_dtype: torch.dtype,
|
| 114 |
+
**extra_weight_attrs,
|
| 115 |
+
):
|
| 116 |
+
"""Create weights for a linear layer.
|
| 117 |
+
The weights will be set as attributes of the layer.
|
| 118 |
+
|
| 119 |
+
Args:
|
| 120 |
+
layer: The layer that is using the LinearMethodBase factory.
|
| 121 |
+
input_size_per_partition: Size of the weight input dim on rank X.
|
| 122 |
+
output_partition_sizes: Sizes of the output dim of each logical
|
| 123 |
+
weight on rank X. E.g., output_partition_sizes for QKVLinear
|
| 124 |
+
is a list contains the width of Wq, Wk, Wv on rank X.
|
| 125 |
+
input_size: Size of the input dim of the weight across all ranks.
|
| 126 |
+
output_size: Size of the output dim of the weight across all ranks.
|
| 127 |
+
params_dtype: Datatype of the parameters.
|
| 128 |
+
"""
|
| 129 |
+
raise NotImplementedError
|
| 130 |
+
|
| 131 |
+
@abstractmethod
|
| 132 |
+
def apply(
|
| 133 |
+
self,
|
| 134 |
+
layer: torch.nn.Module,
|
| 135 |
+
x: torch.Tensor,
|
| 136 |
+
bias: Optional[torch.Tensor] = None,
|
| 137 |
+
) -> torch.Tensor:
|
| 138 |
+
"""Apply the weights in layer to the input tensor.
|
| 139 |
+
Expects create_weights to have been called before on the layer."""
|
| 140 |
+
raise NotImplementedError
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
class UnquantizedLinearMethod(LinearMethodBase):
|
| 144 |
+
"""Linear method without quantization."""
|
| 145 |
+
|
| 146 |
+
def create_weights(
|
| 147 |
+
self,
|
| 148 |
+
layer: torch.nn.Module,
|
| 149 |
+
input_size_per_partition: int,
|
| 150 |
+
output_partition_sizes: List[int],
|
| 151 |
+
input_size: int,
|
| 152 |
+
output_size: int,
|
| 153 |
+
params_dtype: torch.dtype,
|
| 154 |
+
**extra_weight_attrs,
|
| 155 |
+
):
|
| 156 |
+
weight = Parameter(
|
| 157 |
+
torch.empty(
|
| 158 |
+
sum(output_partition_sizes),
|
| 159 |
+
input_size_per_partition,
|
| 160 |
+
dtype=params_dtype,
|
| 161 |
+
),
|
| 162 |
+
requires_grad=False,
|
| 163 |
+
)
|
| 164 |
+
set_weight_attrs(weight, {"input_dim": 1, "output_dim": 0})
|
| 165 |
+
layer.register_parameter("weight", weight)
|
| 166 |
+
set_weight_attrs(weight, extra_weight_attrs)
|
| 167 |
+
|
| 168 |
+
def apply(
|
| 169 |
+
self,
|
| 170 |
+
layer: torch.nn.Module,
|
| 171 |
+
x: torch.Tensor,
|
| 172 |
+
bias: Optional[torch.Tensor] = None,
|
| 173 |
+
) -> torch.Tensor:
|
| 174 |
+
|
| 175 |
+
return F.linear(x, layer.weight, bias)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
class LinearBase(torch.nn.Module):
|
| 179 |
+
"""Base linear layer.
|
| 180 |
+
|
| 181 |
+
Args:
|
| 182 |
+
input_size: input dimension of the linear layer.
|
| 183 |
+
output_size: output dimension of the linear layer.
|
| 184 |
+
bias: If true, add bias.
|
| 185 |
+
skip_bias_add: If true, skip adding bias but instead return it.
|
| 186 |
+
params_dtype: Data type for the parameters.
|
| 187 |
+
quant_config: Quantization configure.
|
| 188 |
+
"""
|
| 189 |
+
|
| 190 |
+
def __init__(
|
| 191 |
+
self,
|
| 192 |
+
input_size: int,
|
| 193 |
+
output_size: int,
|
| 194 |
+
skip_bias_add: bool = False,
|
| 195 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 196 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 197 |
+
prefix: str = "",
|
| 198 |
+
):
|
| 199 |
+
super().__init__()
|
| 200 |
+
|
| 201 |
+
# Keep input parameters
|
| 202 |
+
self.input_size = input_size
|
| 203 |
+
self.output_size = output_size
|
| 204 |
+
self.skip_bias_add = skip_bias_add
|
| 205 |
+
if params_dtype is None:
|
| 206 |
+
params_dtype = torch.get_default_dtype()
|
| 207 |
+
self.params_dtype = params_dtype
|
| 208 |
+
if quant_config is None:
|
| 209 |
+
self.quant_method: Optional[QuantizeMethodBase] = UnquantizedLinearMethod()
|
| 210 |
+
else:
|
| 211 |
+
self.quant_method = quant_config.get_quant_method(self, prefix=prefix)
|
| 212 |
+
|
| 213 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 214 |
+
raise NotImplementedError
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
class ReplicatedLinear(LinearBase):
|
| 218 |
+
"""Replicated linear layer.
|
| 219 |
+
|
| 220 |
+
Args:
|
| 221 |
+
input_size: input dimension of the linear layer.
|
| 222 |
+
output_size: output dimension of the linear layer.
|
| 223 |
+
bias: If true, add bias.
|
| 224 |
+
skip_bias_add: If true, skip adding bias but instead return it.
|
| 225 |
+
params_dtype: Data type for the parameters.
|
| 226 |
+
quant_config: Quantization configure.
|
| 227 |
+
prefix: The name of the layer in the state dict, including all parents
|
| 228 |
+
(e.g. model.layers.0.qkv_proj)
|
| 229 |
+
"""
|
| 230 |
+
|
| 231 |
+
def __init__(
|
| 232 |
+
self,
|
| 233 |
+
input_size: int,
|
| 234 |
+
output_size: int,
|
| 235 |
+
bias: bool = True,
|
| 236 |
+
skip_bias_add: bool = False,
|
| 237 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 238 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 239 |
+
prefix: str = "",
|
| 240 |
+
):
|
| 241 |
+
super().__init__(
|
| 242 |
+
input_size,
|
| 243 |
+
output_size,
|
| 244 |
+
skip_bias_add,
|
| 245 |
+
params_dtype,
|
| 246 |
+
quant_config,
|
| 247 |
+
prefix=prefix,
|
| 248 |
+
)
|
| 249 |
+
|
| 250 |
+
# All the linear layer supports quant method.
|
| 251 |
+
assert self.quant_method is not None
|
| 252 |
+
self.quant_method.create_weights(
|
| 253 |
+
self,
|
| 254 |
+
self.input_size,
|
| 255 |
+
[self.output_size],
|
| 256 |
+
self.input_size,
|
| 257 |
+
self.output_size,
|
| 258 |
+
self.params_dtype,
|
| 259 |
+
weight_loader=self.weight_loader,
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
if bias:
|
| 263 |
+
self.bias = Parameter(
|
| 264 |
+
torch.empty(self.output_size, dtype=self.params_dtype)
|
| 265 |
+
)
|
| 266 |
+
set_weight_attrs(
|
| 267 |
+
self.bias,
|
| 268 |
+
{
|
| 269 |
+
"output_dim": 0,
|
| 270 |
+
"weight_loader": self.weight_loader,
|
| 271 |
+
},
|
| 272 |
+
)
|
| 273 |
+
else:
|
| 274 |
+
self.register_parameter("bias", None)
|
| 275 |
+
|
| 276 |
+
def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
|
| 277 |
+
# If the weight on disk does not have a shape, give it one
|
| 278 |
+
# (such scales for AutoFp8).
|
| 279 |
+
if len(loaded_weight.shape) == 0:
|
| 280 |
+
loaded_weight = loaded_weight.reshape(1)
|
| 281 |
+
|
| 282 |
+
assert param.size() == loaded_weight.size()
|
| 283 |
+
param.data.copy_(loaded_weight)
|
| 284 |
+
|
| 285 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 286 |
+
bias = self.bias if not self.skip_bias_add else None
|
| 287 |
+
assert self.quant_method is not None
|
| 288 |
+
output = self.quant_method.apply(self, x, bias)
|
| 289 |
+
output_bias = self.bias if self.skip_bias_add else None
|
| 290 |
+
return output, output_bias
|
| 291 |
+
|
| 292 |
+
def extra_repr(self) -> str:
|
| 293 |
+
s = f"in_features={self.input_size}"
|
| 294 |
+
s += f", output_features={self.output_size}"
|
| 295 |
+
s += f", bias={self.bias is not None}"
|
| 296 |
+
return s
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
class ColumnParallelLinear(LinearBase):
|
| 300 |
+
"""Linear layer with column parallelism.
|
| 301 |
+
|
| 302 |
+
The linear layer is defined as Y = XA + b. A is parallelized along
|
| 303 |
+
its second dimension as A = [A_1, ..., A_p].
|
| 304 |
+
|
| 305 |
+
Args:
|
| 306 |
+
input_size: first dimension of matrix A.
|
| 307 |
+
output_size: second dimension of matrix A.
|
| 308 |
+
bias: If true, add bias.
|
| 309 |
+
gather_output: If true, call all-gather on output and make Y available
|
| 310 |
+
to all GPUs, otherwise, every GPU will have its output
|
| 311 |
+
which is Y_i = XA_i
|
| 312 |
+
skip_bias_add: This was added to enable performance optimizations where
|
| 313 |
+
bias can be fused with other element-wise operations. we
|
| 314 |
+
skip adding bias but instead return it.
|
| 315 |
+
params_dtype: Data type for the parameters.
|
| 316 |
+
quant_config: Quantization configure.
|
| 317 |
+
output_sizes: list of output sizes packed into one output, like for QKV
|
| 318 |
+
the list would be size 3.
|
| 319 |
+
prefix: The name of the layer in the state dict, including all parents
|
| 320 |
+
(e.g. model.layers.0.qkv_proj)
|
| 321 |
+
"""
|
| 322 |
+
|
| 323 |
+
def __init__(
|
| 324 |
+
self,
|
| 325 |
+
input_size: int,
|
| 326 |
+
output_size: int,
|
| 327 |
+
bias: bool = True,
|
| 328 |
+
gather_output: bool = False,
|
| 329 |
+
skip_bias_add: bool = False,
|
| 330 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 331 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 332 |
+
output_sizes: Optional[List[int]] = None,
|
| 333 |
+
prefix: str = "",
|
| 334 |
+
tp_rank: Optional[int] = None,
|
| 335 |
+
tp_size: Optional[int] = None,
|
| 336 |
+
use_presharded_weights: bool = False,
|
| 337 |
+
):
|
| 338 |
+
super().__init__(
|
| 339 |
+
input_size, output_size, skip_bias_add, params_dtype, quant_config, prefix
|
| 340 |
+
)
|
| 341 |
+
|
| 342 |
+
self.gather_output = gather_output
|
| 343 |
+
self.use_presharded_weights = use_presharded_weights
|
| 344 |
+
|
| 345 |
+
# Divide the weight matrix along the last dimension.
|
| 346 |
+
if tp_rank is None:
|
| 347 |
+
tp_rank = get_tensor_model_parallel_rank()
|
| 348 |
+
if tp_size is None:
|
| 349 |
+
tp_size = get_tensor_model_parallel_world_size()
|
| 350 |
+
self.tp_rank, self.tp_size = tp_rank, tp_size
|
| 351 |
+
assert self.quant_method is not None
|
| 352 |
+
self.output_size_per_partition = divide(self.output_size, tp_size)
|
| 353 |
+
self.output_partition_sizes = [self.output_size_per_partition]
|
| 354 |
+
# If QKV or MergedColumn, use output size of each partition.
|
| 355 |
+
if hasattr(self, "output_sizes"):
|
| 356 |
+
self.output_partition_sizes = [
|
| 357 |
+
divide(output_size, tp_size) for output_size in self.output_sizes
|
| 358 |
+
]
|
| 359 |
+
|
| 360 |
+
if output_sizes is None:
|
| 361 |
+
output_sizes = [output_size]
|
| 362 |
+
|
| 363 |
+
self.quant_method.create_weights(
|
| 364 |
+
layer=self,
|
| 365 |
+
input_size_per_partition=self.input_size,
|
| 366 |
+
output_partition_sizes=self.output_partition_sizes,
|
| 367 |
+
input_size=self.input_size,
|
| 368 |
+
output_size=self.output_size,
|
| 369 |
+
params_dtype=self.params_dtype,
|
| 370 |
+
weight_loader=(
|
| 371 |
+
self.weight_loader_v2
|
| 372 |
+
if self.quant_method.__class__.__name__ in WEIGHT_LOADER_V2_SUPPORTED
|
| 373 |
+
else self.weight_loader
|
| 374 |
+
),
|
| 375 |
+
)
|
| 376 |
+
if bias:
|
| 377 |
+
self.bias = Parameter(
|
| 378 |
+
torch.empty(self.output_size_per_partition, dtype=params_dtype)
|
| 379 |
+
)
|
| 380 |
+
set_weight_attrs(
|
| 381 |
+
self.bias,
|
| 382 |
+
{
|
| 383 |
+
"output_dim": 0,
|
| 384 |
+
"weight_loader": self.weight_loader,
|
| 385 |
+
},
|
| 386 |
+
)
|
| 387 |
+
else:
|
| 388 |
+
self.register_parameter("bias", None)
|
| 389 |
+
|
| 390 |
+
def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
|
| 391 |
+
output_dim = getattr(param, "output_dim", None)
|
| 392 |
+
|
| 393 |
+
# Special case for GGUF
|
| 394 |
+
is_gguf_weight = getattr(param, "is_gguf_weight", False)
|
| 395 |
+
is_gguf_weight_type = getattr(param, "is_gguf_weight_type", False)
|
| 396 |
+
if is_gguf_weight_type:
|
| 397 |
+
param.weight_type = loaded_weight.item()
|
| 398 |
+
|
| 399 |
+
# Materialize GGUF UninitializedParameter
|
| 400 |
+
if is_gguf_weight and isinstance(param, UninitializedParameter):
|
| 401 |
+
param.materialize(loaded_weight.shape, dtype=loaded_weight.dtype)
|
| 402 |
+
|
| 403 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 404 |
+
|
| 405 |
+
param_data = param.data
|
| 406 |
+
# bitsandbytes loads the weights of the specific portion
|
| 407 |
+
# no need to narrow here
|
| 408 |
+
if output_dim is not None and not use_bitsandbytes_4bit:
|
| 409 |
+
shard_size = param_data.shape[output_dim]
|
| 410 |
+
start_idx = self.tp_rank * shard_size
|
| 411 |
+
if not self.use_presharded_weights:
|
| 412 |
+
loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
|
| 413 |
+
|
| 414 |
+
# Special case for loading scales off disk, which often do not
|
| 415 |
+
# have a shape (such as in the case of AutoFP8).
|
| 416 |
+
if len(loaded_weight.shape) == 0:
|
| 417 |
+
loaded_weight = loaded_weight.reshape(1)
|
| 418 |
+
|
| 419 |
+
assert param_data.shape == loaded_weight.shape
|
| 420 |
+
param_data.copy_(loaded_weight)
|
| 421 |
+
|
| 422 |
+
def weight_loader_v2(self, param: Parameter, loaded_weight: torch.Tensor):
|
| 423 |
+
# Special case for loading scales off disk, which often do not
|
| 424 |
+
# have a shape (such as in the case of AutoFP8).
|
| 425 |
+
if len(loaded_weight.shape) == 0:
|
| 426 |
+
assert loaded_weight.numel() == 1
|
| 427 |
+
loaded_weight = loaded_weight.reshape(1)
|
| 428 |
+
|
| 429 |
+
if isinstance(param, _ColumnvLLMParameter):
|
| 430 |
+
param.load_column_parallel_weight(
|
| 431 |
+
loaded_weight,
|
| 432 |
+
tp_rank=self.tp_rank,
|
| 433 |
+
use_presharded_weights=self.use_presharded_weights,
|
| 434 |
+
)
|
| 435 |
+
else:
|
| 436 |
+
# FIXME: This branch is needed to load deepseek v3 awq.
|
| 437 |
+
# However, we should fix this and avoid the branching here.
|
| 438 |
+
param.load_column_parallel_weight(loaded_weight)
|
| 439 |
+
|
| 440 |
+
def forward(self, input_):
|
| 441 |
+
bias = self.bias if not self.skip_bias_add else None
|
| 442 |
+
|
| 443 |
+
# Matrix multiply.
|
| 444 |
+
assert self.quant_method is not None
|
| 445 |
+
output_parallel = self.quant_method.apply(self, input_, bias)
|
| 446 |
+
if self.gather_output:
|
| 447 |
+
# All-gather across the partitions.
|
| 448 |
+
output = tensor_model_parallel_all_gather(output_parallel)
|
| 449 |
+
else:
|
| 450 |
+
output = output_parallel
|
| 451 |
+
output_bias = self.bias if self.skip_bias_add else None
|
| 452 |
+
return output, output_bias
|
| 453 |
+
|
| 454 |
+
def extra_repr(self) -> str:
|
| 455 |
+
s = f"in_features={self.input_size}"
|
| 456 |
+
s += f", output_features={self.output_size_per_partition}"
|
| 457 |
+
s += f", bias={self.bias is not None}"
|
| 458 |
+
s += f", tp_size={self.tp_size}"
|
| 459 |
+
s += f", gather_output={self.gather_output}"
|
| 460 |
+
return s
|
| 461 |
+
|
| 462 |
+
|
| 463 |
+
class MergedColumnParallelLinear(ColumnParallelLinear):
|
| 464 |
+
"""Packed linear layers with column parallelism.
|
| 465 |
+
|
| 466 |
+
Similar to ColumnParallelLinear, but the weight matrix is concatenated
|
| 467 |
+
along the output dimension. When the weight matrix is loaded, the
|
| 468 |
+
different partitions are sharded separately.
|
| 469 |
+
|
| 470 |
+
Args:
|
| 471 |
+
input_size: input dimension of the linear layer.
|
| 472 |
+
output_sizes: list of output dimensions of the linear layer.
|
| 473 |
+
bias: If true, add bias.
|
| 474 |
+
gather_output: If true, call all-gather on output and make the output
|
| 475 |
+
available to all GPUs, otherwise, every GPU will have
|
| 476 |
+
its own output.
|
| 477 |
+
skip_bias_add: This was added to enable performance optimizations where
|
| 478 |
+
bias can be fused with other element-wise operations. we
|
| 479 |
+
skip adding bias but instead return it.
|
| 480 |
+
params_dtype: Data type for the parameters.
|
| 481 |
+
quant_config: Quantization configure.
|
| 482 |
+
prefix: The name of the layer in the state dict, including all parents
|
| 483 |
+
(e.g. model.layers.0.qkv_proj)
|
| 484 |
+
"""
|
| 485 |
+
|
| 486 |
+
def __init__(
|
| 487 |
+
self,
|
| 488 |
+
input_size: int,
|
| 489 |
+
output_sizes: List[int],
|
| 490 |
+
bias: bool = True,
|
| 491 |
+
gather_output: bool = False,
|
| 492 |
+
skip_bias_add: bool = False,
|
| 493 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 494 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 495 |
+
prefix: str = "",
|
| 496 |
+
tp_rank: Optional[int] = None,
|
| 497 |
+
tp_size: Optional[int] = None,
|
| 498 |
+
use_presharded_weights: bool = False,
|
| 499 |
+
):
|
| 500 |
+
self.output_sizes = output_sizes
|
| 501 |
+
if tp_rank is None:
|
| 502 |
+
tp_rank = get_tensor_model_parallel_rank()
|
| 503 |
+
if tp_size is None:
|
| 504 |
+
tp_size = get_tensor_model_parallel_world_size()
|
| 505 |
+
self.tp_rank, self.tp_size = tp_rank, tp_size
|
| 506 |
+
assert all(output_size % tp_size == 0 for output_size in output_sizes)
|
| 507 |
+
self.use_presharded_weights = use_presharded_weights
|
| 508 |
+
super().__init__(
|
| 509 |
+
input_size=input_size,
|
| 510 |
+
output_size=sum(output_sizes),
|
| 511 |
+
bias=bias,
|
| 512 |
+
gather_output=gather_output,
|
| 513 |
+
skip_bias_add=skip_bias_add,
|
| 514 |
+
params_dtype=params_dtype,
|
| 515 |
+
quant_config=quant_config,
|
| 516 |
+
prefix=prefix,
|
| 517 |
+
tp_rank=tp_rank,
|
| 518 |
+
tp_size=tp_size,
|
| 519 |
+
use_presharded_weights=use_presharded_weights,
|
| 520 |
+
)
|
| 521 |
+
self.prefix = prefix
|
| 522 |
+
|
| 523 |
+
def weight_loader(
|
| 524 |
+
self,
|
| 525 |
+
param: Parameter,
|
| 526 |
+
loaded_weight: torch.Tensor,
|
| 527 |
+
loaded_shard_id: Optional[int] = None,
|
| 528 |
+
):
|
| 529 |
+
|
| 530 |
+
# Special case for GGUF
|
| 531 |
+
# initialize GGUF param after we know the quantize type
|
| 532 |
+
is_gguf_weight = getattr(param, "is_gguf_weight", False)
|
| 533 |
+
is_gguf_weight_type = getattr(param, "is_gguf_weight_type", False)
|
| 534 |
+
if is_gguf_weight_type:
|
| 535 |
+
param.data[loaded_shard_id].copy_(loaded_weight)
|
| 536 |
+
param.shard_weight_type[loaded_shard_id] = loaded_weight.item()
|
| 537 |
+
return
|
| 538 |
+
|
| 539 |
+
if is_gguf_weight:
|
| 540 |
+
output_dim = getattr(param, "output_dim", None)
|
| 541 |
+
shard_size = loaded_weight.size(output_dim) // self.tp_size
|
| 542 |
+
start_idx = self.tp_rank * shard_size
|
| 543 |
+
|
| 544 |
+
loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
|
| 545 |
+
|
| 546 |
+
param.shard_id.append(loaded_shard_id)
|
| 547 |
+
param.shard_id_map[loaded_shard_id] = len(param.data_container)
|
| 548 |
+
param.data_container.append(loaded_weight)
|
| 549 |
+
if len(param.data_container) == 2:
|
| 550 |
+
self.qweight = param.materialize_nested()
|
| 551 |
+
return
|
| 552 |
+
|
| 553 |
+
param_data = param.data
|
| 554 |
+
output_dim = getattr(param, "output_dim", None)
|
| 555 |
+
# Special case for AQLM codebooks.
|
| 556 |
+
is_metadata = getattr(param, "is_metadata", False)
|
| 557 |
+
# Special case for per-tensor scale to load scalar into fused array.
|
| 558 |
+
needs_scalar_to_array = getattr(param, "needs_scalar_to_array", False)
|
| 559 |
+
|
| 560 |
+
if loaded_shard_id is None:
|
| 561 |
+
# Loaded weight is already fused on disk (qkv/mlp).
|
| 562 |
+
if output_dim is None:
|
| 563 |
+
if needs_scalar_to_array:
|
| 564 |
+
param_data, loaded_weight = adjust_scalar_to_fused_array(
|
| 565 |
+
param_data, loaded_weight, 0
|
| 566 |
+
)
|
| 567 |
+
|
| 568 |
+
assert param_data.shape == loaded_weight.shape
|
| 569 |
+
param_data.copy_(loaded_weight)
|
| 570 |
+
return
|
| 571 |
+
current_shard_offset = 0
|
| 572 |
+
shard_offsets: List[Tuple[int, int, int]] = []
|
| 573 |
+
for i, output_size in enumerate(self.output_sizes):
|
| 574 |
+
shard_offsets.append((i, current_shard_offset, output_size))
|
| 575 |
+
current_shard_offset += output_size
|
| 576 |
+
packed_dim = getattr(param, "packed_dim", None)
|
| 577 |
+
|
| 578 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 579 |
+
for shard_id, shard_offset, shard_size in shard_offsets:
|
| 580 |
+
# Special case for Quantization.
|
| 581 |
+
# If quantized, we need to adjust the offset and size to account
|
| 582 |
+
# for the packing.
|
| 583 |
+
if packed_dim == output_dim:
|
| 584 |
+
shard_size = shard_size // param.pack_factor
|
| 585 |
+
shard_offset = shard_offset // param.pack_factor
|
| 586 |
+
# Special case for Marlin.
|
| 587 |
+
shard_size, shard_offset = adjust_marlin_shard(
|
| 588 |
+
param, shard_size, shard_offset
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
if use_bitsandbytes_4bit:
|
| 592 |
+
index = list(itertools.accumulate([0] + self.output_sizes))
|
| 593 |
+
orig_offsets = {
|
| 594 |
+
str(i): (index[i], size)
|
| 595 |
+
for i, size in enumerate(self.output_sizes)
|
| 596 |
+
}
|
| 597 |
+
orig_offsets["total"] = (self.output_size, 0)
|
| 598 |
+
shard_size, shard_offset = adjust_bitsandbytes_4bit_shard(
|
| 599 |
+
param, orig_offsets, str(shard_id)
|
| 600 |
+
)
|
| 601 |
+
|
| 602 |
+
loaded_weight_shard = loaded_weight.narrow(
|
| 603 |
+
output_dim, shard_offset, shard_size
|
| 604 |
+
)
|
| 605 |
+
self.weight_loader(param, loaded_weight_shard, shard_id)
|
| 606 |
+
return
|
| 607 |
+
|
| 608 |
+
assert loaded_shard_id < len(self.output_sizes)
|
| 609 |
+
if output_dim is not None:
|
| 610 |
+
shard_offset = sum(self.output_sizes[:loaded_shard_id]) // self.tp_size
|
| 611 |
+
shard_size = self.output_sizes[loaded_shard_id] // self.tp_size
|
| 612 |
+
# Special case for quantization.
|
| 613 |
+
# If quantized, we need to adjust the offset and size to account
|
| 614 |
+
# for the packing.
|
| 615 |
+
packed_dim = getattr(param, "packed_dim", None)
|
| 616 |
+
if packed_dim == output_dim:
|
| 617 |
+
shard_size = shard_size // param.pack_factor
|
| 618 |
+
shard_offset = shard_offset // param.pack_factor
|
| 619 |
+
# Special case for Marlin.
|
| 620 |
+
shard_size, shard_offset = adjust_marlin_shard(
|
| 621 |
+
param, shard_size, shard_offset
|
| 622 |
+
)
|
| 623 |
+
|
| 624 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 625 |
+
if use_bitsandbytes_4bit:
|
| 626 |
+
shard_size = loaded_weight.shape[output_dim]
|
| 627 |
+
shard_offset = loaded_weight.shape[output_dim] * loaded_shard_id
|
| 628 |
+
|
| 629 |
+
param_data = param_data.narrow(output_dim, shard_offset, shard_size)
|
| 630 |
+
start_idx = self.tp_rank * shard_size
|
| 631 |
+
# bitsandbytes loads the weights of the specific portion
|
| 632 |
+
# no need to narrow here
|
| 633 |
+
if not use_bitsandbytes_4bit and not self.use_presharded_weights:
|
| 634 |
+
loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
|
| 635 |
+
# Special case for AQLM codebooks.
|
| 636 |
+
elif is_metadata:
|
| 637 |
+
# metadata indicates fixed size concatenated along dim 0
|
| 638 |
+
shard_size = loaded_weight.shape[0]
|
| 639 |
+
shard_offset = loaded_shard_id * shard_size
|
| 640 |
+
param_data = param_data.narrow(0, shard_offset, shard_size)
|
| 641 |
+
|
| 642 |
+
# Special case for per-tensor scales in fused case.
|
| 643 |
+
elif needs_scalar_to_array:
|
| 644 |
+
param_data, loaded_weight = adjust_scalar_to_fused_array(
|
| 645 |
+
param_data, loaded_weight, loaded_shard_id
|
| 646 |
+
)
|
| 647 |
+
|
| 648 |
+
else:
|
| 649 |
+
ignore_warning = getattr(param, "ignore_warning", False)
|
| 650 |
+
if not ignore_warning:
|
| 651 |
+
logger.warning(
|
| 652 |
+
"Loading a weight without `output_dim` attribute in "
|
| 653 |
+
"MergedColumnParallelLinear, assume the weight is "
|
| 654 |
+
"the same for all partitions."
|
| 655 |
+
)
|
| 656 |
+
|
| 657 |
+
assert param_data.shape == loaded_weight.shape
|
| 658 |
+
param_data.copy_(loaded_weight)
|
| 659 |
+
|
| 660 |
+
def _load_fused_module_from_checkpoint(
|
| 661 |
+
self, param: BasevLLMParameter, loaded_weight: torch.Tensor
|
| 662 |
+
):
|
| 663 |
+
"""
|
| 664 |
+
Handle special case for models where MLP layers are already
|
| 665 |
+
fused on disk. In this case, we have no shard id. This function
|
| 666 |
+
determmines the shard id by splitting these layers and then calls
|
| 667 |
+
the weight loader using the shard id.
|
| 668 |
+
|
| 669 |
+
An example of a model with these fused layers:
|
| 670 |
+
https://huggingface.co/microsoft/Phi-3-mini-4k-instruct
|
| 671 |
+
"""
|
| 672 |
+
|
| 673 |
+
current_shard_offset = 0
|
| 674 |
+
shard_offsets: List[Tuple[int, int, int]] = []
|
| 675 |
+
for i, output_size in enumerate(self.output_sizes):
|
| 676 |
+
shard_offsets.append((i, current_shard_offset, output_size))
|
| 677 |
+
current_shard_offset += output_size
|
| 678 |
+
|
| 679 |
+
for shard_id, shard_offset, shard_size in shard_offsets:
|
| 680 |
+
# Special case for Quantization.
|
| 681 |
+
# If quantized, we need to adjust the offset and size to account
|
| 682 |
+
# for the packing.
|
| 683 |
+
if (
|
| 684 |
+
isinstance(param, (PackedColumnParameter, PackedvLLMParameter))
|
| 685 |
+
and param.packed_dim == param.output_dim
|
| 686 |
+
):
|
| 687 |
+
shard_size, shard_offset = param.adjust_shard_indexes_for_packing(
|
| 688 |
+
shard_size=shard_size, shard_offset=shard_offset
|
| 689 |
+
)
|
| 690 |
+
|
| 691 |
+
loaded_weight_shard = loaded_weight.narrow(
|
| 692 |
+
param.output_dim, shard_offset, shard_size
|
| 693 |
+
)
|
| 694 |
+
self.weight_loader_v2(param, loaded_weight_shard, shard_id)
|
| 695 |
+
|
| 696 |
+
def weight_loader_v2(
|
| 697 |
+
self,
|
| 698 |
+
param: BasevLLMParameter,
|
| 699 |
+
loaded_weight: torch.Tensor,
|
| 700 |
+
loaded_shard_id: Optional[int] = None,
|
| 701 |
+
):
|
| 702 |
+
if loaded_shard_id is None:
|
| 703 |
+
if isinstance(param, PerTensorScaleParameter):
|
| 704 |
+
param.load_merged_column_weight(
|
| 705 |
+
loaded_weight=loaded_weight,
|
| 706 |
+
shard_id=0,
|
| 707 |
+
tp_rank=self.tp_rank,
|
| 708 |
+
tp_size=self.tp_size,
|
| 709 |
+
)
|
| 710 |
+
return
|
| 711 |
+
elif type(param) in (RowvLLMParameter, BasevLLMParameter):
|
| 712 |
+
param.load_merged_column_weight(
|
| 713 |
+
loaded_weight=loaded_weight,
|
| 714 |
+
tp_rank=self.tp_rank,
|
| 715 |
+
tp_size=self.tp_size,
|
| 716 |
+
)
|
| 717 |
+
return
|
| 718 |
+
# TODO: @dsikka - move to parameter.py
|
| 719 |
+
self._load_fused_module_from_checkpoint(param, loaded_weight)
|
| 720 |
+
return
|
| 721 |
+
|
| 722 |
+
assert loaded_shard_id < len(self.output_sizes)
|
| 723 |
+
|
| 724 |
+
if isinstance(param, BlockQuantScaleParameter):
|
| 725 |
+
weight_block_size = self.quant_method.quant_config.weight_block_size
|
| 726 |
+
block_n, _ = weight_block_size[0], weight_block_size[1]
|
| 727 |
+
shard_offset = (
|
| 728 |
+
(sum(self.output_sizes[:loaded_shard_id]) + block_n - 1) // block_n
|
| 729 |
+
) // self.tp_size
|
| 730 |
+
shard_size = (
|
| 731 |
+
(self.output_sizes[loaded_shard_id] + block_n - 1)
|
| 732 |
+
// block_n
|
| 733 |
+
// self.tp_size
|
| 734 |
+
)
|
| 735 |
+
else:
|
| 736 |
+
shard_offset = sum(self.output_sizes[:loaded_shard_id]) // self.tp_size
|
| 737 |
+
shard_size = self.output_sizes[loaded_shard_id] // self.tp_size
|
| 738 |
+
|
| 739 |
+
param.load_merged_column_weight(
|
| 740 |
+
loaded_weight=loaded_weight,
|
| 741 |
+
shard_id=loaded_shard_id,
|
| 742 |
+
shard_offset=shard_offset,
|
| 743 |
+
shard_size=shard_size,
|
| 744 |
+
use_presharded_weights=self.use_presharded_weights,
|
| 745 |
+
tp_rank=self.tp_rank,
|
| 746 |
+
tp_size=self.tp_size,
|
| 747 |
+
)
|
| 748 |
+
|
| 749 |
+
|
| 750 |
+
class QKVParallelLinear(ColumnParallelLinear):
|
| 751 |
+
"""Linear layers for the attention's QKV transformation.
|
| 752 |
+
|
| 753 |
+
Linear layers for the linear transformation of the query, key, and value
|
| 754 |
+
vectors in the attention layer. The weight matrix is concatenated along
|
| 755 |
+
the output dimension. The layer is parallelized along the head dimension.
|
| 756 |
+
When the number of key/value heads is smaller than the number of query
|
| 757 |
+
heads (e.g., multi-query/grouped-query attention), the key/value head may
|
| 758 |
+
be replicated while the query heads are partitioned.
|
| 759 |
+
|
| 760 |
+
Args:
|
| 761 |
+
hidden_size: input hidden state size of the transformer.
|
| 762 |
+
head_size: size of each attention head.
|
| 763 |
+
total_num_heads: total number of attention query heads.
|
| 764 |
+
total_num_kv_heads: total number of attention key/value heads. If
|
| 765 |
+
None, assume total_num_kv_heads = total_num_heads.
|
| 766 |
+
bias: If true, add bias.
|
| 767 |
+
skip_bias_add: This was added to enable performance optimizations where
|
| 768 |
+
bias can be fused with other element-wise operations. we
|
| 769 |
+
skip adding bias but instead return it.
|
| 770 |
+
params_dtype: Data type for the parameters.
|
| 771 |
+
quant_config: Quantization configure.
|
| 772 |
+
prefix: The name of the layer in the state dict, including all parents
|
| 773 |
+
(e.g. model.layers.0.qkv_proj)
|
| 774 |
+
"""
|
| 775 |
+
|
| 776 |
+
def __init__(
|
| 777 |
+
self,
|
| 778 |
+
hidden_size: int,
|
| 779 |
+
head_size: int,
|
| 780 |
+
total_num_heads: int,
|
| 781 |
+
total_num_kv_heads: Optional[int] = None,
|
| 782 |
+
bias: bool = True,
|
| 783 |
+
skip_bias_add: bool = False,
|
| 784 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 785 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 786 |
+
prefix: str = "",
|
| 787 |
+
tp_rank: Optional[int] = None,
|
| 788 |
+
tp_size: Optional[int] = None,
|
| 789 |
+
load_presharded_attn: bool = False,
|
| 790 |
+
):
|
| 791 |
+
self.hidden_size = hidden_size
|
| 792 |
+
self.head_size = head_size
|
| 793 |
+
self.total_num_heads = total_num_heads
|
| 794 |
+
if total_num_kv_heads is None:
|
| 795 |
+
total_num_kv_heads = total_num_heads
|
| 796 |
+
self.total_num_kv_heads = total_num_kv_heads
|
| 797 |
+
# Divide the weight matrix along the last dimension.
|
| 798 |
+
if tp_rank is None:
|
| 799 |
+
tp_rank = get_tensor_model_parallel_rank()
|
| 800 |
+
if tp_size is None:
|
| 801 |
+
tp_size = get_tensor_model_parallel_world_size()
|
| 802 |
+
self.tp_rank, self.tp_size = tp_rank, tp_size
|
| 803 |
+
self.num_heads = divide(self.total_num_heads, tp_size)
|
| 804 |
+
if tp_size >= self.total_num_kv_heads:
|
| 805 |
+
self.num_kv_heads = 1
|
| 806 |
+
self.num_kv_head_replicas = divide(tp_size, self.total_num_kv_heads)
|
| 807 |
+
else:
|
| 808 |
+
self.num_kv_heads = divide(self.total_num_kv_heads, tp_size)
|
| 809 |
+
self.num_kv_head_replicas = 1
|
| 810 |
+
self.q_proj_shard_size = self.num_heads * self.head_size
|
| 811 |
+
self.kv_proj_shard_size = self.num_kv_heads * self.head_size
|
| 812 |
+
input_size = self.hidden_size
|
| 813 |
+
output_size = (
|
| 814 |
+
(self.num_heads + 2 * self.num_kv_heads) * tp_size * self.head_size
|
| 815 |
+
)
|
| 816 |
+
self.output_sizes = [
|
| 817 |
+
self.num_heads * self.head_size * tp_size, # q_proj
|
| 818 |
+
self.num_kv_heads * self.head_size * tp_size, # k_proj
|
| 819 |
+
self.num_kv_heads * self.head_size * tp_size, # v_proj
|
| 820 |
+
]
|
| 821 |
+
self.use_presharded_weights = load_presharded_attn
|
| 822 |
+
|
| 823 |
+
super().__init__(
|
| 824 |
+
input_size=input_size,
|
| 825 |
+
output_size=output_size,
|
| 826 |
+
bias=bias,
|
| 827 |
+
gather_output=False,
|
| 828 |
+
skip_bias_add=skip_bias_add,
|
| 829 |
+
params_dtype=params_dtype,
|
| 830 |
+
quant_config=quant_config,
|
| 831 |
+
prefix=prefix,
|
| 832 |
+
tp_rank=tp_rank,
|
| 833 |
+
tp_size=tp_size,
|
| 834 |
+
use_presharded_weights=self.use_presharded_weights,
|
| 835 |
+
)
|
| 836 |
+
|
| 837 |
+
def _get_shard_offset_mapping(self, loaded_shard_id: str):
|
| 838 |
+
shard_offset_mapping = {
|
| 839 |
+
"q": 0,
|
| 840 |
+
"k": self.num_heads * self.head_size,
|
| 841 |
+
"v": (self.num_heads + self.num_kv_heads) * self.head_size,
|
| 842 |
+
"total": (self.num_heads + 2 * self.num_kv_heads) * self.head_size,
|
| 843 |
+
}
|
| 844 |
+
return shard_offset_mapping.get(loaded_shard_id)
|
| 845 |
+
|
| 846 |
+
def _get_shard_size_mapping(self, loaded_shard_id: str):
|
| 847 |
+
shard_size_mapping = {
|
| 848 |
+
"q": self.num_heads * self.head_size,
|
| 849 |
+
"k": self.num_kv_heads * self.head_size,
|
| 850 |
+
"v": self.num_kv_heads * self.head_size,
|
| 851 |
+
}
|
| 852 |
+
return shard_size_mapping.get(loaded_shard_id)
|
| 853 |
+
|
| 854 |
+
def _load_fused_module_from_checkpoint(
|
| 855 |
+
self, param: BasevLLMParameter, loaded_weight: torch.Tensor
|
| 856 |
+
):
|
| 857 |
+
"""
|
| 858 |
+
Handle special case for models where QKV layers are already
|
| 859 |
+
fused on disk. In this case, we have no shard id. This function
|
| 860 |
+
determmines the shard id by splitting these layers and then calls
|
| 861 |
+
the weight loader using the shard id.
|
| 862 |
+
|
| 863 |
+
An example of a model with these fused layers:
|
| 864 |
+
https://huggingface.co/microsoft/Phi-3-mini-4k-instruct
|
| 865 |
+
"""
|
| 866 |
+
shard_offsets = [
|
| 867 |
+
# (shard_id, shard_offset, shard_size)
|
| 868 |
+
("q", 0, self.total_num_heads * self.head_size),
|
| 869 |
+
(
|
| 870 |
+
"k",
|
| 871 |
+
self.total_num_heads * self.head_size,
|
| 872 |
+
self.total_num_kv_heads * self.head_size,
|
| 873 |
+
),
|
| 874 |
+
(
|
| 875 |
+
"v",
|
| 876 |
+
(self.total_num_heads + self.total_num_kv_heads) * self.head_size,
|
| 877 |
+
self.total_num_kv_heads * self.head_size,
|
| 878 |
+
),
|
| 879 |
+
]
|
| 880 |
+
|
| 881 |
+
for shard_id, shard_offset, shard_size in shard_offsets:
|
| 882 |
+
# Special case for Quantization.
|
| 883 |
+
# If quantized, we need to adjust the offset and size to account
|
| 884 |
+
# for the packing.
|
| 885 |
+
if (
|
| 886 |
+
isinstance(param, (PackedColumnParameter, PackedvLLMParameter))
|
| 887 |
+
and param.packed_dim == param.output_dim
|
| 888 |
+
):
|
| 889 |
+
shard_size, shard_offset = param.adjust_shard_indexes_for_packing(
|
| 890 |
+
shard_size=shard_size, shard_offset=shard_offset
|
| 891 |
+
)
|
| 892 |
+
|
| 893 |
+
if not self.use_presharded_weights:
|
| 894 |
+
loaded_weight_shard = loaded_weight.narrow(
|
| 895 |
+
param.output_dim, shard_offset, shard_size
|
| 896 |
+
)
|
| 897 |
+
self.weight_loader_v2(param, loaded_weight_shard, shard_id)
|
| 898 |
+
|
| 899 |
+
def weight_loader_v2(
|
| 900 |
+
self,
|
| 901 |
+
param: BasevLLMParameter,
|
| 902 |
+
loaded_weight: torch.Tensor,
|
| 903 |
+
loaded_shard_id: Optional[str] = None,
|
| 904 |
+
):
|
| 905 |
+
if loaded_shard_id is None: # special case for certain models
|
| 906 |
+
if isinstance(param, PerTensorScaleParameter):
|
| 907 |
+
param.load_qkv_weight(loaded_weight=loaded_weight, shard_id=0)
|
| 908 |
+
return
|
| 909 |
+
elif type(param) in (RowvLLMParameter, BasevLLMParameter):
|
| 910 |
+
param.load_qkv_weight(loaded_weight=loaded_weight)
|
| 911 |
+
return
|
| 912 |
+
# TODO: @dsikka - move to parameter.py
|
| 913 |
+
self._load_fused_module_from_checkpoint(param, loaded_weight)
|
| 914 |
+
return
|
| 915 |
+
|
| 916 |
+
assert loaded_shard_id in ["q", "k", "v"]
|
| 917 |
+
|
| 918 |
+
shard_offset = self._get_shard_offset_mapping(loaded_shard_id)
|
| 919 |
+
shard_size = self._get_shard_size_mapping(loaded_shard_id)
|
| 920 |
+
|
| 921 |
+
if isinstance(param, BlockQuantScaleParameter):
|
| 922 |
+
weight_block_size = self.quant_method.quant_config.weight_block_size
|
| 923 |
+
block_n, _ = weight_block_size[0], weight_block_size[1]
|
| 924 |
+
shard_offset = (shard_offset + block_n - 1) // block_n
|
| 925 |
+
shard_size = (shard_size + block_n - 1) // block_n
|
| 926 |
+
|
| 927 |
+
param.load_qkv_weight(
|
| 928 |
+
loaded_weight=loaded_weight,
|
| 929 |
+
num_heads=self.num_kv_head_replicas,
|
| 930 |
+
shard_id=loaded_shard_id,
|
| 931 |
+
shard_offset=shard_offset,
|
| 932 |
+
shard_size=shard_size,
|
| 933 |
+
tp_rank=self.tp_rank,
|
| 934 |
+
use_presharded_weights=self.use_presharded_weights,
|
| 935 |
+
)
|
| 936 |
+
|
| 937 |
+
def weight_loader(
|
| 938 |
+
self,
|
| 939 |
+
param: Parameter,
|
| 940 |
+
loaded_weight: torch.Tensor,
|
| 941 |
+
loaded_shard_id: Optional[str] = None,
|
| 942 |
+
):
|
| 943 |
+
|
| 944 |
+
# Special case for GGUF
|
| 945 |
+
# initialize GGUF param after we know the quantize type
|
| 946 |
+
is_gguf_weight = getattr(param, "is_gguf_weight", False)
|
| 947 |
+
is_gguf_weight_type = getattr(param, "is_gguf_weight_type", False)
|
| 948 |
+
if is_gguf_weight_type and loaded_shard_id is not None:
|
| 949 |
+
idx_map = {"q": 0, "k": 1, "v": 2}
|
| 950 |
+
param.data[idx_map[loaded_shard_id]].copy_(loaded_weight)
|
| 951 |
+
param.shard_weight_type[loaded_shard_id] = loaded_weight.item()
|
| 952 |
+
return
|
| 953 |
+
|
| 954 |
+
if is_gguf_weight:
|
| 955 |
+
output_dim = getattr(param, "output_dim", None)
|
| 956 |
+
shard_size = loaded_weight.size(output_dim) // self.tp_size
|
| 957 |
+
start_idx = self.tp_rank * shard_size
|
| 958 |
+
|
| 959 |
+
loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
|
| 960 |
+
|
| 961 |
+
param.shard_id.append(loaded_shard_id)
|
| 962 |
+
param.shard_id_map[loaded_shard_id] = len(param.data_container)
|
| 963 |
+
param.data_container.append(loaded_weight)
|
| 964 |
+
if len(param.data_container) == 3:
|
| 965 |
+
self.qweight = param.materialize_nested()
|
| 966 |
+
return
|
| 967 |
+
|
| 968 |
+
param_data = param.data
|
| 969 |
+
output_dim = getattr(param, "output_dim", None)
|
| 970 |
+
# Special case for AQLM codebooks.
|
| 971 |
+
is_metadata = getattr(param, "is_metadata", False)
|
| 972 |
+
|
| 973 |
+
# Special case for per-tensor scales in fused case.
|
| 974 |
+
needs_scalar_to_array = getattr(param, "needs_scalar_to_array", False)
|
| 975 |
+
|
| 976 |
+
if loaded_shard_id is None:
|
| 977 |
+
# Loaded weight is already fused on disk (qkv/mlp).
|
| 978 |
+
if output_dim is None:
|
| 979 |
+
if needs_scalar_to_array:
|
| 980 |
+
param_data, loaded_weight = adjust_scalar_to_fused_array(
|
| 981 |
+
param_data, loaded_weight, 0
|
| 982 |
+
)
|
| 983 |
+
|
| 984 |
+
assert param_data.shape == loaded_weight.shape
|
| 985 |
+
param_data.copy_(loaded_weight)
|
| 986 |
+
return
|
| 987 |
+
shard_offsets = [
|
| 988 |
+
# (shard_id, shard_offset, shard_size)
|
| 989 |
+
("q", 0, self.total_num_heads * self.head_size),
|
| 990 |
+
(
|
| 991 |
+
"k",
|
| 992 |
+
self.total_num_heads * self.head_size,
|
| 993 |
+
self.total_num_kv_heads * self.head_size,
|
| 994 |
+
),
|
| 995 |
+
(
|
| 996 |
+
"v",
|
| 997 |
+
(self.total_num_heads + self.total_num_kv_heads) * self.head_size,
|
| 998 |
+
self.total_num_kv_heads * self.head_size,
|
| 999 |
+
),
|
| 1000 |
+
]
|
| 1001 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 1002 |
+
|
| 1003 |
+
packed_dim = getattr(param, "packed_dim", None)
|
| 1004 |
+
for shard_id, shard_offset, shard_size in shard_offsets:
|
| 1005 |
+
# Special case for Quantized Weights.
|
| 1006 |
+
# If quantized, we need to adjust the offset and size to account
|
| 1007 |
+
# for the packing.
|
| 1008 |
+
if packed_dim == output_dim:
|
| 1009 |
+
shard_size = shard_size // param.pack_factor
|
| 1010 |
+
shard_offset = shard_offset // param.pack_factor
|
| 1011 |
+
|
| 1012 |
+
# Special case for Marlin.
|
| 1013 |
+
shard_size, shard_offset = adjust_marlin_shard(
|
| 1014 |
+
param, shard_size, shard_offset
|
| 1015 |
+
)
|
| 1016 |
+
|
| 1017 |
+
if use_bitsandbytes_4bit:
|
| 1018 |
+
orig_qkv_offsets = {
|
| 1019 |
+
"q": (0, self.total_num_heads * self.head_size),
|
| 1020 |
+
"k": (
|
| 1021 |
+
self.total_num_heads * self.head_size,
|
| 1022 |
+
self.total_num_kv_heads * self.head_size,
|
| 1023 |
+
),
|
| 1024 |
+
"v": (
|
| 1025 |
+
(self.total_num_heads + self.total_num_kv_heads)
|
| 1026 |
+
* self.head_size,
|
| 1027 |
+
self.total_num_kv_heads * self.head_size,
|
| 1028 |
+
),
|
| 1029 |
+
"total": (
|
| 1030 |
+
(self.total_num_heads + 2 * self.total_num_kv_heads)
|
| 1031 |
+
* self.head_size,
|
| 1032 |
+
0,
|
| 1033 |
+
),
|
| 1034 |
+
}
|
| 1035 |
+
|
| 1036 |
+
shard_size, shard_offset = adjust_bitsandbytes_4bit_shard(
|
| 1037 |
+
param, orig_qkv_offsets, shard_id
|
| 1038 |
+
)
|
| 1039 |
+
|
| 1040 |
+
if not self.use_presharded_weights:
|
| 1041 |
+
loaded_weight_shard = loaded_weight.narrow(
|
| 1042 |
+
output_dim, shard_offset, shard_size
|
| 1043 |
+
)
|
| 1044 |
+
self.weight_loader(param, loaded_weight_shard, shard_id)
|
| 1045 |
+
return
|
| 1046 |
+
|
| 1047 |
+
assert loaded_shard_id in ["q", "k", "v"]
|
| 1048 |
+
|
| 1049 |
+
# If output dim is defined, use the default loading process.
|
| 1050 |
+
if output_dim is not None:
|
| 1051 |
+
if loaded_shard_id == "q":
|
| 1052 |
+
shard_offset = 0
|
| 1053 |
+
shard_size = self.num_heads * self.head_size
|
| 1054 |
+
elif loaded_shard_id == "k":
|
| 1055 |
+
shard_offset = self.num_heads * self.head_size
|
| 1056 |
+
shard_size = self.num_kv_heads * self.head_size
|
| 1057 |
+
elif loaded_shard_id == "v":
|
| 1058 |
+
shard_offset = (self.num_heads + self.num_kv_heads) * self.head_size
|
| 1059 |
+
shard_size = self.num_kv_heads * self.head_size
|
| 1060 |
+
# Special case for Quantized Weights.
|
| 1061 |
+
# If quantized, we need to adjust the offset and size to account
|
| 1062 |
+
# for the packing.
|
| 1063 |
+
packed_dim = getattr(param, "packed_dim", None)
|
| 1064 |
+
if packed_dim == output_dim:
|
| 1065 |
+
shard_size = shard_size // param.pack_factor
|
| 1066 |
+
shard_offset = shard_offset // param.pack_factor
|
| 1067 |
+
|
| 1068 |
+
# Special case for Marlin.
|
| 1069 |
+
shard_size, shard_offset = adjust_marlin_shard(
|
| 1070 |
+
param, shard_size, shard_offset
|
| 1071 |
+
)
|
| 1072 |
+
|
| 1073 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 1074 |
+
if use_bitsandbytes_4bit:
|
| 1075 |
+
orig_qkv_offsets = {
|
| 1076 |
+
"q": (0, self.num_heads * self.head_size),
|
| 1077 |
+
"k": (
|
| 1078 |
+
self.num_heads * self.head_size,
|
| 1079 |
+
self.num_kv_heads * self.head_size,
|
| 1080 |
+
),
|
| 1081 |
+
"v": (
|
| 1082 |
+
(self.num_heads + self.num_kv_heads) * self.head_size,
|
| 1083 |
+
self.num_kv_heads * self.head_size,
|
| 1084 |
+
),
|
| 1085 |
+
"total": (
|
| 1086 |
+
(self.num_heads + 2 * self.num_kv_heads) * self.head_size,
|
| 1087 |
+
0,
|
| 1088 |
+
),
|
| 1089 |
+
}
|
| 1090 |
+
shard_size, shard_offset = adjust_bitsandbytes_4bit_shard(
|
| 1091 |
+
param, orig_qkv_offsets, loaded_shard_id
|
| 1092 |
+
)
|
| 1093 |
+
|
| 1094 |
+
param_data = param_data.narrow(output_dim, shard_offset, shard_size)
|
| 1095 |
+
if loaded_shard_id == "q":
|
| 1096 |
+
shard_id = self.tp_rank
|
| 1097 |
+
else:
|
| 1098 |
+
shard_id = self.tp_rank // self.num_kv_head_replicas
|
| 1099 |
+
start_idx = shard_id * shard_size
|
| 1100 |
+
|
| 1101 |
+
# bitsandbytes loads the weights of the specific portion
|
| 1102 |
+
# no need to narrow here
|
| 1103 |
+
if not use_bitsandbytes_4bit and not self.use_presharded_weights:
|
| 1104 |
+
loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
|
| 1105 |
+
|
| 1106 |
+
# Special case for for AQLM codebooks.
|
| 1107 |
+
elif is_metadata:
|
| 1108 |
+
# metadata indicates fixed size concatenated along dim 0
|
| 1109 |
+
shard_size = loaded_weight.shape[0]
|
| 1110 |
+
shard_index = ["q", "k", "v"].index(loaded_shard_id)
|
| 1111 |
+
param_data = param_data.narrow(0, shard_index * shard_size, shard_size)
|
| 1112 |
+
# Special case for per-tensor scales in fused case.
|
| 1113 |
+
elif needs_scalar_to_array:
|
| 1114 |
+
param_data, loaded_weight = adjust_scalar_to_fused_array(
|
| 1115 |
+
param_data, loaded_weight, loaded_shard_id
|
| 1116 |
+
)
|
| 1117 |
+
else:
|
| 1118 |
+
ignore_warning = getattr(param, "ignore_warning", False)
|
| 1119 |
+
if not ignore_warning:
|
| 1120 |
+
logger.warning(
|
| 1121 |
+
"Loading a weight without `output_dim` attribute in "
|
| 1122 |
+
"QKVParallelLinear, assume the weight is the same "
|
| 1123 |
+
"for all partitions."
|
| 1124 |
+
)
|
| 1125 |
+
|
| 1126 |
+
assert param_data.shape == loaded_weight.shape
|
| 1127 |
+
param_data.copy_(loaded_weight)
|
| 1128 |
+
|
| 1129 |
+
|
| 1130 |
+
class RowParallelLinear(LinearBase):
|
| 1131 |
+
"""Linear layer with row parallelism.
|
| 1132 |
+
|
| 1133 |
+
The linear layer is defined as Y = XA + b. A is parallelized along
|
| 1134 |
+
its first dimension and X along its second dimension as:
|
| 1135 |
+
- -
|
| 1136 |
+
| A_1 |
|
| 1137 |
+
| . |
|
| 1138 |
+
A = | . | X = [X_1, ..., X_p]
|
| 1139 |
+
| . |
|
| 1140 |
+
| A_p |
|
| 1141 |
+
- -
|
| 1142 |
+
Arguments:
|
| 1143 |
+
input_size: first dimension of matrix A.
|
| 1144 |
+
output_size: second dimension of matrix A.
|
| 1145 |
+
bias: If true, add bias. Note that bias is not parallelized.
|
| 1146 |
+
input_is_parallel: If true, we assume that the input is already
|
| 1147 |
+
split across the GPUs and we do not split
|
| 1148 |
+
again.
|
| 1149 |
+
skip_bias_add: This was added to enable performance optimization where
|
| 1150 |
+
bias can be fused with other element-wise operations.
|
| 1151 |
+
We skip adding bias but instead return it.
|
| 1152 |
+
params_dtype: Data type for the parameters.
|
| 1153 |
+
quant_config: Quantization configure.
|
| 1154 |
+
"""
|
| 1155 |
+
|
| 1156 |
+
def __init__(
|
| 1157 |
+
self,
|
| 1158 |
+
input_size: int,
|
| 1159 |
+
output_size: int,
|
| 1160 |
+
bias: bool = True,
|
| 1161 |
+
input_is_parallel: bool = True,
|
| 1162 |
+
skip_bias_add: bool = False,
|
| 1163 |
+
params_dtype: Optional[torch.dtype] = None,
|
| 1164 |
+
reduce_results: bool = True,
|
| 1165 |
+
quant_config: Optional[QuantizationConfig] = None,
|
| 1166 |
+
prefix: str = "",
|
| 1167 |
+
tp_rank: Optional[int] = None,
|
| 1168 |
+
tp_size: Optional[int] = None,
|
| 1169 |
+
use_presharded_weights: bool = False,
|
| 1170 |
+
):
|
| 1171 |
+
super().__init__(
|
| 1172 |
+
input_size, output_size, skip_bias_add, params_dtype, quant_config, prefix
|
| 1173 |
+
)
|
| 1174 |
+
|
| 1175 |
+
self.input_is_parallel = input_is_parallel
|
| 1176 |
+
self.reduce_results = reduce_results
|
| 1177 |
+
|
| 1178 |
+
# Divide the weight matrix along the last dimension.
|
| 1179 |
+
if tp_rank is None:
|
| 1180 |
+
tp_rank = get_tensor_model_parallel_rank()
|
| 1181 |
+
if tp_size is None:
|
| 1182 |
+
tp_size = get_tensor_model_parallel_world_size()
|
| 1183 |
+
self.tp_rank, self.tp_size = tp_rank, tp_size
|
| 1184 |
+
self.input_size_per_partition = divide(input_size, self.tp_size)
|
| 1185 |
+
assert self.quant_method is not None
|
| 1186 |
+
self.use_presharded_weights = use_presharded_weights
|
| 1187 |
+
|
| 1188 |
+
self.quant_method.create_weights(
|
| 1189 |
+
layer=self,
|
| 1190 |
+
input_size_per_partition=self.input_size_per_partition,
|
| 1191 |
+
output_partition_sizes=[self.output_size],
|
| 1192 |
+
input_size=self.input_size,
|
| 1193 |
+
output_size=self.output_size,
|
| 1194 |
+
params_dtype=self.params_dtype,
|
| 1195 |
+
weight_loader=(
|
| 1196 |
+
self.weight_loader_v2
|
| 1197 |
+
if self.quant_method.__class__.__name__ in WEIGHT_LOADER_V2_SUPPORTED
|
| 1198 |
+
else self.weight_loader
|
| 1199 |
+
),
|
| 1200 |
+
)
|
| 1201 |
+
if not reduce_results and (bias and not skip_bias_add):
|
| 1202 |
+
raise ValueError(
|
| 1203 |
+
"When not reduce the results, adding bias to the "
|
| 1204 |
+
"results can lead to incorrect results"
|
| 1205 |
+
)
|
| 1206 |
+
|
| 1207 |
+
if bias:
|
| 1208 |
+
self.bias = Parameter(torch.empty(self.output_size, dtype=params_dtype))
|
| 1209 |
+
set_weight_attrs(
|
| 1210 |
+
self.bias,
|
| 1211 |
+
{
|
| 1212 |
+
"output_dim": 0,
|
| 1213 |
+
"weight_loader": self.weight_loader,
|
| 1214 |
+
},
|
| 1215 |
+
)
|
| 1216 |
+
else:
|
| 1217 |
+
self.register_parameter("bias", None)
|
| 1218 |
+
|
| 1219 |
+
def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
|
| 1220 |
+
input_dim = getattr(param, "input_dim", None)
|
| 1221 |
+
use_bitsandbytes_4bit = getattr(param, "use_bitsandbytes_4bit", False)
|
| 1222 |
+
|
| 1223 |
+
# Special case for GGUF
|
| 1224 |
+
is_gguf_weight = getattr(param, "is_gguf_weight", False)
|
| 1225 |
+
is_gguf_weight_type = getattr(param, "is_gguf_weight_type", False)
|
| 1226 |
+
if is_gguf_weight_type:
|
| 1227 |
+
param.weight_type = loaded_weight.item()
|
| 1228 |
+
|
| 1229 |
+
# Materialize GGUF UninitializedParameter
|
| 1230 |
+
if is_gguf_weight and isinstance(param, UninitializedParameter):
|
| 1231 |
+
weight_shape = list(loaded_weight.shape)
|
| 1232 |
+
if input_dim:
|
| 1233 |
+
weight_shape[input_dim] = weight_shape[input_dim] // self.tp_size
|
| 1234 |
+
param.materialize(tuple(weight_shape), dtype=loaded_weight.dtype)
|
| 1235 |
+
|
| 1236 |
+
param_data = param.data
|
| 1237 |
+
# bitsandbytes loads the weights of the specific portion
|
| 1238 |
+
# no need to narrow here
|
| 1239 |
+
if (
|
| 1240 |
+
input_dim is not None
|
| 1241 |
+
and not use_bitsandbytes_4bit
|
| 1242 |
+
and not self.use_presharded_weights
|
| 1243 |
+
):
|
| 1244 |
+
shard_size = param_data.shape[input_dim]
|
| 1245 |
+
start_idx = self.tp_rank * shard_size
|
| 1246 |
+
loaded_weight = loaded_weight.narrow(input_dim, start_idx, shard_size)
|
| 1247 |
+
|
| 1248 |
+
# Special case for loading scales off disk, which often do not
|
| 1249 |
+
# have a shape (such as in the case of AutoFP8).
|
| 1250 |
+
if len(loaded_weight.shape) == 0:
|
| 1251 |
+
loaded_weight = loaded_weight.reshape(1)
|
| 1252 |
+
|
| 1253 |
+
assert param_data.shape == loaded_weight.shape
|
| 1254 |
+
param_data.copy_(loaded_weight)
|
| 1255 |
+
|
| 1256 |
+
def weight_loader_v2(self, param: BasevLLMParameter, loaded_weight: torch.Tensor):
|
| 1257 |
+
|
| 1258 |
+
# Special case for loading scales off disk, which often do not
|
| 1259 |
+
# have a shape (such as in the case of AutoFP8).
|
| 1260 |
+
if len(loaded_weight.shape) == 0:
|
| 1261 |
+
assert loaded_weight.numel() == 1
|
| 1262 |
+
loaded_weight = loaded_weight.reshape(1)
|
| 1263 |
+
|
| 1264 |
+
if isinstance(param, RowvLLMParameter):
|
| 1265 |
+
# This `BasevLLMParameter` is defined in sglang/srt/layers/parameter.py,
|
| 1266 |
+
# It supports additional parameters like tp_rank and use_presharded_weights.
|
| 1267 |
+
param.load_row_parallel_weight(
|
| 1268 |
+
loaded_weight,
|
| 1269 |
+
tp_rank=self.tp_rank,
|
| 1270 |
+
use_presharded_weights=self.use_presharded_weights,
|
| 1271 |
+
)
|
| 1272 |
+
else:
|
| 1273 |
+
# `params` is defined in `vllm/model_executor/parameter.py`,
|
| 1274 |
+
# It does not support additional parameters.
|
| 1275 |
+
param.load_row_parallel_weight(loaded_weight)
|
| 1276 |
+
|
| 1277 |
+
def forward(self, input_):
|
| 1278 |
+
if self.input_is_parallel:
|
| 1279 |
+
input_parallel = input_
|
| 1280 |
+
else:
|
| 1281 |
+
splitted_input = split_tensor_along_last_dim(
|
| 1282 |
+
input_, num_partitions=self.tp_size
|
| 1283 |
+
)
|
| 1284 |
+
input_parallel = splitted_input[self.tp_rank].contiguous()
|
| 1285 |
+
|
| 1286 |
+
# Matrix multiply.
|
| 1287 |
+
assert self.quant_method is not None
|
| 1288 |
+
# Only fuse bias add into GEMM for rank 0 (this ensures that
|
| 1289 |
+
# bias will not get added more than once in TP>1 case)
|
| 1290 |
+
bias_ = None if (self.tp_rank > 0 or self.skip_bias_add) else self.bias
|
| 1291 |
+
output_parallel = self.quant_method.apply(self, input_parallel, bias=bias_)
|
| 1292 |
+
if self.reduce_results and self.tp_size > 1:
|
| 1293 |
+
output = tensor_model_parallel_all_reduce(output_parallel)
|
| 1294 |
+
else:
|
| 1295 |
+
output = output_parallel
|
| 1296 |
+
|
| 1297 |
+
output_bias = self.bias if self.skip_bias_add else None
|
| 1298 |
+
|
| 1299 |
+
return output, output_bias
|
| 1300 |
+
|
| 1301 |
+
def extra_repr(self) -> str:
|
| 1302 |
+
s = f"input_features={self.input_size_per_partition}"
|
| 1303 |
+
s += f", output_features={self.output_size}"
|
| 1304 |
+
s += f", bias={self.bias is not None}"
|
| 1305 |
+
s += f", tp_size={self.tp_size}"
|
| 1306 |
+
s += f", reduce_results={self.reduce_results}"
|
| 1307 |
+
return s
|
lib/python3.12/site-packages/sglang/srt/layers/logits_processor.py
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023-2024 SGLang Team
|
| 2 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 3 |
+
# you may not use this file except in compliance with the License.
|
| 4 |
+
# You may obtain a copy of the License at
|
| 5 |
+
#
|
| 6 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 7 |
+
#
|
| 8 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 9 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 10 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 11 |
+
# See the License for the specific language governing permissions and
|
| 12 |
+
# limitations under the License.
|
| 13 |
+
# ==============================================================================
|
| 14 |
+
"""Logits processing."""
|
| 15 |
+
|
| 16 |
+
import dataclasses
|
| 17 |
+
import logging
|
| 18 |
+
from typing import List, Optional, Union
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
import triton
|
| 22 |
+
import triton.language as tl
|
| 23 |
+
from torch import nn
|
| 24 |
+
|
| 25 |
+
from sglang.srt.distributed import (
|
| 26 |
+
get_tensor_model_parallel_rank,
|
| 27 |
+
get_tensor_model_parallel_world_size,
|
| 28 |
+
tensor_model_parallel_all_gather,
|
| 29 |
+
)
|
| 30 |
+
from sglang.srt.layers.dp_attention import (
|
| 31 |
+
dp_gather_replicate,
|
| 32 |
+
dp_scatter,
|
| 33 |
+
get_attention_dp_rank,
|
| 34 |
+
get_attention_dp_size,
|
| 35 |
+
)
|
| 36 |
+
from sglang.srt.layers.vocab_parallel_embedding import VocabParallelEmbedding
|
| 37 |
+
from sglang.srt.managers.schedule_batch import global_server_args_dict
|
| 38 |
+
from sglang.srt.model_executor.forward_batch_info import (
|
| 39 |
+
CaptureHiddenMode,
|
| 40 |
+
ForwardBatch,
|
| 41 |
+
ForwardMode,
|
| 42 |
+
)
|
| 43 |
+
from sglang.srt.utils import dump_to_file
|
| 44 |
+
|
| 45 |
+
logger = logging.getLogger(__name__)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
@dataclasses.dataclass
|
| 49 |
+
class LogitsProcessorOutput:
|
| 50 |
+
## Part 1: This part will be assigned in python/sglang/srt/layers/logits_processor.py::LogitsProcessor
|
| 51 |
+
# The logits of the next tokens. shape: [#seq, vocab_size]
|
| 52 |
+
next_token_logits: torch.Tensor
|
| 53 |
+
# Used by speculative decoding (EAGLE)
|
| 54 |
+
# The last hidden layers
|
| 55 |
+
hidden_states: Optional[torch.Tensor] = None
|
| 56 |
+
|
| 57 |
+
## Part 2: This part will be assigned in python/sglang/srt/layers/sampler.py::Sampler
|
| 58 |
+
# The logprobs of the next tokens. shape: [#seq]
|
| 59 |
+
next_token_logprobs: Optional[torch.Tensor] = None
|
| 60 |
+
# The logprobs and ids of the top-k tokens in output positions. shape: [#seq, k]
|
| 61 |
+
next_token_top_logprobs_val: Optional[List] = None
|
| 62 |
+
next_token_top_logprobs_idx: Optional[List] = None
|
| 63 |
+
# The logprobs and ids of the requested token ids in output positions. shape: [#seq, n] (n is the number of requested token ids)
|
| 64 |
+
next_token_token_ids_logprobs_val: Optional[List] = None
|
| 65 |
+
next_token_token_ids_logprobs_idx: Optional[List] = None
|
| 66 |
+
|
| 67 |
+
## Part 3: Prefill-only. This part will be assigned in python/sglang/srt/layers/logits_processor.py::LogitsProcessor
|
| 68 |
+
# The logprobs of input tokens. shape: [#token]
|
| 69 |
+
input_token_logprobs: Optional[torch.Tensor] = None
|
| 70 |
+
# The logprobs and ids of the top-k tokens in input positions. shape: [#seq, #token, k]
|
| 71 |
+
input_top_logprobs_val: List = None
|
| 72 |
+
input_top_logprobs_idx: List = None
|
| 73 |
+
# The logprobs and ids of the requested token ids in input positions. shape: [#seq, n] (n is the number of requested token ids)
|
| 74 |
+
input_token_ids_logprobs_val: Optional[List] = None
|
| 75 |
+
input_token_ids_logprobs_idx: Optional[List] = None
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
@dataclasses.dataclass
|
| 79 |
+
class LogitsMetadata:
|
| 80 |
+
forward_mode: ForwardMode
|
| 81 |
+
capture_hidden_mode: CaptureHiddenMode = CaptureHiddenMode.NULL
|
| 82 |
+
|
| 83 |
+
extend_return_logprob: bool = False
|
| 84 |
+
extend_return_top_logprob: bool = False
|
| 85 |
+
extend_token_ids_logprob: bool = False
|
| 86 |
+
extend_seq_lens: Optional[torch.Tensor] = None
|
| 87 |
+
extend_seq_lens_cpu: Optional[List[int]] = None
|
| 88 |
+
extend_logprob_start_lens_cpu: Optional[List[int]] = None
|
| 89 |
+
extend_logprob_pruned_lens_cpu: Optional[List[int]] = None
|
| 90 |
+
top_logprobs_nums: Optional[List[int]] = None
|
| 91 |
+
extend_input_logprob_token_ids_gpu: Optional[torch.Tensor] = None
|
| 92 |
+
token_ids_logprobs: Optional[List[List[int]]] = None
|
| 93 |
+
|
| 94 |
+
# logits and logprobs post processing
|
| 95 |
+
temp_scaled_logprobs: bool = False
|
| 96 |
+
temperature: torch.Tensor = None
|
| 97 |
+
top_p_normalized_logprobs: bool = False
|
| 98 |
+
top_p: torch.Tensor = None
|
| 99 |
+
|
| 100 |
+
# DP attention metadata. Not needed when DP attention is not used.
|
| 101 |
+
# Number of tokens in the request.
|
| 102 |
+
global_num_tokens_gpu: Optional[torch.Tensor] = None
|
| 103 |
+
# The start position of local hidden states.
|
| 104 |
+
dp_local_start_pos: Optional[torch.Tensor] = None
|
| 105 |
+
dp_local_num_tokens: Optional[torch.Tensor] = None
|
| 106 |
+
gathered_buffer: Optional[torch.Tensor] = None
|
| 107 |
+
# Buffer to gather logits from all ranks.
|
| 108 |
+
forward_batch_gathered_buffer: Optional[torch.Tensor] = None
|
| 109 |
+
# Number of tokens to sample per DP rank
|
| 110 |
+
global_num_tokens_for_logprob_cpu: Optional[torch.Tensor] = None
|
| 111 |
+
global_num_tokens_for_logprob_gpu: Optional[torch.Tensor] = None
|
| 112 |
+
|
| 113 |
+
# for padding
|
| 114 |
+
padded_static_len: int = -1
|
| 115 |
+
|
| 116 |
+
@classmethod
|
| 117 |
+
def from_forward_batch(cls, forward_batch: ForwardBatch):
|
| 118 |
+
if (
|
| 119 |
+
forward_batch.forward_mode.is_extend()
|
| 120 |
+
and forward_batch.return_logprob
|
| 121 |
+
and not forward_batch.forward_mode.is_target_verify()
|
| 122 |
+
):
|
| 123 |
+
extend_return_top_logprob = any(
|
| 124 |
+
x > 0 for x in forward_batch.top_logprobs_nums
|
| 125 |
+
)
|
| 126 |
+
extend_token_ids_logprob = any(
|
| 127 |
+
x is not None for x in forward_batch.token_ids_logprobs
|
| 128 |
+
)
|
| 129 |
+
extend_return_logprob = False
|
| 130 |
+
extend_logprob_pruned_lens_cpu = []
|
| 131 |
+
for extend_len, start_len in zip(
|
| 132 |
+
forward_batch.extend_seq_lens_cpu,
|
| 133 |
+
forward_batch.extend_logprob_start_lens_cpu,
|
| 134 |
+
):
|
| 135 |
+
if extend_len - start_len > 0:
|
| 136 |
+
extend_return_logprob = True
|
| 137 |
+
extend_logprob_pruned_lens_cpu.append(extend_len - start_len)
|
| 138 |
+
else:
|
| 139 |
+
extend_return_logprob = extend_return_top_logprob = (
|
| 140 |
+
extend_token_ids_logprob
|
| 141 |
+
) = extend_logprob_pruned_lens_cpu = False
|
| 142 |
+
|
| 143 |
+
return cls(
|
| 144 |
+
forward_mode=forward_batch.forward_mode,
|
| 145 |
+
capture_hidden_mode=forward_batch.capture_hidden_mode,
|
| 146 |
+
extend_return_logprob=extend_return_logprob,
|
| 147 |
+
extend_return_top_logprob=extend_return_top_logprob,
|
| 148 |
+
extend_token_ids_logprob=extend_token_ids_logprob,
|
| 149 |
+
extend_seq_lens=forward_batch.extend_seq_lens,
|
| 150 |
+
extend_seq_lens_cpu=forward_batch.extend_seq_lens_cpu,
|
| 151 |
+
extend_logprob_start_lens_cpu=forward_batch.extend_logprob_start_lens_cpu,
|
| 152 |
+
extend_logprob_pruned_lens_cpu=extend_logprob_pruned_lens_cpu,
|
| 153 |
+
top_logprobs_nums=forward_batch.top_logprobs_nums,
|
| 154 |
+
token_ids_logprobs=forward_batch.token_ids_logprobs,
|
| 155 |
+
extend_input_logprob_token_ids_gpu=forward_batch.extend_input_logprob_token_ids_gpu,
|
| 156 |
+
padded_static_len=forward_batch.padded_static_len,
|
| 157 |
+
global_num_tokens_gpu=forward_batch.global_num_tokens_gpu,
|
| 158 |
+
dp_local_start_pos=forward_batch.dp_local_start_pos,
|
| 159 |
+
dp_local_num_tokens=forward_batch.dp_local_num_tokens,
|
| 160 |
+
gathered_buffer=forward_batch.gathered_buffer,
|
| 161 |
+
forward_batch_gathered_buffer=forward_batch.gathered_buffer,
|
| 162 |
+
global_num_tokens_for_logprob_cpu=forward_batch.global_num_tokens_for_logprob_cpu,
|
| 163 |
+
global_num_tokens_for_logprob_gpu=forward_batch.global_num_tokens_for_logprob_gpu,
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
def compute_dp_attention_metadata(self, hidden_states: torch.Tensor):
|
| 167 |
+
if self.global_num_tokens_for_logprob_cpu is None:
|
| 168 |
+
# we are capturing cuda graph
|
| 169 |
+
return
|
| 170 |
+
|
| 171 |
+
cumtokens = torch.cumsum(self.global_num_tokens_for_logprob_gpu, dim=0)
|
| 172 |
+
dp_rank = get_attention_dp_rank()
|
| 173 |
+
if dp_rank == 0:
|
| 174 |
+
dp_local_start_pos = torch.zeros_like(
|
| 175 |
+
self.global_num_tokens_for_logprob_gpu[0]
|
| 176 |
+
)
|
| 177 |
+
else:
|
| 178 |
+
dp_local_start_pos = cumtokens[dp_rank - 1]
|
| 179 |
+
dp_local_num_tokens = self.global_num_tokens_for_logprob_gpu[dp_rank]
|
| 180 |
+
gathered_buffer = torch.zeros(
|
| 181 |
+
(
|
| 182 |
+
sum(self.global_num_tokens_for_logprob_cpu),
|
| 183 |
+
hidden_states.shape[1],
|
| 184 |
+
),
|
| 185 |
+
dtype=hidden_states.dtype,
|
| 186 |
+
device=hidden_states.device,
|
| 187 |
+
)
|
| 188 |
+
|
| 189 |
+
self.dp_local_start_pos = dp_local_start_pos
|
| 190 |
+
self.dp_local_num_tokens = dp_local_num_tokens
|
| 191 |
+
self.gathered_buffer = gathered_buffer
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
class LogitsProcessor(nn.Module):
|
| 195 |
+
def __init__(
|
| 196 |
+
self, config, skip_all_gather: bool = False, logit_scale: Optional[float] = None
|
| 197 |
+
):
|
| 198 |
+
super().__init__()
|
| 199 |
+
self.config = config
|
| 200 |
+
self.logit_scale = logit_scale
|
| 201 |
+
self.do_tensor_parallel_all_gather = (
|
| 202 |
+
not skip_all_gather and get_tensor_model_parallel_world_size() > 1
|
| 203 |
+
)
|
| 204 |
+
self.do_tensor_parallel_all_gather_dp_attn = (
|
| 205 |
+
self.do_tensor_parallel_all_gather and get_attention_dp_size() != 1
|
| 206 |
+
)
|
| 207 |
+
self.final_logit_softcapping = getattr(
|
| 208 |
+
self.config, "final_logit_softcapping", None
|
| 209 |
+
)
|
| 210 |
+
if (
|
| 211 |
+
self.final_logit_softcapping is not None
|
| 212 |
+
and self.final_logit_softcapping < 0
|
| 213 |
+
):
|
| 214 |
+
self.final_logit_softcapping = None
|
| 215 |
+
|
| 216 |
+
self.debug_tensor_dump_output_folder = global_server_args_dict.get(
|
| 217 |
+
"debug_tensor_dump_output_folder", None
|
| 218 |
+
)
|
| 219 |
+
|
| 220 |
+
def forward(
|
| 221 |
+
self,
|
| 222 |
+
input_ids,
|
| 223 |
+
hidden_states,
|
| 224 |
+
lm_head: VocabParallelEmbedding,
|
| 225 |
+
logits_metadata: Union[LogitsMetadata, ForwardBatch],
|
| 226 |
+
aux_hidden_states: Optional[torch.Tensor] = None,
|
| 227 |
+
) -> LogitsProcessorOutput:
|
| 228 |
+
if isinstance(logits_metadata, ForwardBatch):
|
| 229 |
+
logits_metadata = LogitsMetadata.from_forward_batch(logits_metadata)
|
| 230 |
+
# Get the last hidden states and last logits for the next token prediction
|
| 231 |
+
if (
|
| 232 |
+
logits_metadata.forward_mode.is_decode_or_idle()
|
| 233 |
+
or logits_metadata.forward_mode.is_target_verify()
|
| 234 |
+
):
|
| 235 |
+
pruned_states = hidden_states
|
| 236 |
+
if aux_hidden_states is not None:
|
| 237 |
+
aux_pruned_states = [hidden for hidden in aux_hidden_states]
|
| 238 |
+
sample_indices = None
|
| 239 |
+
input_logprob_indices = None
|
| 240 |
+
elif (
|
| 241 |
+
logits_metadata.forward_mode.is_extend()
|
| 242 |
+
and not logits_metadata.extend_return_logprob
|
| 243 |
+
):
|
| 244 |
+
# Prefill without input logprobs.
|
| 245 |
+
if logits_metadata.padded_static_len < 0:
|
| 246 |
+
last_index = torch.cumsum(logits_metadata.extend_seq_lens, dim=0) - 1
|
| 247 |
+
else:
|
| 248 |
+
# If padding_static length is 5 and extended_seq_lens is [2, 3],
|
| 249 |
+
# then our batch looks like [t00, t01, p, p, p, t10, t11, t12, p, p]
|
| 250 |
+
# and this retrieves t01 and t12, which are the valid last tokens
|
| 251 |
+
idx = torch.arange(
|
| 252 |
+
len(logits_metadata.extend_seq_lens),
|
| 253 |
+
device=logits_metadata.extend_seq_lens.device,
|
| 254 |
+
)
|
| 255 |
+
last_index = (
|
| 256 |
+
idx * logits_metadata.padded_static_len
|
| 257 |
+
+ logits_metadata.extend_seq_lens
|
| 258 |
+
- 1
|
| 259 |
+
)
|
| 260 |
+
pruned_states = hidden_states[last_index]
|
| 261 |
+
if aux_hidden_states is not None:
|
| 262 |
+
aux_pruned_states = [hidden[last_index] for hidden in aux_hidden_states]
|
| 263 |
+
sample_indices = None
|
| 264 |
+
input_logprob_indices = None
|
| 265 |
+
else:
|
| 266 |
+
# Input logprobs are required.
|
| 267 |
+
# Find 3 different indices.
|
| 268 |
+
# 1. pruned_states: hidden states that we want logprobs from.
|
| 269 |
+
# 2. sample_indices: Indices that have sampled tokens.
|
| 270 |
+
# 3. input_logprob_indices: Indices that have input logprob tokens.
|
| 271 |
+
sample_index_pt = -1
|
| 272 |
+
sample_indices = []
|
| 273 |
+
input_logprob_indices_pt = 0
|
| 274 |
+
input_logprob_indices = []
|
| 275 |
+
pt, pruned_states = 0, []
|
| 276 |
+
for extend_logprob_start_len, extend_len in zip(
|
| 277 |
+
logits_metadata.extend_logprob_start_lens_cpu,
|
| 278 |
+
logits_metadata.extend_seq_lens_cpu,
|
| 279 |
+
):
|
| 280 |
+
# It can happen in chunked prefill. We still need to sample 1 token,
|
| 281 |
+
# But we don't want to include it in input logprob.
|
| 282 |
+
if extend_len == extend_logprob_start_len:
|
| 283 |
+
start_len = extend_logprob_start_len - 1
|
| 284 |
+
else:
|
| 285 |
+
start_len = extend_logprob_start_len
|
| 286 |
+
|
| 287 |
+
# We always need at least 1 token to sample because that's required
|
| 288 |
+
# by a caller.
|
| 289 |
+
assert extend_len > start_len
|
| 290 |
+
pruned_states.append(hidden_states[pt + start_len : pt + extend_len])
|
| 291 |
+
pt += extend_len
|
| 292 |
+
sample_index_pt += extend_len - start_len
|
| 293 |
+
sample_indices.append(sample_index_pt)
|
| 294 |
+
input_logprob_indices.extend(
|
| 295 |
+
[
|
| 296 |
+
input_logprob_indices_pt + i
|
| 297 |
+
for i in range(extend_len - extend_logprob_start_len)
|
| 298 |
+
]
|
| 299 |
+
)
|
| 300 |
+
input_logprob_indices_pt += extend_len - start_len
|
| 301 |
+
|
| 302 |
+
pruned_states = torch.cat(pruned_states)
|
| 303 |
+
sample_indices = torch.tensor(
|
| 304 |
+
sample_indices, device=pruned_states.device, dtype=torch.int64
|
| 305 |
+
)
|
| 306 |
+
input_logprob_indices = torch.tensor(
|
| 307 |
+
input_logprob_indices, device=pruned_states.device, dtype=torch.int64
|
| 308 |
+
)
|
| 309 |
+
|
| 310 |
+
# Compute logits for both input and sampled tokens.
|
| 311 |
+
logits = self._get_logits(pruned_states, lm_head, logits_metadata)
|
| 312 |
+
sampled_logits = (
|
| 313 |
+
logits[sample_indices] if sample_indices is not None else logits
|
| 314 |
+
)
|
| 315 |
+
|
| 316 |
+
if self.debug_tensor_dump_output_folder:
|
| 317 |
+
assert (
|
| 318 |
+
not self.do_tensor_parallel_all_gather or get_attention_dp_size() == 1
|
| 319 |
+
), "dp attention + sharded lm_head doesn't support full logits"
|
| 320 |
+
full_logits = self._get_logits(hidden_states, lm_head, logits_metadata)
|
| 321 |
+
dump_to_file(self.debug_tensor_dump_output_folder, "logits", full_logits)
|
| 322 |
+
|
| 323 |
+
hidden_states_to_store: Optional[torch.Tensor] = None
|
| 324 |
+
if logits_metadata.capture_hidden_mode.need_capture():
|
| 325 |
+
if logits_metadata.capture_hidden_mode.is_full():
|
| 326 |
+
if aux_hidden_states is not None:
|
| 327 |
+
aux_hidden_states = torch.cat(aux_hidden_states, dim=-1)
|
| 328 |
+
hidden_states_to_store = aux_hidden_states
|
| 329 |
+
else:
|
| 330 |
+
hidden_states_to_store = hidden_states
|
| 331 |
+
elif logits_metadata.capture_hidden_mode.is_last():
|
| 332 |
+
# Get the last token hidden states. If sample_indices is None,
|
| 333 |
+
# pruned states only contain the last tokens already.
|
| 334 |
+
if aux_hidden_states is not None:
|
| 335 |
+
aux_pruned_states = torch.cat(aux_pruned_states, dim=-1)
|
| 336 |
+
hidden_states_to_store = (
|
| 337 |
+
aux_pruned_states[sample_indices]
|
| 338 |
+
if sample_indices is not None
|
| 339 |
+
else aux_pruned_states
|
| 340 |
+
)
|
| 341 |
+
else:
|
| 342 |
+
hidden_states_to_store = (
|
| 343 |
+
pruned_states[sample_indices]
|
| 344 |
+
if sample_indices is not None
|
| 345 |
+
else pruned_states
|
| 346 |
+
)
|
| 347 |
+
else:
|
| 348 |
+
assert False, "Should never reach"
|
| 349 |
+
|
| 350 |
+
if not logits_metadata.extend_return_logprob:
|
| 351 |
+
# Decode mode or extend mode without return_logprob.
|
| 352 |
+
return LogitsProcessorOutput(
|
| 353 |
+
next_token_logits=sampled_logits,
|
| 354 |
+
hidden_states=hidden_states_to_store,
|
| 355 |
+
)
|
| 356 |
+
else:
|
| 357 |
+
input_logprobs = logits[input_logprob_indices]
|
| 358 |
+
del hidden_states, logits
|
| 359 |
+
|
| 360 |
+
# Normalize the logprob w/o temperature, top-p
|
| 361 |
+
pruned_lens = torch.tensor(
|
| 362 |
+
logits_metadata.extend_logprob_pruned_lens_cpu,
|
| 363 |
+
device=input_logprobs.device,
|
| 364 |
+
)
|
| 365 |
+
if logits_metadata.temp_scaled_logprobs:
|
| 366 |
+
logits_metadata.temperature = torch.repeat_interleave(
|
| 367 |
+
logits_metadata.temperature.view(-1),
|
| 368 |
+
pruned_lens,
|
| 369 |
+
).view(-1, 1)
|
| 370 |
+
if logits_metadata.top_p_normalized_logprobs:
|
| 371 |
+
logits_metadata.top_p = torch.repeat_interleave(
|
| 372 |
+
logits_metadata.top_p,
|
| 373 |
+
pruned_lens,
|
| 374 |
+
)
|
| 375 |
+
input_logprobs = self.compute_temp_top_p_normalized_logprobs(
|
| 376 |
+
input_logprobs, logits_metadata
|
| 377 |
+
)
|
| 378 |
+
|
| 379 |
+
# Get the logprob of top-k tokens
|
| 380 |
+
if logits_metadata.extend_return_top_logprob:
|
| 381 |
+
(
|
| 382 |
+
input_top_logprobs_val,
|
| 383 |
+
input_top_logprobs_idx,
|
| 384 |
+
) = self.get_top_logprobs(input_logprobs, logits_metadata)
|
| 385 |
+
else:
|
| 386 |
+
input_top_logprobs_val = input_top_logprobs_idx = None
|
| 387 |
+
|
| 388 |
+
# Get the logprob of given token id
|
| 389 |
+
if logits_metadata.extend_token_ids_logprob:
|
| 390 |
+
(
|
| 391 |
+
input_token_ids_logprobs_val,
|
| 392 |
+
input_token_ids_logprobs_idx,
|
| 393 |
+
) = self.get_token_ids_logprobs(input_logprobs, logits_metadata)
|
| 394 |
+
else:
|
| 395 |
+
input_token_ids_logprobs_val = input_token_ids_logprobs_idx = None
|
| 396 |
+
|
| 397 |
+
input_token_logprobs = input_logprobs[
|
| 398 |
+
torch.arange(input_logprobs.shape[0], device=input_logprobs.device),
|
| 399 |
+
logits_metadata.extend_input_logprob_token_ids_gpu,
|
| 400 |
+
]
|
| 401 |
+
|
| 402 |
+
return LogitsProcessorOutput(
|
| 403 |
+
next_token_logits=sampled_logits,
|
| 404 |
+
input_token_logprobs=input_token_logprobs,
|
| 405 |
+
input_top_logprobs_val=input_top_logprobs_val,
|
| 406 |
+
input_top_logprobs_idx=input_top_logprobs_idx,
|
| 407 |
+
hidden_states=hidden_states_to_store,
|
| 408 |
+
input_token_ids_logprobs_val=input_token_ids_logprobs_val,
|
| 409 |
+
input_token_ids_logprobs_idx=input_token_ids_logprobs_idx,
|
| 410 |
+
)
|
| 411 |
+
|
| 412 |
+
def _get_logits(
|
| 413 |
+
self,
|
| 414 |
+
hidden_states: torch.Tensor,
|
| 415 |
+
lm_head: VocabParallelEmbedding,
|
| 416 |
+
logits_metadata: LogitsMetadata,
|
| 417 |
+
embedding_bias: Optional[torch.Tensor] = None,
|
| 418 |
+
) -> torch.Tensor:
|
| 419 |
+
"""Get logits from hidden_states.
|
| 420 |
+
|
| 421 |
+
If sampled_logits_only is True, it means hidden_states only contain the
|
| 422 |
+
last position (e.g., extend without input logprobs). The caller should
|
| 423 |
+
guarantee the given hidden_states follow this constraint.
|
| 424 |
+
"""
|
| 425 |
+
if self.do_tensor_parallel_all_gather_dp_attn:
|
| 426 |
+
logits_metadata.compute_dp_attention_metadata(hidden_states)
|
| 427 |
+
hidden_states, local_hidden_states = (
|
| 428 |
+
logits_metadata.gathered_buffer,
|
| 429 |
+
hidden_states.clone(),
|
| 430 |
+
)
|
| 431 |
+
dp_gather_replicate(hidden_states, local_hidden_states, logits_metadata)
|
| 432 |
+
|
| 433 |
+
if hasattr(lm_head, "weight"):
|
| 434 |
+
logits = torch.matmul(
|
| 435 |
+
hidden_states.to(lm_head.weight.dtype), lm_head.weight.T
|
| 436 |
+
)
|
| 437 |
+
else:
|
| 438 |
+
# GGUF models
|
| 439 |
+
logits = lm_head.quant_method.apply(lm_head, hidden_states, embedding_bias)
|
| 440 |
+
|
| 441 |
+
if self.logit_scale is not None:
|
| 442 |
+
logits.mul_(self.logit_scale)
|
| 443 |
+
|
| 444 |
+
if self.do_tensor_parallel_all_gather:
|
| 445 |
+
logits = tensor_model_parallel_all_gather(logits)
|
| 446 |
+
|
| 447 |
+
if self.do_tensor_parallel_all_gather_dp_attn:
|
| 448 |
+
logits, global_logits = (
|
| 449 |
+
torch.empty(
|
| 450 |
+
(local_hidden_states.shape[0], logits.shape[1]),
|
| 451 |
+
device=logits.device,
|
| 452 |
+
dtype=logits.dtype,
|
| 453 |
+
),
|
| 454 |
+
logits,
|
| 455 |
+
)
|
| 456 |
+
dp_scatter(logits, global_logits, logits_metadata)
|
| 457 |
+
|
| 458 |
+
logits = logits[:, : self.config.vocab_size].float()
|
| 459 |
+
|
| 460 |
+
if self.final_logit_softcapping:
|
| 461 |
+
fused_softcap(logits, self.final_logit_softcapping)
|
| 462 |
+
|
| 463 |
+
return logits
|
| 464 |
+
|
| 465 |
+
@staticmethod
|
| 466 |
+
def get_top_logprobs(all_logprobs: torch.Tensor, logits_metadata: LogitsMetadata):
|
| 467 |
+
max_k = max(logits_metadata.top_logprobs_nums)
|
| 468 |
+
ret = all_logprobs.topk(max_k, dim=1)
|
| 469 |
+
values = ret.values.tolist()
|
| 470 |
+
indices = ret.indices.tolist()
|
| 471 |
+
|
| 472 |
+
input_top_logprobs_val, input_top_logprobs_idx = [], []
|
| 473 |
+
|
| 474 |
+
pt = 0
|
| 475 |
+
for k, pruned_len in zip(
|
| 476 |
+
logits_metadata.top_logprobs_nums,
|
| 477 |
+
logits_metadata.extend_logprob_pruned_lens_cpu,
|
| 478 |
+
):
|
| 479 |
+
if pruned_len <= 0:
|
| 480 |
+
input_top_logprobs_val.append([])
|
| 481 |
+
input_top_logprobs_idx.append([])
|
| 482 |
+
continue
|
| 483 |
+
|
| 484 |
+
input_top_logprobs_val.append(
|
| 485 |
+
[values[pt + j][:k] for j in range(pruned_len)]
|
| 486 |
+
)
|
| 487 |
+
input_top_logprobs_idx.append(
|
| 488 |
+
[indices[pt + j][:k] for j in range(pruned_len)]
|
| 489 |
+
)
|
| 490 |
+
pt += pruned_len
|
| 491 |
+
|
| 492 |
+
return input_top_logprobs_val, input_top_logprobs_idx
|
| 493 |
+
|
| 494 |
+
@staticmethod
|
| 495 |
+
def get_token_ids_logprobs(
|
| 496 |
+
all_logprobs: torch.Tensor, logits_metadata: LogitsMetadata
|
| 497 |
+
):
|
| 498 |
+
input_token_ids_logprobs_val, input_token_ids_logprobs_idx = [], []
|
| 499 |
+
pt = 0
|
| 500 |
+
for token_ids, pruned_len in zip(
|
| 501 |
+
logits_metadata.token_ids_logprobs,
|
| 502 |
+
logits_metadata.extend_logprob_pruned_lens_cpu,
|
| 503 |
+
):
|
| 504 |
+
if pruned_len <= 0:
|
| 505 |
+
input_token_ids_logprobs_val.append([])
|
| 506 |
+
input_token_ids_logprobs_idx.append([])
|
| 507 |
+
continue
|
| 508 |
+
|
| 509 |
+
input_token_ids_logprobs_val.append(
|
| 510 |
+
[all_logprobs[pt + j, token_ids].tolist() for j in range(pruned_len)]
|
| 511 |
+
)
|
| 512 |
+
input_token_ids_logprobs_idx.append([token_ids for _ in range(pruned_len)])
|
| 513 |
+
pt += pruned_len
|
| 514 |
+
|
| 515 |
+
return input_token_ids_logprobs_val, input_token_ids_logprobs_idx
|
| 516 |
+
|
| 517 |
+
@staticmethod
|
| 518 |
+
def compute_temp_top_p_normalized_logprobs(
|
| 519 |
+
last_logits: torch.Tensor, logits_metadata: LogitsMetadata
|
| 520 |
+
) -> torch.Tensor:
|
| 521 |
+
"""
|
| 522 |
+
compute logprobs for the output token from the given logits.
|
| 523 |
+
|
| 524 |
+
Returns:
|
| 525 |
+
torch.Tensor: logprobs from logits
|
| 526 |
+
"""
|
| 527 |
+
# Scale logits if temperature scaling is enabled
|
| 528 |
+
if logits_metadata.temp_scaled_logprobs:
|
| 529 |
+
last_logits = last_logits / logits_metadata.temperature
|
| 530 |
+
|
| 531 |
+
# Normalize logprobs if top_p normalization is enabled
|
| 532 |
+
# NOTE: only normalize logprobs when top_p is set and not equal to 1.0
|
| 533 |
+
if (
|
| 534 |
+
logits_metadata.top_p_normalized_logprobs
|
| 535 |
+
and (logits_metadata.top_p != 1.0).any()
|
| 536 |
+
):
|
| 537 |
+
from sglang.srt.layers.sampler import top_p_normalize_probs_torch
|
| 538 |
+
|
| 539 |
+
probs = torch.softmax(last_logits, dim=-1)
|
| 540 |
+
del last_logits
|
| 541 |
+
probs = top_p_normalize_probs_torch(probs, logits_metadata.top_p)
|
| 542 |
+
return torch.log(probs)
|
| 543 |
+
else:
|
| 544 |
+
return torch.nn.functional.log_softmax(last_logits, dim=-1)
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
@triton.jit
|
| 548 |
+
def fused_softcap_kernel(
|
| 549 |
+
full_logits_ptr,
|
| 550 |
+
softcapping_value,
|
| 551 |
+
n_elements,
|
| 552 |
+
BLOCK_SIZE: tl.constexpr,
|
| 553 |
+
):
|
| 554 |
+
pid = tl.program_id(0).to(tl.int64)
|
| 555 |
+
block_start = pid * BLOCK_SIZE
|
| 556 |
+
offsets = block_start + tl.arange(0, BLOCK_SIZE)
|
| 557 |
+
mask = offsets < n_elements
|
| 558 |
+
|
| 559 |
+
# Load values
|
| 560 |
+
x = tl.load(full_logits_ptr + offsets, mask=mask)
|
| 561 |
+
|
| 562 |
+
# Perform operations in-place
|
| 563 |
+
x = x / softcapping_value
|
| 564 |
+
|
| 565 |
+
# Manual tanh implementation using exp
|
| 566 |
+
exp2x = tl.exp(2 * x)
|
| 567 |
+
x = (exp2x - 1) / (exp2x + 1)
|
| 568 |
+
|
| 569 |
+
x = x * softcapping_value
|
| 570 |
+
|
| 571 |
+
# Store result
|
| 572 |
+
tl.store(full_logits_ptr + offsets, x, mask=mask)
|
| 573 |
+
|
| 574 |
+
|
| 575 |
+
def fused_softcap(full_logits, final_logit_softcapping):
|
| 576 |
+
n_elements = full_logits.numel()
|
| 577 |
+
BLOCK_SIZE = 1024
|
| 578 |
+
grid = ((n_elements + BLOCK_SIZE - 1) // BLOCK_SIZE, 1, 1)
|
| 579 |
+
|
| 580 |
+
fused_softcap_kernel[grid](
|
| 581 |
+
full_logits_ptr=full_logits,
|
| 582 |
+
softcapping_value=final_logit_softcapping,
|
| 583 |
+
n_elements=n_elements,
|
| 584 |
+
BLOCK_SIZE=BLOCK_SIZE,
|
| 585 |
+
)
|
| 586 |
+
return full_logits
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_native.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Torch-native implementation for FusedMoE. This is used for torch.compile.
|
| 3 |
+
It is based on https://github.com/pytorch-labs/gpt-fast/blob/32971d3129541c5bfb4f715abc33d1c5f408d204/mixtral-moe/model.py#L204
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from typing import Callable, Optional
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
from torch.nn import functional as F
|
| 10 |
+
|
| 11 |
+
from sglang.srt.layers.activation import GeluAndMul, SiluAndMul
|
| 12 |
+
from sglang.srt.layers.moe.topk import select_experts
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def fused_moe_forward_native(
|
| 16 |
+
layer: torch.nn.Module,
|
| 17 |
+
x: torch.Tensor,
|
| 18 |
+
use_grouped_topk: bool,
|
| 19 |
+
top_k: int,
|
| 20 |
+
router_logits: torch.Tensor,
|
| 21 |
+
renormalize: bool,
|
| 22 |
+
topk_group: Optional[int] = None,
|
| 23 |
+
num_expert_group: Optional[int] = None,
|
| 24 |
+
custom_routing_function: Optional[Callable] = None,
|
| 25 |
+
correction_bias: Optional[torch.Tensor] = None,
|
| 26 |
+
activation: str = "silu",
|
| 27 |
+
apply_router_weight_on_input: bool = False,
|
| 28 |
+
inplace: bool = True,
|
| 29 |
+
no_combine: bool = False,
|
| 30 |
+
routed_scaling_factor: Optional[float] = None,
|
| 31 |
+
) -> torch.Tensor:
|
| 32 |
+
|
| 33 |
+
if apply_router_weight_on_input:
|
| 34 |
+
raise NotImplementedError()
|
| 35 |
+
|
| 36 |
+
topk_weights, topk_ids = select_experts(
|
| 37 |
+
hidden_states=x,
|
| 38 |
+
router_logits=router_logits,
|
| 39 |
+
use_grouped_topk=use_grouped_topk,
|
| 40 |
+
top_k=top_k,
|
| 41 |
+
renormalize=renormalize,
|
| 42 |
+
topk_group=topk_group,
|
| 43 |
+
num_expert_group=num_expert_group,
|
| 44 |
+
custom_routing_function=custom_routing_function,
|
| 45 |
+
correction_bias=correction_bias,
|
| 46 |
+
routed_scaling_factor=routed_scaling_factor,
|
| 47 |
+
torch_native=True,
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
w13_weights = layer.w13_weight[topk_ids]
|
| 51 |
+
w1_weights, w3_weights = torch.chunk(w13_weights, 2, dim=2)
|
| 52 |
+
w2_weights = layer.w2_weight[topk_ids]
|
| 53 |
+
x1 = torch.einsum("ti,taoi -> tao", x, w1_weights)
|
| 54 |
+
if activation == "silu":
|
| 55 |
+
x1 = F.silu(x1)
|
| 56 |
+
elif activation == "gelu":
|
| 57 |
+
x1 = F.gelu(x1)
|
| 58 |
+
else:
|
| 59 |
+
raise ValueError(f"Unsupported activation: {activation=}")
|
| 60 |
+
x3 = torch.einsum("ti, taoi -> tao", x, w3_weights)
|
| 61 |
+
expert_outs = torch.einsum("tao, taio -> tai", (x1 * x3), w2_weights)
|
| 62 |
+
return torch.einsum("tai,ta -> ti", expert_outs, topk_weights.to(expert_outs.dtype))
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def moe_forward_native(
|
| 66 |
+
layer: torch.nn.Module,
|
| 67 |
+
x: torch.Tensor,
|
| 68 |
+
use_grouped_topk: bool,
|
| 69 |
+
top_k: int,
|
| 70 |
+
router_logits: torch.Tensor,
|
| 71 |
+
renormalize: bool,
|
| 72 |
+
topk_group: Optional[int] = None,
|
| 73 |
+
num_expert_group: Optional[int] = None,
|
| 74 |
+
custom_routing_function: Optional[Callable] = None,
|
| 75 |
+
correction_bias: Optional[torch.Tensor] = None,
|
| 76 |
+
activation: str = "silu",
|
| 77 |
+
routed_scaling_factor: Optional[float] = None,
|
| 78 |
+
) -> torch.Tensor:
|
| 79 |
+
topk_weights, topk_ids = select_experts(
|
| 80 |
+
hidden_states=x,
|
| 81 |
+
router_logits=router_logits,
|
| 82 |
+
use_grouped_topk=use_grouped_topk,
|
| 83 |
+
top_k=top_k,
|
| 84 |
+
renormalize=renormalize,
|
| 85 |
+
topk_group=topk_group,
|
| 86 |
+
num_expert_group=num_expert_group,
|
| 87 |
+
custom_routing_function=custom_routing_function,
|
| 88 |
+
correction_bias=correction_bias,
|
| 89 |
+
torch_native=True,
|
| 90 |
+
routed_scaling_factor=routed_scaling_factor,
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
# Ref code from https://huggingface.co/deepseek-ai/DeepSeek-V2/blob/e0828e3cc0a03408724b80c3cc92c8e072db8d01/modeling_deepseek.py#L589
|
| 94 |
+
len_experts = layer.num_experts
|
| 95 |
+
|
| 96 |
+
cnts = topk_ids.new_zeros((topk_ids.shape[0], len_experts))
|
| 97 |
+
cnts.scatter_(1, topk_ids.to(torch.int64), 1)
|
| 98 |
+
tokens_per_expert = cnts.sum(dim=0)
|
| 99 |
+
idxs = topk_ids.view(-1).argsort()
|
| 100 |
+
|
| 101 |
+
sorted_tokens = x[idxs // topk_ids.shape[1]]
|
| 102 |
+
tokens_per_expert = tokens_per_expert.cpu().numpy()
|
| 103 |
+
|
| 104 |
+
if activation == "silu":
|
| 105 |
+
act = SiluAndMul()
|
| 106 |
+
elif activation == "gelu":
|
| 107 |
+
act = GeluAndMul()
|
| 108 |
+
else:
|
| 109 |
+
raise ValueError(f"Unsupported activation: {activation=}")
|
| 110 |
+
|
| 111 |
+
outputs = []
|
| 112 |
+
start_idx = 0
|
| 113 |
+
for i, num_tokens in enumerate(tokens_per_expert):
|
| 114 |
+
end_idx = start_idx + num_tokens
|
| 115 |
+
if num_tokens == 0:
|
| 116 |
+
continue
|
| 117 |
+
tokens_for_this_expert = sorted_tokens[start_idx:end_idx]
|
| 118 |
+
|
| 119 |
+
layer_w13_weight = layer.w13_weight[i]
|
| 120 |
+
layer_w2_weight = layer.w2_weight[i]
|
| 121 |
+
|
| 122 |
+
gate_up = F.linear(tokens_for_this_expert, layer_w13_weight)
|
| 123 |
+
gate_up = act(gate_up)
|
| 124 |
+
expert_out = F.linear(gate_up, layer_w2_weight)
|
| 125 |
+
outputs.append(expert_out)
|
| 126 |
+
start_idx = end_idx
|
| 127 |
+
|
| 128 |
+
outs = torch.cat(outputs, dim=0) if len(outputs) else sorted_tokens.new_empty(0)
|
| 129 |
+
new_x = torch.empty_like(outs)
|
| 130 |
+
|
| 131 |
+
new_x[idxs] = outs
|
| 132 |
+
final_out = (
|
| 133 |
+
new_x.view(*topk_ids.shape, -1)
|
| 134 |
+
.type(topk_weights.dtype)
|
| 135 |
+
.mul_(topk_weights.unsqueeze(dim=-1))
|
| 136 |
+
.sum(dim=1)
|
| 137 |
+
.type(new_x.dtype)
|
| 138 |
+
)
|
| 139 |
+
return final_out
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/__init__.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from contextlib import contextmanager
|
| 2 |
+
from typing import Any, Dict, Optional
|
| 3 |
+
|
| 4 |
+
import sglang.srt.layers.moe.fused_moe_triton.fused_moe # noqa
|
| 5 |
+
from sglang.srt.layers.moe.fused_moe_triton.fused_moe import (
|
| 6 |
+
fused_experts,
|
| 7 |
+
get_config_file_name,
|
| 8 |
+
)
|
| 9 |
+
from sglang.srt.layers.moe.fused_moe_triton.layer import (
|
| 10 |
+
FusedMoE,
|
| 11 |
+
FusedMoEMethodBase,
|
| 12 |
+
FusedMoeWeightScaleSupported,
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
_config: Optional[Dict[str, Any]] = None
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
@contextmanager
|
| 19 |
+
def override_config(config):
|
| 20 |
+
global _config
|
| 21 |
+
old_config = _config
|
| 22 |
+
_config = config
|
| 23 |
+
yield
|
| 24 |
+
_config = old_config
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def get_config() -> Optional[Dict[str, Any]]:
|
| 28 |
+
return _config
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
__all__ = [
|
| 32 |
+
"FusedMoE",
|
| 33 |
+
"FusedMoEMethodBase",
|
| 34 |
+
"FusedMoeWeightScaleSupported",
|
| 35 |
+
"override_config",
|
| 36 |
+
"get_config",
|
| 37 |
+
"fused_moe",
|
| 38 |
+
"fused_experts",
|
| 39 |
+
"get_config_file_name",
|
| 40 |
+
]
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=14336,device_name=NVIDIA_A100-SXM4-80GB,dtype=int8_w8a16.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 32,
|
| 5 |
+
"BLOCK_SIZE_K": 128,
|
| 6 |
+
"GROUP_SIZE_M": 1,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 4
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 32,
|
| 13 |
+
"BLOCK_SIZE_K": 128,
|
| 14 |
+
"GROUP_SIZE_M": 64,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 3
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 32,
|
| 21 |
+
"BLOCK_SIZE_K": 128,
|
| 22 |
+
"GROUP_SIZE_M": 1,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 4
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 32,
|
| 29 |
+
"BLOCK_SIZE_K": 256,
|
| 30 |
+
"GROUP_SIZE_M": 32,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 3
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 32,
|
| 37 |
+
"BLOCK_SIZE_K": 128,
|
| 38 |
+
"GROUP_SIZE_M": 1,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 4
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 16,
|
| 44 |
+
"BLOCK_SIZE_N": 64,
|
| 45 |
+
"BLOCK_SIZE_K": 64,
|
| 46 |
+
"GROUP_SIZE_M": 16,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 5
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 16,
|
| 52 |
+
"BLOCK_SIZE_N": 32,
|
| 53 |
+
"BLOCK_SIZE_K": 256,
|
| 54 |
+
"GROUP_SIZE_M": 1,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 2
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 64,
|
| 60 |
+
"BLOCK_SIZE_N": 64,
|
| 61 |
+
"BLOCK_SIZE_K": 64,
|
| 62 |
+
"GROUP_SIZE_M": 1,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 3
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 64,
|
| 68 |
+
"BLOCK_SIZE_N": 64,
|
| 69 |
+
"BLOCK_SIZE_K": 64,
|
| 70 |
+
"GROUP_SIZE_M": 1,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 3
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 32,
|
| 76 |
+
"BLOCK_SIZE_N": 128,
|
| 77 |
+
"BLOCK_SIZE_K": 128,
|
| 78 |
+
"GROUP_SIZE_M": 1,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 3
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 64,
|
| 84 |
+
"BLOCK_SIZE_N": 64,
|
| 85 |
+
"BLOCK_SIZE_K": 64,
|
| 86 |
+
"GROUP_SIZE_M": 16,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 3
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 64,
|
| 92 |
+
"BLOCK_SIZE_N": 64,
|
| 93 |
+
"BLOCK_SIZE_K": 64,
|
| 94 |
+
"GROUP_SIZE_M": 32,
|
| 95 |
+
"num_warps": 4,
|
| 96 |
+
"num_stages": 4
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 64,
|
| 100 |
+
"BLOCK_SIZE_N": 256,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 32,
|
| 103 |
+
"num_warps": 4,
|
| 104 |
+
"num_stages": 4
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 64,
|
| 108 |
+
"BLOCK_SIZE_N": 256,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 64,
|
| 111 |
+
"num_warps": 4,
|
| 112 |
+
"num_stages": 4
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 64,
|
| 116 |
+
"BLOCK_SIZE_N": 256,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 64,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 4
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 64,
|
| 124 |
+
"BLOCK_SIZE_N": 256,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 32,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 4
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 64,
|
| 132 |
+
"BLOCK_SIZE_N": 256,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 32,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 4
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 64,
|
| 140 |
+
"BLOCK_SIZE_N": 256,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 16,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 4
|
| 145 |
+
}
|
| 146 |
+
}
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=14336,device_name=NVIDIA_A100-SXM4-80GB.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 64,
|
| 5 |
+
"BLOCK_SIZE_K": 256,
|
| 6 |
+
"GROUP_SIZE_M": 16,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 4
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 64,
|
| 13 |
+
"BLOCK_SIZE_K": 256,
|
| 14 |
+
"GROUP_SIZE_M": 32,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 4
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 64,
|
| 21 |
+
"BLOCK_SIZE_K": 256,
|
| 22 |
+
"GROUP_SIZE_M": 16,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 4
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 64,
|
| 29 |
+
"BLOCK_SIZE_K": 256,
|
| 30 |
+
"GROUP_SIZE_M": 32,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 4
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 64,
|
| 37 |
+
"BLOCK_SIZE_K": 256,
|
| 38 |
+
"GROUP_SIZE_M": 64,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 4
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 32,
|
| 44 |
+
"BLOCK_SIZE_N": 64,
|
| 45 |
+
"BLOCK_SIZE_K": 128,
|
| 46 |
+
"GROUP_SIZE_M": 16,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 5
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 32,
|
| 52 |
+
"BLOCK_SIZE_N": 64,
|
| 53 |
+
"BLOCK_SIZE_K": 128,
|
| 54 |
+
"GROUP_SIZE_M": 1,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 5
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 32,
|
| 60 |
+
"BLOCK_SIZE_N": 64,
|
| 61 |
+
"BLOCK_SIZE_K": 64,
|
| 62 |
+
"GROUP_SIZE_M": 16,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 5
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 64,
|
| 68 |
+
"BLOCK_SIZE_N": 64,
|
| 69 |
+
"BLOCK_SIZE_K": 128,
|
| 70 |
+
"GROUP_SIZE_M": 1,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 4
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 32,
|
| 76 |
+
"BLOCK_SIZE_N": 256,
|
| 77 |
+
"BLOCK_SIZE_K": 64,
|
| 78 |
+
"GROUP_SIZE_M": 16,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 5
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 64,
|
| 84 |
+
"BLOCK_SIZE_N": 128,
|
| 85 |
+
"BLOCK_SIZE_K": 64,
|
| 86 |
+
"GROUP_SIZE_M": 64,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 4
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 128,
|
| 92 |
+
"BLOCK_SIZE_N": 128,
|
| 93 |
+
"BLOCK_SIZE_K": 64,
|
| 94 |
+
"GROUP_SIZE_M": 16,
|
| 95 |
+
"num_warps": 8,
|
| 96 |
+
"num_stages": 4
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 128,
|
| 100 |
+
"BLOCK_SIZE_N": 128,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 64,
|
| 103 |
+
"num_warps": 4,
|
| 104 |
+
"num_stages": 3
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 128,
|
| 108 |
+
"BLOCK_SIZE_N": 128,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 64,
|
| 111 |
+
"num_warps": 4,
|
| 112 |
+
"num_stages": 3
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 128,
|
| 116 |
+
"BLOCK_SIZE_N": 128,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 16,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 3
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 128,
|
| 124 |
+
"BLOCK_SIZE_N": 128,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 32,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 3
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 128,
|
| 132 |
+
"BLOCK_SIZE_N": 128,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 16,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 3
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 128,
|
| 140 |
+
"BLOCK_SIZE_N": 128,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 16,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 3
|
| 145 |
+
}
|
| 146 |
+
}
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=7168,device_name=NVIDIA_A100-SXM4-80GB,dtype=int8_w8a16.json
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 32,
|
| 5 |
+
"BLOCK_SIZE_K": 256,
|
| 6 |
+
"GROUP_SIZE_M": 16,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 3
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 32,
|
| 13 |
+
"BLOCK_SIZE_K": 256,
|
| 14 |
+
"GROUP_SIZE_M": 16,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 3
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 32,
|
| 21 |
+
"BLOCK_SIZE_K": 256,
|
| 22 |
+
"GROUP_SIZE_M": 16,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 3
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 32,
|
| 29 |
+
"BLOCK_SIZE_K": 256,
|
| 30 |
+
"GROUP_SIZE_M": 32,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 3
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 32,
|
| 37 |
+
"BLOCK_SIZE_K": 256,
|
| 38 |
+
"GROUP_SIZE_M": 32,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 3
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 16,
|
| 44 |
+
"BLOCK_SIZE_N": 32,
|
| 45 |
+
"BLOCK_SIZE_K": 256,
|
| 46 |
+
"GROUP_SIZE_M": 1,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 3
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 16,
|
| 52 |
+
"BLOCK_SIZE_N": 32,
|
| 53 |
+
"BLOCK_SIZE_K": 256,
|
| 54 |
+
"GROUP_SIZE_M": 1,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 3
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 16,
|
| 60 |
+
"BLOCK_SIZE_N": 32,
|
| 61 |
+
"BLOCK_SIZE_K": 128,
|
| 62 |
+
"GROUP_SIZE_M": 1,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 3
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 32,
|
| 68 |
+
"BLOCK_SIZE_N": 128,
|
| 69 |
+
"BLOCK_SIZE_K": 128,
|
| 70 |
+
"GROUP_SIZE_M": 1,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 3
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 32,
|
| 76 |
+
"BLOCK_SIZE_N": 128,
|
| 77 |
+
"BLOCK_SIZE_K": 128,
|
| 78 |
+
"GROUP_SIZE_M": 1,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 3
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 128,
|
| 84 |
+
"BLOCK_SIZE_N": 32,
|
| 85 |
+
"BLOCK_SIZE_K": 128,
|
| 86 |
+
"GROUP_SIZE_M": 1,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 3
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 64,
|
| 92 |
+
"BLOCK_SIZE_N": 64,
|
| 93 |
+
"BLOCK_SIZE_K": 64,
|
| 94 |
+
"GROUP_SIZE_M": 1,
|
| 95 |
+
"num_warps": 4,
|
| 96 |
+
"num_stages": 3
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 64,
|
| 100 |
+
"BLOCK_SIZE_N": 256,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 16,
|
| 103 |
+
"num_warps": 4,
|
| 104 |
+
"num_stages": 4
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 64,
|
| 108 |
+
"BLOCK_SIZE_N": 256,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 16,
|
| 111 |
+
"num_warps": 4,
|
| 112 |
+
"num_stages": 4
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 64,
|
| 116 |
+
"BLOCK_SIZE_N": 256,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 32,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 4
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 64,
|
| 124 |
+
"BLOCK_SIZE_N": 256,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 32,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 4
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 64,
|
| 132 |
+
"BLOCK_SIZE_N": 256,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 64,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 4
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 64,
|
| 140 |
+
"BLOCK_SIZE_N": 256,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 32,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 4
|
| 145 |
+
},
|
| 146 |
+
"5120": {
|
| 147 |
+
"BLOCK_SIZE_M": 64,
|
| 148 |
+
"BLOCK_SIZE_N": 256,
|
| 149 |
+
"BLOCK_SIZE_K": 64,
|
| 150 |
+
"GROUP_SIZE_M": 32,
|
| 151 |
+
"num_warps": 4,
|
| 152 |
+
"num_stages": 4
|
| 153 |
+
},
|
| 154 |
+
"9216": {
|
| 155 |
+
"BLOCK_SIZE_M": 64,
|
| 156 |
+
"BLOCK_SIZE_N": 256,
|
| 157 |
+
"BLOCK_SIZE_K": 64,
|
| 158 |
+
"GROUP_SIZE_M": 32,
|
| 159 |
+
"num_warps": 4,
|
| 160 |
+
"num_stages": 3
|
| 161 |
+
},
|
| 162 |
+
"13312": {
|
| 163 |
+
"BLOCK_SIZE_M": 64,
|
| 164 |
+
"BLOCK_SIZE_N": 256,
|
| 165 |
+
"BLOCK_SIZE_K": 64,
|
| 166 |
+
"GROUP_SIZE_M": 16,
|
| 167 |
+
"num_warps": 4,
|
| 168 |
+
"num_stages": 4
|
| 169 |
+
},
|
| 170 |
+
"17408": {
|
| 171 |
+
"BLOCK_SIZE_M": 64,
|
| 172 |
+
"BLOCK_SIZE_N": 256,
|
| 173 |
+
"BLOCK_SIZE_K": 64,
|
| 174 |
+
"GROUP_SIZE_M": 16,
|
| 175 |
+
"num_warps": 4,
|
| 176 |
+
"num_stages": 4
|
| 177 |
+
},
|
| 178 |
+
"25600": {
|
| 179 |
+
"BLOCK_SIZE_M": 64,
|
| 180 |
+
"BLOCK_SIZE_N": 256,
|
| 181 |
+
"BLOCK_SIZE_K": 64,
|
| 182 |
+
"GROUP_SIZE_M": 16,
|
| 183 |
+
"num_warps": 4,
|
| 184 |
+
"num_stages": 4
|
| 185 |
+
},
|
| 186 |
+
"33792": {
|
| 187 |
+
"BLOCK_SIZE_M": 64,
|
| 188 |
+
"BLOCK_SIZE_N": 256,
|
| 189 |
+
"BLOCK_SIZE_K": 64,
|
| 190 |
+
"GROUP_SIZE_M": 16,
|
| 191 |
+
"num_warps": 4,
|
| 192 |
+
"num_stages": 4
|
| 193 |
+
},
|
| 194 |
+
"41984": {
|
| 195 |
+
"BLOCK_SIZE_M": 64,
|
| 196 |
+
"BLOCK_SIZE_N": 256,
|
| 197 |
+
"BLOCK_SIZE_K": 64,
|
| 198 |
+
"GROUP_SIZE_M": 16,
|
| 199 |
+
"num_warps": 4,
|
| 200 |
+
"num_stages": 4
|
| 201 |
+
},
|
| 202 |
+
"50176": {
|
| 203 |
+
"BLOCK_SIZE_M": 64,
|
| 204 |
+
"BLOCK_SIZE_N": 256,
|
| 205 |
+
"BLOCK_SIZE_K": 64,
|
| 206 |
+
"GROUP_SIZE_M": 16,
|
| 207 |
+
"num_warps": 4,
|
| 208 |
+
"num_stages": 4
|
| 209 |
+
},
|
| 210 |
+
"58368": {
|
| 211 |
+
"BLOCK_SIZE_M": 64,
|
| 212 |
+
"BLOCK_SIZE_N": 256,
|
| 213 |
+
"BLOCK_SIZE_K": 64,
|
| 214 |
+
"GROUP_SIZE_M": 16,
|
| 215 |
+
"num_warps": 4,
|
| 216 |
+
"num_stages": 4
|
| 217 |
+
}
|
| 218 |
+
}
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=1,N=7168,device_name=NVIDIA_A100-SXM4-80GB.json
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 64,
|
| 5 |
+
"BLOCK_SIZE_K": 64,
|
| 6 |
+
"GROUP_SIZE_M": 32,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 5
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 64,
|
| 13 |
+
"BLOCK_SIZE_K": 256,
|
| 14 |
+
"GROUP_SIZE_M": 1,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 4
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 64,
|
| 21 |
+
"BLOCK_SIZE_K": 256,
|
| 22 |
+
"GROUP_SIZE_M": 32,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 4
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 64,
|
| 29 |
+
"BLOCK_SIZE_K": 256,
|
| 30 |
+
"GROUP_SIZE_M": 32,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 4
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 64,
|
| 37 |
+
"BLOCK_SIZE_K": 256,
|
| 38 |
+
"GROUP_SIZE_M": 64,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 4
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 32,
|
| 44 |
+
"BLOCK_SIZE_N": 64,
|
| 45 |
+
"BLOCK_SIZE_K": 64,
|
| 46 |
+
"GROUP_SIZE_M": 1,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 5
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 32,
|
| 52 |
+
"BLOCK_SIZE_N": 64,
|
| 53 |
+
"BLOCK_SIZE_K": 64,
|
| 54 |
+
"GROUP_SIZE_M": 1,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 5
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 64,
|
| 60 |
+
"BLOCK_SIZE_N": 64,
|
| 61 |
+
"BLOCK_SIZE_K": 64,
|
| 62 |
+
"GROUP_SIZE_M": 1,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 4
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 64,
|
| 68 |
+
"BLOCK_SIZE_N": 64,
|
| 69 |
+
"BLOCK_SIZE_K": 128,
|
| 70 |
+
"GROUP_SIZE_M": 32,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 4
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 64,
|
| 76 |
+
"BLOCK_SIZE_N": 128,
|
| 77 |
+
"BLOCK_SIZE_K": 64,
|
| 78 |
+
"GROUP_SIZE_M": 64,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 4
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 64,
|
| 84 |
+
"BLOCK_SIZE_N": 128,
|
| 85 |
+
"BLOCK_SIZE_K": 64,
|
| 86 |
+
"GROUP_SIZE_M": 64,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 4
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 64,
|
| 92 |
+
"BLOCK_SIZE_N": 256,
|
| 93 |
+
"BLOCK_SIZE_K": 128,
|
| 94 |
+
"GROUP_SIZE_M": 1,
|
| 95 |
+
"num_warps": 8,
|
| 96 |
+
"num_stages": 3
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 64,
|
| 100 |
+
"BLOCK_SIZE_N": 128,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 16,
|
| 103 |
+
"num_warps": 4,
|
| 104 |
+
"num_stages": 3
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 128,
|
| 108 |
+
"BLOCK_SIZE_N": 128,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 32,
|
| 111 |
+
"num_warps": 8,
|
| 112 |
+
"num_stages": 4
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 128,
|
| 116 |
+
"BLOCK_SIZE_N": 128,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 32,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 3
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 128,
|
| 124 |
+
"BLOCK_SIZE_N": 128,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 16,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 3
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 128,
|
| 132 |
+
"BLOCK_SIZE_N": 128,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 16,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 3
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 128,
|
| 140 |
+
"BLOCK_SIZE_N": 128,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 16,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 3
|
| 145 |
+
},
|
| 146 |
+
"5120": {
|
| 147 |
+
"BLOCK_SIZE_M": 128,
|
| 148 |
+
"BLOCK_SIZE_N": 128,
|
| 149 |
+
"BLOCK_SIZE_K": 64,
|
| 150 |
+
"GROUP_SIZE_M": 16,
|
| 151 |
+
"num_warps": 4,
|
| 152 |
+
"num_stages": 3
|
| 153 |
+
},
|
| 154 |
+
"9216": {
|
| 155 |
+
"BLOCK_SIZE_M": 128,
|
| 156 |
+
"BLOCK_SIZE_N": 128,
|
| 157 |
+
"BLOCK_SIZE_K": 64,
|
| 158 |
+
"GROUP_SIZE_M": 16,
|
| 159 |
+
"num_warps": 4,
|
| 160 |
+
"num_stages": 3
|
| 161 |
+
},
|
| 162 |
+
"13312": {
|
| 163 |
+
"BLOCK_SIZE_M": 128,
|
| 164 |
+
"BLOCK_SIZE_N": 128,
|
| 165 |
+
"BLOCK_SIZE_K": 64,
|
| 166 |
+
"GROUP_SIZE_M": 16,
|
| 167 |
+
"num_warps": 4,
|
| 168 |
+
"num_stages": 3
|
| 169 |
+
},
|
| 170 |
+
"17408": {
|
| 171 |
+
"BLOCK_SIZE_M": 128,
|
| 172 |
+
"BLOCK_SIZE_N": 128,
|
| 173 |
+
"BLOCK_SIZE_K": 64,
|
| 174 |
+
"GROUP_SIZE_M": 16,
|
| 175 |
+
"num_warps": 4,
|
| 176 |
+
"num_stages": 3
|
| 177 |
+
},
|
| 178 |
+
"25600": {
|
| 179 |
+
"BLOCK_SIZE_M": 128,
|
| 180 |
+
"BLOCK_SIZE_N": 128,
|
| 181 |
+
"BLOCK_SIZE_K": 64,
|
| 182 |
+
"GROUP_SIZE_M": 16,
|
| 183 |
+
"num_warps": 4,
|
| 184 |
+
"num_stages": 3
|
| 185 |
+
},
|
| 186 |
+
"33792": {
|
| 187 |
+
"BLOCK_SIZE_M": 128,
|
| 188 |
+
"BLOCK_SIZE_N": 128,
|
| 189 |
+
"BLOCK_SIZE_K": 64,
|
| 190 |
+
"GROUP_SIZE_M": 16,
|
| 191 |
+
"num_warps": 4,
|
| 192 |
+
"num_stages": 3
|
| 193 |
+
},
|
| 194 |
+
"41984": {
|
| 195 |
+
"BLOCK_SIZE_M": 128,
|
| 196 |
+
"BLOCK_SIZE_N": 128,
|
| 197 |
+
"BLOCK_SIZE_K": 64,
|
| 198 |
+
"GROUP_SIZE_M": 16,
|
| 199 |
+
"num_warps": 4,
|
| 200 |
+
"num_stages": 3
|
| 201 |
+
},
|
| 202 |
+
"50176": {
|
| 203 |
+
"BLOCK_SIZE_M": 128,
|
| 204 |
+
"BLOCK_SIZE_N": 128,
|
| 205 |
+
"BLOCK_SIZE_K": 64,
|
| 206 |
+
"GROUP_SIZE_M": 16,
|
| 207 |
+
"num_warps": 4,
|
| 208 |
+
"num_stages": 3
|
| 209 |
+
},
|
| 210 |
+
"58368": {
|
| 211 |
+
"BLOCK_SIZE_M": 128,
|
| 212 |
+
"BLOCK_SIZE_N": 128,
|
| 213 |
+
"BLOCK_SIZE_K": 64,
|
| 214 |
+
"GROUP_SIZE_M": 16,
|
| 215 |
+
"num_warps": 4,
|
| 216 |
+
"num_stages": 3
|
| 217 |
+
}
|
| 218 |
+
}
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=128,N=192,device_name=NVIDIA_H20.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 64,
|
| 5 |
+
"BLOCK_SIZE_K": 64,
|
| 6 |
+
"GROUP_SIZE_M": 1,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 5
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 128,
|
| 13 |
+
"BLOCK_SIZE_K": 64,
|
| 14 |
+
"GROUP_SIZE_M": 16,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 5
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 64,
|
| 21 |
+
"BLOCK_SIZE_K": 64,
|
| 22 |
+
"GROUP_SIZE_M": 32,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 4
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 128,
|
| 29 |
+
"BLOCK_SIZE_K": 64,
|
| 30 |
+
"GROUP_SIZE_M": 1,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 4
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 128,
|
| 37 |
+
"BLOCK_SIZE_K": 64,
|
| 38 |
+
"GROUP_SIZE_M": 16,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 3
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 16,
|
| 44 |
+
"BLOCK_SIZE_N": 128,
|
| 45 |
+
"BLOCK_SIZE_K": 64,
|
| 46 |
+
"GROUP_SIZE_M": 32,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 3
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 16,
|
| 52 |
+
"BLOCK_SIZE_N": 128,
|
| 53 |
+
"BLOCK_SIZE_K": 64,
|
| 54 |
+
"GROUP_SIZE_M": 64,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 3
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 16,
|
| 60 |
+
"BLOCK_SIZE_N": 128,
|
| 61 |
+
"BLOCK_SIZE_K": 64,
|
| 62 |
+
"GROUP_SIZE_M": 32,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 3
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 16,
|
| 68 |
+
"BLOCK_SIZE_N": 128,
|
| 69 |
+
"BLOCK_SIZE_K": 64,
|
| 70 |
+
"GROUP_SIZE_M": 1,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 3
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 16,
|
| 76 |
+
"BLOCK_SIZE_N": 128,
|
| 77 |
+
"BLOCK_SIZE_K": 64,
|
| 78 |
+
"GROUP_SIZE_M": 1,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 3
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 16,
|
| 84 |
+
"BLOCK_SIZE_N": 128,
|
| 85 |
+
"BLOCK_SIZE_K": 64,
|
| 86 |
+
"GROUP_SIZE_M": 1,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 3
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 16,
|
| 92 |
+
"BLOCK_SIZE_N": 128,
|
| 93 |
+
"BLOCK_SIZE_K": 64,
|
| 94 |
+
"GROUP_SIZE_M": 32,
|
| 95 |
+
"num_warps": 4,
|
| 96 |
+
"num_stages": 3
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 64,
|
| 100 |
+
"BLOCK_SIZE_N": 128,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 1,
|
| 103 |
+
"num_warps": 8,
|
| 104 |
+
"num_stages": 3
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 64,
|
| 108 |
+
"BLOCK_SIZE_N": 128,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 16,
|
| 111 |
+
"num_warps": 4,
|
| 112 |
+
"num_stages": 3
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 64,
|
| 116 |
+
"BLOCK_SIZE_N": 128,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 32,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 3
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 64,
|
| 124 |
+
"BLOCK_SIZE_N": 128,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 1,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 3
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 64,
|
| 132 |
+
"BLOCK_SIZE_N": 64,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 16,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 2
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 64,
|
| 140 |
+
"BLOCK_SIZE_N": 128,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 1,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 2
|
| 145 |
+
}
|
| 146 |
+
}
|
lib/python3.12/site-packages/sglang/srt/layers/moe/fused_moe_triton/configs/E=128,N=384,device_name=NVIDIA_H20.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"1": {
|
| 3 |
+
"BLOCK_SIZE_M": 16,
|
| 4 |
+
"BLOCK_SIZE_N": 64,
|
| 5 |
+
"BLOCK_SIZE_K": 64,
|
| 6 |
+
"GROUP_SIZE_M": 1,
|
| 7 |
+
"num_warps": 4,
|
| 8 |
+
"num_stages": 4
|
| 9 |
+
},
|
| 10 |
+
"2": {
|
| 11 |
+
"BLOCK_SIZE_M": 16,
|
| 12 |
+
"BLOCK_SIZE_N": 64,
|
| 13 |
+
"BLOCK_SIZE_K": 64,
|
| 14 |
+
"GROUP_SIZE_M": 1,
|
| 15 |
+
"num_warps": 4,
|
| 16 |
+
"num_stages": 4
|
| 17 |
+
},
|
| 18 |
+
"4": {
|
| 19 |
+
"BLOCK_SIZE_M": 16,
|
| 20 |
+
"BLOCK_SIZE_N": 64,
|
| 21 |
+
"BLOCK_SIZE_K": 64,
|
| 22 |
+
"GROUP_SIZE_M": 64,
|
| 23 |
+
"num_warps": 4,
|
| 24 |
+
"num_stages": 5
|
| 25 |
+
},
|
| 26 |
+
"8": {
|
| 27 |
+
"BLOCK_SIZE_M": 16,
|
| 28 |
+
"BLOCK_SIZE_N": 128,
|
| 29 |
+
"BLOCK_SIZE_K": 64,
|
| 30 |
+
"GROUP_SIZE_M": 1,
|
| 31 |
+
"num_warps": 4,
|
| 32 |
+
"num_stages": 3
|
| 33 |
+
},
|
| 34 |
+
"16": {
|
| 35 |
+
"BLOCK_SIZE_M": 16,
|
| 36 |
+
"BLOCK_SIZE_N": 64,
|
| 37 |
+
"BLOCK_SIZE_K": 64,
|
| 38 |
+
"GROUP_SIZE_M": 1,
|
| 39 |
+
"num_warps": 4,
|
| 40 |
+
"num_stages": 4
|
| 41 |
+
},
|
| 42 |
+
"24": {
|
| 43 |
+
"BLOCK_SIZE_M": 16,
|
| 44 |
+
"BLOCK_SIZE_N": 64,
|
| 45 |
+
"BLOCK_SIZE_K": 64,
|
| 46 |
+
"GROUP_SIZE_M": 16,
|
| 47 |
+
"num_warps": 4,
|
| 48 |
+
"num_stages": 3
|
| 49 |
+
},
|
| 50 |
+
"32": {
|
| 51 |
+
"BLOCK_SIZE_M": 16,
|
| 52 |
+
"BLOCK_SIZE_N": 128,
|
| 53 |
+
"BLOCK_SIZE_K": 64,
|
| 54 |
+
"GROUP_SIZE_M": 32,
|
| 55 |
+
"num_warps": 4,
|
| 56 |
+
"num_stages": 3
|
| 57 |
+
},
|
| 58 |
+
"48": {
|
| 59 |
+
"BLOCK_SIZE_M": 16,
|
| 60 |
+
"BLOCK_SIZE_N": 64,
|
| 61 |
+
"BLOCK_SIZE_K": 128,
|
| 62 |
+
"GROUP_SIZE_M": 1,
|
| 63 |
+
"num_warps": 4,
|
| 64 |
+
"num_stages": 3
|
| 65 |
+
},
|
| 66 |
+
"64": {
|
| 67 |
+
"BLOCK_SIZE_M": 16,
|
| 68 |
+
"BLOCK_SIZE_N": 64,
|
| 69 |
+
"BLOCK_SIZE_K": 64,
|
| 70 |
+
"GROUP_SIZE_M": 1,
|
| 71 |
+
"num_warps": 4,
|
| 72 |
+
"num_stages": 4
|
| 73 |
+
},
|
| 74 |
+
"96": {
|
| 75 |
+
"BLOCK_SIZE_M": 16,
|
| 76 |
+
"BLOCK_SIZE_N": 128,
|
| 77 |
+
"BLOCK_SIZE_K": 64,
|
| 78 |
+
"GROUP_SIZE_M": 1,
|
| 79 |
+
"num_warps": 4,
|
| 80 |
+
"num_stages": 3
|
| 81 |
+
},
|
| 82 |
+
"128": {
|
| 83 |
+
"BLOCK_SIZE_M": 16,
|
| 84 |
+
"BLOCK_SIZE_N": 128,
|
| 85 |
+
"BLOCK_SIZE_K": 64,
|
| 86 |
+
"GROUP_SIZE_M": 1,
|
| 87 |
+
"num_warps": 4,
|
| 88 |
+
"num_stages": 3
|
| 89 |
+
},
|
| 90 |
+
"256": {
|
| 91 |
+
"BLOCK_SIZE_M": 16,
|
| 92 |
+
"BLOCK_SIZE_N": 128,
|
| 93 |
+
"BLOCK_SIZE_K": 64,
|
| 94 |
+
"GROUP_SIZE_M": 16,
|
| 95 |
+
"num_warps": 4,
|
| 96 |
+
"num_stages": 3
|
| 97 |
+
},
|
| 98 |
+
"512": {
|
| 99 |
+
"BLOCK_SIZE_M": 64,
|
| 100 |
+
"BLOCK_SIZE_N": 128,
|
| 101 |
+
"BLOCK_SIZE_K": 64,
|
| 102 |
+
"GROUP_SIZE_M": 1,
|
| 103 |
+
"num_warps": 8,
|
| 104 |
+
"num_stages": 3
|
| 105 |
+
},
|
| 106 |
+
"1024": {
|
| 107 |
+
"BLOCK_SIZE_M": 64,
|
| 108 |
+
"BLOCK_SIZE_N": 64,
|
| 109 |
+
"BLOCK_SIZE_K": 64,
|
| 110 |
+
"GROUP_SIZE_M": 64,
|
| 111 |
+
"num_warps": 4,
|
| 112 |
+
"num_stages": 4
|
| 113 |
+
},
|
| 114 |
+
"1536": {
|
| 115 |
+
"BLOCK_SIZE_M": 64,
|
| 116 |
+
"BLOCK_SIZE_N": 128,
|
| 117 |
+
"BLOCK_SIZE_K": 64,
|
| 118 |
+
"GROUP_SIZE_M": 1,
|
| 119 |
+
"num_warps": 4,
|
| 120 |
+
"num_stages": 3
|
| 121 |
+
},
|
| 122 |
+
"2048": {
|
| 123 |
+
"BLOCK_SIZE_M": 64,
|
| 124 |
+
"BLOCK_SIZE_N": 64,
|
| 125 |
+
"BLOCK_SIZE_K": 64,
|
| 126 |
+
"GROUP_SIZE_M": 1,
|
| 127 |
+
"num_warps": 4,
|
| 128 |
+
"num_stages": 3
|
| 129 |
+
},
|
| 130 |
+
"3072": {
|
| 131 |
+
"BLOCK_SIZE_M": 64,
|
| 132 |
+
"BLOCK_SIZE_N": 64,
|
| 133 |
+
"BLOCK_SIZE_K": 64,
|
| 134 |
+
"GROUP_SIZE_M": 32,
|
| 135 |
+
"num_warps": 4,
|
| 136 |
+
"num_stages": 3
|
| 137 |
+
},
|
| 138 |
+
"4096": {
|
| 139 |
+
"BLOCK_SIZE_M": 64,
|
| 140 |
+
"BLOCK_SIZE_N": 128,
|
| 141 |
+
"BLOCK_SIZE_K": 64,
|
| 142 |
+
"GROUP_SIZE_M": 64,
|
| 143 |
+
"num_warps": 4,
|
| 144 |
+
"num_stages": 4
|
| 145 |
+
}
|
| 146 |
+
}
|