main
py 640 lines 23.7 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # Copyright 2025 The vLLM team.
5 # Copyright 2025 The Qwen Team.
6 # Copyright 2025 The HuggingFace Inc. team.
7 # All rights reserved.
8 #
9 # This code is based on EleutherAI's GPT-NeoX library and the GPT-NeoX
10 # and OPT implementations in this library. It has been modified from its
11 # original forms to accommodate minor architectural differences compared
12 # to GPT-NeoX and OPT used by the Meta AI team that trained the model.
13 #
14 # Licensed under the Apache License, Version 2.0 (the "License");
15 # you may not use this file except in compliance with the License.
16 # You may obtain a copy of the License at
17 #
18 # http://www.apache.org/licenses/LICENSE-2.0
19 #
20 # Unless required by applicable law or agreed to in writing, software
21 # distributed under the License is distributed on an "AS IS" BASIS,
22 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 # See the License for the specific language governing permissions and
24 # limitations under the License.
25 """Inference-only InternS1Pro model compatible with HuggingFace weights."""
26
27 import functools
28 from collections.abc import Iterable
29 from typing import Any, ClassVar
30
31 import torch
32 from torch import nn
33 from transformers import AutoProcessor, PreTrainedConfig
34
35 from vllm.config import CacheConfig, VllmConfig
36 from vllm.distributed import (
37 get_ep_group,
38 get_tensor_model_parallel_world_size,
39 tensor_model_parallel_all_gather,
40 )
41 from vllm.logger import init_logger
42 from vllm.model_executor.layers.activation import SiluAndMul
43 from vllm.model_executor.layers.attention import Attention
44 from vllm.model_executor.layers.fused_moe import (
45 FusedMoEFactory,
46 GateLinear,
47 )
48 from vllm.model_executor.layers.fusion.mm_input_norm import build_mm_input_norm
49 from vllm.model_executor.layers.layernorm import RMSNorm
50 from vllm.model_executor.layers.linear import (
51 MergedColumnParallelLinear,
52 QKVParallelLinear,
53 RowParallelLinear,
54 )
55 from vllm.model_executor.layers.logits_processor import LogitsProcessor
56 from vllm.model_executor.layers.quantization import QuantizationConfig
57 from vllm.model_executor.layers.rotary_embedding import get_rope
58 from vllm.model_executor.layers.vocab_parallel_embedding import (
59 ParallelLMHead,
60 )
61 from vllm.model_executor.models.utils import sequence_parallel_chunk
62 from vllm.multimodal import MULTIMODAL_REGISTRY
63
64 from .interfaces import MixtureOfExperts
65 from .qwen3_moe import (
66 Qwen3MoeForCausalLM,
67 )
68 from .qwen3_vl import (
69 Qwen3_VisionTransformer,
70 Qwen3VLDummyInputsBuilder,
71 Qwen3VLForConditionalGeneration,
72 Qwen3VLMultiModalProcessor,
73 Qwen3VLProcessingInfo,
74 )
75 from .qwen3_vl_moe import Qwen3MoeLLMModel
76 from .utils import (
77 AutoWeightsLoader,
78 WeightsMapper,
79 extract_layer_index,
80 maybe_prefix,
81 )
82
83 logger = init_logger(__name__)
84
85
86 class InternS1ProProcessingInfo(Qwen3VLProcessingInfo):
87 def get_hf_config(self):
88 return self.ctx.get_hf_config()
89
90 def get_hf_processor(self, **kwargs: object) -> AutoProcessor:
91 return self.ctx.get_hf_processor(**kwargs)
92
93
94 class InternS1ProMoeMLP(nn.Module):
95 def __init__(
96 self,
97 hidden_size: int,
98 intermediate_size: int,
99 hidden_act: str,
100 quant_config: QuantizationConfig | None = None,
101 reduce_results: bool = True,
102 prefix: str = "",
103 ) -> None:
104 super().__init__()
105 self.gate_up_proj = MergedColumnParallelLinear(
106 hidden_size,
107 [intermediate_size] * 2,
108 bias=False,
109 quant_config=quant_config,
110 prefix=f"{prefix}.gate_up_proj",
111 )
112 self.down_proj = RowParallelLinear(
113 intermediate_size,
114 hidden_size,
115 bias=False,
116 quant_config=quant_config,
117 reduce_results=reduce_results,
118 prefix=f"{prefix}.down_proj",
119 )
120 if hidden_act != "silu":
121 raise ValueError(
122 f"Unsupported activation: {hidden_act}. Only silu is supported for now."
123 )
124 self.act_fn = SiluAndMul()
125
126 def forward(self, x):
127 gate_up, _ = self.gate_up_proj(x)
128 x = self.act_fn(gate_up)
129 x, _ = self.down_proj(x)
130 return x
131
132
133 class InternS1ProMoeSparseMoeBlock(nn.Module):
134 def __init__(
135 self,
136 vllm_config: VllmConfig,
137 prefix: str = "",
138 ):
139 super().__init__()
140
141 config = vllm_config.model_config.hf_text_config
142 parallel_config = vllm_config.parallel_config
143 quant_config = vllm_config.quant_config
144
145 self.tp_size = get_tensor_model_parallel_world_size()
146
147 self.ep_group = get_ep_group().device_group
148 self.ep_size = self.ep_group.size()
149 self.n_routed_experts = config.num_experts
150
151 self.is_sequence_parallel = parallel_config.use_sequence_parallel_moe
152
153 if self.tp_size > config.num_experts:
154 raise ValueError(
155 f"Tensor parallel size {self.tp_size} is greater than "
156 f"the number of experts {config.num_experts}."
157 )
158
159 # Load balancing settings.
160 eplb_config = vllm_config.parallel_config.eplb_config
161 self.enable_eplb = parallel_config.enable_eplb
162
163 self.n_logical_experts = self.n_routed_experts
164 self.n_redundant_experts = eplb_config.num_redundant_experts
165 self.n_physical_experts = self.n_logical_experts + self.n_redundant_experts
166 self.n_local_physical_experts = self.n_physical_experts // self.ep_size
167
168 # For custom routing function
169 self.n_groups = getattr(config, "router_n_groups", -1)
170
171 self.experts = FusedMoEFactory(
172 num_experts=self.n_routed_experts,
173 top_k=config.num_experts_per_tok,
174 hidden_size=config.hidden_size,
175 intermediate_size=config.moe_intermediate_size,
176 renormalize=config.norm_topk_prob,
177 quant_config=quant_config,
178 prefix=f"{prefix}.experts",
179 enable_eplb=self.enable_eplb,
180 num_redundant_experts=self.n_redundant_experts,
181 is_sequence_parallel=self.is_sequence_parallel,
182 custom_routing_function=self._custom_routing_function,
183 )
184
185 self.gate = GateLinear(
186 config.hidden_size,
187 config.num_experts,
188 prefix=f"{prefix}.gate",
189 )
190
191 @staticmethod
192 @functools.lru_cache
193 def get_group_offsets(n_groups: int, group_size: int, device: str):
194 group_offsets = (torch.arange(n_groups, device=device) * group_size).view(
195 1, -1, 1
196 ) # [1, n_groups, 1]
197 return group_offsets
198
199 # TODO: zhouxinyu, use vllm routing functions
200 def _custom_routing_function(
201 self,
202 hidden_states: torch.Tensor,
203 gating_output: torch.Tensor,
204 topk: int,
205 renormalize: bool,
206 ) -> torch.Tensor:
207 routing_weights = torch.softmax(gating_output, dim=-1, dtype=torch.float32)
208
209 if self.n_groups > 0:
210 assert routing_weights.shape[-1] % self.n_groups == 0, (
211 f"{routing_weights.shape[-1]} cannot be divided by {self.n_groups}"
212 )
213 per_group_top_k = topk // self.n_groups
214 group_size = routing_weights.shape[-1] // self.n_groups
215 group_offsets = self.get_group_offsets(
216 self.n_groups, group_size, routing_weights.device
217 )
218 routing_weights = routing_weights.unflatten(-1, (self.n_groups, group_size))
219 topk_weights, topk_ids = torch.topk(
220 routing_weights, per_group_top_k, dim=-1
221 )
222 topk_ids = (topk_ids + group_offsets).flatten(-2, -1)
223 topk_weights = topk_weights.flatten(-2, -1)
224 else:
225 topk_weights, topk_ids = torch.topk(routing_weights, topk, dim=-1)
226
227 if renormalize:
228 topk_weights = topk_weights / topk_weights.sum(dim=-1, keepdim=True)
229
230 return topk_weights, topk_ids
231
232 def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
233 assert hidden_states.dim() <= 2, (
234 "InternS1ProMoeSparseMoeBlock only supports 1D or 2D inputs"
235 )
236 is_input_1d = hidden_states.dim() == 1
237 num_tokens, hidden_dim = hidden_states.shape
238 hidden_states = hidden_states.view(-1, hidden_dim)
239
240 if self.is_sequence_parallel:
241 hidden_states = sequence_parallel_chunk(hidden_states)
242
243 # router_logits: (num_tokens, n_experts)
244 router_logits, _ = self.gate(hidden_states)
245 final_hidden_states = self.experts(
246 hidden_states=hidden_states, router_logits=router_logits
247 )
248
249 if self.is_sequence_parallel:
250 final_hidden_states = tensor_model_parallel_all_gather(
251 final_hidden_states, 0
252 )
253 final_hidden_states = final_hidden_states[:num_tokens]
254
255 # return to 1d if input is 1d
256 return final_hidden_states.squeeze(0) if is_input_1d else final_hidden_states
257
258
259 class InternS1ProMoeAttention(nn.Module):
260 def __init__(
261 self,
262 hidden_size: int,
263 num_heads: int,
264 num_kv_heads: int,
265 rope_parameters: dict[str, Any],
266 max_position_embeddings: int = 32768,
267 head_dim: int | None = None,
268 rms_norm_eps: float = 1e-06,
269 qkv_bias: bool = False,
270 cache_config: CacheConfig | None = None,
271 quant_config: QuantizationConfig | None = None,
272 prefix: str = "",
273 dual_chunk_attention_config: dict[str, Any] | None = None,
274 ) -> None:
275 super().__init__()
276 self.hidden_size = hidden_size
277 tp_size = get_tensor_model_parallel_world_size()
278 self.total_num_heads = num_heads
279 assert self.total_num_heads % tp_size == 0
280 self.num_heads = self.total_num_heads // tp_size
281 self.total_num_kv_heads = num_kv_heads
282 if self.total_num_kv_heads >= tp_size:
283 # Number of KV heads is greater than TP size, so we partition
284 # the KV heads across multiple tensor parallel GPUs.
285 assert self.total_num_kv_heads % tp_size == 0
286 else:
287 # Number of KV heads is less than TP size, so we replicate
288 # the KV heads across multiple tensor parallel GPUs.
289 assert tp_size % self.total_num_kv_heads == 0
290 self.num_kv_heads = max(1, self.total_num_kv_heads // tp_size)
291 self.head_dim = head_dim or (hidden_size // self.total_num_heads)
292 self.q_size = self.num_heads * self.head_dim
293 self.kv_size = self.num_kv_heads * self.head_dim
294 self.scaling = self.head_dim**-0.5
295 self.max_position_embeddings = max_position_embeddings
296 self.dual_chunk_attention_config = dual_chunk_attention_config
297
298 self.qkv_proj = QKVParallelLinear(
299 hidden_size,
300 self.head_dim,
301 self.total_num_heads,
302 self.total_num_kv_heads,
303 bias=qkv_bias,
304 quant_config=quant_config,
305 prefix=f"{prefix}.qkv_proj",
306 )
307
308 self.o_proj = RowParallelLinear(
309 self.total_num_heads * self.head_dim,
310 hidden_size,
311 bias=False,
312 quant_config=quant_config,
313 prefix=f"{prefix}.o_proj",
314 )
315
316 rope_parameters["num_key_value_heads"] = self.num_kv_heads
317 self.rotary_emb = get_rope(
318 self.head_dim,
319 max_position=max_position_embeddings,
320 rope_parameters=rope_parameters,
321 dual_chunk_attention_config=dual_chunk_attention_config,
322 )
323
324 attn_kwargs: dict[str, Any] = (
325 {
326 "layer_idx": extract_layer_index(prefix),
327 "dual_chunk_attention_config": dual_chunk_attention_config,
328 }
329 if dual_chunk_attention_config
330 else {}
331 )
332 self.attn = Attention(
333 self.num_heads,
334 self.head_dim,
335 self.scaling,
336 num_kv_heads=self.num_kv_heads,
337 cache_config=cache_config,
338 quant_config=quant_config,
339 prefix=f"{prefix}.attn",
340 **attn_kwargs,
341 )
342
343 self.q_norm = RMSNorm(self.head_dim, eps=rms_norm_eps)
344 self.k_norm = RMSNorm(self.head_dim, eps=rms_norm_eps)
345
346 def forward(
347 self,
348 positions: torch.Tensor,
349 hidden_states: torch.Tensor,
350 ) -> torch.Tensor:
351 qkv, _ = self.qkv_proj(hidden_states)
352 q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
353 # Add qk-norm
354 q_by_head = q.view(*q.shape[:-1], q.shape[-1] // self.head_dim, self.head_dim)
355 q_by_head = self.q_norm(q_by_head)
356 q = q_by_head.view(q.shape)
357
358 k_by_head = k.view(*k.shape[:-1], k.shape[-1] // self.head_dim, self.head_dim)
359 k_by_head = self.k_norm(k_by_head)
360 k = k_by_head.view(k.shape)
361 q, k = self.rotary_emb.forward_native(positions, q, k)
362 attn_output = self.attn(q, k, v)
363 output, _ = self.o_proj(attn_output)
364 return output
365
366
367 class InternS1ProMoeDecoderLayer(nn.Module):
368 def __init__(self, vllm_config: VllmConfig, prefix: str = "") -> None:
369 super().__init__()
370
371 config = vllm_config.model_config.hf_text_config
372 cache_config = vllm_config.cache_config
373 quant_config = vllm_config.quant_config
374
375 self.hidden_size = config.hidden_size
376 max_position_embeddings = getattr(config, "max_position_embeddings", 32768)
377 dual_chunk_attention_config = getattr(
378 config, "dual_chunk_attention_config", None
379 )
380
381 # update rope related parameters
382 rope_scaling = config.rope_scaling
383 fope_keys = {"fope_init_factor", "fope_sep_head", "num_inv_freq"}
384 use_fope = any(rope_scaling.get(key) is not None for key in fope_keys)
385 fope_init_factor = rope_scaling.get("fope_init_factor", None)
386 fope_sep_head = rope_scaling.get("fope_sep_head", None)
387 num_inv_freq = rope_scaling.get("num_inv_freq", None)
388
389 config.rope_parameters["use_fope"] = use_fope
390 config.rope_parameters["fope_init_factor"] = fope_init_factor
391 config.rope_parameters["fope_sep_head"] = fope_sep_head
392 config.rope_parameters["num_inv_freq"] = num_inv_freq
393
394 assert use_fope, "should use FOPE for InternS1Pro model"
395 self.self_attn = InternS1ProMoeAttention(
396 hidden_size=self.hidden_size,
397 num_heads=config.num_attention_heads,
398 num_kv_heads=config.num_key_value_heads,
399 rope_parameters=config.rope_parameters,
400 max_position_embeddings=max_position_embeddings,
401 rms_norm_eps=config.rms_norm_eps,
402 qkv_bias=getattr(config, "attention_bias", False),
403 head_dim=getattr(config, "head_dim", None),
404 cache_config=cache_config,
405 quant_config=quant_config,
406 prefix=f"{prefix}.self_attn",
407 dual_chunk_attention_config=dual_chunk_attention_config,
408 )
409
410 # `mlp_only_layers` in the config.
411 layer_idx = extract_layer_index(prefix)
412 mlp_only_layers = (
413 [] if not hasattr(config, "mlp_only_layers") else config.mlp_only_layers
414 )
415 if (layer_idx not in mlp_only_layers) and (
416 config.num_experts > 0 and (layer_idx + 1) % config.decoder_sparse_step == 0
417 ):
418 self.mlp = InternS1ProMoeSparseMoeBlock(
419 vllm_config=vllm_config, prefix=f"{prefix}.mlp"
420 )
421 else:
422 self.mlp = InternS1ProMoeMLP(
423 hidden_size=config.hidden_size,
424 intermediate_size=config.intermediate_size,
425 hidden_act=config.hidden_act,
426 quant_config=quant_config,
427 prefix=f"{prefix}.mlp",
428 )
429 self.input_layernorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
430 self.post_attention_layernorm = RMSNorm(
431 config.hidden_size, eps=config.rms_norm_eps
432 )
433
434 def forward(
435 self,
436 positions: torch.Tensor,
437 hidden_states: torch.Tensor,
438 residual: torch.Tensor | None,
439 ) -> tuple[torch.Tensor, torch.Tensor]:
440 # Self Attention
441 if residual is None:
442 residual = hidden_states
443 hidden_states = self.input_layernorm(hidden_states)
444 else:
445 hidden_states, residual = self.input_layernorm(hidden_states, residual)
446 hidden_states = self.self_attn(
447 positions=positions,
448 hidden_states=hidden_states,
449 )
450
451 # Fully Connected
452 hidden_states, residual = self.post_attention_layernorm(hidden_states, residual)
453 hidden_states = self.mlp(hidden_states)
454 return hidden_states, residual
455
456
457 class InternS1ProMoeLLMModel(Qwen3MoeLLMModel):
458 def __init__(
459 self,
460 *,
461 vllm_config: VllmConfig,
462 prefix: str = "",
463 decoder_layer_type: type[torch.nn.Module] = InternS1ProMoeDecoderLayer,
464 ):
465 super().__init__(
466 vllm_config=vllm_config,
467 prefix=prefix,
468 decoder_layer_type=decoder_layer_type,
469 )
470
471
472 class InternS1ProMoeLLMForCausalLM(Qwen3MoeForCausalLM):
473 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
474 super(Qwen3MoeForCausalLM, self).__init__()
475 self.config = vllm_config.model_config.hf_config.text_config
476 self.quant_config = vllm_config.quant_config
477 self.model = InternS1ProMoeLLMModel(
478 vllm_config=vllm_config, prefix=maybe_prefix(prefix, "model")
479 )
480 self.lm_head = ParallelLMHead(
481 self.config.vocab_size,
482 self.config.hidden_size,
483 quant_config=self.quant_config,
484 prefix=maybe_prefix(prefix, "lm_head"),
485 )
486 if self.config.tie_word_embeddings:
487 self.lm_head = self.lm_head.tie_weights(self.model.embed_tokens)
488 self.logits_processor = LogitsProcessor(self.config.vocab_size)
489 self.make_empty_intermediate_tensors = (
490 self.model.make_empty_intermediate_tensors
491 )
492
493
494 class InternS1ProMoeMixtureOfExperts(MixtureOfExperts):
495 language_model: InternS1ProMoeLLMForCausalLM
496 num_local_physical_experts: int
497
498 def update_physical_experts_metadata(
499 self,
500 num_physical_experts: int,
501 num_local_physical_experts: int,
502 ) -> None:
503 assert self.num_local_physical_experts == num_local_physical_experts
504 self.num_physical_experts = num_physical_experts
505 self.num_local_physical_experts = num_local_physical_experts
506 self.num_redundant_experts = num_physical_experts - self.num_logical_experts
507 for layer in self.language_model.model.layers:
508 if isinstance(layer.mlp, InternS1ProMoeSparseMoeBlock):
509 moe = layer.mlp
510 moe.n_local_physical_experts = num_local_physical_experts
511 moe.n_physical_experts = num_physical_experts
512 moe.n_redundant_experts = self.num_redundant_experts
513 moe.experts.update_expert_map()
514
515 def set_moe_parameters(self):
516 self.moe_layers = []
517 example_moe = None
518 for layer in self.language_model.model.layers:
519 if hasattr(layer, "mlp") and isinstance(
520 layer.mlp, InternS1ProMoeSparseMoeBlock
521 ):
522 example_moe = layer.mlp
523 self.moe_layers.append(layer.mlp.experts)
524
525 if example_moe is None:
526 raise RuntimeError("No InternS1ProMoe layer found in the language_model.")
527
528 # Set MoE hyperparameters
529 self.num_moe_layers = len(self.moe_layers)
530 self.num_expert_groups = 1
531 self.num_shared_experts = 0
532 self.num_logical_experts = example_moe.n_logical_experts
533 self.num_physical_experts = example_moe.n_physical_experts
534 self.num_local_physical_experts = example_moe.n_local_physical_experts
535 self.num_routed_experts = example_moe.n_routed_experts
536 self.num_redundant_experts = example_moe.n_redundant_experts
537
538
539 @MULTIMODAL_REGISTRY.register_processor(
540 Qwen3VLMultiModalProcessor,
541 info=InternS1ProProcessingInfo,
542 dummy_inputs=Qwen3VLDummyInputsBuilder,
543 )
544 class InternS1ProForConditionalGeneration(
545 Qwen3VLForConditionalGeneration, InternS1ProMoeMixtureOfExperts
546 ):
547 is_3d_moe_weight: ClassVar[bool] = True
548 packed_modules_mapping: dict[str, list[str]] = {
549 "qkv_proj": [
550 "q_proj",
551 "k_proj",
552 "v_proj",
553 ],
554 }
555
556 # To ensure correct weight loading and mapping.
557 hf_to_vllm_mapper = WeightsMapper(
558 orig_to_new_prefix={
559 "model.visual.": "visual.",
560 "lm_head.": "language_model.lm_head.",
561 "model.language_model.": "language_model.model.",
562 },
563 )
564
565 def __init__(self, *, vllm_config: VllmConfig, prefix: str = ""):
566 super(Qwen3VLForConditionalGeneration, self).__init__()
567 config: PreTrainedConfig = vllm_config.model_config.hf_config
568 multimodal_config = vllm_config.model_config.get_multimodal_config()
569
570 self.config = config
571 self.multimodal_config = multimodal_config
572 self.use_data_parallel = multimodal_config.mm_encoder_tp_mode == "data"
573 self._init_video_pruning(multimodal_config)
574
575 with self._mark_tower_model(vllm_config, {"image", "video"}):
576 self.visual = Qwen3_VisionTransformer(
577 config.vision_config,
578 norm_eps=getattr(config, "rms_norm_eps", 1e-6),
579 input_norm=build_mm_input_norm(self.model_config),
580 prefix=maybe_prefix(prefix, "visual"),
581 )
582
583 with self._mark_language_model(vllm_config):
584 self.language_model = InternS1ProMoeLLMForCausalLM(
585 vllm_config=vllm_config,
586 prefix=maybe_prefix(prefix, "language_model"),
587 )
588
589 # Whether to include the gate_up_proj mapping is determined by
590 # the language model.
591 self.packed_modules_mapping = (
592 self.packed_modules_mapping | self.language_model.packed_modules_mapping
593 )
594
595 self.make_empty_intermediate_tensors = (
596 self.language_model.make_empty_intermediate_tensors
597 )
598
599 self.use_deepstack = hasattr(config.vision_config, "deepstack_visual_indexes")
600 self.deepstack_num_level = (
601 len(config.vision_config.deepstack_visual_indexes)
602 if self.use_deepstack
603 else 0
604 )
605 self.visual_dim = config.vision_config.out_hidden_size
606 self.multiscale_dim = self.visual_dim * self.deepstack_num_level
607
608 # Set MoE hyperparameters
609 self.set_moe_parameters()
610
611 def get_frope_params_map(self) -> dict[str, str]:
612 mapper: dict[str, str] = {}
613 for name, params in self.language_model.model.named_parameters():
614 if "rotary_emb.sin_coef" in name:
615 mapper["language_model.model.rotary_emb.sin_coef"] = (
616 f"language_model.model.{name}"
617 )
618 if "rotary_emb.cos_coef" in name:
619 mapper["language_model.model.rotary_emb.cos_coef"] = (
620 f"language_model.model.{name}"
621 )
622 return mapper
623
624 def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]):
625 """Load weights"""
626 orig_to_new_prefix: dict[str, str | None] = {
627 "model.visual.": "visual.",
628 "lm_head.": "language_model.lm_head.",
629 "model.language_model.": "language_model.model.",
630 "model.time_series.": None,
631 }
632 if self.visual is None:
633 orig_to_new_prefix["visual."] = None
634 # FIXME(Isotr0py): See if we can avoid tighing FoPE to PP layers
635 weights_mapper = WeightsMapper(
636 orig_to_new_prefix=orig_to_new_prefix,
637 orig_to_new_suffix=self.get_frope_params_map(),
638 )
639 loader = AutoWeightsLoader(self)
640 return loader.load_weights(weights, mapper=weights_mapper)