code: def vlm_attention(
      self,
      image_features,
      prompts=None,
      image_counts=None,
      long_video=False,
  ):
      img_feat_lst = []
      if image_counts is None:
          assert len(image_features) == len(
              prompts
          ), f"Size mismatch! image_features: {len(image_features)}, prompts: {len(prompts)}"
      else:
          assert len(prompts) == len(
              image_counts
          ), f"Size mismatch! prompts: {len(prompts)}, image_counts: {len(image_counts)}"
      image_atts = torch.ones(
          image_features.size()[:-1], dtype=torch.long
      ).to(image_features.device)
  
      total_count = 0
      # calculate each image feat according to the prompt
      for _idx in range(len(prompts)):
          assert isinstance(
              prompts[_idx], list
          ), f"Prompt should be a list, but got {type(prompts[_idx])}"
          input_token = (
              self.get_model()
              .vlm_att_tokenlizer(
                  prompts[_idx],
                  padding="longest",
                  truncation=True,
                  max_length=256,
                  return_tensors="pt",
              )
              .to(image_features.device)
          )
  
          input_ids = input_token.input_ids
          attention_masks = input_token.attention_mask
  
          if image_counts is None:
              img_feat_prompt = image_features[_idx, None].expand(
                  len(prompts[_idx]), -1, -1
              )
              img_att_prompt = image_atts[_idx, None].expand(
                  len(prompts[_idx]), -1
              )
          else:
              # shape: [prompt_num*frame_num, image_shape, feat_dim]
              img_feat_prompt = image_features[
                  total_count : total_count + image_counts[_idx]
              ]
              img_feat_prompt = (
                  img_feat_prompt[None]
                  .expand(len(prompts[_idx]), -1, -1, -1)
                  .flatten(0, 1)
              )
              img_att_prompt = image_atts[
                  total_count : total_count + image_counts[_idx]
              ]
              img_att_prompt = (
                  img_att_prompt[None]
                  .expand(len(prompts[_idx]), -1, -1)
                  .flatten(0, 1)
              )
              input_ids = (
                  input_ids[:, None]
                  .expand(-1, image_counts[_idx], -1)
                  .flatten(0, 1)
              )
              attention_masks = (
                  attention_masks[:, None]
                  .expand(-1, image_counts[_idx], -1)
                  .flatten(0, 1)
              )
              total_count += image_counts[_idx]
  
          if (
              "pretrain" in self.config.bert_type
              and self.get_model().vlm_att_bert_proj is not None
          ):
              bert_feat = self.get_model().vlm_att_bert_proj(
                  img_feat_prompt
              )
          else:
              bert_feat = img_feat_prompt.clone()
  
          # remove cls embedding
          if self.config.mm_vision_select_feature == "patch":
              if img_feat_prompt.shape[1] % 2 == 1:
                  img_feat_prompt = img_feat_prompt[:, 1:]
  
          if "qformer" in self.config.bert_type:
              query_tokens = self.get_model().vlm_att_query.expand(
                  bert_feat.shape[0], -1, -1
              )
              query_atts = torch.cat(
                  [
                      torch.ones(
                          query_tokens.size()[:-1], dtype=torch.long
                      ).to(bert_feat.device),
                      attention_masks,
                  ],
                  dim=1,
              )
  
              if "pretrain" in self.config.bert_type:
                  mm_img_in = self.get_model().vlm_att_ln(bert_feat)
              else:
                  mm_img_in = bert_feat
  
              if long_video:
                  outputs = []
                  block_size = 64
                  for L in range(0, len(input_ids), block_size):
                      R = L + block_size
                      mm_output = self.get_model().vlm_att_encoder.bert(
                          input_ids[L:R],
                          query_embeds=query_tokens[L:R],
                          attention_mask=query_atts[L:R],
                          encoder_hidden_states=mm_img_in[L:R],
                          encoder_attention_mask=img_att_prompt[L:R],
                          return_dict=True,
                      )
                      mm_output = mm_output.last_hidden_state[
                          :, : query_tokens.shape[1]
                      ]
                      outputs.append(mm_output)
                  mm_output = torch.cat(outputs)
                  torch.cuda.empty_cache()
              else:
                  mm_output = self.get_model().vlm_att_encoder.bert(
                      input_ids,
                      query_embeds=query_tokens,
                      attention_mask=query_atts,
                      encoder_hidden_states=mm_img_in,
                      encoder_attention_mask=img_att_prompt,
                      return_dict=True,
                  )
                  mm_output = mm_output.last_hidden_state[
                      :, : query_tokens.shape[1]
                  ]
  
          elif "raw" in self.config.bert_type:
              if (
                  self.config.mm_vision_select_feature == "patch"
                  and bert_feat.shape[1] % 2 == 1
              ):
                  bert_feat = bert_feat[:, 1:]
                  img_att_prompt = img_att_prompt[:, 1:]
  
              mm_output = self.get_model().vlm_att_encoder.bert(
                  input_ids,
                  attention_mask=attention_masks,
                  encoder_hidden_states=self.get_model().vlm_att_bert_proj(
                      bert_feat
                  ),
                  encoder_attention_mask=img_att_prompt,
                  return_dict=True,
              )
              mm_output = mm_output.last_hidden_state
          else:
              raise ValueError(
                  f"Unexpected bert type: {self.config.bert_type}"
              )
  
          text_q = self.get_model().vlm_att_projector(mm_output)
          final_token = self.token_generation(
              text_q, img_feat_prompt, long_video=long_video
          )
  
          if image_counts is not None:
              # shape: [prompt_num, frame_num*image_shape, feat_dim]
              final_token = final_token.reshape(
                  len(prompts[_idx]),
                  image_counts[_idx],
                  *final_token.shape[-2:],
              )
              final_token = final_token.flatten(1, 2)
          img_feat_lst.append(final_token)
  
      return img_feat_lst
  
imports: from abc import ABC, abstractmethod
  import os
  import json
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from transformers import BertTokenizer
  from transformers.models.bert.modeling_bert import BertLMHeadModel
  from .qformer import BertConfig
  from .qformer import BertLMHeadModel
  from .multimodal_encoder.builder import build_vision_tower
  from .multimodal_projector.builder import build_vision_projector
  from llamavid.constants import IGNORE_INDEX, IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_PATCH_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
label_desc: Use image node_id 4 for calling the LLaMAVIDMetaForCausalLM obj's underlying member method code with example usage: obj.vlm_attention(image_features, prompts, image_counts, long_video) and returns: img_feat_lst