main
py 788 lines 28.9 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 # Apache License, Version 2.0:
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16 # MIT License:
17 # Permission is hereby granted, free of charge, to any person obtaining a copy
18 # of this software and associated documentation files (the "Software"), to deal
19 # in the Software without restriction, including without limitation the rights
20 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 # copies of the Software, and to permit persons to whom the Software is
22 # furnished to do so, subject to the following conditions:
23 #
24 # The above copyright notice and this permission notice shall be included in all
25 # copies or substantial portions of the Software.
26 #
27 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 # SOFTWARE.
34 """Inference-only Flash model compatible with HuggingFace weights."""
35
36 import typing
37 from collections.abc import Callable, Iterable
38 from itertools import islice
39
40 import torch
41 from torch import nn
42 from transformers import PreTrainedConfig
43
44 from vllm.compilation.decorators import support_torch_compile
45 from vllm.config import CacheConfig, VllmConfig
46 from vllm.distributed import get_pp_group
47 from vllm.logger import init_logger
48 from vllm.model_executor.layers.activation import SiluAndMul
49 from vllm.model_executor.layers.fused_moe import (
50 FusedMoEFactory,
51 GateLinear,
52 fused_moe_make_expert_params_mapping,
53 )
54 from vllm.model_executor.layers.layernorm import RMSNorm
55 from vllm.model_executor.layers.linear import (
56 MergedColumnParallelLinear,
57 RowParallelLinear,
58 )
59 from vllm.model_executor.layers.logits_processor import LogitsProcessor
60 from vllm.model_executor.layers.quantization import QuantizationConfig
61 from vllm.model_executor.layers.quantization.utils.int8_utils import block_dequant
62 from vllm.model_executor.layers.vocab_parallel_embedding import (
63 ParallelLMHead,
64 VocabParallelEmbedding,
65 )
66 from vllm.model_executor.model_loader.weight_utils import default_weight_loader
67 from vllm.model_executor.models.deepseek_v2 import DeepseekV2MLAAttention
68 from vllm.sequence import IntermediateTensors
69
70 from .interfaces import SupportsLoRA, SupportsPP
71 from .utils import (
72 AutoWeightsLoader,
73 PPMissingLayer,
74 is_pp_missing_parameter,
75 make_empty_intermediate_tensors_factory,
76 make_layers,
77 maybe_prefix,
78 )
79
80 logger = init_logger(__name__)
81
82
83 class FlashConfig(PreTrainedConfig):
84 """Flash model configuration."""
85
86 moe_intermediate_size: int
87
88 model_type = "longcat_flash"
89 keys_to_ignore_at_inference = ["past_key_values"]
90
91 def __init__(
92 self,
93 vocab_size=131072,
94 hidden_size=4096,
95 intermediate_size=8192,
96 num_layers=28,
97 num_hidden_layers=None,
98 num_attention_heads=96,
99 num_key_value_heads=128,
100 ep_size=1,
101 kv_lora_rank=512,
102 q_lora_rank=1536,
103 qk_rope_head_dim=64,
104 v_head_dim=128,
105 qk_nope_head_dim=128,
106 num_experts_per_tok=None,
107 norm_topk_prob=False,
108 max_position_embeddings=8192,
109 initializer_range=0.02,
110 rms_norm_eps=1e-05,
111 use_cache=True,
112 pad_token_id=None,
113 bos_token_id=100000,
114 eos_token_id=100001,
115 pretraining_tp=1,
116 tie_word_embeddings=False,
117 rope_parameters=None,
118 attention_bias=False,
119 attention_dropout=0.0,
120 mla_scale_q_lora=False,
121 mla_scale_kv_lora=False,
122 dtype="bfloat16",
123 params_dtype="bfloat16",
124 router_dtype="float32",
125 router_bias=False,
126 topk_method=None,
127 routed_scaling_factor=1.0,
128 zero_expert_num=0,
129 zero_expert_type=None,
130 nextn_use_scmoe=False,
131 **kwargs,
132 ):
133 super().__init__(
134 pad_token_id=pad_token_id,
135 bos_token_id=bos_token_id,
136 eos_token_id=eos_token_id,
137 tie_word_embeddings=tie_word_embeddings,
138 dtype=dtype,
139 params_dtype=params_dtype,
140 router_dtype=router_dtype,
141 topk_method=topk_method,
142 router_bias=router_bias,
143 nextn_use_scmoe=nextn_use_scmoe,
144 **kwargs,
145 )
146 self.vocab_size = vocab_size
147 self.max_position_embeddings = max_position_embeddings
148 self.hidden_size = hidden_size
149 self.num_hidden_layers = (
150 num_hidden_layers if num_hidden_layers is not None else num_layers
151 )
152 self.num_attention_heads = num_attention_heads
153 self.ep_size = ep_size
154 self.kv_lora_rank = kv_lora_rank
155 self.q_lora_rank = q_lora_rank
156 self.qk_rope_head_dim = qk_rope_head_dim
157 self.v_head_dim = v_head_dim
158 self.qk_nope_head_dim = qk_nope_head_dim
159 self.num_experts_per_tok = num_experts_per_tok
160 self.norm_topk_prob = norm_topk_prob
161 # for backward compatibility
162 if num_key_value_heads is None:
163 num_key_value_heads = num_attention_heads
164
165 self.num_key_value_heads = num_key_value_heads
166 self.initializer_range = initializer_range
167 self.rms_norm_eps = rms_norm_eps
168 self.pretraining_tp = pretraining_tp
169 self.use_cache = use_cache
170 # Try to set `rope_scaling` if available, otherwise use `rope_parameters`
171 rope_scaling = kwargs.pop("rope_scaling", None)
172 rope_parameters = rope_scaling or rope_parameters or {"rope_type": "default"}
173 rope_theta = kwargs.pop("rope_theta", 1000000.0)
174 if "rope_theta" not in rope_parameters:
175 rope_parameters["rope_theta"] = rope_theta
176 self.rope_parameters = rope_parameters
177 self.attention_bias = attention_bias
178 self.attention_dropout = attention_dropout
179 self.mla_scale_q_lora = mla_scale_q_lora
180 self.mla_scale_kv_lora = mla_scale_kv_lora
181 self.zero_expert_num = zero_expert_num
182 self.zero_expert_type = zero_expert_type
183 self.routed_scaling_factor = routed_scaling_factor
184 self.hidden_act = "silu"
185 self.intermediate_size = (
186 self.ffn_hidden_size
187 if hasattr(self, "ffn_hidden_size")
188 else intermediate_size
189 )
190 if hasattr(self, "moe_intermediate_size"):
191 self.moe_intermediate_size = self.moe_intermediate_size
192 elif hasattr(self, "expert_ffn_hidden_size"):
193 self.moe_intermediate_size = self.expert_ffn_hidden_size
194 else:
195 self.moe_intermediate_size = self.intermediate_size
196
197
198 class FlashMLP(nn.Module):
199 """Flash MLP layer."""
200
201 def __init__(
202 self,
203 hidden_size: int,
204 intermediate_size: int,
205 hidden_act: str,
206 quant_config: QuantizationConfig | None = None,
207 reduce_results: bool = True,
208 prefix: str = "",
209 ) -> None:
210 super().__init__()
211 self.gate_up_proj = MergedColumnParallelLinear(
212 hidden_size,
213 [intermediate_size] * 2,
214 bias=False,
215 quant_config=quant_config,
216 prefix=f"{prefix}.gate_up_proj",
217 )
218 self.down_proj = RowParallelLinear(
219 intermediate_size,
220 hidden_size,
221 bias=False,
222 quant_config=quant_config,
223 reduce_results=reduce_results,
224 prefix=f"{prefix}.down_proj",
225 )
226 if hidden_act != "silu":
227 raise ValueError(
228 f"Unsupported activation: {hidden_act}. Only silu is supported for now."
229 )
230 self.act_fn = SiluAndMul()
231
232 def forward(self, x: torch.Tensor) -> torch.Tensor:
233 if x.numel() == 0:
234 return x
235
236 gate_up, _ = self.gate_up_proj(x)
237 x = self.act_fn(gate_up)
238 x, _ = self.down_proj(x)
239 return x
240
241
242 class LongcatRouter(nn.Module):
243 def __init__(
244 self,
245 config: FlashConfig,
246 zero_expert_num: int,
247 router_params_dtype: torch.dtype,
248 prefix: str = "",
249 ):
250 super().__init__()
251 self.n_routed_experts = (
252 config.n_routed_experts
253 if hasattr(config, "n_routed_experts")
254 else config.num_experts[0]
255 )
256 self.n_routed_experts = self.n_routed_experts + zero_expert_num
257 self.classifier = GateLinear(
258 config.hidden_size,
259 self.n_routed_experts,
260 bias=config.router_bias,
261 out_dtype=router_params_dtype,
262 params_dtype=router_params_dtype,
263 prefix=f"{prefix}.classifier",
264 )
265 self.e_score_correction_bias = nn.Parameter(
266 torch.zeros((self.n_routed_experts), dtype=router_params_dtype)
267 )
268
269 def forward(self, hidden_states):
270 logits, _ = self.classifier(hidden_states)
271 return logits
272
273
274 class LongcatMoe(nn.Module):
275 def __init__(
276 self,
277 config: FlashConfig,
278 num_experts: int,
279 top_k: int,
280 hidden_size: int,
281 intermediate_size: int,
282 params_dtype: torch.dtype | None = None,
283 quant_config: QuantizationConfig | None = None,
284 prefix: str = "",
285 enable_eplb: bool = False,
286 ):
287 super().__init__()
288 self.hidden_size = hidden_size
289 # Gate always runs at half / full precision for now.
290 self.router_params_dtype = params_dtype
291 if config.router_dtype == "float32":
292 self.router_params_dtype = torch.float32
293
294 self.router = LongcatRouter(
295 config=config,
296 zero_expert_num=config.zero_expert_num,
297 router_params_dtype=self.router_params_dtype,
298 prefix=f"{prefix}.gate",
299 )
300
301 assert config.zero_expert_type is not None
302 self.experts = FusedMoEFactory(
303 zero_expert_type=config.zero_expert_type,
304 e_score_correction_bias=self.router.e_score_correction_bias,
305 num_experts=num_experts,
306 top_k=top_k,
307 hidden_size=hidden_size,
308 intermediate_size=intermediate_size,
309 params_dtype=params_dtype,
310 renormalize=False,
311 quant_config=quant_config,
312 prefix=f"{prefix}.experts",
313 enable_eplb=enable_eplb,
314 routed_scaling_factor=config.routed_scaling_factor,
315 router_logits_dtype=self.router_params_dtype,
316 )
317
318 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
319 num_tokens, hidden_dim = hidden_states.shape
320 hidden_states = hidden_states.view(-1, hidden_dim)
321
322 # Align to MoERunner padded hidden size to avoid dim mismatch
323 padded_hidden = self.experts.moe_config.hidden_dim
324 if hidden_dim < padded_hidden:
325 hidden_states_padded = torch.nn.functional.pad(
326 hidden_states,
327 (0, padded_hidden - hidden_dim),
328 mode="constant",
329 value=0.0,
330 )
331 else:
332 hidden_states_padded = hidden_states
333
334 router_logits_full = self.router(hidden_states_padded)
335
336 # MoERunner handles routing memoization and zero expert computation
337 # internally. Pass full router_logits (including zero experts) so that
338 # zero experts can be properly identified in routing.
339 final_hidden_states = self.experts(
340 hidden_states=hidden_states_padded,
341 router_logits=router_logits_full, # Full logits (includes zero experts)
342 )
343
344 # Crop back to original hidden dimension if padded earlier
345 if padded_hidden != hidden_dim:
346 final_hidden_states = final_hidden_states[..., :hidden_dim]
347
348 return final_hidden_states.view(num_tokens, hidden_dim)
349
350
351 class FlashDecoderLayer(nn.Module):
352 """Flash decoder layer with dual attention and MLP structure."""
353
354 def __init__(
355 self,
356 vllm_config: VllmConfig,
357 config: FlashConfig,
358 cache_config: CacheConfig | None = None,
359 quant_config: QuantizationConfig | None = None,
360 prefix: str = "",
361 enable_eplb: bool = False,
362 ) -> None:
363 super().__init__()
364 self.layer_idx = int(prefix.split(sep=".")[-1])
365 self.hidden_size = config.hidden_size
366 max_position_embeddings = getattr(config, "max_position_embeddings", 8192)
367
368 # Dual attention structure
369 self.self_attn = nn.ModuleList(
370 [
371 DeepseekV2MLAAttention(
372 vllm_config=vllm_config,
373 config=config,
374 hidden_size=self.hidden_size,
375 num_heads=config.num_attention_heads,
376 qk_nope_head_dim=config.qk_nope_head_dim,
377 qk_rope_head_dim=config.qk_rope_head_dim,
378 v_head_dim=config.v_head_dim,
379 q_lora_rank=(
380 config.q_lora_rank if hasattr(config, "q_lora_rank") else None
381 ),
382 kv_lora_rank=config.kv_lora_rank,
383 max_position_embeddings=max_position_embeddings,
384 cache_config=cache_config,
385 quant_config=None
386 if "self_attn" in getattr(config, "disable_quant_module", [])
387 else quant_config,
388 prefix=f"{prefix}.self_attn.{i}",
389 )
390 for i in range(2)
391 ]
392 )
393 self.input_layernorm = nn.ModuleList(
394 [RMSNorm(config.hidden_size, eps=config.rms_norm_eps) for i in range(2)]
395 )
396 self.post_attention_layernorm = nn.ModuleList(
397 [RMSNorm(config.hidden_size, eps=config.rms_norm_eps) for i in range(2)]
398 )
399
400 # Dual MLP structure
401 self.mlps = nn.ModuleList(
402 [
403 FlashMLP(
404 hidden_size=self.hidden_size,
405 intermediate_size=config.intermediate_size,
406 hidden_act=config.hidden_act,
407 quant_config=None
408 if "mlps" in getattr(config, "disable_quant_module", [])
409 else quant_config,
410 prefix=f"{prefix}.mlps.{i}",
411 )
412 for i in range(2)
413 ]
414 )
415
416 self.mlp = LongcatMoe(
417 config=config,
418 num_experts=config.n_routed_experts
419 if hasattr(config, "n_routed_experts")
420 else config.num_experts[self.layer_idx],
421 top_k=config.moe_topk
422 if hasattr(config, "moe_topk")
423 else config.num_experts_per_tok,
424 hidden_size=config.hidden_size,
425 intermediate_size=config.moe_intermediate_size,
426 quant_config=quant_config,
427 prefix=(f"{prefix}.mlp"),
428 )
429
430 def forward(
431 self,
432 positions: torch.Tensor,
433 hidden_states: torch.Tensor,
434 residual: torch.Tensor | None,
435 ) -> tuple[torch.Tensor, torch.Tensor]:
436 if residual is None:
437 residual = hidden_states
438 hidden_states = self.input_layernorm[0](hidden_states)
439 else:
440 hidden_states, residual = self.input_layernorm[0](hidden_states, residual)
441
442 hidden_states = self.self_attn[0](
443 positions=positions,
444 hidden_states=hidden_states,
445 llama_4_scaling=None,
446 )
447
448 hidden_states, residual = self.post_attention_layernorm[0](
449 hidden_states, residual
450 )
451
452 # moe
453 hidden_states_copy = hidden_states.clone()
454 moe_hidden_states = self.mlp(hidden_states_copy)
455
456 # first mlp
457 hidden_states = self.mlps[0](hidden_states)
458
459 hidden_states, residual = self.input_layernorm[1](hidden_states, residual)
460
461 # second_attn
462 hidden_states = self.self_attn[1](
463 positions=positions,
464 hidden_states=hidden_states,
465 llama_4_scaling=None,
466 )
467 hidden_states, residual = self.post_attention_layernorm[1](
468 hidden_states, residual
469 )
470
471 # second_mlp
472 hidden_states = self.mlps[1](hidden_states)
473
474 hidden_states = hidden_states + moe_hidden_states
475
476 return hidden_states, residual
477
478
479 @support_torch_compile
480 class FlashModel(nn.Module):
481 """Flash model."""
482
483 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
484 super().__init__()
485 config = FlashConfig(**vllm_config.model_config.hf_config.__dict__)
486 cache_config = vllm_config.cache_config
487 quant_config = vllm_config.quant_config
488 self.config = config
489 self.quant_config = quant_config
490
491 self.vocab_size = config.vocab_size
492
493 if get_pp_group().is_first_rank:
494 self.embed_tokens = VocabParallelEmbedding(
495 config.vocab_size,
496 config.hidden_size,
497 prefix=maybe_prefix(prefix, "embed_tokens"),
498 )
499 else:
500 self.embed_tokens = PPMissingLayer()
501 self.start_layer, self.end_layer, self.layers = make_layers(
502 config.num_hidden_layers,
503 lambda prefix: FlashDecoderLayer(
504 vllm_config,
505 config,
506 cache_config=cache_config,
507 quant_config=quant_config,
508 prefix=prefix,
509 ),
510 prefix=f"{prefix}.layers",
511 )
512 if get_pp_group().is_last_rank:
513 self.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
514 else:
515 self.norm = PPMissingLayer()
516 self.make_empty_intermediate_tensors = make_empty_intermediate_tensors_factory(
517 ["hidden_states", "residual"], config.hidden_size
518 )
519
520 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
521 return self.embed_tokens(input_ids)
522
523 def forward(
524 self,
525 input_ids: torch.Tensor | None,
526 positions: torch.Tensor,
527 intermediate_tensors: IntermediateTensors | None = None,
528 inputs_embeds: torch.Tensor | None = None,
529 ) -> torch.Tensor | IntermediateTensors:
530 if get_pp_group().is_first_rank:
531 if inputs_embeds is not None:
532 hidden_states = inputs_embeds
533 else:
534 hidden_states = self.embed_input_ids(input_ids)
535 residual = None
536 else:
537 assert intermediate_tensors is not None
538 hidden_states = intermediate_tensors["hidden_states"]
539 residual = intermediate_tensors["residual"]
540
541 for layer in islice(self.layers, self.start_layer, self.end_layer):
542 hidden_states, residual = layer(
543 positions,
544 hidden_states,
545 residual,
546 )
547
548 if not get_pp_group().is_last_rank:
549 return IntermediateTensors(
550 {"hidden_states": hidden_states, "residual": residual}
551 )
552
553 hidden_states, _ = self.norm(hidden_states, residual)
554 return hidden_states
555
556 def get_expert_mapping(self) -> list[tuple[str, str, int, str]]:
557 # Params for weights, fp8 weight scales, fp8 activation scales
558 # (param_name, weight_name, expert_id, shard_id)
559 return fused_moe_make_expert_params_mapping(
560 self,
561 ckpt_gate_proj_name="gate_proj",
562 ckpt_down_proj_name="down_proj",
563 ckpt_up_proj_name="up_proj",
564 num_experts=self.config.n_routed_experts
565 if hasattr(self.config, "n_routed_experts")
566 else self.config.num_experts[0],
567 )
568
569 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
570 stacked_params_mapping = [
571 ("fused_qkv_a_proj", "q_a_proj", 0),
572 ("fused_qkv_a_proj", "kv_a_proj_with_mqa", 1),
573 (".gate_up_proj", ".gate_proj", 0),
574 (".gate_up_proj", ".up_proj", 1),
575 ]
576
577 expert_params_mapping = self.get_expert_mapping()
578 loaded_params: set[str] = set()
579
580 params_dict = dict(self.named_parameters())
581 for name, loaded_weight in weights:
582 if "rotary_emb.inv_freq" in name:
583 continue
584 for param_name, weight_name, shard_id in stacked_params_mapping:
585 if weight_name not in name:
586 continue
587 if "mlp" in name and "mlps" not in name:
588 continue
589 name = name.replace(weight_name, param_name)
590 # Skip loading extra bias for GPTQ models.
591 if (
592 name.endswith(".bias") or name.endswith("_bias")
593 ) and name not in params_dict:
594 continue
595 # Skip mtp
596 if ".mtp." in name:
597 continue
598 if is_pp_missing_parameter(name, self):
599 continue
600 param = params_dict[name]
601 weight_loader = param.weight_loader
602 weight_loader(param, loaded_weight, shard_id)
603 break
604 else:
605 is_expert_weight = False
606 for mapping in expert_params_mapping:
607 param_name, weight_name, expert_id, expert_shard_id = mapping
608 if weight_name not in name:
609 continue
610 is_expert_weight = True
611 name_mapped = name.replace(weight_name, param_name)
612 # Skip mtp
613 if ".mtp." in name_mapped:
614 continue
615 if (
616 name_mapped.endswith(".bias") or name_mapped.endswith("_bias")
617 ) and name not in params_dict:
618 continue
619 if is_pp_missing_parameter(name, self):
620 continue
621 param = params_dict[name_mapped]
622 weight_loader = param.weight_loader
623 weight_loader = typing.cast(
624 Callable[..., bool], param.weight_loader
625 )
626 success = weight_loader(
627 param,
628 loaded_weight,
629 name_mapped,
630 shard_id=expert_shard_id,
631 expert_id=expert_id,
632 return_success=True,
633 )
634 if success:
635 name = name_mapped
636 break
637 else:
638 if is_expert_weight:
639 # We've checked that this is an expert weight
640 # However it's not mapped locally to this rank
641 # So we simply skip it
642 continue
643 # Skip loading extra bias for GPTQ models.
644 if name.endswith(".bias") and name not in params_dict:
645 continue
646 # Skip loading kv_scale from ckpts towards new design.
647 if name.endswith(".kv_scale") and name not in params_dict:
648 continue
649 # Skip mtp
650 if ".mtp." in name:
651 continue
652 if name is None:
653 continue
654 if is_pp_missing_parameter(name, self):
655 continue
656 param = params_dict[name]
657 weight_loader = getattr(
658 param, "weight_loader", default_weight_loader
659 )
660 weight_loader(param, loaded_weight)
661 loaded_params.add(name)
662 for layer_id in range(self.config.num_hidden_layers):
663 for i in range(2):
664 if isinstance(self.layers[layer_id], PPMissingLayer):
665 continue
666 self_attn = self.layers[layer_id].self_attn[i]
667 if (
668 self.quant_config is not None
669 and hasattr(self.quant_config, "weight_block_size")
670 and self_attn.kv_b_proj.weight.dtype
671 in (
672 torch.float8_e4m3fn,
673 torch.float8_e4m3fnuz,
674 )
675 ):
676 weight_block_size = self.quant_config.weight_block_size
677 if weight_block_size is not None:
678 assert hasattr(self_attn.kv_b_proj, "weight_scale_inv")
679 dtype = torch.get_default_dtype()
680 w = block_dequant(
681 self_attn.kv_b_proj.weight,
682 self_attn.kv_b_proj.weight_scale_inv,
683 weight_block_size,
684 ).to(dtype)
685 else:
686 w = self_attn.kv_b_proj.weight
687
688 w_kc, w_vc = w.unflatten(
689 0, (-1, self_attn.qk_nope_head_dim + self_attn.v_head_dim)
690 ).split([self_attn.qk_nope_head_dim, self_attn.v_head_dim], dim=1)
691 self_attn.w_kc = w_kc.transpose(1, 2).contiguous().transpose(1, 2)
692 self_attn.w_vc = w_vc.contiguous().transpose(1, 2)
693 # Guard against compounding on incremental load_weights calls:
694 # the in-place ``*=`` would otherwise re-apply the MLA LoRA
695 # scaling to the layernorm weights on each pass.
696 if self.config.mla_scale_q_lora and not getattr(
697 self_attn, "_mla_q_lora_scaled", False
698 ):
699 self_attn.q_a_layernorm.weight.data *= (
700 self.config.hidden_size / self.config.q_lora_rank
701 ) ** 0.5
702 self_attn._mla_q_lora_scaled = True
703 if self.config.mla_scale_kv_lora and not getattr(
704 self_attn, "_mla_kv_lora_scaled", False
705 ):
706 self_attn.kv_a_layernorm.weight.data *= (
707 self.config.hidden_size / self.config.kv_lora_rank
708 ) ** 0.5
709 self_attn._mla_kv_lora_scaled = True
710 return loaded_params
711
712
713 class LongcatFlashForCausalLM(nn.Module, SupportsLoRA, SupportsPP):
714 """Flash model for causal language modeling."""
715
716 packed_modules_mapping = {
717 "qkv_proj": [
718 "q_proj",
719 "k_proj",
720 "v_proj",
721 ],
722 "gate_up_proj": [
723 "gate_proj",
724 "up_proj",
725 ],
726 }
727
728 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
729 super().__init__()
730 config = FlashConfig(**vllm_config.model_config.hf_config.__dict__)
731 quant_config = vllm_config.quant_config
732
733 self.config = config
734 config.intermediate_size = (
735 config.ffn_hidden_size
736 if hasattr(config, "ffn_hidden_size")
737 else config.intermediate_size
738 )
739
740 self.quant_config = quant_config
741
742 self.model = FlashModel(
743 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
744 )
745
746 if get_pp_group().is_last_rank:
747 self.lm_head = ParallelLMHead(
748 config.vocab_size,
749 config.hidden_size,
750 quant_config=quant_config,
751 prefix=maybe_prefix(prefix, "lm_head"),
752 )
753 else:
754 self.lm_head = PPMissingLayer()
755
756 self.logits_processor = LogitsProcessor(config.vocab_size)
757 self.make_empty_intermediate_tensors = (
758 self.model.make_empty_intermediate_tensors
759 )
760
761 def embed_input_ids(self, input_ids: torch.Tensor) -> torch.Tensor:
762 return self.model.embed_input_ids(input_ids)
763
764 def forward(
765 self,
766 input_ids: torch.Tensor | None,
767 positions: torch.Tensor,
768 intermediate_tensors: IntermediateTensors | None = None,
769 inputs_embeds: torch.Tensor | None = None,
770 ) -> torch.Tensor | IntermediateTensors:
771 hidden_states = self.model(
772 input_ids, positions, intermediate_tensors, inputs_embeds
773 )
774 return hidden_states
775
776 def compute_logits(
777 self,
778 hidden_states: torch.Tensor,
779 ) -> torch.Tensor | None:
780 logits = self.logits_processor(self.lm_head, hidden_states)
781 return logits
782
783 def get_expert_mapping(self) -> list[tuple[str, str, int, str]]:
784 return self.model.get_expert_mapping()
785
786 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
787 loader = AutoWeightsLoader(self)
788 return loader.load_weights(weights)