# -------------------------------------------------------- # InternVL # Copyright (c) 2024 OpenGVLab # Licensed under The MIT License [see LICENSE for details] # -------------------------------------------------------- import torch from flash_attn.flash_attn_interface import flash_attn_varlen_func from transformers.models.llama.modeling_llama import (LLAMA_ATTENTION_CLASSES, LlamaFlashAttention2) # Modified from transformers.models.llama.modeling_llama.LlamaFlashAttention2 class LlamaFlashAttention2ForPackedTraining(LlamaFlashAttention2): 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 (`int`, *optional*): 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: # TODO: Remove the `query_length != 1` check once Flash Attention for RoCm is bumped to 2.1. For details, please see the comment in LlamaFlashAttention2 __init__. causal = self.is_causal and query_length != 1 # Decide whether to use SWA or not by layer index. 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_llama_attention_class(): LLAMA_ATTENTION_CLASSES['flash_attention_2'] = LlamaFlashAttention2ForPackedTraining print('Replace LLAMA_ATTENTION_CLASSES to support packed training!!')