code: def pre_process(self, batch_data_samples, device):
      extra = {}
      if self.task != "caption":
          # have text
          all_text_prompts = []
          num_thing_class = 0
          for data_samples in batch_data_samples:
              if isinstance(data_samples.text, str):
                  text = data_samples.text.split(".")
              elif isinstance(data_samples.text, Sequence):
                  text = data_samples.text
              else:
                  raise TypeError(
                      "Type pf data_sample.text must be sequence or str"
                  )
              text = list(filter(lambda x: len(x) > 0, text))
              all_text_prompts.append(text)
              num_thing_class = len(text)
              # for panoptic
              if "stuff_text" in data_samples:
                  if isinstance(data_samples.stuff_text, str):
                      text = data_samples.stuff_text.split(".")
                  elif isinstance(data_samples.stuff_text, Sequence):
                      text = data_samples.stuff_text
                  else:
                      raise TypeError(
                          "Type pf data_sample.stuff_text "
                          "must be sequence or str"
                      )
                  text = list(filter(lambda x: len(x) > 0, text))
                  all_text_prompts[-1].extend(text)
  
          # TODO: support batch
          all_text_prompts = all_text_prompts[0]
  
          if (
              all_text_prompts != self._all_text_prompts
              or self._force_not_use_cache
          ):
              # avoid redundant computation
              self._all_text_prompts = all_text_prompts
              if self.task in ["semseg", "instance", "panoptic"]:
                  self.predictor.lang_encoder.get_mean_embeds(
                      all_text_prompts + ["background"]
                  )
              elif self.task == "ref-seg":
                  token_info = (
                      self.predictor.lang_encoder.get_text_embeds(
                          all_text_prompts, norm=False
                      )
                  )
                  token_emb = token_info["token_emb"]
                  tokens = token_info["tokens"]
                  query_emb = token_emb[tokens["attention_mask"].bool()]
                  extra["grounding_tokens"] = query_emb[:, None]
                  extra["class_emb"] = token_info["class_emb"]
              elif self.task == "retrieval":
                  token_info = (
                      self.predictor.lang_encoder.get_text_embeds(
                          all_text_prompts, norm=True
                      )
                  )
                  extra["class_emb"] = token_info["class_emb"]
              self._extra = extra
              return extra, all_text_prompts, num_thing_class
          else:
              return self._extra, all_text_prompts, num_thing_class
      else:
          if not hasattr(self, "start_token"):
              self.start_token = (
                  self.predictor.lang_encoder.get_sot_token(
                      device=device
                  )
              )
          extra["start_token"] = self.start_token
          return extra, None, None
  
file_path: mmdetection/projects/XDecoder/xdecoder/unified_head.py
imports: import copy
  from typing import Sequence
  import torch
  from mmengine.structures import InstanceData, PixelData
  from torch import nn
  from torch.nn import functional
  from mmdet.evaluation.functional import INSTANCE_OFFSET
  from mmdet.registry import MODELS
  from .utils import is_lower_torch_version, retry_if_cuda_oom, sem_seg_postprocess
label_desc: Use image node_id 2 for calling the XDecoderUnifiedhead obj's underlying member method code with example usage: obj.pre_process(batch_data_samples, device) and returns: extra,  None,  None, extra,  all_text_prompts,  num_thing_class, self,  all_text_prompts,  num_thing_class