code: def forward(
      self,
      x,
      rope: Optional[torch.Tensor] = None,
      attn_mask: Optional[torch.Tensor] = None,
  ):
      B, N, C = x.shape
  
      if self.qkv is not None:
          qkv_bias = (
              torch.cat((self.q_bias, self.k_bias, self.v_bias))
              if self.q_bias is not None
              else None
          )
          qkv = F.linear(input=x, weight=self.qkv.weight, bias=qkv_bias)
          qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(
              2, 0, 3, 1, 4
          )
          q, k, v = qkv.unbind(0)  # B, num_heads, N, head_dim
      else:
          q = (
              self.q_proj(x)
              .reshape(B, N, self.num_heads, -1)
              .transpose(1, 2)
          )  # B, num_heads, N, C
          k = (
              self.k_proj(x)
              .reshape(B, N, self.num_heads, -1)
              .transpose(1, 2)
          )
          v = (
              self.v_proj(x)
              .reshape(B, N, self.num_heads, -1)
              .transpose(1, 2)
          )
  
      if rope is not None:
          q = torch.cat(
              [
                  q[:, :, :1, :],
                  apply_rot_embed_cat(q[:, :, 1:, :], rope),
              ],
              2,
          ).type_as(v)
          k = torch.cat(
              [
                  k[:, :, :1, :],
                  apply_rot_embed_cat(k[:, :, 1:, :], rope),
              ],
              2,
          ).type_as(v)
  
      if self.fused_attn:
          x = F.scaled_dot_product_attention(
              q,
              k,
              v,
              attn_mask=attn_mask,
              dropout_p=self.attn_drop.p if self.training else 0.0,
          )
      else:
          q = q * self.scale
          attn = q @ k.transpose(-2, -1)
          attn = attn.softmax(dim=-1)
          if attn_mask is not None:
              attn_mask = attn_mask.to(torch.bool)
              attn = attn.masked_fill(
                  ~attn_mask[:, None, None, :], float("-inf")
              )
          attn = self.attn_drop(attn)
          x = attn @ v
  
      x = x.transpose(1, 2).reshape(B, N, C)
      x = self.norm(x)
      x = self.proj(x)
      x = self.proj_drop(x)
      return x
  
imports: import math
  from typing import Callable, Optional, Tuple, Union
  import torch
  import torch.nn
  import torch.nn.functional
  from torch.utils.checkpoint import checkpoint
  from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD, OPENAI_CLIP_MEAN, OPENAI_CLIP_STD
  from timm.layers import PatchEmbed, Mlp, GluMlp, SwiGLU, LayerNorm, DropPath, PatchDropout, RotaryEmbeddingCat, apply_rot_embed_cat, apply_keep_indices_nlc, trunc_normal_, resample_patch_embed, resample_abs_pos_embed, to_2tuple, use_fused_attn
  from ._builder import build_model_with_cfg
  from ._registry import generate_default_cfgs, register_model
label_desc: Use image node_id 2 for calling the EvaAttention obj's underlying member method code with example usage: obj.forward(x, rope, attn_mask) and returns: x