CoolFace
Modelpublic

Nethermind/Mpt-Instruct-DotNet-XS

sourceHugging Facecc-by-sa-3.0updated 3y agoView on Hugging Face
0likes49downloads
attention.py409 linesDownload Raw Back to root
1# Copyright 2022 MosaicML Examples authors2# SPDX-License-Identifier: Apache-2.03 4"""Attention layers."""5 6import math7import warnings8from typing import Optional9 10import torch11import torch.nn as nn12from einops import rearrange13from torch import nn14 15from .low_precision_layernorm import LPLayerNorm16 17 18def _reset_is_causal(num_query_tokens: int, num_key_tokens: int,19                     original_is_causal: bool):20    if original_is_causal and num_query_tokens != num_key_tokens:21        if num_query_tokens != 1:22            raise NotImplementedError(23                'MosaicGPT does not support query and key with different number of tokens, unless number of query tokens is 1.'24            )25        else:26            return False27    return original_is_causal28 29 30def scaled_multihead_dot_product_attention(31    query,32    key,33    value,34    n_heads,35    softmax_scale=None,36    attn_bias=None,37    key_padding_mask=None,38    is_causal=False,39    dropout_p=0.0,40    training=False,41    needs_weights=False,42):43 44    q = rearrange(query, 'b s (h d) -> b h s d', h=n_heads)45    k = rearrange(key, 'b s (h d) -> b h d s', h=n_heads)  # includes key.t()46    v = rearrange(value, 'b s (h d) -> b h s d', h=n_heads)47 48    min_val = torch.finfo(q.dtype).min49 50    b, _, s_q, d = q.shape51    s_k = k.size(-1)52 53    if softmax_scale is None:54        softmax_scale = 1 / math.sqrt(d)55 56    attn_weight = q.matmul(k) * softmax_scale57 58    if attn_bias is not None:59        if (attn_bias.size(-1) != 1 and60                attn_bias.size(-1) != s_k) or (attn_bias.size(-2) != 1 and61                                               attn_bias.size(-2) != s_q):62            raise RuntimeError(63                f'attn_bias (shape: {attn_bias.shape}) is expected to broadcast to shape: {attn_weight.shape}.'64            )65        attn_weight = attn_weight + attn_bias66 67    if key_padding_mask is not None:68        if attn_bias is not None:69            warnings.warn(70                'Propogating key_padding_mask to the attention module ' +\71                'and applying it within the attention module can cause ' +\72                'unneccessary computation/memory usage. Consider integrating ' +\73                'into attn_bias once and passing that to each attention ' +\74                'module instead.'75            )76        attn_weight = attn_weight.masked_fill(77            ~key_padding_mask.view((b, 1, 1, s_k)), min_val)78 79    if is_causal:80        s = max(s_q, s_k)81        causal_mask = attn_weight.new_ones(s, s, dtype=torch.float16)82        causal_mask = causal_mask.tril()83        causal_mask = causal_mask.to(torch.bool)84        causal_mask = ~causal_mask85        causal_mask = causal_mask[-s_q:, -s_k:]86        attn_weight = attn_weight.masked_fill(causal_mask.view(1, 1, s_q, s_k),87                                              min_val)88 89    attn_weight = torch.softmax(attn_weight, dim=-1)90 91    if dropout_p:92        attn_weight = torch.nn.functional.dropout(attn_weight,93                                                  p=dropout_p,94                                                  training=training,95                                                  inplace=True)96 97    out = attn_weight.matmul(v)98    out = rearrange(out, 'b h s d -> b s (h d)')99 100    if needs_weights:101        return out, attn_weight102    return out, None103 104 105def check_valid_inputs(*tensors, valid_dtypes=[torch.float16, torch.bfloat16]):106    for tensor in tensors:107        if tensor.dtype not in valid_dtypes:108            raise TypeError(f'{tensor.dtype=} must be in {valid_dtypes=}.')109        if not tensor.is_cuda:110            raise TypeError(f'Inputs must be cuda tensors ({tensor.is_cuda=}).')111 112 113def flash_attn_fn(114    query,115    key,116    value,117    n_heads,118    softmax_scale=None,119    attn_bias=None,120    key_padding_mask=None,121    is_causal=False,122    dropout_p=0.0,123    training=False,124    needs_weights=False,125):126    try:127        from flash_attn import bert_padding, flash_attn_interface128    except:129        raise RuntimeError('Please install flash_attn==0.2.8')130 131    check_valid_inputs(query, key, value)132 133    if attn_bias is not None:134        raise NotImplementedError(f'attn_bias not implemented for flash attn.')135 136    batch_size, seqlen = query.shape[:2]137 138    if key_padding_mask is None:139        key_padding_mask = torch.ones_like(key[:, :, 0], dtype=torch.bool)140    query_padding_mask = key_padding_mask[:, -query.size(1):]141 142    query_unpad, indices_q, cu_seqlens_q, max_seqlen_q = bert_padding.unpad_input(143        query, query_padding_mask)144    query_unpad = rearrange(query_unpad, 'nnz (h d) -> nnz h d', h=n_heads)145 146    key_unpad, _, cu_seqlens_k, max_seqlen_k = bert_padding.unpad_input(147        key, key_padding_mask)148    key_unpad = rearrange(key_unpad, 'nnz (h d) -> nnz h d', h=n_heads)149 150    value_unpad, _, _, _ = bert_padding.unpad_input(value, key_padding_mask)151    value_unpad = rearrange(value_unpad, 'nnz (h d) -> nnz h d', h=n_heads)152 153    dropout_p = dropout_p if training else 0.0154 155    reset_is_causal = _reset_is_causal(query.size(1), key.size(1), is_causal)156 157    output_unpad = flash_attn_interface.flash_attn_unpadded_func(158        query_unpad,159        key_unpad,160        value_unpad,161        cu_seqlens_q,162        cu_seqlens_k,163        max_seqlen_q,164        max_seqlen_k,165        dropout_p,166        softmax_scale=softmax_scale,167        causal=reset_is_causal,168        return_attn_probs=needs_weights)169 170    output = bert_padding.pad_input(171        rearrange(output_unpad, 'nnz h d -> nnz (h d)'), indices_q, batch_size,172        seqlen)173    return output, None174 175 176def triton_flash_attn_fn(177    query,178    key,179    value,180    n_heads,181    softmax_scale=None,182    attn_bias=None,183    key_padding_mask=None,184    is_causal=False,185    dropout_p=0.0,186    training=False,187    needs_weights=False,188):189    try:190        from flash_attn import flash_attn_triton  # type: ignore191    except:192        raise RuntimeError('Please install flash_attn==0.2.8 and triton==2.0.0.dev20221202.')193 194    check_valid_inputs(query, key, value)195 196    if dropout_p:197        raise NotImplementedError(198            f'Dropout not implemented for attn_impl: triton.')199 200    if needs_weights:201        raise NotImplementedError(202            f'attn_impl: triton cannot return attn weights.')203 204    if key_padding_mask is not None:205        warnings.warn(206            'Propagating key_padding_mask to the attention module ' +\207            'and applying it within the attention module can cause ' +\208            'unnecessary computation/memory usage. Consider integrating ' +\209            'into attn_bias once and passing that to each attention ' +\210            'module instead.'211        )212        b_size, s_k = key_padding_mask.shape[:2]213 214        if attn_bias is None:215            attn_bias = query.new_zeros(b_size, 1, 1, s_k)216 217        attn_bias = attn_bias.masked_fill(218            ~key_padding_mask.view((b_size, 1, 1, s_k)),219            torch.finfo(query.dtype).min)220 221    query = rearrange(query, 'b s (h d) -> b s h d', h=n_heads)222    key = rearrange(key, 'b s (h d) -> b s h d', h=n_heads)223    value = rearrange(value, 'b s (h d) -> b s h d', h=n_heads)224 225    reset_is_causal = _reset_is_causal(query.size(1), key.size(1), is_causal)226    attn_output = flash_attn_triton.flash_attn_func(query, key, value,227                                                    attn_bias, reset_is_causal,228                                                    softmax_scale)229 230    output = attn_output.view(*attn_output.shape[:2], -1)231 232    return output, None233 234 235class MultiheadAttention(nn.Module):236    """Multi-head self attention.237 238    Using torch or triton attention implemetation enables user to also use239    additive bias.240    """241 242    def __init__(243        self,244        d_model: int,245        n_heads: int,246        attn_impl: str = 'triton',247        attn_clip_qkv: Optional[float] = None,248        attn_qk_ln: bool = False,249        softmax_scale: Optional[float] = None,250        attn_pdrop: float = 0.0,251        low_precision_layernorm: bool = False,252        device: Optional[str] = None,253    ):254        super().__init__()255 256        self.attn_impl = attn_impl257        self.clip_qkv = attn_clip_qkv258        self.attn_qk_ln = attn_qk_ln259 260        self.d_model = d_model261        self.n_heads = n_heads262        self.softmax_scale = softmax_scale263        if self.softmax_scale is None:264            self.softmax_scale = 1 / math.sqrt(self.d_model / self.n_heads)265        self.attn_dropout_p = attn_pdrop266 267        self.Wqkv = nn.Linear(self.d_model, 3 * self.d_model, device=device)268        # for param init fn; enables shape based init of fused layers269        fuse_splits = (d_model, 2 * d_model)270        self.Wqkv._fused = (0, fuse_splits)  # type: ignore271 272        if self.attn_qk_ln:273            layernorm_class = LPLayerNorm if low_precision_layernorm else nn.LayerNorm274            self.q_ln = layernorm_class(self.d_model, device=device)275            self.k_ln = layernorm_class(self.d_model, device=device)276 277        if self.attn_impl == 'flash':278            self.attn_fn = flash_attn_fn279        elif self.attn_impl == 'triton':280            self.attn_fn = triton_flash_attn_fn281            warnings.warn(282                'While `attn_impl: triton` can be faster than `attn_impl: flash` ' +\283                'it uses more memory. When training larger models this can trigger '  +\284                'alloc retries which hurts performance. If encountered, we recommend ' +\285                'using `attn_impl: flash` if your model does not use `alibi` or `prefix_lm`.')286        elif self.attn_impl == 'torch':287            self.attn_fn = scaled_multihead_dot_product_attention288            if torch.cuda.is_available():289                warnings.warn(290                    'Using `attn_impl: torch`. If your model does not use `alibi` or ' +\291                    '`prefix_lm` we recommend using `attn_impl: flash` otherwise ' +\292                    'we recommend using `attn_impl: triton`.'293                )294        else:295            raise ValueError(f'{attn_impl=} is an invalid setting.')296 297        self.out_proj = nn.Linear(self.d_model, self.d_model, device=device)298        self.out_proj._is_residual = True  # type: ignore299 300    def forward(self,301                x,302                past_key_value=None,303                attn_bias=None,304                attention_mask=None,305                is_causal=True,306                needs_weights=False):307        qkv = self.Wqkv(x)308 309        if self.clip_qkv:310            qkv.clamp_(min=-self.clip_qkv, max=self.clip_qkv)311 312        query, key, value = qkv.chunk(3, dim=2)313 314        key_padding_mask = attention_mask315 316        if self.attn_qk_ln:317            # Applying layernorm to qk318            dtype = query.dtype319            query = self.q_ln(query).to(dtype)320            key = self.k_ln(key).to(dtype)321 322        if past_key_value is not None:323            if len(past_key_value) != 0:324                key = torch.cat([past_key_value[0], key], dim=1)325                value = torch.cat([past_key_value[1], value], dim=1)326 327            past_key_value = (key, value)328 329        if attn_bias is not None:330            attn_bias = attn_bias[:, :, -query.size(1):, -key.size(1):]331 332        context, attn_weights = self.attn_fn(333            query,334            key,335            value,336            self.n_heads,337            softmax_scale=self.softmax_scale,338            attn_bias=attn_bias,339            key_padding_mask=key_padding_mask,340            is_causal=is_causal,341            dropout_p=self.attn_dropout_p,342            training=self.training,343            needs_weights=needs_weights,344        )345 346        return self.out_proj(context), attn_weights, past_key_value347 348 349def attn_bias_shape(attn_impl, n_heads, seq_len, alibi, prefix_lm, causal,350                    use_sequence_id):351    if attn_impl == 'flash':352        return None353    elif attn_impl in ['torch', 'triton']:354        if alibi:355            if (prefix_lm or not causal) or use_sequence_id:356                return (1, n_heads, seq_len, seq_len)357            return (1, n_heads, 1, seq_len)358        elif prefix_lm or use_sequence_id:359            return (1, 1, seq_len, seq_len)360        return None361    else:362        raise ValueError(f'{attn_impl=} is an invalid setting.')363 364 365def attn_bias(attn_impl,366              attn_bias,367              n_heads,368              seq_len,369              causal=False,370              alibi=False,371              alibi_bias_max=8):372    if attn_impl == 'flash':373        return None374    elif attn_impl in ['torch', 'triton']:375        if alibi:376            # in place add alibi to attn bias377            device, dtype = attn_bias.device, attn_bias.dtype378            attn_bias = attn_bias.add(379                alibi_bias(n_heads,380                           seq_len,381                           full=not causal,382                           alibi_bias_max=alibi_bias_max,383                           device=device,384                           dtype=dtype))385        return attn_bias386    else:387        raise ValueError(f'{attn_impl=} is an invalid setting.')388 389 390def alibi_bias(n_heads,391               seq_len,392               full=False,393               alibi_bias_max=8,394               device=None,395               dtype=None):396    alibi_bias = torch.arange(1 - seq_len, 1, dtype=dtype,397                              device=device).view(1, 1, 1, seq_len)398    if full:399        # generate 1 x Heads x SeqLen x SeqLen alibi bias mask400        # otherwise the mask is 1 x Heads x 1 x SeqLen (which is broadcast to the appropriate size)401        alibi_bias = alibi_bias - torch.arange(402            1 - seq_len, 1, dtype=dtype, device=device).view(1, 1, seq_len, 1)403        alibi_bias = alibi_bias.abs().mul(-1)404 405    m = torch.arange(1, n_heads + 1, dtype=dtype, device=device)406    m = m.mul(alibi_bias_max / n_heads)407    alibi_bias = alibi_bias * (1. / (2**m.view(1, n_heads, 1, 1)))408    return alibi_bias409