class_docstr: Model from "Engaging Image Chat: Modeling Personality in Grounded Dialogue".
  
  See paper for more details: (https://arxiv.org/abs/1811.00945)
  
  An extension of the model from https://arxiv.org/abs/1810.10665; given
  an image, personality, and dialogue history, predicts the next utterance
  in a dialogue.
class_docstr_tok: ["Model","from","``","Engaging","Image","Chat",":","Modeling","Personality","in","Grounded","Dialogue","''",".","See","paper","for","more","details",":","(","https",":","\/\/arxiv.org\/abs\/1811.00945",")","An","extension","of","the","model","from","https",":","\/\/arxiv.org\/abs\/1810.10665",";","given","an","image",",","personality",",","and","dialogue","history",",","predicts","the","next","utterance","in","a","dialogue","."]
docstr: Act on a batch of observations.
  
  :param observations:
      list of observations
  
  :return:
      A list of acts, one for each observation
docstr_tok: ["Act","on","a","batch","of","observations",".",":","param","observations",":","list","of","observations",":","return",":","A","list","of","acts",",","one","for","each","observation"]
code: def batch_act(self, observations):
      """
      Act on a batch of observations.
  
      :param observations:
          list of observations
  
      :return:
          A list of acts, one for each observation
      """
      is_training = any(["labels" in obs for obs in observations])
      valid_obs, valid_indexes = self.filter_valid_obs(
          observations, is_training
      )
      image_feats = self.extract_image_feats(valid_obs)
      (
          personalities,
          dialogue_histories,
          dialogue_round,
      ) = self.extract_texts(valid_obs)
      chosen_responses = None
      med_rank = None
      if is_training:
          self.optimizer.zero_grad()
          loss, num_correct = self.train_step(
              valid_obs, image_feats, personalities, dialogue_histories
          )
          loss.backward()
          self.optimizer.step()
      else:
          (
              loss,
              num_correct,
              med_rank,
              chosen_responses,
          ) = self.eval_step(
              valid_obs, image_feats, personalities, dialogue_histories
          )
      self.update_metrics(
          loss, num_correct, len(valid_obs), dialogue_round, med_rank
      )
      result = [
          {"text": "No Response During Traiing", "id": self.getID()}
          for _ in range(len(observations))
      ]
      if chosen_responses is not None:
          for i, index_obs in enumerate(valid_indexes):
              result[index_obs]["text"] = chosen_responses[i][0]
              result[index_obs]["text_candidates"] = chosen_responses[i]
      return result
  
imports: from typing import Optional
  from parlai.core.params import ParlaiParser
  from parlai.core.opt import Opt
  from parlai.utils.misc import round_sigfigs
  from parlai.core.message import Message
  from .modules import TransresnetMultimodalModel
  from projects.personality_captions.transresnet.transresnet import TransresnetAgent
  from parlai.utils.io import PathManager
  import parlai.utils.torch
  import torch
  from torch import optim
  import random
  import numpy
  import tqdm
  from collections import deque
label_desc: Use image node_id 9 for calling the TransresnetMultimodalAgent obj's underlying member method code with example usage: obj.batch_act(observations) and returns: result