class_docstr: Dialogue State Tracking Model SGD-QA (https://arxiv.org/abs/2105.08049)
  
  The SGD-QA model is a fast multi-pass schema-guided state-tracking model, that is trained on the Google schema-guided state tracking dataset (https://arxiv.org/abs/1909.05855).
  The model takes dialogue as input and outputs the dialogue state, which includes slot-value pairs. 
  The model consists of two components: a neural natural language understanding model (NLU), and a rule-based state tracker.
  The NLU takes in a dialogue turn and different schema (entity) information options and outputs their match score. The state tracker takes the highest rated entities and composes
  the dialogue state across turns.
class_docstr_tok: ["Dialogue","State","Tracking","Model","SGD-QA","(","https",":","\/\/arxiv.org\/abs\/2105.08049",")","The","SGD-QA","model","is","a","fast","multi-pass","schema-guided","state-tracking","model",",","that","is","trained","on","the","Google","schema-guided","state","tracking","dataset","(","https",":","\/\/arxiv.org\/abs\/1909.05855",")",".","The","model","takes","dialogue","as","input","and","outputs","the","dialogue","state",",","which","includes","slot-value","pairs",".","The","model","consists","of","two","components",":","a","neural","natural","language","understanding","model","(","NLU",")",",","and","a","rule-based","state","tracker",".","The","NLU","takes","in","a","dialogue","turn","and","different","schema","(","entity",")","information","options","and","outputs","their","match","score",".","The","state","tracker","takes","the","highest","rated","entities","and","composes","the","dialogue","state","across","turns","."]
docstr: Helper called at every validation/test step to aggregate and postprocess outputs on each GPU
  Args:
      batch: input batch at step
  Returns:
      loss: averaged batch loss
      tensors: collection of aggregated output tensors across all GPU workers
docstr_tok: ["Helper","called","at","every","validation\/test","step","to","aggregate","and","postprocess","outputs","on","each","GPU","Args",":","batch",":","input","batch","at","step","Returns",":","loss",":","averaged","batch","loss","tensors",":","collection","of","aggregated","output","tensors","across","all","GPU","workers"]
code: def eval_step_helper(self, batch: List[torch.Tensor]):
      """
      Helper called at every validation/test step to aggregate and postprocess outputs on each GPU
      Args:
          batch: input batch at step
      Returns:
          loss: averaged batch loss
          tensors: collection of aggregated output tensors across all GPU workers
      """
      (
          example_id_num,
          service_id,
          utterance_ids,
          token_type_ids,
          attention_mask,
          intent_status,
          requested_slot_status,
          categorical_slot_status,
          categorical_slot_value_status,
          noncategorical_slot_status,
          noncategorical_slot_value_start,
          noncategorical_slot_value_end,
          start_char_idx,
          end_char_idx,
          task_mask,
      ) = batch
      (
          logit_intent_status,
          logit_req_slot_status,
          logit_cat_slot_status,
          logit_cat_slot_value_status,
          logit_noncat_slot_status,
          logit_spans,
      ) = self(
          input_ids=utterance_ids,
          token_type_ids=token_type_ids,
          attention_mask=attention_mask,
      )
      loss = self.loss(
          logit_intent_status=logit_intent_status,
          intent_status=intent_status,
          logit_req_slot_status=logit_req_slot_status,
          requested_slot_status=requested_slot_status,
          logit_cat_slot_status=logit_cat_slot_status,
          categorical_slot_status=categorical_slot_status,
          logit_cat_slot_value_status=logit_cat_slot_value_status,
          categorical_slot_value_status=categorical_slot_value_status,
          logit_noncat_slot_status=logit_noncat_slot_status,
          noncategorical_slot_status=noncategorical_slot_status,
          logit_spans=logit_spans,
          noncategorical_slot_value_start=noncategorical_slot_value_start,
          noncategorical_slot_value_end=noncategorical_slot_value_end,
          task_mask=task_mask,
      )
  
      all_example_id_num = []
      all_service_id = []
      all_logit_intent_status = []
      all_logit_req_slot_status = []
      all_logit_cat_slot_status = []
      all_logit_cat_slot_value_status = []
      all_logit_noncat_slot_status = []
      all_logit_spans = []
      all_start_char_idx = []
      all_end_char_idx = []
  
      if self.trainer.num_devices and self.trainer.world_size > 1:
          world_size = self.trainer.world_size
          for ind in range(world_size):
              all_example_id_num.append(
                  torch.empty_like(example_id_num)
              )
              all_service_id.append(torch.empty_like(service_id))
              all_logit_intent_status.append(
                  torch.empty_like(logit_intent_status)
              )
              all_logit_req_slot_status.append(
                  torch.empty_like(logit_req_slot_status)
              )
              all_logit_cat_slot_status.append(
                  torch.empty_like(logit_cat_slot_status)
              )
              all_logit_cat_slot_value_status.append(
                  torch.empty_like(logit_cat_slot_value_status)
              )
              all_logit_noncat_slot_status.append(
                  torch.empty_like(logit_noncat_slot_status)
              )
              all_logit_spans.append(torch.empty_like(logit_spans))
              all_start_char_idx.append(
                  torch.empty_like(start_char_idx)
              )
              all_end_char_idx.append(torch.empty_like(end_char_idx))
  
          torch.distributed.all_gather(
              all_example_id_num, example_id_num
          )
          torch.distributed.all_gather(all_service_id, service_id)
          torch.distributed.all_gather(
              all_logit_intent_status, logit_intent_status
          )
          torch.distributed.all_gather(
              all_logit_req_slot_status, logit_req_slot_status
          )
          torch.distributed.all_gather(
              all_logit_cat_slot_status, logit_cat_slot_status
          )
          torch.distributed.all_gather(
              all_logit_cat_slot_value_status,
              logit_cat_slot_value_status,
          )
          torch.distributed.all_gather(
              all_logit_noncat_slot_status, logit_noncat_slot_status
          )
          torch.distributed.all_gather(all_logit_spans, logit_spans)
          torch.distributed.all_gather(
              all_start_char_idx, start_char_idx
          )
          torch.distributed.all_gather(all_end_char_idx, end_char_idx)
      else:
          all_example_id_num.append(example_id_num)
          all_service_id.append(service_id)
          all_logit_intent_status.append(logit_intent_status)
          all_logit_req_slot_status.append(logit_req_slot_status)
          all_logit_cat_slot_status.append(logit_cat_slot_status)
          all_logit_cat_slot_value_status.append(
              logit_cat_slot_value_status
          )
          all_logit_noncat_slot_status.append(logit_noncat_slot_status)
          all_logit_spans.append(logit_spans)
          all_start_char_idx.append(start_char_idx)
          all_end_char_idx.append(end_char_idx)
  
      # after this: all_x is list of tensors, of length world_size
      example_id_num = torch.cat(all_example_id_num)
      service_id = torch.cat(all_service_id)
      logit_intent_status = torch.cat(all_logit_intent_status)
      logit_req_slot_status = torch.cat(all_logit_req_slot_status)
      logit_cat_slot_status = torch.cat(all_logit_cat_slot_status)
      logit_cat_slot_value_status = torch.cat(
          all_logit_cat_slot_value_status
      )
      logit_noncat_slot_status = torch.cat(all_logit_noncat_slot_status)
      logit_spans = torch.cat(all_logit_spans)
      start_char_idx = torch.cat(all_start_char_idx)
      end_char_idx = torch.cat(all_end_char_idx)
  
      intent_status = torch.nn.Sigmoid()(logit_intent_status)
  
      # Scores are output for each requested slot.
      req_slot_status = torch.nn.Sigmoid()(logit_req_slot_status)
  
      # For categorical slots, the status of each slot and the predicted value are output.
      cat_slot_status_dist = torch.nn.Softmax(dim=-1)(
          logit_cat_slot_status
      )
  
      cat_slot_status = torch.argmax(logit_cat_slot_status, axis=-1)
      cat_slot_status_p = torch.max(cat_slot_status_dist, axis=-1)[0]
      cat_slot_value_status = torch.nn.Sigmoid()(
          logit_cat_slot_value_status
      )
  
      # For non-categorical slots, the status of each slot and the indices for spans are output.
      noncat_slot_status_dist = torch.nn.Softmax(dim=-1)(
          logit_noncat_slot_status
      )
  
      noncat_slot_status = torch.argmax(
          logit_noncat_slot_status, axis=-1
      )
      noncat_slot_status_p = torch.max(
          noncat_slot_status_dist, axis=-1
      )[0]
  
      softmax = torch.nn.Softmax(dim=1)
  
      scores = softmax(logit_spans)
      start_scores, end_scores = torch.unbind(scores, dim=-1)
  
      batch_size, max_num_tokens = end_scores.size()
      # Find the span with the maximum sum of scores for start and end indices.
      total_scores = torch.unsqueeze(
          start_scores, axis=2
      ) + torch.unsqueeze(end_scores, axis=1)
      start_idx = torch.arange(
          max_num_tokens, device=total_scores.get_device()
      ).view(1, -1, 1)
      end_idx = torch.arange(
          max_num_tokens, device=total_scores.get_device()
      ).view(1, 1, -1)
      invalid_index_mask = (start_idx > end_idx).repeat(
          batch_size, 1, 1
      )
      total_scores = torch.where(
          invalid_index_mask,
          torch.zeros(
              total_scores.size(),
              device=total_scores.get_device(),
              dtype=total_scores.dtype,
          ),
          total_scores,
      )
      max_span_index = torch.argmax(
          total_scores.view(-1, max_num_tokens**2), axis=-1
      )
      max_span_p = torch.max(
          total_scores.view(-1, max_num_tokens**2), axis=-1
      )[0]
  
      span_start_index = torch.floor_divide(
          max_span_index, max_num_tokens
      )
      span_end_index = torch.fmod(max_span_index, max_num_tokens)
  
      tensors = {
          "example_id_num": example_id_num,
          "service_id": service_id,
          "intent_status": intent_status,
          "req_slot_status": req_slot_status,
          "cat_slot_status": cat_slot_status,
          "cat_slot_status_p": cat_slot_status_p,
          "cat_slot_value_status": cat_slot_value_status,
          "noncat_slot_status": noncat_slot_status,
          "noncat_slot_status_p": noncat_slot_status_p,
          "noncat_slot_p": max_span_p,
          "noncat_slot_start": span_start_index,
          "noncat_slot_end": span_end_index,
          "noncat_alignment_start": start_char_idx,
          "noncat_alignment_end": end_char_idx,
      }
      return loss, tensors
  
imports: import os
  from typing import List, Optional
  import torch
  from omegaconf import DictConfig
  from pytorch_lightning import Trainer
  from torch.utils.data import DataLoader
  from nemo.collections.nlp.data.dialogue import DialogueSGDBERTDataset, DialogueSGDDataProcessor
  from nemo.collections.nlp.data.dialogue.sgd.evaluate import evaluate, get_in_domain_services
  from nemo.collections.nlp.data.dialogue.sgd.prediction_utils import write_predictions_to_file
  from nemo.collections.nlp.losses import SGDDialogueStateLoss
  from nemo.collections.nlp.models.nlp_model import NLPModel
  from nemo.collections.nlp.modules import SGDDecoder, SGDEncoder
  from nemo.collections.nlp.parts.utils_funcs import tensor2list
  from nemo.core.classes.common import PretrainedModelInfo, typecheck
  from nemo.utils import logging
label_desc: Use image node_id 7 for calling the SGDQAModel obj's underlying member method code with example usage: obj.eval_step_helper(batch) and returns: loss,  tensors