A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 15, 22:15 UTC
[Model] Support Grok1 (#13795)
Signed-off-by: mgoin <mgoin64@gmail.com>
Michael Goin committed
Feb 25, 2025 at 20:07 UTC
07c4353057c2abb65db87104d44973c8cf5833bf
11 files changed
+634
-17
docs/source/models/supported_models.md
+5
@@ -286,6 +286,11 @@ See [this page](#generative-models) for more information on how to use generativ
286
* `parasail-ai/GritLM-7B-vllm`.
287
* ✅︎
288
* ✅︎
289
+- * `Grok1ModelForCausalLM`
290
+ * Grok1
291
+ * `hpcai-tech/grok-1`.
292
+ * ✅︎
293
+ * ✅︎
294
- * `InternLMForCausalLM`
295
* InternLM
296
* `internlm/internlm-7b`, `internlm/internlm-chat-7b`, etc.
tests/models/registry.py
+2
@@ -130,6 +130,8 @@ _TEXT_GENERATION_EXAMPLE_MODELS = {
130
"GPTNeoXForCausalLM": _HfExamplesInfo("EleutherAI/pythia-160m"),
131
"GraniteForCausalLM": _HfExamplesInfo("ibm/PowerLM-3b"),
132
"GraniteMoeForCausalLM": _HfExamplesInfo("ibm/PowerMoE-3b"),
133
+ "Grok1ModelForCausalLM": _HfExamplesInfo("hpcai-tech/grok-1",
134
+ trust_remote_code=True),
135
"InternLMForCausalLM": _HfExamplesInfo("internlm/internlm-chat-7b",
136
trust_remote_code=True),
137
"InternLM2ForCausalLM": _HfExamplesInfo("internlm/internlm2-chat-7b",
vllm/model_executor/layers/fused_moe/fused_moe.py
+31
-12
@@ -1040,6 +1040,7 @@ def inplace_fused_experts(hidden_states: torch.Tensor,
1040
w2: torch.Tensor,
1041
topk_weights: torch.Tensor,
1042
topk_ids: torch.Tensor,
1043
+ activation: str = "silu",
1044
use_fp8_w8a8: bool = False,
1045
use_int8_w8a16: bool = False,
1046
use_int4_w4a16: bool = False,
@@ -1053,9 +1054,10 @@ def inplace_fused_experts(hidden_states: torch.Tensor,
1054
a2_scale: Optional[torch.Tensor] = None,
1055
block_shape: Optional[List[int]] = None) -> None:
1056
fused_experts_impl(hidden_states, w1, w2, topk_weights, topk_ids, True,
1056
- use_fp8_w8a8, use_int8_w8a16, use_int4_w4a16,
1057
- global_num_experts, expert_map, w1_scale, w2_scale,
1058
- w1_zp, w2_zp, a1_scale, a2_scale, block_shape)
1057
+ activation, use_fp8_w8a8, use_int8_w8a16,
1058
+ use_int4_w4a16, global_num_experts, expert_map,
1059
+ w1_scale, w2_scale, w1_zp, w2_zp, a1_scale, a2_scale,
1060
+ block_shape)
1061
1062
1063
def inplace_fused_experts_fake(
@@ -1064,6 +1066,7 @@ def inplace_fused_experts_fake(
1066
w2: torch.Tensor,
1067
topk_weights: torch.Tensor,
1068
topk_ids: torch.Tensor,
1069
+ activation: str = "silu",
1070
use_fp8_w8a8: bool = False,
1071
use_int8_w8a16: bool = False,
1072
use_int4_w4a16: bool = False,
@@ -1093,6 +1096,7 @@ def outplace_fused_experts(
1096
w2: torch.Tensor,
1097
topk_weights: torch.Tensor,
1098
topk_ids: torch.Tensor,
1099
+ activation: str = "silu",
1100
use_fp8_w8a8: bool = False,
1101
use_int8_w8a16: bool = False,
1102
use_int4_w4a16: bool = False,
@@ -1106,7 +1110,7 @@ def outplace_fused_experts(
1110
a2_scale: Optional[torch.Tensor] = None,
1111
block_shape: Optional[List[int]] = None) -> torch.Tensor:
1112
return fused_experts_impl(hidden_states, w1, w2, topk_weights, topk_ids,
1109
- False, use_fp8_w8a8, use_int8_w8a16,
1113
+ False, activation, use_fp8_w8a8, use_int8_w8a16,
1114
use_int4_w4a16, global_num_experts, expert_map,
1115
w1_scale, w2_scale, w1_zp, w2_zp, a1_scale,
1116
a2_scale, block_shape)
@@ -1118,6 +1122,7 @@ def outplace_fused_experts_fake(
1122
w2: torch.Tensor,
1123
topk_weights: torch.Tensor,
1124
topk_ids: torch.Tensor,
1125
+ activation: str = "silu",
1126
use_fp8_w8a8: bool = False,
1127
use_int8_w8a16: bool = False,
1128
use_int4_w4a16: bool = False,
@@ -1147,6 +1152,7 @@ def fused_experts(hidden_states: torch.Tensor,
1152
topk_weights: torch.Tensor,
1153
topk_ids: torch.Tensor,
1154
inplace: bool = False,
1155
+ activation: str = "silu",
1156
use_fp8_w8a8: bool = False,
1157
use_int8_w8a16: bool = False,
1158
use_int4_w4a16: bool = False,
@@ -1162,15 +1168,17 @@ def fused_experts(hidden_states: torch.Tensor,
1168
1169
if inplace:
1170
torch.ops.vllm.inplace_fused_experts(
1165
- hidden_states, w1, w2, topk_weights, topk_ids, use_fp8_w8a8,
1166
- use_int8_w8a16, use_int4_w4a16, global_num_experts, expert_map,
1167
- w1_scale, w2_scale, w1_zp, w2_zp, a1_scale, a2_scale, block_shape)
1171
+ hidden_states, w1, w2, topk_weights, topk_ids, activation,
1172
+ use_fp8_w8a8, use_int8_w8a16, use_int4_w4a16, global_num_experts,
1173
+ expert_map, w1_scale, w2_scale, w1_zp, w2_zp, a1_scale, a2_scale,
1174
+ block_shape)
1175
return hidden_states
1176
else:
1177
return torch.ops.vllm.outplace_fused_experts(
1171
- hidden_states, w1, w2, topk_weights, topk_ids, use_fp8_w8a8,
1172
- use_int8_w8a16, use_int4_w4a16, global_num_experts, expert_map,
1173
- w1_scale, w2_scale, w1_zp, w2_zp, a1_scale, a2_scale, block_shape)
1178
+ hidden_states, w1, w2, topk_weights, topk_ids, activation,
1179
+ use_fp8_w8a8, use_int8_w8a16, use_int4_w4a16, global_num_experts,
1180
+ expert_map, w1_scale, w2_scale, w1_zp, w2_zp, a1_scale, a2_scale,
1181
+ block_shape)
1182
1183
1184
def fused_experts_impl(hidden_states: torch.Tensor,
@@ -1179,6 +1187,7 @@ def fused_experts_impl(hidden_states: torch.Tensor,
1187
topk_weights: torch.Tensor,
1188
topk_ids: torch.Tensor,
1189
inplace: bool = False,
1190
+ activation: str = "silu",
1191
use_fp8_w8a8: bool = False,
1192
use_int8_w8a16: bool = False,
1193
use_int4_w4a16: bool = False,
@@ -1303,8 +1312,14 @@ def fused_experts_impl(hidden_states: torch.Tensor,
1312
use_int4_w4a16=use_int4_w4a16,
1313
block_shape=block_shape)
1314
1306
- torch.ops._C.silu_and_mul(intermediate_cache2,
1307
- intermediate_cache1.view(-1, N))
1315
+ if activation == "silu":
1316
+ torch.ops._C.silu_and_mul(intermediate_cache2,
1317
+ intermediate_cache1.view(-1, N))
1318
+ elif activation == "gelu":
1319
+ torch.ops._C.gelu_and_mul(intermediate_cache2,
1320
+ intermediate_cache1.view(-1, N))
1321
+ else:
1322
+ raise ValueError(f"Unsupported FusedMoe activation: {activation}")
1323
1324
invoke_fused_moe_kernel(intermediate_cache2,
1325
w2,
@@ -1339,6 +1354,7 @@ def fused_moe(
1354
topk: int,
1355
renormalize: bool,
1356
inplace: bool = False,
1357
+ activation: str = "silu",
1358
use_grouped_topk: bool = False,
1359
num_expert_group: Optional[int] = None,
1360
topk_group: Optional[int] = None,
@@ -1370,6 +1386,8 @@ def fused_moe(
1386
- renormalize (bool): If True, renormalize the top-k weights to sum to 1.
1387
- inplace (bool): If True, perform the operation in-place.
1388
Defaults to False.
1389
+ - activation (str): The activation function to apply after the first
1390
+ MoE layer.
1391
- num_expert_group: Optional[int]: additional parameter for grouped_topk
1392
- topk_group: Optional[int]: additional parameter for grouped_topk
1393
- use_grouped_topk: If True, use grouped_topk instead of fused_topk
@@ -1420,6 +1438,7 @@ def fused_moe(
1438
topk_weights,
1439
topk_ids,
1440
inplace=inplace,
1441
+ activation=activation,
1442
use_fp8_w8a8=use_fp8_w8a8,
1443
use_int8_w8a16=use_int8_w8a16,
1444
use_int4_w4a16=use_int4_w4a16,
vllm/model_executor/layers/fused_moe/layer.py
+17
-5
@@ -120,7 +120,8 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
120
expert_map: Optional[torch.Tensor] = None,
121
custom_routing_function: Optional[Callable] = None,
122
scoring_func: str = "softmax",
123
- e_score_correction_bias: Optional[torch.Tensor] = None
123
+ e_score_correction_bias: Optional[torch.Tensor] = None,
124
+ activation: str = "silu",
125
) -> torch.Tensor:
126
return self.forward(x=x,
127
layer=layer,
@@ -134,7 +135,8 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
135
expert_map=expert_map,
136
custom_routing_function=custom_routing_function,
137
scoring_func=scoring_func,
137
- e_score_correction_bias=e_score_correction_bias)
138
+ e_score_correction_bias=e_score_correction_bias,
139
+ activation=activation)
140
141
def forward_cuda(
142
self,
@@ -150,7 +152,8 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
152
expert_map: Optional[torch.Tensor] = None,
153
custom_routing_function: Optional[Callable] = None,
154
scoring_func: str = "softmax",
153
- e_score_correction_bias: Optional[torch.Tensor] = None
155
+ e_score_correction_bias: Optional[torch.Tensor] = None,
156
+ activation: str = "silu",
157
) -> torch.Tensor:
158
topk_weights, topk_ids = FusedMoE.select_experts(
159
hidden_states=x,
@@ -170,6 +173,7 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
173
topk_weights=topk_weights,
174
topk_ids=topk_ids,
175
inplace=True,
176
+ activation=activation,
177
global_num_experts=global_num_experts,
178
expert_map=expert_map)
179
@@ -186,9 +190,11 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
190
global_num_experts: int = -1,
191
expert_map: Optional[torch.Tensor] = None,
192
custom_routing_function: Optional[Callable] = None,
193
+ activation: str = "silu",
194
**kwargs,
195
):
196
assert custom_routing_function is None
197
+ assert activation == "silu", f"{activation} is not supported."
198
return layer.ipex_fusion(
199
x,
200
use_grouped_topk,
@@ -213,7 +219,8 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
219
expert_map: Optional[torch.Tensor] = None,
220
custom_routing_function: Optional[Callable] = None,
221
scoring_func: str = "softmax",
216
- e_score_correction_bias: Optional[torch.Tensor] = None
222
+ e_score_correction_bias: Optional[torch.Tensor] = None,
223
+ activation: str = "silu",
224
) -> torch.Tensor:
225
assert not use_grouped_topk
226
assert num_expert_group is None
@@ -225,6 +232,7 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
232
if e_score_correction_bias is not None:
233
raise NotImplementedError(
234
"Expert score correction bias is not supported for TPU.")
235
+ assert activation == "silu", f"{activation} is not supported for TPU."
236
return fused_moe_pallas(hidden_states=x,
237
w1=layer.w13_weight,
238
w2=layer.w2_weight,
@@ -277,6 +285,7 @@ class FusedMoE(torch.nn.Module):
285
custom_routing_function: Optional[Callable] = None,
286
scoring_func: str = "softmax",
287
e_score_correction_bias: Optional[torch.Tensor] = None,
288
+ activation: str = "silu",
289
):
290
super().__init__()
291
@@ -305,6 +314,7 @@ class FusedMoE(torch.nn.Module):
314
self.custom_routing_function = custom_routing_function
315
self.scoring_func = scoring_func
316
self.e_score_correction_bias = e_score_correction_bias
317
+ self.activation = activation
318
self.expert_map = None
319
320
if self.ep_size > 1:
@@ -653,7 +663,9 @@ class FusedMoE(torch.nn.Module):
663
num_expert_group=self.num_expert_group,
664
custom_routing_function=self.custom_routing_function,
665
scoring_func=self.scoring_func,
656
- e_score_correction_bias=self.e_score_correction_bias)
666
+ e_score_correction_bias=self.e_score_correction_bias,
667
+ activation=self.activation,
668
+ )
669
670
if self.reduce_results and (self.tp_size > 1 or self.ep_size > 1):
671
# Default set to False. (May have to add shared expert outputs.)
vllm/model_executor/layers/quantization/awq_marlin.py
+2
@@ -469,7 +469,9 @@ class AWQMoEMethod(FusedMoEMethodBase):
469
custom_routing_function: Optional[Callable] = None,
470
scoring_func: str = "softmax",
471
e_score_correction_bias: Optional[torch.Tensor] = None,
472
+ activation: str = "silu",
473
) -> torch.Tensor:
474
+ assert activation == "silu", "Only SiLU activation is supported."
475
if expert_map is not None:
476
raise NotImplementedError(
477
"Expert Parallelism is not supported for "
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_moe.py
+4
@@ -219,6 +219,7 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
219
custom_routing_function: Optional[Callable] = None,
220
scoring_func: str = "softmax",
221
e_score_correction_bias: Optional[torch.Tensor] = None,
222
+ activation: str = "silu",
223
) -> torch.Tensor:
224
from vllm.model_executor.layers.fused_moe import fused_experts
225
@@ -240,6 +241,7 @@ class CompressedTensorsW8A8Fp8MoEMethod(CompressedTensorsMoEMethod):
241
topk_weights=topk_weights,
242
topk_ids=topk_ids,
243
inplace=True,
244
+ activation=activation,
245
use_fp8_w8a8=True,
246
global_num_experts=global_num_experts,
247
expert_map=expert_map,
@@ -550,7 +552,9 @@ class CompressedTensorsWNA16MoEMethod(CompressedTensorsMoEMethod):
552
custom_routing_function: Optional[Callable] = None,
553
scoring_func: str = "softmax",
554
e_score_correction_bias: Optional[torch.Tensor] = None,
555
+ activation: str = "silu",
556
) -> torch.Tensor:
557
+ assert activation == "silu", "Only SiLU activation is supported."
558
if expert_map is not None:
559
raise NotImplementedError(
560
"Expert Parallelism is not supported for "
vllm/model_executor/layers/quantization/experts_int8.py
+2
@@ -113,6 +113,7 @@ class ExpertsInt8MoEMethod(FusedMoEMethodBase):
113
custom_routing_function: Optional[Callable] = None,
114
scoring_func: str = "softmax",
115
e_score_correction_bias: Optional[torch.Tensor] = None,
116
+ activation: str = "silu",
117
) -> torch.Tensor:
118
from vllm.model_executor.layers.fused_moe import fused_experts
119
@@ -134,6 +135,7 @@ class ExpertsInt8MoEMethod(FusedMoEMethodBase):
135
topk_weights=topk_weights,
136
topk_ids=topk_ids,
137
inplace=True,
138
+ activation=activation,
139
use_int8_w8a16=True,
140
global_num_experts=global_num_experts,
141
expert_map=expert_map,
vllm/model_executor/layers/quantization/fp8.py
+2
@@ -675,6 +675,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
675
custom_routing_function: Optional[Callable] = None,
676
scoring_func: str = "softmax",
677
e_score_correction_bias: Optional[torch.Tensor] = None,
678
+ activation: str = "silu",
679
) -> torch.Tensor:
680
from vllm.model_executor.layers.fused_moe import fused_experts
681
@@ -698,6 +699,7 @@ class Fp8MoEMethod(FusedMoEMethodBase):
699
topk_weights=topk_weights,
700
topk_ids=topk_ids,
701
inplace=True,
702
+ activation=activation,
703
use_fp8_w8a8=True,
704
global_num_experts=global_num_experts,
705
expert_map=expert_map,
vllm/model_executor/layers/quantization/gptq_marlin.py
+3
@@ -590,7 +590,10 @@ class GPTQMarlinMoEMethod(FusedMoEMethodBase):
590
custom_routing_function: Optional[Callable] = None,
591
scoring_func: str = "softmax",
592
e_score_correction_bias: Optional[torch.Tensor] = None,
593
+ activation: str = "silu",
594
) -> torch.Tensor:
595
+ assert activation == "silu", "Only SiLU activation is supported."
596
+
597
# The input must currently be float16
598
orig_dtype = x.dtype
599
x = x.half()
vllm/model_executor/models/grok1.py
new
+565
@@ -0,0 +1,565 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# Adapted from
3
+# https://github.com/ROCm/vllm/blob/cea7419f151cc50293a05b7fac8547f8f887c9f6/vllm/model_executor/models/grok1.py
4
+# Copyright 2023 The vLLM team.
5
+# Copyright 2022 EleutherAI and the HuggingFace Inc. team. All rights reserved.
6
+#
7
+# This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
8
+# and OPT implementations in this library. It has been modified from its
9
+# original forms to accommodate minor architectural differences compared
10
+# to GPT-NeoX and OPT used by the Meta AI team that trained the model.
11
+#
12
+# Licensed under the Apache License, Version 2.0 (the "License");
13
+# you may not use this file except in compliance with the License.
14
+# You may obtain a copy of the License at
15
+#
16
+# http://www.apache.org/licenses/LICENSE-2.0
17
+#
18
+# Unless required by applicable law or agreed to in writing, software
19
+# distributed under the License is distributed on an "AS IS" BASIS,
20
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+# See the License for the specific language governing permissions and
22
+# limitations under the License.
23
+"""Inference-only Grok1 model."""
24
+from typing import Iterable, List, Optional, Set, Tuple, Union
25
+
26
+import torch
27
+import torch.nn.functional as F
28
+from torch import nn
29
+
30
+from vllm.attention import Attention, AttentionMetadata
31
+from vllm.compilation.decorators import support_torch_compile
32
+from vllm.config import CacheConfig, VllmConfig
33
+from vllm.distributed import get_pp_group, get_tensor_model_parallel_world_size
34
+from vllm.model_executor.layers.fused_moe import FusedMoE
35
+from vllm.model_executor.layers.layernorm import RMSNorm
36
+from vllm.model_executor.layers.linear import (QKVParallelLinear,
37
+ ReplicatedLinear,
38
+ RowParallelLinear)
39
+from vllm.model_executor.layers.logits_processor import LogitsProcessor
40
+from vllm.model_executor.layers.quantization import QuantizationConfig
41
+from vllm.model_executor.layers.rotary_embedding import get_rope
42
+from vllm.model_executor.layers.sampler import SamplerOutput, get_sampler
43
+from vllm.model_executor.layers.vocab_parallel_embedding import (
44
+ DEFAULT_VOCAB_PADDING_SIZE, ParallelLMHead, VocabParallelEmbedding)
45
+from vllm.model_executor.model_loader.weight_utils import (
46
+ default_weight_loader, maybe_remap_kv_scale_name)
47
+from vllm.model_executor.sampling_metadata import SamplingMetadata
48
+from vllm.sequence import IntermediateTensors
49
+
50
+from .interfaces import SupportsLoRA, SupportsPP
51
+from .utils import (is_pp_missing_parameter,
52
+ make_empty_intermediate_tensors_factory, make_layers,
53
+ maybe_prefix)
54
+
55
+# Default Grok1-specific constants, overridden by config values if present
56
+DEFAULT_ATTN_OUTPUT_MULTIPLIER = 0.08838834764831845
57
+DEFAULT_OUTPUT_MULTIPLIER_SCALE = 0.5773502691896257
58
+DEFAULT_EMBEDDING_MULTIPLIER_SCALE = 78.38367176906169
59
+
60
+
61
+class Grok1MoE(nn.Module):
62
+ """A tensor-parallel MoE implementation for Grok1 that shards each expert
63
+ across all ranks.
64
+
65
+ Each expert's weights are sharded across all ranks and a fused MoE
66
+ kernel is used for the forward pass, and finally we reduce the outputs
67
+ across ranks.
68
+ """
69
+
70
+ def __init__(self,
71
+ num_experts: int,
72
+ top_k: int,
73
+ hidden_size: int,
74
+ intermediate_size: int,
75
+ params_dtype: Optional[torch.dtype] = None,
76
+ quant_config: Optional[QuantizationConfig] = None,
77
+ tp_size: Optional[int] = None,
78
+ prefix: str = ""):
79
+ super().__init__()
80
+ self.hidden_size = hidden_size
81
+
82
+ # Gate always runs at half / full precision for now.
83
+ self.gate = ReplicatedLinear(hidden_size,
84
+ num_experts,
85
+ bias=False,
86
+ params_dtype=params_dtype,
87
+ quant_config=None,
88
+ prefix=f"{prefix}.gate")
89
+
90
+ self.experts = FusedMoE(num_experts=num_experts,
91
+ top_k=top_k,
92
+ hidden_size=hidden_size,
93
+ intermediate_size=intermediate_size,
94
+ params_dtype=params_dtype,
95
+ reduce_results=True,
96
+ renormalize=True,
97
+ quant_config=quant_config,
98
+ tp_size=tp_size,
99
+ activation="gelu",
100
+ prefix=f"{prefix}.experts")
101
+
102
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
103
+ # NOTE: hidden_states can have either 1D or 2D shape.
104
+ orig_shape = hidden_states.shape
105
+ hidden_states = hidden_states.view(-1, self.hidden_size)
106
+ # router_logits: (num_tokens, n_experts)
107
+ router_logits, _ = self.gate(hidden_states)
108
+ router_logits = 30.0 * F.tanh(router_logits / 30.0)
109
+ final_hidden_states = self.experts(hidden_states, router_logits)
110
+ return final_hidden_states.view(orig_shape)
111
+
112
+
113
+class Grok1Attention(nn.Module):
114
+
115
+ def __init__(
116
+ self,
117
+ hidden_size: int,
118
+ num_heads: int,
119
+ num_kv_heads: int,
120
+ max_position: int = 4096 * 32,
121
+ rope_theta: float = 10000,
122
+ cache_config: Optional[CacheConfig] = None,
123
+ quant_config: Optional[QuantizationConfig] = None,
124
+ prefix: str = "",
125
+ config=None, # Added config parameter
126
+ ) -> None:
127
+ super().__init__()
128
+ self.hidden_size = hidden_size
129
+ self.config = config # Store config reference
130
+ tp_size = get_tensor_model_parallel_world_size()
131
+ self.total_num_heads = num_heads
132
+ assert self.total_num_heads % tp_size == 0
133
+ self.num_heads = self.total_num_heads // tp_size
134
+ self.total_num_kv_heads = num_kv_heads
135
+ if self.total_num_kv_heads >= tp_size:
136
+ # Number of KV heads is greater than TP size, so we partition
137
+ # the KV heads across multiple tensor parallel GPUs.
138
+ assert self.total_num_kv_heads % tp_size == 0
139
+ else:
140
+ # Number of KV heads is less than TP size, so we replicate
141
+ # the KV heads across multiple tensor parallel GPUs.
142
+ assert tp_size % self.total_num_kv_heads == 0
143
+ self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
144
+ self.head_dim = hidden_size // self.total_num_heads
145
+ self.q_size = self.num_heads * self.head_dim
146
+ self.kv_size = self.num_kv_heads * self.head_dim
147
+ self.scaling = self.head_dim**-0.5
148
+ self.rope_theta = rope_theta
149
+
150
+ self.qkv_proj = QKVParallelLinear(
151
+ hidden_size,
152
+ self.head_dim,
153
+ self.total_num_heads,
154
+ self.total_num_kv_heads,
155
+ bias=False,
156
+ quant_config=quant_config,
157
+ prefix=f"{prefix}.qkv_proj",
158
+ )
159
+ self.o_proj = RowParallelLinear(
160
+ self.total_num_heads * self.head_dim,
161
+ hidden_size,
162
+ bias=False,
163
+ quant_config=quant_config,
164
+ prefix=f"{prefix}.o_proj",
165
+ )
166
+ self.rotary_emb = get_rope(
167
+ self.head_dim,
168
+ rotary_dim=self.head_dim,
169
+ max_position=max_position,
170
+ base=int(self.rope_theta),
171
+ is_neox_style=True,
172
+ )
173
+
174
+ attn_logits_soft_cap = max(
175
+ getattr(config, "attn_logit_softcapping", 30.0), 0.0)
176
+
177
+ self.attn = Attention(self.num_heads,
178
+ self.head_dim,
179
+ self.scaling,
180
+ num_kv_heads=self.num_kv_heads,
181
+ cache_config=cache_config,
182
+ quant_config=quant_config,
183
+ logits_soft_cap=attn_logits_soft_cap,
184
+ prefix=f"{prefix}.attn")
185
+
186
+ def forward(
187
+ self,
188
+ positions: torch.Tensor,
189
+ hidden_states: torch.Tensor,
190
+ kv_cache: torch.Tensor,
191
+ attn_metadata: AttentionMetadata,
192
+ ) -> torch.Tensor:
193
+ qkv, _ = self.qkv_proj(hidden_states)
194
+ q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
195
+ q, k = self.rotary_emb(positions, q, k)
196
+ attn_output = self.attn(q, k, v, kv_cache, attn_metadata)
197
+ output, _ = self.o_proj(attn_output)
198
+
199
+ # Apply attention output multiplier if specified in config
200
+ attn_multiplier = getattr(self.config, "attn_output_multiplier",
201
+ None) if self.config else None
202
+ if attn_multiplier is not None:
203
+ output = output * attn_multiplier
204
+ return output
205
+
206
+
207
+class Grok1DecoderLayer(nn.Module):
208
+
209
+ def __init__(
210
+ self,
211
+ config,
212
+ cache_config: Optional[CacheConfig] = None,
213
+ quant_config: Optional[QuantizationConfig] = None,
214
+ prefix: str = "",
215
+ ) -> None:
216
+ super().__init__()
217
+ self.hidden_size = config.hidden_size
218
+ # Check for fp8 quantization
219
+ self.use_fp8 = False
220
+ if quant_config is not None:
221
+ self.use_fp8 = getattr(quant_config, "is_fp8_w8a8",
222
+ lambda: False)()
223
+ if not self.use_fp8 and hasattr(quant_config, "is_fp8"):
224
+ self.use_fp8 = quant_config.is_fp8
225
+
226
+ # Requires transformers > 4.32.0
227
+ # Default rope_theta value if not in config
228
+ rope_theta = 10000
229
+ self.attn = Grok1Attention(
230
+ hidden_size=self.hidden_size,
231
+ num_heads=config.num_attention_heads,
232
+ max_position=config.max_position_embeddings,
233
+ num_kv_heads=config.num_key_value_heads,
234
+ rope_theta=rope_theta,
235
+ cache_config=cache_config,
236
+ quant_config=quant_config,
237
+ prefix=f"{prefix}.attn",
238
+ config=config) # Pass config to Grok1Attention
239
+
240
+ # Grok1 uses "num_experts" in its config
241
+ num_experts = getattr(config, "num_experts", 8)
242
+ num_experts_per_tok = getattr(config, "num_experts_per_tok", 2)
243
+
244
+ self.moe_block = Grok1MoE(num_experts=num_experts,
245
+ top_k=num_experts_per_tok,
246
+ hidden_size=config.hidden_size,
247
+ intermediate_size=config.intermediate_size,
248
+ quant_config=quant_config,
249
+ prefix=f"{prefix}.moe_block")
250
+
251
+ self.pre_attn_norm = RMSNorm(config.hidden_size,
252
+ eps=config.rms_norm_eps)
253
+ self.post_attn_norm = RMSNorm(config.hidden_size,
254
+ eps=config.rms_norm_eps)
255
+ self.pre_moe_norm = RMSNorm(config.hidden_size,
256
+ eps=config.rms_norm_eps)
257
+ self.post_moe_norm = RMSNorm(config.hidden_size,
258
+ eps=config.rms_norm_eps)
259
+
260
+ def forward(
261
+ self,
262
+ positions: torch.Tensor,
263
+ hidden_states: torch.Tensor,
264
+ kv_cache: torch.Tensor,
265
+ attn_metadata: AttentionMetadata,
266
+ residual: Optional[torch.Tensor],
267
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
268
+ # Self Attention
269
+ if residual is None:
270
+ residual = hidden_states
271
+ hidden_states = self.pre_attn_norm(hidden_states)
272
+ else:
273
+ hidden_states, residual = self.pre_attn_norm(
274
+ hidden_states, residual)
275
+
276
+ hidden_states = self.attn(
277
+ positions=positions,
278
+ hidden_states=hidden_states,
279
+ kv_cache=kv_cache,
280
+ attn_metadata=attn_metadata,
281
+ )
282
+
283
+ # Post attention normalization
284
+ hidden_states = self.post_attn_norm(hidden_states)
285
+
286
+ # MoE block with normalization
287
+ hidden_states, residual = self.pre_moe_norm(hidden_states, residual)
288
+ hidden_states = self.moe_block(hidden_states)
289
+ hidden_states = self.post_moe_norm(hidden_states)
290
+
291
+ return hidden_states, residual
292
+
293
+
294
+@support_torch_compile
295
+class Grok1Model(nn.Module):
296
+
297
+ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
298
+ super().__init__()
299
+
300
+ config = vllm_config.model_config.hf_config
301
+ cache_config = vllm_config.cache_config
302
+ quant_config = vllm_config.quant_config
303
+ lora_config = vllm_config.lora_config
304
+
305
+ self.padding_idx = config.pad_token_id
306
+ lora_vocab = (lora_config.lora_extra_vocab_size *
307
+ (lora_config.max_loras or 1)) if lora_config else 0
308
+ self.vocab_size = config.vocab_size + lora_vocab
309
+ self.org_vocab_size = config.vocab_size
310
+ self.embedding_multiplier_scale = getattr(
311
+ config, "embedding_multiplier_scale",
312
+ DEFAULT_EMBEDDING_MULTIPLIER_SCALE)
313
+
314
+ self.embed_tokens = VocabParallelEmbedding(
315
+ self.vocab_size,
316
+ config.hidden_size,
317
+ org_num_embeddings=config.vocab_size,
318
+ quant_config=quant_config,
319
+ )
320
+
321
+ self.start_layer, self.end_layer, self.layers = make_layers(
322
+ config.num_hidden_layers,
323
+ lambda prefix: Grok1DecoderLayer(
324
+ config, cache_config, quant_config=quant_config, prefix=prefix
325
+ ),
326
+ prefix=f"{prefix}.layers")
327
+
328
+ self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
329
+ self.make_empty_intermediate_tensors = (
330
+ make_empty_intermediate_tensors_factory(
331
+ ["hidden_states", "residual"], config.hidden_size))
332
+
333
+ def get_input_embeddings(self, input_ids: torch.Tensor) -> torch.Tensor:
334
+ hidden_states = self.embed_tokens(input_ids)
335
+ hidden_states = hidden_states * self.embedding_multiplier_scale
336
+ return hidden_states
337
+
338
+ def forward(
339
+ self,
340
+ input_ids: torch.Tensor,
341
+ positions: torch.Tensor,
342
+ kv_caches: List[torch.Tensor],
343
+ attn_metadata: AttentionMetadata,
344
+ intermediate_tensors: Optional[IntermediateTensors],
345
+ inputs_embeds: Optional[torch.Tensor] = None,
346
+ ) -> Union[torch.Tensor, IntermediateTensors]:
347
+ if get_pp_group().is_first_rank:
348
+ if inputs_embeds is not None:
349
+ hidden_states = inputs_embeds
350
+ else:
351
+ hidden_states = self.get_input_embeddings(input_ids)
352
+ residual = None
353
+ else:
354
+ assert intermediate_tensors is not None
355
+ hidden_states = intermediate_tensors["hidden_states"]
356
+ residual = intermediate_tensors["residual"]
357
+
358
+ for i in range(self.start_layer, self.end_layer):
359
+ layer = self.layers[i]
360
+ hidden_states, residual = layer(positions, hidden_states,
361
+ kv_caches[i - self.start_layer],
362
+ attn_metadata, residual)
363
+
364
+ if not get_pp_group().is_last_rank:
365
+ return IntermediateTensors({
366
+ "hidden_states": hidden_states,
367
+ "residual": residual
368
+ })
369
+
370
+ hidden_states, _ = self.norm(hidden_states, residual)
371
+ return hidden_states
372
+
373
+
374
+class Grok1ForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
375
+ fall_back_to_pt_during_load = False
376
+
377
+ packed_modules_mapping = {
378
+ "qkv_proj": [
379
+ "q_proj",
380
+ "k_proj",
381
+ "v_proj",
382
+ ],
383
+ }
384
+
385
+ def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
386
+ super().__init__()
387
+
388
+ config = vllm_config.model_config.hf_config
389
+ quant_config = vllm_config.quant_config
390
+ lora_config = vllm_config.lora_config
391
+
392
+ self.config = config
393
+ self.lora_config = lora_config
394
+ self.quant_config = quant_config
395
+
396
+ self.model = Grok1Model(vllm_config=vllm_config,
397
+ prefix=maybe_prefix(prefix, "model"))
398
+
399
+ self.unpadded_vocab_size = config.vocab_size
400
+ if lora_config:
401
+ self.unpadded_vocab_size += lora_config.lora_extra_vocab_size
402
+
403
+ self.lm_head = ParallelLMHead(
404
+ self.unpadded_vocab_size,
405
+ config.hidden_size,
406
+ org_num_embeddings=config.vocab_size,
407
+ padding_size=DEFAULT_VOCAB_PADDING_SIZE
408
+ # We need bigger padding if using lora for kernel compatibility
409
+ if not lora_config else lora_config.lora_vocab_padding_size,
410
+ quant_config=quant_config,
411
+ prefix=maybe_prefix(prefix, "lm_head"),
412
+ )
413
+
414
+ if self.config.tie_word_embeddings:
415
+ self.lm_head.weight = self.model.embed_tokens.weight
416
+
417
+ self.output_multiplier_scale = getattr(
418
+ config, "output_multiplier_scale", DEFAULT_OUTPUT_MULTIPLIER_SCALE)
419
+ self.logits_processor = LogitsProcessor(self.unpadded_vocab_size,
420
+ config.vocab_size,
421
+ self.output_multiplier_scale)
422
+
423
+ self.sampler = get_sampler()
424
+ self.make_empty_intermediate_tensors = (
425
+ self.model.make_empty_intermediate_tensors)
426
+
427
+ def get_input_embeddings(self, input_ids: torch.Tensor) -> torch.Tensor:
428
+ return self.model.get_input_embeddings(input_ids)
429
+
430
+ def forward(
431
+ self,
432
+ input_ids: torch.Tensor,
433
+ positions: torch.Tensor,
434
+ kv_caches: List[torch.Tensor],
435
+ attn_metadata: AttentionMetadata,
436
+ intermediate_tensors: Optional[IntermediateTensors] = None,
437
+ inputs_embeds: Optional[torch.Tensor] = None,
438
+ ) -> Union[torch.Tensor, IntermediateTensors]:
439
+ hidden_states = self.model(input_ids, positions, kv_caches,
440
+ attn_metadata, intermediate_tensors,
441
+ inputs_embeds)
442
+ return hidden_states
443
+
444
+ def compute_logits(
445
+ self,
446
+ hidden_states: torch.Tensor,
447
+ sampling_metadata: SamplingMetadata,
448
+ ) -> Optional[torch.Tensor]:
449
+ logits = self.logits_processor(self.lm_head, hidden_states,
450
+ sampling_metadata)
451
+ return logits
452
+
453
+ def sample(
454
+ self,
455
+ logits: Optional[torch.Tensor],
456
+ sampling_metadata: SamplingMetadata,
457
+ ) -> Optional[SamplerOutput]:
458
+ next_tokens = self.sampler(logits, sampling_metadata)
459
+ return next_tokens
460
+
461
+ def load_weights(self, weights: Iterable[Tuple[str,
462
+ torch.Tensor]]) -> Set[str]:
463
+ stacked_params_mapping = [
464
+ # (param_name, shard_name, shard_id)
465
+ ("qkv_proj", "q_proj", "q"),
466
+ ("qkv_proj", "k_proj", "k"),
467
+ ("qkv_proj", "v_proj", "v"),
468
+ ]
469
+
470
+ # Map Grok1's unique expert parameter names to standard names
471
+ # Grok1 uses "num_experts" in its config
472
+ num_experts = getattr(self.config, "num_experts", 8)
473
+ expert_params_mapping = FusedMoE.make_expert_params_mapping(
474
+ ckpt_gate_proj_name="linear", # Grok1 specific
475
+ ckpt_down_proj_name="linear_1", # Grok1 specific
476
+ ckpt_up_proj_name="linear_v", # Grok1 specific
477
+ num_experts=num_experts)
478
+
479
+ params_dict = dict(self.named_parameters())
480
+ loaded_params: Set[str] = set()
481
+
482
+ for name, loaded_weight in weights:
483
+ if "rotary_emb.inv_freq" in name:
484
+ continue
485
+
486
+ if (self.quant_config is not None and
487
+ (scale_name := self.quant_config.get_cache_scale(name))):
488
+ # Loading kv cache quantization scales
489
+ param = params_dict[scale_name]
490
+ weight_loader = getattr(param, "weight_loader",
491
+ default_weight_loader)
492
+ loaded_weight = (loaded_weight if loaded_weight.dim() == 0 else
493
+ loaded_weight[0])
494
+ weight_loader(param, loaded_weight)
495
+ loaded_params.add(scale_name)
496
+ continue
497
+
498
+ for (param_name, weight_name, shard_id) in stacked_params_mapping:
499
+ if weight_name not in name:
500
+ continue
501
+ name = name.replace(weight_name, param_name)
502
+ # Skip loading extra bias for GPTQ models.
503
+ if ((name.endswith(".bias") or name.endswith("_bias"))
504
+ and name not in params_dict):
505
+ continue
506
+ # Skip layers on other devices.
507
+ if is_pp_missing_parameter(name, self):
508
+ continue
509
+ if name.endswith("scale"):
510
+ # Remapping the name of FP8 kv-scale.
511
+ name = maybe_remap_kv_scale_name(name, params_dict)
512
+ if name is None:
513
+ continue
514
+ param = params_dict[name]
515
+ weight_loader = param.weight_loader
516
+ weight_loader(param, loaded_weight, shard_id)
517
+ break
518
+ else:
519
+ for mapping in expert_params_mapping:
520
+ param_name, weight_name, expert_id, shard_id = mapping
521
+ if weight_name not in name:
522
+ continue
523
+ name = name.replace(weight_name, param_name)
524
+ # Skip layers on other devices.
525
+ if is_pp_missing_parameter(name, self):
526
+ continue
527
+ if ((name.endswith(".bias") or name.endswith("_bias"))
528
+ and name not in params_dict):
529
+ continue
530
+ param = params_dict[name]
531
+ weight_loader = param.weight_loader
532
+ weight_loader(param,
533
+ loaded_weight,
534
+ name,
535
+ shard_id=shard_id,
536
+ expert_id=expert_id)
537
+ break
538
+ else:
539
+ # Skip loading extra bias for GPTQ models.
540
+ if ((name.endswith(".bias") or name.endswith("_bias"))
541
+ and name not in params_dict):
542
+ continue
543
+ # Skip layers on other devices.
544
+ if is_pp_missing_parameter(name, self):
545
+ continue
546
+
547
+ # Remapping the name of FP8 kv-scale.
548
+ name = maybe_remap_kv_scale_name(name, params_dict)
549
+ if name is None:
550
+ continue
551
+
552
+ # Handle Grok1-specific norm.scale naming
553
+ if "norm.scale" in name:
554
+ name = name.replace("scale", "weight")
555
+
556
+ # Skip lm_head when tie_word_embeddings is True
557
+ if "lm_head" in name and self.config.tie_word_embeddings:
558
+ continue
559
+
560
+ param = params_dict[name]
561
+ weight_loader = getattr(param, "weight_loader",
562
+ default_weight_loader)
563
+ weight_loader(param, loaded_weight)
564
+ loaded_params.add(name)
565
+ return loaded_params
vllm/model_executor/models/registry.py
+1
@@ -60,6 +60,7 @@ _TEXT_GENERATION_MODELS = {
60
"GraniteForCausalLM": ("granite", "GraniteForCausalLM"),
61
"GraniteMoeForCausalLM": ("granitemoe", "GraniteMoeForCausalLM"),
62
"GritLM": ("gritlm", "GritLM"),
63
+ "Grok1ModelForCausalLM": ("grok1", "Grok1ForCausalLM"),
64
"InternLMForCausalLM": ("llama", "LlamaForCausalLM"),
65
"InternLM2ForCausalLM": ("internlm2", "InternLM2ForCausalLM"),
66
"InternLM2VEForCausalLM": ("internlm2_ve", "InternLM2VEForCausalLM"),