class_docstr: Base world for running TOD model-model chats. Includes the following agents:
  
  * User utt agent
  * API call agent
      * Currently assumed to be same as system utt agent in script code, though used as if separate in this world for clarity
  * API responder agent
  * System utt agent
  * API schema groundinger agent (given to api call + response agent)
  * Goal groundinger agent (given to user)
  
  As is standard for ParlAI, these agents may be models or may be standalone classes that extend the "Agent" class. The models for these *are* expected to have their utterances in a standard format.
  
  We do expect these agents to be passed in with a set order (see above), since some assumptions of regular ParlAI Worlds (ex. task = agent[0], model = agent[1]) are broken here since there is no "task agent" and one agent can be two "roles" (ex. system agent also making API calls)
docstr: Report all metrics of all subagents + of this world in aggregate.
docstr_tok: ["Report","all","metrics","of","all","subagents","+","of","this","world","in","aggregate","."]
code: def report(self):
      """
      Report all metrics of all subagents + of this world in aggregate.
      """
      metrics_separate = []
      for i in range(self.batchsize):
          here_metrics = self.batch_tod_world_metrics[i].report()
          for name, agent in [
              (SPEAKER_TO_NAME[j], self.batch_agents[i][j])
              for j in [
                  USER_UTT_IDX,
                  API_CALL_IDX,
                  API_RESP_IDX,
                  SYSTEM_UTT_IDX,
              ]
          ]:
              name_prefix = name[:-6]  # strip "_agent"
              if hasattr(agent, "report"):
                  m = agent.report()
                  if m is None:
                      continue
                  for k, v in m.items():
                      if not isinstance(v, Metric):
                          v = LegacyMetric(v)
                      here_metrics[f"{name_prefix}_{k}"] = v
          metrics_separate.append(here_metrics)
      metrics = metrics_separate[0]
      for i in range(1, self.batchsize):
          for k, v in metrics_separate[i].items():
              if k not in metrics:
                  metrics[k] = v
              else:
                  metrics[k] = metrics[k] + v
      return metrics
  
imports: from parlai.core.metrics import Metric, LegacyMetric
  from parlai.core.message import Message
  from parlai.core.opt import Opt
  from parlai.core.worlds import World
  from parlai.agents.local_human.local_human import LocalHumanAgent
  from parlai.utils.misc import display_messages
  import parlai.core.tod.tod_core
  import parlai.core.tod.world_metrics
  import sys
  import copy
label_desc: Use image node_id 5 for calling the TodWorld obj's underlying member method code with example usage: obj.report() and returns: metrics