class_docstr: Abstract TorchRankerAgent class; only meant to be extended.
  
  TorchRankerAgents aim to provide convenient functionality for building ranking
  models. This includes:
  
  - Training/evaluating on candidates from a variety of sources.
  - Computing hits@1, hits@5, mean reciprical rank (MRR), and other metrics.
  - Caching representations for fast runtime when deploying models to production.
class_docstr_tok: ["Abstract","TorchRankerAgent","class",";","only","meant","to","be","extended",".","TorchRankerAgents","aim","to","provide","convenient","functionality","for","building","ranking","models",".","This","includes",":","-","Training\/evaluating","on","candidates","from","a","variety","of","sources",".","-","Computing","hits","@","1",",","hits","@","5",",","mean","reciprical","rank","(","MRR",")",",","and","other","metrics",".","-","Caching","representations","for","fast","runtime","when","deploying","models","to","production","."]
code: def __init__(self, opt: Opt, shared=None):
      # Must call _get_init_model() first so that paths are updated if necessary
      # (e.g., a .dict file)
      init_model, is_finetune = self._get_init_model(opt, shared)
      opt["rank_candidates"] = True
      self._set_candidate_variables(opt)
      super().__init__(opt, shared)
  
      states: Dict[str, Any]
      if shared:
          states = {}
      else:
          # Note: we cannot change the type of metrics ahead of time, so you
          # should correctly initialize to floats or ints here
          self.criterion = self.build_criterion()
          self.model = self.build_model()
  
          if self.model is None or self.criterion is None:
              raise AttributeError(
                  "build_model() and build_criterion() need to return the model "
                  "or criterion"
              )
          train_params = trainable_parameters(self.model)
          total_params = total_parameters(self.model)
          logging.info(
              f"Total parameters: {total_params:,d} ({train_params:,d} trainable)"
          )
  
          if self.fp16:
              self.model = self.model.half()
          if init_model:
              logging.info(
                  f"Loading existing model parameters from {init_model}"
              )
              states = self.load(init_model)
          else:
              states = {}
  
          if self.use_cuda:
              if self.model_parallel:
                  ph = PipelineHelper()
                  ph.check_compatibility(self.opt)
                  self.model = ph.make_parallel(self.model)
              else:
                  self.model.cuda()
              if self.data_parallel:
                  self.model = torch.nn.DataParallel(self.model)
              self.criterion.cuda()
  
      self.rank_top_k = opt.get("rank_top_k", -1)
  
      # Set fixed and vocab candidates if applicable
      self.set_fixed_candidates(shared)
      self.set_vocab_candidates(shared)
  
      if shared:
          # We don't use get here because hasattr is used on optimizer later.
          if "optimizer" in shared:
              self.optimizer = shared["optimizer"]
      elif self._should_initialize_optimizer():
          # only build an optimizer if we're training
          optim_params = [
              p for p in self.model.parameters() if p.requires_grad
          ]
          was_reset = self.init_optim(
              optim_params,
              states.get("optimizer"),
              states.get("optimizer_type"),
              is_finetune=is_finetune,
          )
          if was_reset:
              logging.warning(
                  "Optimizer was reset. Also resetting LR scheduler."
              )
          self.build_lr_scheduler(
              states, hard_reset=is_finetune or was_reset
          )
  
      if shared is None and is_distributed():
          device_ids = (
              None if self.model_parallel else [self.opt["gpu"]]
          )
          self.model = torch.nn.parallel.DistributedDataParallel(
              self.model, device_ids=device_ids, broadcast_buffers=False
          )
  
imports: from typing import Optional
  from parlai.core.params import ParlaiParser
  from typing import Dict, Any
  from abc import abstractmethod
  from itertools import islice
  import os
  from tqdm import tqdm
  import random
  import torch
  from parlai.core.opt import Opt
  from parlai.utils.distributed import is_distributed
  from parlai.core.torch_agent import TorchAgent, Output
  from parlai.utils.misc import warn_once
  from parlai.utils.io import PathManager
  from parlai.utils.torch import padded_3d, total_parameters, trainable_parameters, PipelineHelper
  from parlai.utils.fp16 import FP16SafeCrossEntropy
  from parlai.core.metrics import AverageMetric
  import parlai.utils.logging
label_desc: Use image node_id 2 to create a new TorchRankerAgent object from inherited base classes: TorchAgent with example: obj = TorchRankerAgent(opt, shared)