| |
| |
| |
| |
| |
|
|
| import torch |
| from flash_attn.flash_attn_interface import flash_attn_varlen_func |
| from internvl.model.phi3.modeling_phi3 import (PHI3_ATTENTION_CLASSES, |
| Phi3FlashAttention2) |
|
|
|
|
| class Phi3FlashAttention2ForPackedTraining(Phi3FlashAttention2): |
|
|
| def _flash_attention_forward( |
| self, |
| query_states, |
| key_states, |
| value_states, |
| attention_mask, |
| query_length, |
| dropout=0.0, |
| softmax_scale=None, |
| use_sliding_windows=False, |
| ): |
| """ |
| Calls the forward method of Flash Attention - if the input hidden states contain at least one padding token |
| first unpad the input, then computes the attention scores and pad the final attention scores. |
| |
| Args: |
| query_states (`torch.Tensor`): |
| Input query states to be passed to Flash Attention API |
| key_states (`torch.Tensor`): |
| Input key states to be passed to Flash Attention API |
| value_states (`torch.Tensor`): |
| Input value states to be passed to Flash Attention API |
| attention_mask (`torch.Tensor`): |
| The padding mask - corresponds to a tensor of size `(batch_size, seq_len)` where 0 stands for the |
| position of padding tokens and 1 for the position of non-padding tokens. |
| dropout (`float`): |
| Attention dropout |
| softmax_scale (`float`, *optional*): |
| The scaling of QK^T before applying softmax. Default to 1 / sqrt(head_dim) |
| use_sliding_windows (`bool`, *optional*): |
| Whether to activate sliding window attention. |
| """ |
| assert query_states.size(0) == key_states.size(0) == value_states.size(0) == 1 |
| query_states = query_states.squeeze(0) |
| key_states = key_states.squeeze(0) |
| value_states = value_states.squeeze(0) |
| cu_seqlens = attention_mask.squeeze(0) |
|
|
| with torch.no_grad(): |
| max_seqlen = max([ |
| cu_seqlens[idx+1] - cu_seqlens[idx] |
| for idx in range(cu_seqlens.size(0) - 1) |
| ]).item() |
|
|
| if not self._flash_attn_uses_top_left_mask: |
| causal = self.is_causal |
| else: |
| |
| causal = self.is_causal and query_length != 1 |
|
|
| |
| if use_sliding_windows and self.layer_idx >= self.config.max_window_layers: |
| use_sliding_windows = False |
|
|
| if not use_sliding_windows: |
| attn_output = flash_attn_varlen_func( |
| q=query_states, |
| k=key_states, |
| v=value_states, |
| cu_seqlens_q=cu_seqlens, |
| cu_seqlens_k=cu_seqlens, |
| max_seqlen_q=max_seqlen, |
| max_seqlen_k=max_seqlen, |
| dropout_p=dropout, |
| softmax_scale=softmax_scale, |
| causal=causal, |
| ) |
| else: |
| attn_output = flash_attn_varlen_func( |
| q=query_states, |
| k=key_states, |
| v=value_states, |
| cu_seqlens_q=cu_seqlens, |
| cu_seqlens_k=cu_seqlens, |
| max_seqlen_q=max_seqlen, |
| max_seqlen_k=max_seqlen, |
| dropout_p=dropout, |
| softmax_scale=softmax_scale, |
| causal=causal, |
| window_size=(self.config.sliding_window, self.config.sliding_window), |
| ) |
|
|
| query_states = query_states.unsqueeze(0) |
| key_states = key_states.unsqueeze(0) |
| value_states = value_states.unsqueeze(0) |
| return attn_output |
|
|
|
|
| def replace_phi3_attention_class(): |
| PHI3_ATTENTION_CLASSES['flash_attention_2'] = Phi3FlashAttention2ForPackedTraining |
| print('Replace PHI3_ATTENTION_CLASSES to support packed training!!') |
|
|