| |
| |
|
|
| import torch |
| import copy |
| from einops import rearrange |
| from flash_attn.layers.rotary import RotaryEmbedding |
| from flash_attn.modules.mha import MHA |
|
|
|
|
| |
| class LinearlyScaledRotaryEmbedding(RotaryEmbedding): |
| def __init__( |
| self, |
| dim: int, |
| scaling_factor: float=1., |
| base=10000.0, |
| interleaved=False, |
| scale_base=None, |
| pos_idx_in_fp32=True, |
| device=None, |
| ): |
| super().__init__( |
| dim=dim, |
| base=base, |
| interleaved=interleaved, |
| scale_base=scale_base, |
| pos_idx_in_fp32=pos_idx_in_fp32, |
| device=device |
| ) |
| self._linear_scaling_factor = scaling_factor |
| |
| def _update_cos_sin_cache(self, seqlen, device=None, dtype=None): |
| |
| |
| |
| if ( |
| seqlen > self._seq_len_cached |
| or self._cos_cached is None |
| or self._cos_cached.device != device |
| or self._cos_cached.dtype != dtype |
| or (self.training and self._cos_cached.is_inference()) |
| ): |
| self._seq_len_cached = seqlen |
| |
| |
| |
| if self.pos_idx_in_fp32: |
| t = torch.arange(seqlen, device=device, dtype=torch.float32) |
| |
| t = t / self._linear_scaling_factor |
| |
| |
| |
| |
| if self.inv_freq.dtype != torch.float32: |
| inv_freq = self._compute_inv_freq(device=device) |
| else: |
| inv_freq = self.inv_freq |
| else: |
| t = torch.arange(seqlen, device=device, dtype=self.inv_freq.dtype) |
| |
| t = t / self._linear_scaling_factor |
| inv_freq = self.inv_freq |
| |
| |
| freqs = torch.outer(t, inv_freq) |
| if self.scale is None: |
| self._cos_cached = torch.cos(freqs).to(dtype) |
| self._sin_cached = torch.sin(freqs).to(dtype) |
| else: |
| power = ( |
| torch.arange(seqlen, dtype=self.scale.dtype, device=self.scale.device) |
| - seqlen // 2 |
| ) / self.scale_base |
| scale = self.scale.to(device=power.device) ** rearrange(power, "s -> s 1") |
| |
| self._cos_cached = (torch.cos(freqs) * scale).to(dtype) |
| self._sin_cached = (torch.sin(freqs) * scale).to(dtype) |
| self._cos_k_cached = (torch.cos(freqs) / scale).to(dtype) |
| self._sin_k_cached = (torch.sin(freqs) / scale).to(dtype) |
|
|
| |
| def swap_mha_rope( |
| mha, |
| new_rope: torch.nn.Module=LinearlyScaledRotaryEmbedding, |
| kwargs_new_rope: dict=None |
| ): |
| |
| dtype = mha.Wq.weight.dtype if mha.cross_attn else mha.Wqkv.weight.dtype |
| device = mha.Wq.weight.device if mha.cross_attn else mha.Wqkv.weight.device |
| |
| kwargs_old_rope = dict( |
| dim = mha.rotary_emb.dim, |
| base = mha.rotary_emb.base, |
| interleaved = mha.rotary_emb.interleaved, |
| scale_base = mha.rotary_emb.scale_base, |
| pos_idx_in_fp32 = mha.rotary_emb.pos_idx_in_fp32, |
| device = mha.rotary_emb.inv_freq.device |
| ) |
| |
| del mha.rotary_emb |
| |
| kwargs_new_rope = kwargs_new_rope or {'scaling_factor': 1.0} |
| scaled_rope = new_rope( |
| **kwargs_new_rope, |
| **kwargs_old_rope |
| ).to(dtype) |
| |
| mha.rotary_emb = scaled_rope |
| |
| assert isinstance(mha.rotary_emb, new_rope) |
| return mha |