class_docstr: Implementation of T-Few (https://arxiv.org/pdf/2205.05638.pdf).
  Refer to https://github.com/r-three/t-few
class_docstr_tok: ["Implementation","of","T-Few","(","https",":","\/\/arxiv.org\/pdf\/2205.05638.pdf",")",".","Refer","to","https",":","\/\/github.com\/r-three\/t-few"]
docstr: Parameters
  ----------
  text_token_ids : torch.Tensor
      Indices of input sequence tokens in the vocabulary.
  text_valid_length : torch.Tensor
      Valid length of the input text sequence.
  choices_ids : torch.Tensor, optional
      The choices ids for multiple-choices tasks.
  text_column_names : list of str, optional
      Names of the text columns.
  text_column_indices : list of torch.Tensor, optional
      Start and stop indices of the text columns.
  
  Returns
  -------
      A dictionary with logits and features.
docstr_tok: ["Parameters","--","--","--","--","--","text_token_ids",":","torch.Tensor","Indices","of","input","sequence","tokens","in","the","vocabulary",".","text_valid_length",":","torch.Tensor","Valid","length","of","the","input","text","sequence",".","choices_ids",":","torch.Tensor",",","optional","The","choices","ids","for","multiple-choices","tasks",".","text_column_names",":","list","of","str",",","optional","Names","of","the","text","columns",".","text_column_indices",":","list","of","torch.Tensor",",","optional","Start","and","stop","indices","of","the","text","columns",".","Returns","--","--","--","-","A","dictionary","with","logits","and","features","."]
code: def forward(
      self,
      text_token_ids: torch.Tensor,
      text_valid_length: torch.Tensor,
      choices_ids: Optional[torch.Tensor] = None,
      text_column_names: Optional[List[str]] = None,
      text_column_indices: Optional[List[torch.Tensor]] = None,
  ):
      """
      Parameters
      ----------
      text_token_ids : torch.Tensor
          Indices of input sequence tokens in the vocabulary.
      text_valid_length : torch.Tensor
          Valid length of the input text sequence.
      choices_ids : torch.Tensor, optional
          The choices ids for multiple-choices tasks.
      text_column_names : list of str, optional
          Names of the text columns.
      text_column_indices : list of torch.Tensor, optional
          Start and stop indices of the text columns.
  
      Returns
      -------
          A dictionary with logits and features.
      """
      # TODO: Bad style, check for choices in multimodal.data. Split TemplateEngine into TextTemplateEngine and LabelTemplateEngine.
  
      if not choices_ids.numel():
          warn_once(
              logger,
              msg="No target choices found in batch. Ensure that 'data.templates_turn_on=True' and that a valid preset or custom templates are provided.",
          )
          warn_once(
              logger,
              msg="Fallback to numerical representation of classes...",
          )
          choices_ids = (
              self.tokenizer(
                  [str(i) for i in range(self.num_classes)],
                  return_tensors="pt",
                  padding=True,
              )["input_ids"]
              .repeat(text_token_ids.size(0), 1, 1)
              .to(text_token_ids)
          )
  
      assert (
          choices_ids.size(1) == self.num_classes
      ), f"Number of target choices is different from number of classes, but they must be the same. Please check template."
  
      bs = text_token_ids.size(0)
      # TODO(?) Currently does not support mixed-task batching, but can be added by adjusting the label_templates dict.
  
      bs, num_choices = choices_ids.size()[:2]
      flat_choices_ids = choices_ids.flatten(0, 1)
  
      text_masks = (
          text_token_ids != self.tokenizer.pad_token_id
      ).float()
  
      inputs_embeds = self.model.encoder.embed_tokens(text_token_ids)
  
      if self.gradient_checkpointing:
          inputs_embeds = self.dummy_layer(inputs_embeds)
  
      # Forward input through the encoder
      encoder_hidden_states_or = self.model.encoder(
          inputs_embeds=inputs_embeds, attention_mask=text_masks
      )[0]
      encoder_hidden_states = (
          encoder_hidden_states_or.unsqueeze(dim=1)
          .repeat(1, num_choices, 1, 1)
          .flatten(0, 1)
      )
  
      attention_mask = (
          text_masks.unsqueeze(dim=1)
          .repeat(1, num_choices, 1)
          .flatten(0, 1)
      )
      decoder_input_ids = torch.cat(
          [
              torch.zeros_like(flat_choices_ids[:, :1]),
              flat_choices_ids[:, :-1],
          ],
          dim=1,
      )
      decoder_attention_mask = (
          decoder_input_ids == decoder_input_ids
      ).float()
      # Forward encoder output and target template as input for decoder
      model_output = self.model(
          attention_mask=attention_mask,
          encoder_outputs=[encoder_hidden_states],
          decoder_input_ids=decoder_input_ids,
          decoder_attention_mask=decoder_attention_mask,
      )
  
      model_output = model_output.logits
  
      target_template_logits = model_output  # Decoder Logits over the vocabulary for target template sequence
  
      lm_target = (
          flat_choices_ids
          - 100
          * (flat_choices_ids == self.tokenizer.pad_token_id).long()
      )
      # Calculate entropy of target templates' logits to target template, i.e. how close the target template is to what
      # the model would predict, going from sentence start token (target_template_logits) to sentence end token (
      # lm_target)
      choices_scores = (
          F.cross_entropy(
              target_template_logits.flatten(0, 1),
              lm_target.flatten(0, 1),
              reduction="none",
          )
          .view(bs, num_choices, -1)
          .sum(dim=-1)
      )
      # Add length normalization to adjust for target templates of different length
      if self.length_norm > 0:
          choices_scores = choices_scores / torch.pow(
              (choices_ids != self.tokenizer.pad_token_id).sum(dim=-1),
              self.length_norm,
          )
      # Use the entropy score as the class "logit" scoring of T-Few.
      choices_scores = -choices_scores
  
      #  FIXME(?) Not sure having column features with the decoder vocabulary logits in T-Few makes sense
      batch = {
          self.text_token_ids_key: text_token_ids,
          self.text_valid_length_key: text_valid_length,
          self.choices_key: choices_ids,
      }
      if text_column_names:
          assert len(text_column_names) == len(
              text_column_indices
          ), "invalid text column inputs"
          for idx, name in enumerate(text_column_names):
              batch[name] = text_column_indices[idx]
      column_features, column_feature_masks = get_column_features(
          batch=batch,
          column_name_prefix=self.text_column_prefix,
          features=model_output,
          valid_lengths=text_valid_length,
      )
  
      # needed to ensure compatibility to encoder-only pipelines
      features = encoder_hidden_states_or[:, 0, :]
      logits = choices_scores
  
      target_template_logits = target_template_logits.view(
          bs, num_choices, *target_template_logits.size()[1:]
      )
      lm_target = lm_target.view(bs, num_choices, *lm_target.size()[1:])
  
      if column_features == {} or column_feature_masks == {}:
          return features, logits, target_template_logits, lm_target
      else:
          return (
              features,
              logits,
              target_template_logits,
              lm_target,
              column_features,
              column_feature_masks,
          )
  
imports: import collections
  import logging
  import os
  import random
  from functools import lru_cache
  from typing import Dict, List, Optional, Tuple
  import torch
  import torch.nn.functional
  from torch import nn
  from transformers import AutoConfig, AutoModelForSeq2SeqLM
  from transformers import logging
  from ..constants import AUTOMM, CHOICES_IDS, COLUMN, COLUMN_FEATURES, FEATURES, LABEL, LM_TARGET, LOGITS, MASKS, TEMPLATE_LOGITS, TEXT_SEGMENT_IDS, TEXT_TOKEN_IDS, TEXT_VALID_LENGTH
  from .utils import DummyLayer, assign_layer_ids, get_column_features, get_pretrained_tokenizer
label_desc: Use image node_id 10 for calling the TFewModel obj's underlying member method code with example usage: obj.forward(text_token_ids, text_valid_length, choices_ids, text_column_names, text_column_indices) and returns: features,  logits,  target_template_logits,  lm_target, features,  logits,  target_template_logits,  lm_target,  column_features,  column_feature_masks