code: def compute_vtm(
      self,
      text_embeds,
      text_atts,
      image_embeds,
      image_atts,
      sim_i2t,
      sim_t2i,
  ):
      device = self.device
  
      # ====== positive pairs =======
      attention_mask = torch.cat([text_atts, image_atts], dim=1)
      embedding_output_pos = torch.cat(
          [text_embeds, image_embeds], dim=1
      )
  
      encoder_outputs_pos = self.text_encoder(
          encoder_embeds=embedding_output_pos,
          attention_mask=attention_mask,
          return_dict=True,
          mode="fusion",
      )
  
      # ====== negative pairs =======
      bs = text_embeds.shape[0]
  
      local_rank = get_rank()
      b_start, b_end = bs * local_rank, bs * (local_rank + 1)
  
      with torch.no_grad():
          weights_v2t = sim_i2t[:, b_start:b_end]
          weights_t2v = sim_t2i[:, b_start:b_end]
  
          # never select self as negative
          weights_v2t.fill_diagonal_(-np.Inf)
          weights_t2v.fill_diagonal_(-np.Inf)
  
          weights_v2t = F.softmax(weights_v2t, dim=1)
          weights_t2v = F.softmax(weights_t2v, dim=1)
  
      # select a negative image for each text
      # FIXME to optimize using indexing operations
      image_embeds_neg = []
      for b in range(bs):
          neg_idx = torch.multinomial(weights_t2v[b], 1).item()
          image_embeds_neg.append(image_embeds[neg_idx])
      image_embeds_neg = torch.stack(image_embeds_neg, dim=0)
  
      # select a negative text for each image
      text_embeds_neg = []
      text_atts_neg = []
      for b in range(bs):
          neg_idx = torch.multinomial(weights_v2t[b], 1).item()
          text_embeds_neg.append(text_embeds[neg_idx])
          text_atts_neg.append(text_atts[neg_idx])
  
      text_embeds_neg = torch.stack(text_embeds_neg, dim=0)
      text_atts_neg = torch.stack(text_atts_neg, dim=0)
  
      text_embeds_all = torch.cat([text_embeds, text_embeds_neg], dim=0)
      text_atts_all = torch.cat([text_atts, text_atts_neg], dim=0)
  
      video_embeds_all = torch.cat(
          [image_embeds_neg, image_embeds], dim=0
      )
      video_atts_all = torch.cat([image_atts, image_atts], dim=0)
  
      attention_mask_all = torch.cat(
          [text_atts_all, video_atts_all], dim=1
      )
      embedding_output_all = torch.cat(
          [text_embeds_all, video_embeds_all], dim=1
      )
  
      # forward negative pairs via cross encoder
      encoder_outputs_neg = self.text_encoder(
          encoder_embeds=embedding_output_all,
          attention_mask=attention_mask_all,
          return_dict=True,
          mode="fusion",
      )
  
      vl_embeddings = torch.cat(
          [
              encoder_outputs_pos.last_hidden_state[:, 0, :],
              encoder_outputs_neg.last_hidden_state[:, 0, :],
          ],
          dim=0,
      )
      vtm_logits = self.itm_head(vl_embeddings)
  
      vtm_labels = torch.cat(
          [
              torch.ones(bs, dtype=torch.long),
              torch.zeros(2 * bs, dtype=torch.long),
          ],
          dim=0,
      ).to(device)
      vtm_loss = F.cross_entropy(vtm_logits, vtm_labels)
  
      return (
          vtm_loss,
          vtm_logits,
          vtm_labels,
          encoder_outputs_pos,
          encoder_outputs_neg,
      )
  
imports: import datetime
  import logging
  import time
  import lavis.common.dist_utils
  import numpy
  import torch
  import torch.distributed
  import torch.nn.functional
  from lavis.common.config import node_to_dict
  from lavis.common.dist_utils import get_rank
  from lavis.common.logger import MetricLogger
  from lavis.common.registry import registry
  from lavis.models.alpro_models import AlproBase
  from lavis.models.alpro_models.alpro_outputs import AlproIntermediateOutput, AlproOutput
  from lavis.models.base_model import all_gather_with_grad
  from lavis.models.med import XBertEncoder
  from lavis.models.timesformer.vit import TimeSformer
  from torch import nn
label_desc: Use image node_id 3 for calling the AlproRetrieval obj's underlying member method code with example usage: obj.compute_vtm(text_embeds, text_atts, image_embeds, image_atts, sim_i2t, sim_t2i) and returns: vtm_loss,  vtm_logits,  vtm_labels,  encoder_outputs_pos,  encoder_outputs_neg