211 lines
7.9 KiB
Python
211 lines
7.9 KiB
Python
|
from typing import Callable, Optional
|
||
|
|
||
|
import torch
|
||
|
import torch.utils.checkpoint
|
||
|
from torch import nn
|
||
|
|
||
|
from ...cache_utils import Cache, DynamicCache
|
||
|
from ...masking_utils import create_causal_mask, create_sliding_window_causal_mask
|
||
|
from ...modeling_flash_attention_utils import FlashAttentionKwargs
|
||
|
from ...modeling_outputs import (
|
||
|
BaseModelOutputWithPast,
|
||
|
)
|
||
|
from ...modeling_utils import ALL_ATTENTION_FUNCTIONS
|
||
|
from ...processing_utils import Unpack
|
||
|
from ...utils import TransformersKwargs, auto_docstring, logging
|
||
|
from ...utils.generic import check_model_inputs
|
||
|
from ..llama.modeling_llama import (
|
||
|
LlamaAttention,
|
||
|
LlamaDecoderLayer,
|
||
|
LlamaForCausalLM,
|
||
|
LlamaForQuestionAnswering,
|
||
|
LlamaForSequenceClassification,
|
||
|
LlamaForTokenClassification,
|
||
|
LlamaMLP,
|
||
|
LlamaPreTrainedModel,
|
||
|
apply_rotary_pos_emb,
|
||
|
eager_attention_forward,
|
||
|
)
|
||
|
from ..mistral.modeling_mistral import MistralModel
|
||
|
from .configuration_qwen2 import Qwen2Config
|
||
|
|
||
|
|
||
|
logger = logging.get_logger(__name__)
|
||
|
|
||
|
|
||
|
class Qwen2MLP(LlamaMLP):
|
||
|
def __init__(self, config):
|
||
|
super().__init__(config)
|
||
|
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
||
|
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
||
|
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
||
|
|
||
|
|
||
|
class Qwen2Attention(LlamaAttention):
|
||
|
def __init__(self, config: Qwen2Config, layer_idx: int):
|
||
|
super().__init__(config, layer_idx)
|
||
|
self.q_proj = nn.Linear(config.hidden_size, config.num_attention_heads * self.head_dim, bias=True)
|
||
|
self.k_proj = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=True)
|
||
|
self.v_proj = nn.Linear(config.hidden_size, config.num_key_value_heads * self.head_dim, bias=True)
|
||
|
self.o_proj = nn.Linear(config.num_attention_heads * self.head_dim, config.hidden_size, bias=False)
|
||
|
self.sliding_window = config.sliding_window if config.layer_types[layer_idx] == "sliding_attention" else None
|
||
|
|
||
|
def forward(
|
||
|
self,
|
||
|
hidden_states: torch.Tensor,
|
||
|
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
||
|
attention_mask: Optional[torch.Tensor],
|
||
|
past_key_value: Optional[Cache] = None,
|
||
|
cache_position: Optional[torch.LongTensor] = None,
|
||
|
**kwargs: Unpack[FlashAttentionKwargs],
|
||
|
) -> tuple[torch.Tensor, Optional[torch.Tensor], Optional[tuple[torch.Tensor]]]:
|
||
|
input_shape = hidden_states.shape[:-1]
|
||
|
hidden_shape = (*input_shape, -1, self.head_dim)
|
||
|
|
||
|
query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
||
|
key_states = self.k_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
||
|
value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
|
||
|
|
||
|
cos, sin = position_embeddings
|
||
|
query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
|
||
|
|
||
|
if past_key_value is not None:
|
||
|
# sin and cos are specific to RoPE models; cache_position needed for the static cache
|
||
|
cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
|
||
|
key_states, value_states = past_key_value.update(key_states, value_states, self.layer_idx, cache_kwargs)
|
||
|
|
||
|
attention_interface: Callable = eager_attention_forward
|
||
|
if self.config._attn_implementation != "eager":
|
||
|
attention_interface = ALL_ATTENTION_FUNCTIONS[self.config._attn_implementation]
|
||
|
|
||
|
attn_output, attn_weights = attention_interface(
|
||
|
self,
|
||
|
query_states,
|
||
|
key_states,
|
||
|
value_states,
|
||
|
attention_mask,
|
||
|
dropout=0.0 if not self.training else self.attention_dropout,
|
||
|
scaling=self.scaling,
|
||
|
sliding_window=self.sliding_window, # main diff with Llama
|
||
|
**kwargs,
|
||
|
)
|
||
|
|
||
|
attn_output = attn_output.reshape(*input_shape, -1).contiguous()
|
||
|
attn_output = self.o_proj(attn_output)
|
||
|
return attn_output, attn_weights
|
||
|
|
||
|
|
||
|
class Qwen2DecoderLayer(LlamaDecoderLayer):
|
||
|
def __init__(self, config: Qwen2Config, layer_idx: int):
|
||
|
super().__init__()
|
||
|
self.attention_type = config.layer_types[layer_idx]
|
||
|
|
||
|
|
||
|
class Qwen2PreTrainedModel(LlamaPreTrainedModel):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class Qwen2Model(MistralModel):
|
||
|
def __init__(self, config: Qwen2Config):
|
||
|
super().__init__(config)
|
||
|
self.has_sliding_layers = "sliding_attention" in self.config.layer_types
|
||
|
|
||
|
@check_model_inputs
|
||
|
@auto_docstring
|
||
|
def forward(
|
||
|
self,
|
||
|
input_ids: Optional[torch.LongTensor] = None,
|
||
|
attention_mask: Optional[torch.Tensor] = None,
|
||
|
position_ids: Optional[torch.LongTensor] = None,
|
||
|
past_key_values: Optional[Cache] = None,
|
||
|
inputs_embeds: Optional[torch.FloatTensor] = None,
|
||
|
use_cache: Optional[bool] = None,
|
||
|
cache_position: Optional[torch.LongTensor] = None,
|
||
|
**kwargs: Unpack[TransformersKwargs],
|
||
|
) -> BaseModelOutputWithPast:
|
||
|
if (input_ids is None) ^ (inputs_embeds is not None):
|
||
|
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
||
|
|
||
|
if inputs_embeds is None:
|
||
|
inputs_embeds = self.embed_tokens(input_ids)
|
||
|
|
||
|
if use_cache and past_key_values is None:
|
||
|
past_key_values = DynamicCache()
|
||
|
|
||
|
if cache_position is None:
|
||
|
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
||
|
cache_position = torch.arange(
|
||
|
past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device
|
||
|
)
|
||
|
|
||
|
if position_ids is None:
|
||
|
position_ids = cache_position.unsqueeze(0)
|
||
|
|
||
|
# It may already have been prepared by e.g. `generate`
|
||
|
if not isinstance(causal_mask_mapping := attention_mask, dict):
|
||
|
# Prepare mask arguments
|
||
|
mask_kwargs = {
|
||
|
"config": self.config,
|
||
|
"input_embeds": inputs_embeds,
|
||
|
"attention_mask": attention_mask,
|
||
|
"cache_position": cache_position,
|
||
|
"past_key_values": past_key_values,
|
||
|
"position_ids": position_ids,
|
||
|
}
|
||
|
# Create the masks
|
||
|
causal_mask_mapping = {
|
||
|
"full_attention": create_causal_mask(**mask_kwargs),
|
||
|
}
|
||
|
# The sliding window alternating layers are not always activated depending on the config
|
||
|
if self.has_sliding_layers:
|
||
|
causal_mask_mapping["sliding_attention"] = create_sliding_window_causal_mask(**mask_kwargs)
|
||
|
|
||
|
hidden_states = inputs_embeds
|
||
|
|
||
|
# create position embeddings to be shared across the decoder layers
|
||
|
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
||
|
|
||
|
for decoder_layer in self.layers[: self.config.num_hidden_layers]:
|
||
|
hidden_states = decoder_layer(
|
||
|
hidden_states,
|
||
|
attention_mask=causal_mask_mapping[decoder_layer.attention_type],
|
||
|
position_ids=position_ids,
|
||
|
past_key_value=past_key_values,
|
||
|
use_cache=use_cache,
|
||
|
cache_position=cache_position,
|
||
|
position_embeddings=position_embeddings,
|
||
|
**kwargs,
|
||
|
)
|
||
|
|
||
|
hidden_states = self.norm(hidden_states)
|
||
|
return BaseModelOutputWithPast(
|
||
|
last_hidden_state=hidden_states,
|
||
|
past_key_values=past_key_values if use_cache else None,
|
||
|
)
|
||
|
|
||
|
|
||
|
class Qwen2ForCausalLM(LlamaForCausalLM):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class Qwen2ForSequenceClassification(LlamaForSequenceClassification):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class Qwen2ForTokenClassification(LlamaForTokenClassification):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class Qwen2ForQuestionAnswering(LlamaForQuestionAnswering):
|
||
|
pass
|
||
|
|
||
|
|
||
|
__all__ = [
|
||
|
"Qwen2PreTrainedModel",
|
||
|
"Qwen2Model",
|
||
|
"Qwen2ForCausalLM",
|
||
|
"Qwen2ForSequenceClassification",
|
||
|
"Qwen2ForTokenClassification",
|
||
|
"Qwen2ForQuestionAnswering",
|
||
|
]
|