# Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved. # Copyright 2024 The Qwen team, Alibaba Group and the HuggingFace Inc. team. All rights reserved. # # This code ijins based on EleutherAI's GPT-NeoX library and the GPT-NeoX # and OPT implementations in this library. It has been modified from its # original forms to accommodate minor architectural differences compared # to GPT-NeoX and OPT used by the Meta AI team that trained the model. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Paddle Qwen2 model.""" from __future__ import annotations import math import warnings from functools import partial from typing import Dict, List, Optional, Tuple, Union import paddle import paddle.distributed as dist import paddle.distributed.fleet.meta_parallel as mpu import paddle.nn.functional as F from paddle import Tensor, nn from paddle.distributed import fleet from paddle.distributed.fleet.meta_parallel import get_rng_state_tracker from paddle.distributed.fleet.recompute.recompute import recompute from ...utils.tools import get_env_device from .. import linear_utils from ..activations import ACT2FN from ..contrastive_loss import SimpleContrastiveLoss from ..conversion_utils import StateDictNameMapping, init_name_mappings from ..embedding_utils import dist_gather_tensor_with_gradient from ..linear_utils import Linear from ..model_outputs import ( BaseModelOutputWithPast, CausalLMOutputWithPast, SequenceClassifierOutputWithPast, TokenClassifierOutput, ) from ..model_utils import PretrainedModel, register_base_model from ..refined_recompute import ( RRColumnParallelLinear, RRColumnSequenceParallelLinear, RRRowParallelLinear, RRRowSequenceParallelLinear, get_skip_recompute_ops, ) from ..refined_recompute import recompute as rr_recompute from ..utils import caculate_llm_per_token_flops, logger from .configuration import Qwen2Config from ..llama.modeling import ( LlamaPretrainedModel, LlamaModel, LlamaForCausalLM, LlamaMLP, LlamaDecoderLayer, LlamaRMSNorm, LlamaRotaryEmbedding, LlamaPretrainingCriterion, LlamaLMHead, fusion_ops, ) from ..llama.modeling import apply_rotary_pos_emb, repeat_kv try: from paddle.incubate.nn.functional import fused_rotary_position_embedding except ImportError: fused_rotary_position_embedding = None try: from paddle.distributed.fleet.utils.sequence_parallel_utils import ( GatherOp, ScatterOp, mark_as_sequence_parallel_parameter, ) except: pass try: from paddle.nn.functional.flash_attention import flash_attention except: flash_attention = None __all__ = [ "Qwen2Model", "Qwen2PretrainedModel", "Qwen2ForCausalLM", "Qwen2PretrainingCriterion", "Qwen2ForSequenceClassification", "Qwen2ForTokenClassification", "Qwen2SentenceEmbedding", ] def get_triangle_upper_mask(x, mask=None): if mask is not None: return mask # [bsz, n_head, q_len, kv_seq_len] shape = x.shape # [bsz, 1, q_len, kv_seq_len] shape[1] = 1 mask = paddle.full(shape, paddle.finfo(x.dtype).min, dtype=x.dtype) mask = paddle.triu(mask, diagonal=1) mask.stop_gradient = True return mask def scaled_dot_product_attention( query_states, config, key_states, value_states, attention_mask, output_attentions, attn_mask_startend_row_indices=None, training=True, sequence_parallel=False, skip_recompute=False, ): bsz, q_len, num_heads, head_dim = query_states.shape _, kv_seq_len, _, _ = value_states.shape if config.use_flash_attention and flash_attention: # Paddle Flash Attention input [ bz, seqlen, nhead, head_dim] # Torch Flash Attention input [ bz, nhead, seqlen, head_dim] return fusion_ops.fusion_flash_attention( query_states, config, key_states, value_states, attention_mask, output_attentions, attn_mask_startend_row_indices=attn_mask_startend_row_indices, sequence_parallel=sequence_parallel, skip_recompute=skip_recompute, ) else: # [ bz, seqlen, nhead, head_dim] -> [bs, nhead, seq_len, head_dim] query_states = paddle.transpose(query_states, [0, 2, 1, 3]) # merge with the next transpose key_states = paddle.transpose(key_states, [0, 2, 1, 3]) value_states = paddle.transpose(value_states, [0, 2, 1, 3]) # Add pre divided factor to fix nan under float16. if paddle.in_dynamic_mode() and query_states.dtype == paddle.float16: pre_divided_factor = 32 else: pre_divided_factor = 1 attn_weights = paddle.matmul( query_states / (math.sqrt(head_dim) * pre_divided_factor), key_states.transpose([0, 1, 3, 2]) ) if attn_weights.shape != [bsz, num_heads, q_len, kv_seq_len]: raise ValueError( f"Attention weights should be of shape {(bsz, num_heads, q_len, kv_seq_len)}, but is" f" {attn_weights.shape}" ) if attention_mask is None: attention_mask = get_triangle_upper_mask(attn_weights) attention_mask = attention_mask.reshape([bsz, 1, q_len, kv_seq_len]) if attention_mask.shape != [bsz, 1, q_len, kv_seq_len]: raise ValueError( f"Attention mask should be of shape {(bsz, 1, q_len, kv_seq_len)}, but is {attention_mask.shape}" ) attn_weights = attn_weights + attention_mask if not paddle.in_dynamic_mode(): attn_weights = F.softmax(attn_weights * pre_divided_factor, axis=-1, dtype="float32").astype( query_states.dtype ) else: with paddle.amp.auto_cast(False): attn_weights = F.softmax( attn_weights.astype("float32") * pre_divided_factor, axis=-1, dtype="float32" ).astype(query_states.dtype) attn_weights = F.dropout(attn_weights, p=config.attention_dropout, training=training) attn_output = paddle.matmul(attn_weights, value_states) attn_output = attn_output.transpose([0, 2, 1, 3]) if sequence_parallel: attn_output = attn_output.reshape([bsz * q_len, head_dim * num_heads]) else: attn_output = attn_output.reshape([bsz, q_len, head_dim * num_heads]) return (attn_output, attn_weights) if output_attentions else attn_output class Qwen2RMSNorm(LlamaRMSNorm): """Qwen2的RMSNorm,继承自LlamaRMSNorm""" def __init__(self, config: Qwen2Config): super().__init__(config) class Qwen2RotaryEmbedding(LlamaRotaryEmbedding): def __init__(self, dim, max_position_embeddings=2048, base=10000): super().__init__(dim, max_position_embeddings, base) def _set_cos_sin_cache(self, seq_len): self.max_seq_len_cached = seq_len if self.inv_freq.dtype != paddle.float32: self.inv_freq = 1.0 / ( self.base ** (paddle.cast(paddle.arange(0, self.dim, 2), dtype="float32") / self.dim) ) super()._set_cos_sin_cache(seq_len) def forward(self, x, seq_len=None): if seq_len > self.max_seq_len_cached: self._set_cos_sin_cache(seq_len) super().forward(x, seq_len) class Qwen2MLP(LlamaMLP): """Qwen2的MLP,继承自LlamaMLP""" def __init__(self, config: Qwen2Config,is_shared=False, skip_recompute_ops=None): super().__init__(config) if config.hidden_act == "silu": self.act_fn = fusion_ops.swiglu self.fuse_swiglu = True else: self.act_fn = ACT2FN[config.hidden_act] self.fuse_swiglu = False # Qwen2的MLP结构与Llama相同,但使用不同的配置 def forward(self, x): if self.fuse_attention_ffn: x = self.gate_up_fused_proj(x) if self.fuse_swiglu: y = None else: x, y = x.chunk(2, axis=-1) else: x, y = self.gate_proj(x), self.up_proj(x) if self.fuse_swiglu: x = self.act_fn(x, y) else: x = self.act_fn(x) * y return self.down_proj(x) class Qwen2Attention(nn.Layer): """ Multi-headed attention from 'Attention Is All You Need' paper. Modified to use sliding window attention: Longformer and "Generating Long Sequences with Sparse Transformers". """ def __init__(self, config: Qwen2Config, layerwise_recompute: bool = True, skip_recompute_ops=None): super().__init__() if skip_recompute_ops is None: skip_recompute_ops = {} self.config = config self.skip_recompute_ops = skip_recompute_ops self.hidden_size = config.hidden_size self.num_heads = config.num_attention_heads self.num_attention_heads = config.num_attention_heads self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads) self.num_key_value_heads = config.num_key_value_heads assert config.num_attention_heads // config.num_key_value_heads self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads self.gqa_or_mqa = config.num_attention_heads != config.num_key_value_heads self.max_position_embeddings = config.max_position_embeddings self.rope_theta = config.rope_theta self.is_causal = True self.attention_dropout = config.attention_dropout # self.seq_length = config.seq_length self.sequence_parallel = config.sequence_parallel self.has_bias = config.attention_bias self.fuse_attention_qkv = config.fuse_attention_qkv # Note that we will actually perform a recompute only if both enable_recompute and layerwise_recompute are set to True # Enable_recompute defaults to False and is controlled by Trainer self.enable_recompute = False self.layerwise_recompute = layerwise_recompute self.recompute_granularity = config.recompute_granularity if config.tensor_parallel_degree > 1: assert ( self.num_heads % config.tensor_parallel_degree == 0 ), f"num_heads: {self.num_heads}, tensor_parallel_degree: {config.tensor_parallel_degree}" self.num_heads = self.num_heads // config.tensor_parallel_degree assert ( self.num_key_value_heads % config.tensor_parallel_degree == 0 ), f"num_key_value_heads: {self.num_key_value_heads}, tensor_parallel_degree: {config.tensor_parallel_degree}" self.num_key_value_heads = self.num_key_value_heads // config.tensor_parallel_degree self.use_fused_rope = config.use_fused_rope if self.use_fused_rope: if get_env_device() not in ["gpu", "xpu"] or fused_rotary_position_embedding is None: warnings.warn( "Enable fuse rope in the config, but fuse rope is not available. " "Will disable fuse rope. Try using latest gpu version of Paddle." ) self.use_fused_rope = False if config.sequence_parallel: ColumnParallelLinear = linear_utils.ColumnSequenceParallelLinear RowParallelLinear = linear_utils.RowSequenceParallelLinear # NOTE: refined_recompute is only supported when `recompute_use_reentrant=False` if config.recompute and not config.recompute_use_reentrant: if skip_recompute_ops.get("attention_column_ln", False): ColumnParallelLinear = RRColumnSequenceParallelLinear if skip_recompute_ops.get("attention_row_ln", False): RowParallelLinear = RRRowSequenceParallelLinear else: ColumnParallelLinear = linear_utils.ColumnParallelLinear RowParallelLinear = linear_utils.RowParallelLinear # NOTE: refined_recompute is only supported when `recompute_use_reentrant=False` if config.recompute and not config.recompute_use_reentrant: if skip_recompute_ops.get("attention_column_ln", False): ColumnParallelLinear = RRColumnParallelLinear if skip_recompute_ops.get("attention_row_ln", False): RowParallelLinear = RRRowParallelLinear if config.tensor_parallel_degree > 1: if self.fuse_attention_qkv: self.qkv_proj = ColumnParallelLinear( self.hidden_size, self.num_attention_heads * self.head_dim + 2 * self.config.num_key_value_heads * self.head_dim, has_bias=self.has_bias, gather_output=False, ) else: self.q_proj = ColumnParallelLinear( self.hidden_size, self.num_attention_heads * self.head_dim, has_bias=self.has_bias, gather_output=False, ) self.k_proj = ColumnParallelLinear(self.hidden_size, self.config.num_key_value_heads * self.head_dim, has_bias=self.has_bias, gather_output=False) # fmt:skip self.v_proj = ColumnParallelLinear(self.hidden_size, self.config.num_key_value_heads * self.head_dim, has_bias=self.has_bias, gather_output=False) # fmt:skip self.o_proj = RowParallelLinear(self.hidden_size, self.hidden_size, has_bias=False, input_is_parallel=True) else: if self.fuse_attention_qkv: self.qkv_proj = Linear( self.hidden_size, self.num_attention_heads * self.head_dim + 2 * self.config.num_key_value_heads * self.head_dim, ) else: self.q_proj = Linear( self.hidden_size, self.num_attention_heads * self.head_dim, bias_attr=self.has_bias ) self.k_proj = Linear( self.hidden_size, self.config.num_key_value_heads * self.head_dim, bias_attr=self.has_bias ) self.v_proj = Linear( self.hidden_size, self.config.num_key_value_heads * self.head_dim, bias_attr=self.has_bias ) self.o_proj = Linear(self.num_attention_heads * self.head_dim, self.hidden_size, bias_attr=False) self.rotary_emb = Qwen2RotaryEmbedding( self.head_dim, max_position_embeddings=self.max_position_embeddings, base=self.rope_theta, ) self.attn_func = scaled_dot_product_attention # NOTE: refined_recompute is only supported when `recompute_use_reentrant=False` if config.recompute and not config.recompute_use_reentrant and skip_recompute_ops.get("flash_attn", False): self.attn_func = partial(scaled_dot_product_attention, skip_recompute=True) def forward( self, hidden_states, position_ids: Optional[Tuple[paddle.Tensor]] = None, past_key_value: Optional[Tuple[paddle.Tensor]] = None, attention_mask: Optional[paddle.Tensor] = None, output_attentions: bool = False, use_cache: bool = False, attn_mask_startend_row_indices: Optional[paddle.Tensor] = None, batch_size: Optional[int] = None, **kwargs, ) -> Tuple[paddle.Tensor, Optional[paddle.Tensor], Optional[Tuple[paddle.Tensor]]]: """Input shape: Batch x Time x Channel""" # [bs, seq_len, num_head * head_dim] -> [seq_len / n, bs, num_head * head_dim] (n is model parallelism) if self.fuse_attention_qkv: mix_layer = self.qkv_proj(hidden_states) if self.sequence_parallel: target_shape = [ batch_size, -1, self.num_key_value_heads, (self.num_key_value_groups + 2) * self.head_dim, ] else: target_shape = [0, 0, self.num_key_value_heads, (self.num_key_value_groups + 2) * self.head_dim] mix_layer = paddle.reshape_(mix_layer, target_shape) query_states, key_states, value_states = paddle.split( mix_layer, num_or_sections=[self.num_key_value_groups * self.head_dim, self.head_dim, self.head_dim], axis=-1, ) if self.gqa_or_mqa: query_states = paddle.reshape_(query_states, [0, 0, self.num_heads, self.head_dim]) else: query_states = self.q_proj(hidden_states) key_states = self.k_proj(hidden_states) value_states = self.v_proj(hidden_states) if self.sequence_parallel: target_query_shape = [batch_size, -1, self.num_heads, self.head_dim] target_key_value_shape = [batch_size, -1, self.num_key_value_heads, self.head_dim] else: target_query_shape = [0, 0, self.num_heads, self.head_dim] target_key_value_shape = [0, 0, self.num_key_value_heads, self.head_dim] query_states = query_states.reshape(shape=target_query_shape) key_states = key_states.reshape(shape=target_key_value_shape) value_states = value_states.reshape(shape=target_key_value_shape) if position_ids is not None and not self.use_fused_rope: kv_seq_len = position_ids.max().item() + 1 else: kv_seq_len = key_states.shape[-3] if past_key_value is not None: kv_seq_len += past_key_value[0].shape[-3] if self.use_fused_rope: assert past_key_value is None, "fuse rotary not support cache kv for now" cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len) query_states, key_states, _ = fused_rotary_position_embedding( query_states, key_states, v=None, sin=sin, cos=cos, position_ids=position_ids, use_neox_rotary_style=False, ) else: cos, sin = self.rotary_emb(value_states, seq_len=kv_seq_len) query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin, position_ids) # [bs, seq_len, num_head, head_dim] if past_key_value is not None: key_states = paddle.concat([past_key_value[0], key_states], axis=1) value_states = paddle.concat([past_key_value[1], value_states], axis=1) past_key_value = (key_states, value_states) if use_cache else None # TODO(wj-Mcat): use broadcast strategy when n_kv_heads = 1 # repeat k/v heads if n_kv_heads < n_heads paddle_version = float(paddle.__version__[:3]) if not self.config.use_flash_attention or ((paddle_version != 0.0) and (paddle_version <= 2.6)): key_states = repeat_kv(key_states, self.num_key_value_groups) value_states = repeat_kv(value_states, self.num_key_value_groups) has_gradient = not (query_states.stop_gradient and key_states.stop_gradient and value_states.stop_gradient) if ( self.enable_recompute and self.layerwise_recompute and has_gradient and self.recompute_granularity == "core_attn" ): recompute_fn = rr_recompute if any(self.skip_recompute_ops.values()) else recompute outputs = recompute_fn( self.attn_func, query_states, self.config, key_states, value_states, attention_mask, output_attentions, attn_mask_startend_row_indices=attn_mask_startend_row_indices, training=self.training, sequence_parallel=self.sequence_parallel, use_reentrant=self.config.recompute_use_reentrant, ) else: outputs = self.attn_func( query_states, self.config, key_states, value_states, attention_mask, output_attentions, attn_mask_startend_row_indices=attn_mask_startend_row_indices, training=self.training, sequence_parallel=self.sequence_parallel, ) if output_attentions: attn_output, attn_weights = outputs else: attn_output = outputs # if sequence_parallel is true, out shape are [q_len / n, bs, num_head * head_dim] # else their shape are [bs, q_len, num_head * head_dim], n is mp parallelism. attn_output = self.o_proj(attn_output) if not output_attentions: attn_weights = None outputs = (attn_output,) if output_attentions: outputs += (attn_weights,) if use_cache: outputs += (past_key_value,) if type(outputs) is tuple and len(outputs) == 1: outputs = outputs[0] return outputs class Qwen2DecoderLayer(LlamaDecoderLayer): """Qwen2的解码器层,继承自LlamaDecoderLayer""" def __init__(self, config: Qwen2Config, layerwise_recompute: bool = False, skip_recompute_ops=None): super().__init__(config) def forward( self, hidden_states: paddle.Tensor, position_ids: Optional[paddle.Tensor] = None, attention_mask: Optional[paddle.Tensor] = None, output_attentions: Optional[bool] = False, past_key_value: Optional[Tuple[paddle.Tensor]] = None, use_cache: Optional[bool] = False, attn_mask_startend_row_indices: Optional[paddle.Tensor] = None, batch_size: Optional[int] = None, **kwargs, ) -> Tuple[paddle.Tensor, Optional[Tuple[paddle.Tensor, paddle.Tensor]]]: """ Args: hidden_states (`paddle.Tensor`): input to the layer of shape `(batch, seq_len, embed_dim)` attention_mask (`paddle.Tensor`, *optional*): attention mask of size `(batch, sequence_length)` where padding elements are indicated by 0. output_attentions (`bool`, *optional*): Whether or not to return the attentions tensors of all attention layers. See `attentions` under returned tensors for more detail. use_cache (`bool`, *optional*): If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding (see `past_key_values`). past_key_value (`Tuple(paddle.Tensor)`, *optional*): cached past key and value projection states """ # [bs * seq_len, embed_dim] -> [seq_len * bs / n, embed_dim] (sequence_parallel) residual = hidden_states hidden_states = self.input_layernorm(hidden_states) # Self Attention has_gradient = not hidden_states.stop_gradient if ( self.enable_recompute and self.layerwise_recompute and has_gradient and self.recompute_granularity == "full_attn" ): recompute_fn = rr_recompute if any(self.skip_recompute_ops.values()) else recompute outputs = recompute_fn( self.self_attn, hidden_states, position_ids, past_key_value, attention_mask, output_attentions, use_cache, attn_mask_startend_row_indices, batch_size, use_reentrant=self.config.recompute_use_reentrant, ) else: outputs = self.self_attn( hidden_states, position_ids, past_key_value, attention_mask, output_attentions, use_cache, attn_mask_startend_row_indices=attn_mask_startend_row_indices, batch_size=batch_size, ) if type(outputs) is tuple: hidden_states = outputs[0] else: hidden_states = outputs if output_attentions: self_attn_weights = outputs[1] if use_cache: present_key_value = outputs[2 if output_attentions else 1] hidden_states = residual + hidden_states # Fully Connected residual = hidden_states hidden_states = self.post_attention_layernorm(hidden_states) hidden_states = self.mlp(hidden_states) hidden_states = residual + hidden_states outputs = (hidden_states,) if output_attentions: outputs += (self_attn_weights,) if use_cache: outputs += (present_key_value,) if type(outputs) is tuple and len(outputs) == 1: outputs = outputs[0] return outputs class Qwen2PretrainedModel(LlamaPretrainedModel): """Qwen2预训练模型基类,继承自LlamaPretrainedModel""" config_class = Qwen2Config base_model_prefix = "qwen2" _keys_to_ignore_on_load_unexpected = [r"self_attn.rotary_emb.inv_freq"] @classmethod def _get_name_mappings(cls, config: Qwen2Config) -> list[StateDictNameMapping]: mappings: list[StateDictNameMapping] = [] model_mappings = [ ["embed_tokens.weight"], ["norm.weight"], ] for layer_index in range(config.num_hidden_layers): layer_mappings = [ [f"layers.{layer_index}.self_attn.q_proj.weight", None, "transpose"], [f"layers.{layer_index}.self_attn.k_proj.weight", None, "transpose"], [f"layers.{layer_index}.self_attn.v_proj.weight", None, "transpose"], [f"layers.{layer_index}.self_attn.q_proj.bias", None], [f"layers.{layer_index}.self_attn.k_proj.bias", None], [f"layers.{layer_index}.self_attn.v_proj.bias", None], [f"layers.{layer_index}.self_attn.o_proj.weight", None, "transpose"], [f"layers.{layer_index}.mlp.up_proj.weight", None, "transpose"], [f"layers.{layer_index}.mlp.gate_proj.weight", None, "transpose"], [f"layers.{layer_index}.mlp.down_proj.weight", None, "transpose"], [f"layers.{layer_index}.self_attn.rotary_emb.inv_freq"], [f"layers.{layer_index}.input_layernorm.weight"], [f"layers.{layer_index}.post_attention_layernorm.weight"], ] model_mappings.extend(layer_mappings) init_name_mappings(mappings=model_mappings) # base-model prefix "Qwen2MoEModel" if "Qwen2Model" not in config.architectures: for mapping in model_mappings: mapping[0] = "model." + mapping[0] mapping[1] = "qwen2." + mapping[1] if not config.tie_word_embeddings: model_mappings.append(["lm_head.weight", "lm_head.weight", "transpose"]) mappings = [StateDictNameMapping(*mapping, index=index) for index, mapping in enumerate(model_mappings)] return mappings @classmethod def _get_tensor_parallel_mappings(cls, config: Qwen2Config, is_split=True): from ..conversion_utils import split_or_merge_func fn = split_or_merge_func( is_split=is_split, tensor_parallel_degree=config.tensor_parallel_degree, tensor_parallel_rank=config.tensor_parallel_rank, num_attention_heads=config.num_attention_heads, ) def get_tensor_parallel_split_mappings(num_layers): final_actions = {} base_actions = { # Row Linear "embed_tokens.weight": partial(fn, is_column=False), "layers.0.self_attn.o_proj.weight": partial(fn, is_column=False), "layers.0.mlp.down_proj.weight": partial(fn, is_column=False), } if config.tie_word_embeddings: base_actions["lm_head.weight"] = partial(fn, is_column=False) else: base_actions["lm_head.weight"] = partial(fn, is_column=True) if not config.vocab_size % config.tensor_parallel_degree == 0: base_actions.pop("lm_head.weight") base_actions.pop("embed_tokens.weight") # Column Linear if config.fuse_attention_qkv: base_actions["layers.0.self_attn.qkv_proj.weight"] = partial(fn, is_column=True) base_actions["layers.0.self_attn.qkv_proj.bias"] = partial(fn, is_column=True) else: base_actions["layers.0.self_attn.q_proj.weight"] = partial(fn, is_column=True) base_actions["layers.0.self_attn.q_proj.bias"] = partial(fn, is_column=True) # if we have enough num_key_value_heads to split, then split it. if config.num_key_value_heads % config.tensor_parallel_degree == 0: base_actions["layers.0.self_attn.k_proj.weight"] = partial(fn, is_column=True) base_actions["layers.0.self_attn.v_proj.weight"] = partial(fn, is_column=True) base_actions["layers.0.self_attn.k_proj.bias"] = partial(fn, is_column=True) base_actions["layers.0.self_attn.v_proj.bias"] = partial(fn, is_column=True) if config.fuse_attention_ffn: base_actions["layers.0.mlp.gate_up_fused_proj.weight"] = partial( fn, is_column=True, is_naive_2fuse=True ) else: base_actions["layers.0.mlp.gate_proj.weight"] = partial(fn, is_column=True) base_actions["layers.0.mlp.up_proj.weight"] = partial(fn, is_column=True) for key, action in base_actions.items(): if "layers.0." in key: for i in range(num_layers): final_actions[key.replace("layers.0.", f"layers.{i}.")] = action final_actions[key] = action return final_actions mappings = get_tensor_parallel_split_mappings(config.num_hidden_layers) return mappings @classmethod def _get_fuse_or_split_param_mappings(cls, config: Qwen2Config, is_fuse=False): # return parameter fuse utils from ..conversion_utils import split_or_fuse_func fn = split_or_fuse_func(is_fuse=is_fuse) # last key is fused key, other keys are to be fused. fuse_qkv_keys = [ ( "layers.0.self_attn.q_proj.weight", "layers.0.self_attn.k_proj.weight", "layers.0.self_attn.v_proj.weight", "layers.0.self_attn.qkv_proj.weight", ), ( "layers.0.self_attn.q_proj.bias", "layers.0.self_attn.k_proj.bias", "layers.0.self_attn.v_proj.bias", "layers.0.self_attn.qkv_proj.bias", ), ] fuse_gate_up_keys = ( "layers.0.mlp.gate_proj.weight", "layers.0.mlp.up_proj.weight", "layers.0.mlp.gate_up_fused_proj.weight", ) num_heads = config.num_attention_heads num_key_value_heads = getattr(config, "num_key_value_heads", num_heads) fuse_attention_qkv = getattr(config, "fuse_attention_qkv", False) fuse_attention_ffn = getattr(config, "fuse_attention_ffn", False) final_actions = {} if is_fuse: if fuse_attention_qkv: for i in range(config.num_hidden_layers): for fuse_keys in fuse_qkv_keys: keys = tuple([key.replace("layers.0.", f"layers.{i}.") for key in fuse_keys]) final_actions[keys] = partial( fn, is_qkv=True, num_heads=num_heads, num_key_value_heads=num_key_value_heads ) if fuse_attention_ffn: for i in range(config.num_hidden_layers): keys = tuple([key.replace("layers.0.", f"layers.{i}.") for key in fuse_gate_up_keys]) final_actions[keys] = fn else: if not fuse_attention_qkv: for i in range(config.num_hidden_layers): for fuse_keys in fuse_qkv_keys: keys = tuple([key.replace("layers.0.", f"layers.{i}.") for key in fuse_keys]) final_actions[keys] = partial( fn, split_nums=3, is_qkv=True, num_heads=num_heads, num_key_value_heads=num_key_value_heads ) if not fuse_attention_ffn: for i in range(config.num_hidden_layers): keys = tuple([key.replace("layers.0.", f"layers.{i}.") for key in fuse_gate_up_keys]) final_actions[keys] = partial(fn, split_nums=2) return final_actions def _get_model_flops(self): if hasattr(self.config, "seq_length"): seq_length = self.config.seq_length else: seq_length = 2048 return caculate_llm_per_token_flops( hidden_size=self.config.hidden_size, intermediate_size=self.config.intermediate_size, layer_num=self.config.num_hidden_layers, vocab_size=self.config.vocab_size, seq_length=seq_length, recompute=False, ) def _get_hardware_flops(self): if hasattr(self.config, "seq_length"): seq_length = self.config.seq_length else: seq_length = 2048 return caculate_llm_per_token_flops( hidden_size=self.config.hidden_size, intermediate_size=self.config.intermediate_size, layer_num=self.config.num_hidden_layers, vocab_size=self.config.vocab_size, seq_length=seq_length, recompute=self.config.recompute, recompute_granularity=self.config.recompute_granularity, ) @register_base_model class Qwen2Model(LlamaModel): """Qwen2模型,继承自LlamaModel""" def __init__(self, config: Qwen2Config): super().__init__(config) self.padding_idx = config.pad_token_id @paddle.jit.not_to_static def recompute_training_full( self, layer_module: nn.Layer, hidden_states: Tensor, position_ids: Optional[Tensor], attention_mask: Tensor, output_attentions: bool, past_key_value: Tensor, use_cache: bool, attn_mask_startend_row_indices=None, batch_size: int = None, ): def create_custom_forward(module): def custom_forward(*inputs): return module(*inputs) return custom_forward recompute_fn = rr_recompute if any(layer_module.skip_recompute_ops.values()) else recompute hidden_states = recompute_fn( create_custom_forward(layer_module), hidden_states, position_ids, attention_mask, output_attentions, past_key_value, use_cache, attn_mask_startend_row_indices, batch_size, use_reentrant=self.config.recompute_use_reentrant, ) return hidden_states def forward( self, input_ids: paddle.Tensor = None, position_ids: Optional[paddle.Tensor] = None, attention_mask: Optional[paddle.Tensor] = None, inputs_embeds: Optional[paddle.Tensor] = None, use_cache: Optional[bool] = None, past_key_values: Optional[List[paddle.Tensor]] = None, output_attentions: Optional[bool] = None, output_hidden_states: Optional[bool] = None, return_dict: Optional[bool] = None, attn_mask_startend_row_indices=None, ) -> Union[Tuple, BaseModelOutputWithPast]: super().forward() class Qwen2PretrainingCriterion(LlamaPretrainingCriterion): """Qwen2的预训练损失计算,继承自LlamaPretrainingCriterion""" def __init__(self, config: Qwen2Config): super().__init__(config) self.enable_parallel_cross_entropy = config.tensor_parallel_degree > 1 and config.tensor_parallel_output class Qwen2LMHead(LlamaLMHead): """Qwen2的语言模型头,继承自LlamaLMHead""" def __init__(self, config: Qwen2Config): super().__init__(config) def forward(self, hidden_states, tensor_parallel_output=None, batch_size=None): if self.config.sequence_parallel: hidden_states = GatherOp.apply(hidden_states) hidden_states = paddle.reshape_(hidden_states, [batch_size, -1, self.config.hidden_size]) if tensor_parallel_output is None: tensor_parallel_output = self.config.tensor_parallel_output logits = parallel_matmul( hidden_states, self.weight, transpose_y=self.transpose_y, tensor_parallel_output=tensor_parallel_output ) return logits class Qwen2ForCausalLM(LlamaForCausalLM): """用于因果语言建模的Qwen2模型,继承自LlamaForCausalLM""" def __init__(self, config: Qwen2Config): super().__init__(config) @staticmethod def update_model_kwargs_for_generation(outputs, model_kwargs, is_encoder_decoder=False): # update cache if isinstance(outputs, tuple) and len(outputs) > 1 and not isinstance(outputs[1], paddle.Tensor): model_kwargs["past_key_values"] = outputs[1] if isinstance(outputs, CausalLMOutputWithPast) and "past_key_values" in outputs: model_kwargs["past_key_values"] = outputs.past_key_values # update position_ids if "position_ids" in model_kwargs and model_kwargs["position_ids"] is not None: position_ids = model_kwargs["position_ids"] model_kwargs["position_ids"] = paddle.concat([position_ids, position_ids[..., -1:] + 1], axis=-1) if not is_encoder_decoder and "attention_mask" in model_kwargs: # TODO: support attention mask for other models attention_mask = model_kwargs["attention_mask"] if len(attention_mask.shape) == 2: model_kwargs["attention_mask"] = paddle.concat( [attention_mask, paddle.ones([attention_mask.shape[0], 1], dtype=attention_mask.dtype)], axis=-1, ) elif len(attention_mask.shape) == 4: model_kwargs["attention_mask"] = paddle.concat( [attention_mask, paddle.ones([*attention_mask.shape[:3], 1], dtype=attention_mask.dtype)], axis=-1, )[:, :, -1:, :] return model_kwargs def forward( self, input_ids: paddle.Tensor = None, position_ids: Optional[paddle.Tensor] = None, attention_mask: Optional[paddle.Tensor] = None, inputs_embeds: Optional[paddle.Tensor] = None, labels: Optional[paddle.Tensor] = None, use_cache: Optional[bool] = None, past_key_values: Optional[List[paddle.Tensor]] = None, output_attentions: Optional[bool] = None, output_hidden_states: Optional[bool] = None, return_dict: Optional[bool] = None, attn_mask_startend_row_indices=None, ) -> Union[Tuple, CausalLMOutputWithPast]: r""" Args: labels (`paddle.Tensor` of shape `(batch_size, sequence_length)`, *optional*): Labels for computing the masked language modeling loss. Indices should either be in `[0, ..., config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`. Returns: Example: ```python >>> from transformers import AutoTokenizer, Qwen2ForCausalLM >>> model = Qwen2ForCausalLM.from_pretrained(PATH_TO_CONVERTED_WEIGHTS) >>> tokenizer = AutoTokenizer.from_pretrained(PATH_TO_CONVERTED_TOKENIZER) >>> prompt = "Hey, are you conscious? Can you talk to me?" >>> inputs = tokenizer(prompt, return_tensors="pt") >>> # Generate >>> generate_ids = model.generate(inputs.input_ids, max_length=30) >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0] "Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you." ```""" output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions output_hidden_states = ( output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states ) return_dict = return_dict if return_dict is not None else self.config.use_return_dict if attn_mask_startend_row_indices is not None and attention_mask is not None: logger.warning( "You have provided both attn_mask_startend_row_indices and attention_mask. " "The attn_mask_startend_row_indices will be used." ) attention_mask = None if input_ids is not None and inputs_embeds is not None: raise ValueError("You cannot specify both decoder_input_ids and decoder_inputs_embeds at the same time") elif input_ids is not None: batch_size = input_ids.shape[0] elif inputs_embeds is not None: batch_size = inputs_embeds.shape[0] else: raise ValueError("You have to specify either decoder_input_ids or decoder_inputs_embeds") # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn) outputs = self.qwen2( input_ids=input_ids, position_ids=position_ids, attention_mask=attention_mask, inputs_embeds=inputs_embeds, use_cache=use_cache, past_key_values=past_key_values, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, attn_mask_startend_row_indices=attn_mask_startend_row_indices, ) hidden_states = outputs[0] # add this for fused_head_and_loss_fn if self.config.use_fused_head_and_loss_fn and self.training: if self.config.tensor_parallel_degree > 1 and self.config.sequence_parallel: hidden_states = GatherOp.apply(hidden_states) hidden_states = hidden_states.reshape( [ batch_size, -1, hidden_states.shape[-1], ] ) return hidden_states, self.lm_head.weight, None, self.lm_head.transpose_y # if labels is None,means we need full output, instead of tensor_parallel_output # tensor_parallel_output is together with ParallelCrossEntropy tensor_parallel_output = self.config.tensor_parallel_output and self.config.tensor_parallel_degree > 1 if labels is not None and self.config.use_fused_linear_cross_entropy: from paddlenlp_kernel.triton.cut_cross_entropy import linear_cross_entropy assert ( self.config.tensor_parallel_degree <= 1 ), "The argument `use_fused_linear_cross_entropy` is imcompatiable with tensor parallel " masked_lm_loss = linear_cross_entropy(hidden_states, self.lm_head.weight, targets=labels) binary_sequence = paddle.where( masked_lm_loss > 0, paddle.ones_like(masked_lm_loss), paddle.zeros_like(masked_lm_loss) ) count = paddle.sum(binary_sequence) if count == 0: loss = paddle.sum(masked_lm_loss * binary_sequence) else: loss = paddle.sum(masked_lm_loss * binary_sequence) / count logits = None else: logits = self.lm_head(hidden_states, tensor_parallel_output=tensor_parallel_output, batch_size=batch_size) loss = None if labels is not None: loss = self.criterion(logits, labels) if not return_dict: output = (logits,) + outputs[1:] return (loss,) + output if loss is not None else output return CausalLMOutputWithPast( loss=loss, logits=logits, past_key_values=outputs.past_key_values, hidden_states=outputs.hidden_states, attentions=outputs.attentions, ) class Qwen2ForSequenceClassification(Qwen2PretrainedModel): def __init__(self, config: Qwen2Config): super().__init__(config) self.num_labels = config.num_labels self.qwen2 = Qwen2Model(config) self.score = Linear(config.hidden_size, self.num_labels, bias_attr=False) def get_input_embeddings(self): return self.qwen2.embed_tokens def set_input_embeddings(self, value): self.qwen2.embed_tokens = value def forward( self, input_ids: paddle.Tensor = None, position_ids: Optional[paddle.Tensor] = None, attention_mask: Optional[paddle.Tensor] = None, inputs_embeds: Optional[paddle.Tensor] = None, past_key_values: Optional[List[paddle.Tensor]] = None, labels: Optional[paddle.Tensor] = None, use_cache: Optional[bool] = None, output_attentions: Optional[bool] = None, output_hidden_states: Optional[bool] = None, return_dict: Optional[bool] = None, ) -> Union[Tuple, SequenceClassifierOutputWithPast]: r""" labels (`paddle.Tensor` of shape `(batch_size,)`, *optional*): Labels for computing the sequence classification/regression loss. Indices should be in `[0, ..., config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If `config.num_labels > 1` a classification loss is computed (Cross-Entropy). """ return_dict = return_dict if return_dict is not None else self.config.use_return_dict transformer_outputs = self.qwen2( input_ids, attention_mask=attention_mask, position_ids=position_ids, past_key_values=past_key_values, inputs_embeds=inputs_embeds, use_cache=use_cache, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, ) hidden_states = transformer_outputs[0] logits = self.score(hidden_states) if input_ids is not None: batch_size = input_ids.shape[0] else: batch_size = inputs_embeds.shape[0] if self.config.pad_token_id is None and batch_size != 1: raise ValueError("Cannot handle batch sizes > 1 if no padding token is defined.") if self.config.pad_token_id is None: sequence_lengths = -1 else: if input_ids is not None: # if no pad token found, use modulo instead of reverse indexing for ONNX compatibility sequence_lengths = paddle.equal(input_ids, self.config.pad_token_id).astype("int32").argmax(-1) - 1 sequence_lengths = sequence_lengths % input_ids.shape[-1] sequence_lengths = sequence_lengths else: sequence_lengths = -1 # pooled_logits = logits[paddle.arange(batch_size), sequence_lengths] pooled_logits = logits.gather_nd(paddle.stack([paddle.arange(logits.shape[0]), sequence_lengths], axis=-1)) loss = None if labels is not None: if self.config.problem_type is None: if self.num_labels == 1: self.config.problem_type = "regression" elif self.num_labels > 1 and (labels.dtype == paddle.int64 or labels.dtype == paddle.int32): self.config.problem_type = "single_label_classification" else: self.config.problem_type = "multi_label_classification" if self.config.problem_type == "regression": loss_fct = nn.MSELoss() if self.num_labels == 1: loss = loss_fct(pooled_logits.squeeze(), labels.squeeze()) else: loss = loss_fct(pooled_logits, labels) elif self.config.problem_type == "single_label_classification": loss_fct = nn.CrossEntropyLoss() loss = loss_fct(pooled_logits.reshape([-1, self.num_labels]), labels.reshape([-1])) elif self.config.problem_type == "multi_label_classification": loss_fct = nn.BCEWithLogitsLoss() loss = loss_fct(pooled_logits, labels) if not return_dict: output = (pooled_logits,) + transformer_outputs[1:] return ((loss,) + output) if loss is not None else output return SequenceClassifierOutputWithPast( loss=loss, logits=pooled_logits, past_key_values=transformer_outputs.past_key_values, hidden_states=transformer_outputs.hidden_states, attentions=transformer_outputs.attentions, ) # Copied from transformers.models.llama.modeling_llama.LlamaForTokenClassification with Llama->Qwen2, LLAMA->QWEN2 class Qwen2ForTokenClassification(Qwen2PretrainedModel): def __init__(self, config: Qwen2Config): super().__init__(config) self.num_labels = config.num_labels self.qwen2 = Qwen2Model(config) if getattr(config, "classifier_dropout", None) is not None: classifier_dropout = config.classifier_dropout elif getattr(config, "hidden_dropout", None) is not None: classifier_dropout = config.hidden_dropout else: classifier_dropout = 0.1 self.dropout = nn.Dropout(classifier_dropout) self.score = Linear(config.hidden_size, config.num_labels) def get_input_embeddings(self): return self.qwen2.embed_tokens def set_input_embeddings(self, value): self.qwen2.embed_tokens = value def forward( self, input_ids: paddle.Tensor = None, attention_mask: Optional[paddle.Tensor] = None, position_ids: Optional[paddle.Tensor] = None, past_key_values: Optional[List[paddle.Tensor]] = None, inputs_embeds: Optional[paddle.Tensor] = None, labels: Optional[paddle.Tensor] = None, use_cache: Optional[bool] = None, output_attentions: Optional[bool] = None, output_hidden_states: Optional[bool] = None, return_dict: Optional[bool] = None, ) -> Union[Tuple, SequenceClassifierOutputWithPast]: r""" labels (`paddle.Tensor` of shape `(batch_size,)`, *optional*): Labels for computing the sequence classification/regression loss. Indices should be in `[0, ..., config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If `config.num_labels > 1` a classification loss is computed (Cross-Entropy). """ return_dict = return_dict if return_dict is not None else self.config.use_return_dict outputs = self.qwen2( input_ids, attention_mask=attention_mask, position_ids=position_ids, past_key_values=past_key_values, inputs_embeds=inputs_embeds, use_cache=use_cache, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, ) sequence_output = outputs[0] sequence_output = self.dropout(sequence_output) logits = self.score(sequence_output) loss = None if labels is not None: loss_fct = nn.CrossEntropyLoss() loss = loss_fct(logits.reshape([-1, self.num_labels]), labels.reshape([-1])) if not return_dict: output = (logits,) + outputs[2:] return ((loss,) + output) if loss is not None else output return TokenClassifierOutput( loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions, ) class Qwen2SentenceEmbedding(Qwen2PretrainedModel): def __init__( self, config: Qwen2Config, embedding_temperature: float = 0.02, ): """Qwen2SentenceEmbedding For getting larger batch_size, we use tensor parallel to get larger batch_size. Args: config (Qwen2Config): _description_ model (Qwen2Model): _description_ embedding_temperature (float, optional): _description_. Defaults to 0.02. """ super(Qwen2SentenceEmbedding, self).__init__(config) self.config = config self.qwen2 = Qwen2Model(config) self.in_batch_negative_loss = SimpleContrastiveLoss(embedding_temperature) self.world_size = dist.get_world_size() self.process_rank = dist.get_rank() self.embedding_negatives_cross_device = config.embedding_negatives_cross_device if self.world_size <= 1: self.embedding_negatives_cross_device = False def forward( self, query: Optional[Dict[str, paddle.Tensor]] = None, passages: Optional[Dict[str, paddle.Tensor]] = None, return_encode=False, ): """forward""" q_reps = self.encode(**query) p_reps = self.encode(**passages) q_reps = nn.functional.normalize(q_reps, axis=-1) p_reps = nn.functional.normalize(p_reps, axis=-1) if return_encode: return q_reps, p_reps if self.embedding_negatives_cross_device: q_reps = dist_gather_tensor_with_gradient(q_reps) p_reps = dist_gather_tensor_with_gradient(p_reps) loss = self.in_batch_negative_loss(q_reps, p_reps) return loss def encode( self, input_ids, position_ids=None, embedding_indices=None, attention_mask=None, output_attentions=False, output_hidden_states=False, return_dict=False, **kwargs, ): """encode""" input_type = type(input_ids) outputs = self.qwen2( input_ids, position_ids=position_ids, attention_mask=attention_mask, output_attentions=output_attentions, output_hidden_states=output_hidden_states, return_dict=return_dict, **kwargs, ) if isinstance(outputs, input_type): hidden_states = outputs else: hidden_states = outputs[0] last_hidden_states = hidden_states.gather_nd(embedding_indices) return last_hidden_states