Team Ai
Modelpublic

stillerman/santacoder-ruby

sourceHugging Faceupdated 4y agoView on Hugging Face
0likes32downloads
modeling_gpt2_mq.py346 linesDownload Raw Back to root
1"""PyTorch OpenAI GPT-2 model modified with MultiQuery attention"""2 3 4import math5import os6from dataclasses import dataclass7from typing import Optional, Tuple, Union8 9import torch10import torch.utils.checkpoint11from torch import nn12from torch.cuda.amp import autocast13from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss14 15from transformers.activations import ACT2FN16from transformers.modeling_outputs import (17    BaseModelOutputWithPastAndCrossAttentions,18    CausalLMOutputWithCrossAttentions,19    SequenceClassifierOutputWithPast,20    TokenClassifierOutput,21)22from transformers.modeling_utils import PreTrainedModel, SequenceSummary23from transformers.pytorch_utils import Conv1D, find_pruneable_heads_and_indices, prune_conv1d_layer24 25from transformers.utils import (26    ModelOutput,27    add_code_sample_docstrings,28    add_start_docstrings,29    add_start_docstrings_to_model_forward,30    logging,31    replace_return_docstrings,32)33from transformers.utils.model_parallel_utils import assert_device_map, get_device_map34from transformers.models.gpt2.modeling_gpt2 import GPT2Model, GPT2Block, GPT2PreTrainedModel, GPT2LMHeadModel35from .configuration_gpt2_mq import GPT2CustomConfig, MULTI_QUERY, MULTI_HEAD36 37 38 39class GPT2MQAttention(nn.Module):40    def __init__(self, config, is_cross_attention=False, layer_idx=None):41        super().__init__()42        assert config.attention_head_type == MULTI_QUERY43 44        max_positions = config.max_position_embeddings45        self.register_buffer(46            "bias",47            torch.tril(torch.ones((max_positions, max_positions), dtype=torch.uint8)).view(48                1, 1, max_positions, max_positions49            ),50        )51        self.register_buffer("masked_bias", torch.tensor(-1e4))52 53        self.embed_dim = config.hidden_size54        self.num_heads = config.num_attention_heads55        self.head_dim = self.embed_dim // self.num_heads56        self.split_size = self.embed_dim57        if self.head_dim * self.num_heads != self.embed_dim:58            raise ValueError(59                f"`embed_dim` must be divisible by num_heads (got `embed_dim`: {self.embed_dim} and `num_heads`:"60                f" {self.num_heads})."61            )62 63        self.scale_attn_weights = config.scale_attn_weights64        if is_cross_attention:65            raise NotImplementedError("Cross-attention not implemented for MQA")66        self.is_cross_attention = is_cross_attention67 68        # Layer-wise attention scaling, reordering, and upcasting69        self.scale_attn_by_inverse_layer_idx = config.scale_attn_by_inverse_layer_idx70        self.layer_idx = layer_idx71        self.reorder_and_upcast_attn = config.reorder_and_upcast_attn72 73        if self.is_cross_attention:74            self.c_attn = Conv1D(2 * self.embed_dim, self.embed_dim)75            self.q_attn = Conv1D(self.embed_dim, self.embed_dim)76        else:77            # self.c_attn = Conv1D(3 * self.embed_dim, self.embed_dim)78            self.q_attn = Conv1D(self.embed_dim, self.embed_dim)79            # Keys and values are shared across heads80            self.kv_attn = Conv1D(2 * self.head_dim, self.embed_dim)81        self.c_proj = Conv1D(self.embed_dim, self.embed_dim)82 83        self.attn_dropout = nn.Dropout(config.attn_pdrop)84        self.resid_dropout = nn.Dropout(config.resid_pdrop)85 86        self.pruned_heads = set()87 88    def prune_heads(self, heads):89        if len(heads) == 0:90            return91        heads, index = find_pruneable_heads_and_indices(heads, self.num_heads, self.head_dim, self.pruned_heads)92        index_attn = torch.cat([index, index + self.split_size, index + (2 * self.split_size)])93 94        # Prune conv1d layers95        self.c_attn = prune_conv1d_layer(self.c_attn, index_attn, dim=1)96        self.c_proj = prune_conv1d_layer(self.c_proj, index, dim=0)97 98        # Update hyper params99        self.split_size = (self.split_size // self.num_heads) * (self.num_heads - len(heads))100        self.num_heads = self.num_heads - len(heads)101        self.pruned_heads = self.pruned_heads.union(heads)102 103    def _attn(self, query, key, value, attention_mask=None, head_mask=None):104        # query: (b, num_heads * sq, head_dim)105        # key: (b, head_dim, sk)106        # value: (b, sk, head_dim)107        batch_size = query.size(0)108        query_length = query.size(1) // self.num_heads109        key_length = key.size(2)110        # (b, num_heads * sq, head_dim) x (b, head_dim, sk) -> (b, num_heads * sq, sk)111        attn_weights = torch.bmm(query, key)112        # -> (b, num_heads, sq, sk)113        attn_weights = attn_weights.view(batch_size, self.num_heads, query_length, key_length)114 115        if self.scale_attn_weights:116            attn_weights = attn_weights / torch.tensor(117                value.size(-1) ** 0.5, dtype=attn_weights.dtype, device=attn_weights.device118            )119 120        # Layer-wise attention scaling121        if self.scale_attn_by_inverse_layer_idx:122            attn_weights = attn_weights / float(self.layer_idx + 1)123 124        if not self.is_cross_attention:125            # if only "normal" attention layer implements causal mask126            causal_mask = self.bias[:, :, key_length - query_length : key_length, :key_length].to(torch.bool)127            mask_value = torch.finfo(attn_weights.dtype).min128            # Need to be a tensor, otherwise we get error: `RuntimeError: expected scalar type float but found double`.129            # Need to be on the same device, otherwise `RuntimeError: ..., x and y to be on the same device`130            mask_value = torch.tensor(mask_value, dtype=attn_weights.dtype).to(attn_weights.device)131            attn_weights = torch.where(causal_mask, attn_weights, mask_value)132 133        if attention_mask is not None:134            # Apply the attention mask135            attn_weights = attn_weights + attention_mask136 137        attn_weights = nn.functional.softmax(attn_weights, dim=-1)138 139        # Downcast (if necessary) back to V's dtype (if in mixed-precision) -- No-Op otherwise140        attn_weights = attn_weights.type(value.dtype)141        attn_weights = self.attn_dropout(attn_weights)142 143        # Mask heads if we want to144        if head_mask is not None:145            attn_weights = attn_weights * head_mask146 147        # (b, num_heads, sq, sk) -> (b, num_heads * sq, sk)148        _attn_weights = attn_weights.view(batch_size, self.num_heads * query_length, key_length)149        # (b, num_heads * sq, sk) x (b, sk, head_dim) -> (b, num_heads * sq, head_dim)150        attn_output = torch.bmm(_attn_weights, value)151        attn_output = attn_output.view(batch_size, self.num_heads, query_length, self.head_dim)152 153        return attn_output, attn_weights154 155    def _upcast_and_reordered_attn(self, query, key, value, attention_mask=None, head_mask=None):156        # Use `torch.baddbmm` (a bit more efficient w/ alpha param for scaling -- from Megatron-LM)157        bsz, num_heads, q_seq_len, dk = query.size()158        _, _, k_seq_len, _ = key.size()159 160        # Preallocate attn_weights for `baddbmm`161        attn_weights = torch.empty(bsz * num_heads, q_seq_len, k_seq_len, dtype=torch.float32, device=query.device)162 163        # Compute Scale Factor164        scale_factor = 1.0165        if self.scale_attn_weights:166            scale_factor /= float(value.size(-1)) ** 0.5167 168        if self.scale_attn_by_inverse_layer_idx:169            scale_factor /= float(self.layer_idx + 1)170 171        # Upcast (turn off autocast) and reorder (Scale K by 1 / root(dk))172        with autocast(enabled=False):173            q, k = query.reshape(-1, q_seq_len, dk), key.transpose(-1, -2).reshape(-1, dk, k_seq_len)174            attn_weights = torch.baddbmm(attn_weights, q.float(), k.float(), beta=0, alpha=scale_factor)175            attn_weights = attn_weights.reshape(bsz, num_heads, q_seq_len, k_seq_len)176 177        if not self.is_cross_attention:178            # if only "normal" attention layer implements causal mask179            query_length, key_length = query.size(-2), key.size(-2)180            causal_mask = self.bias[:, :, key_length - query_length : key_length, :key_length].bool()181            mask_value = torch.finfo(attn_weights.dtype).min182            # Need to be a tensor, otherwise we get error: `RuntimeError: expected scalar type float but found double`.183            # Need to be on the same device, otherwise `RuntimeError: ..., x and y to be on the same device`184            mask_value = torch.tensor(mask_value, dtype=attn_weights.dtype).to(attn_weights.device)185            attn_weights = torch.where(causal_mask, attn_weights, mask_value)186 187        if attention_mask is not None:188            # Apply the attention mask189            attn_weights = attn_weights + attention_mask190 191        attn_weights = nn.functional.softmax(attn_weights, dim=-1)192 193        # Downcast (if necessary) back to V's dtype (if in mixed-precision) -- No-Op if otherwise194        if attn_weights.dtype != torch.float32:195            raise RuntimeError("Error with upcasting, attn_weights does not have dtype torch.float32")196        attn_weights = attn_weights.type(value.dtype)197        attn_weights = self.attn_dropout(attn_weights)198 199        # Mask heads if we want to200        if head_mask is not None:201            attn_weights = attn_weights * head_mask202 203        attn_output = torch.matmul(attn_weights, value)204 205        return attn_output, attn_weights206 207    def _split_heads(self, tensor, num_heads, attn_head_size):208        """209        Splits hidden_size dim into attn_head_size and num_heads210        """211        new_shape = tensor.size()[:-1] + (num_heads, attn_head_size)212        tensor = tensor.view(new_shape)213        return tensor.permute(0, 2, 1, 3)  # (batch, head, seq_length, head_features)214 215    def _merge_heads(self, tensor, num_heads, attn_head_size):216        """217        Merges attn_head_size dim and num_attn_heads dim into hidden_size218        """219        tensor = tensor.permute(0, 2, 1, 3).contiguous()220        new_shape = tensor.size()[:-2] + (num_heads * attn_head_size,)221        return tensor.view(new_shape)222 223    def forward(224        self,225        hidden_states: Optional[Tuple[torch.FloatTensor]],226        layer_past: Optional[Tuple[torch.Tensor]] = None,227        attention_mask: Optional[torch.FloatTensor] = None,228        head_mask: Optional[torch.FloatTensor] = None,229        encoder_hidden_states: Optional[torch.Tensor] = None,230        encoder_attention_mask: Optional[torch.FloatTensor] = None,231        use_cache: Optional[bool] = False,232        output_attentions: Optional[bool] = False,233    ) -> Tuple[Union[torch.Tensor, Tuple[torch.Tensor]], ...]:234        if encoder_hidden_states is not None:235            raise NotImplementedError("Cross-attention not implemented for MQA")236            if not hasattr(self, "q_attn"):237                raise ValueError(238                    "If class is used as cross attention, the weights `q_attn` have to be defined. "239                    "Please make sure to instantiate class with `GPT2Attention(..., is_cross_attention=True)`."240                )241 242            query = self.q_attn(hidden_states)243            key, value = self.c_attn(encoder_hidden_states).split(self.split_size, dim=2)244            attention_mask = encoder_attention_mask245        else:246            query = self.q_attn(hidden_states)247            key, value = self.kv_attn(hidden_states).split(self.head_dim, dim=2)248 249 250        batch_size, seq_length = query.shape[:2]251        # (query_length, batch, num_heads, head_dim)252        # (batch, num_heads * query_length, head_dim)\253 254        # (batch, query_length, hidden_size) -> (batch, num_heads, query_length, head_dim)255        query = query.view(batch_size, seq_length, self.num_heads, self.head_dim).permute([0, 2, 1, 3])256        # -> (batch, num_heads * query_length, head_dim)257        query = query.reshape(batch_size, self.num_heads * seq_length, self.head_dim)258 259        # (batch, query_length, hidden_size) -> (batch, query_length * num_heads, head_dim)260        # query = query.view(261        #     batch_size, seq_length, self.num_heads, self.head_dim,262        # ).reshape(263        #     batch_size, seq_length * self.num_heads, self.head_dim264        # )265        key = key.permute(0, 2, 1)  # (batch_size, head_dim, seq_length)266        # value (batch_size, seq_length, head_dim)267 268        if layer_past is not None:269            past_key, past_value = layer_past270            # Concatenate on sequence dimension271            key = torch.cat((past_key, key), dim=-1)272            value = torch.cat((past_value, value), dim=-2)273 274        if use_cache is True:275            present = (key, value)276        else:277            present = None278 279        if self.reorder_and_upcast_attn:280            raise NotImplementedError("Reorder and upcast attention not implemented for MQA")281            attn_output, attn_weights = self._upcast_and_reordered_attn(query, key, value, attention_mask, head_mask)282        else:283            attn_output, attn_weights = self._attn(query, key, value, attention_mask, head_mask)284 285        attn_output = self._merge_heads(attn_output, self.num_heads, self.head_dim)286        attn_output = self.c_proj(attn_output)287        attn_output = self.resid_dropout(attn_output)288 289        outputs = (attn_output, present)290        if output_attentions:291            outputs += (attn_weights,)292 293        return outputs  # a, present, (attentions)294 295 296# inherit from gpt_modeling.py, and override `attn` module297class GPT2CustomBlock(GPT2Block):298 299    def __init__(self, config: GPT2CustomConfig, layer_idx=None):300        super().__init__(config, layer_idx)301        # Override attention module if using multiquery302        if config.attention_head_type == MULTI_QUERY:303            self.attn = GPT2MQAttention(config, layer_idx=layer_idx)304            if config.add_cross_attention:305                raise NotImplementedError("Cross-attention not implemented for MQA")306 307 308# inherit from gpt_modeling.py and override `__init__` method309class GPT2CustomModel(GPT2Model):310    config_class = GPT2CustomConfig311    312    def __init__(self, config):313        GPT2PreTrainedModel.__init__(self, config)314 315        self.embed_dim = config.hidden_size316 317        self.wte = nn.Embedding(config.vocab_size, self.embed_dim)318        self.wpe = nn.Embedding(config.max_position_embeddings, self.embed_dim)319 320        self.drop = nn.Dropout(config.embd_pdrop)321        self.h = nn.ModuleList([GPT2CustomBlock(config, layer_idx=i) for i in range(config.num_hidden_layers)])322        self.ln_f = nn.LayerNorm(self.embed_dim, eps=config.layer_norm_epsilon)323 324        # Model parallel325        self.model_parallel = False326        self.device_map = None327        self.gradient_checkpointing = False328 329        # Initialize weights and apply final processing330        self.post_init()331 332 333class GPT2LMHeadCustomModel(GPT2LMHeadModel):334    config_class = GPT2CustomConfig335 336    def __init__(self, config):337        GPT2PreTrainedModel.__init__(self, config)338        self.transformer = GPT2CustomModel(config)339        self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)340 341        # Model parallel342        self.model_parallel = False343        self.device_map = None344 345        # Initialize weights and apply final processing346        self.post_init()