class_docstr: Base Teacher that extract metadata for dialogues.
class_docstr_tok: ["Base","Teacher","that","extract","metadata","for","dialogues","."]
code: def _get_perfect_episode(self, chat, is_training):
      raw_dialog = chat["dialog"]
      assert len(raw_dialog) % 2 == 0, "odd number of utterances"
      perfect_dialog = []
      # store all bot/human acts before the bot generate the next perfect response
      bot_acts = []
      human_acts = []
      perfect_dialog_context = []
      raw_feedback_examples = []
      for i, utt in enumerate(raw_dialog):
          # whether it's human message or bot message
          if utt.get("id") in ["YOU", "Speaker 1"]:
              human_acts.append(utt)
          else:
              if (
                  i == len(raw_dialog) - 1
                  and utt.get(
                      "improve_bucket", FeedbackType.PERFECT.value
                  )
                  != FeedbackType.PERFECT.value
              ):
                  utt["improve_bucket"] = FeedbackType.PERFECT.value
              bot_acts.append(utt)
              if (
                  utt.get("improve_bucket", FeedbackType.PERFECT.value)
                  == FeedbackType.PERFECT.value
                  or i == len(raw_dialog) - 1
              ):
                  (
                      utts_with_feedbacks,
                      feedback_examples,
                  ) = self._add_feedback_to_perfect_utt(
                      bot_acts, human_acts, perfect_dialog_context
                  )
                  perfect_dialog.extend(utts_with_feedbacks)
                  perfect_dialog_context.extend(
                      [
                          normalize_reply(t["text"])
                          for t in utts_with_feedbacks
                      ]
                  )
                  raw_feedback_examples.extend(feedback_examples)
                  bot_acts = []
                  human_acts = []
  
      perfect_episode = []
      chat_metadata = {
          "specific_task": chat["chat_task_name"],
          "task_requirement": chat["chat_task_requirement"],
          "topic": chat["topic"],
          "generic_topic": chat["generic_topic"],
          "domain": chat["domain"],
          "task_uid": chat["chat_task_uid"],
      }
      for i in range(0, len(perfect_dialog) - 1, 2):
          action = {
              "id": self.id,
              "text": normalize_reply(perfect_dialog[i]["text"]),
              "labels": [
                  normalize_reply(perfect_dialog[i + 1]["text"])
              ],
          }
          for k, v in perfect_dialog[i + 1].items():
              if k not in ["text", "id", "labels"]:
                  action[k] = v
          action.update(chat_metadata)
          perfect_episode.append(action)
  
      feedback_examples_with_metadata = []
      for act in raw_feedback_examples:
          feedback_examples_with_metadata.append(
              {
                  **act,
                  **chat_metadata,
              }
          )
  
      return perfect_episode, feedback_examples_with_metadata
  
imports: import os
  import copy
  import json
  import random
  from typing import Optional
  from parlai.utils.misc import warn_once
  from parlai.utils.data import DatatypeHelper
  from parlai.core.opt import Opt
  from parlai.core.teachers import DialogTeacher
  from parlai.core.params import ParlaiParser
  from parlai.core.message import Message
  from parlai.utils.io import PathManager
  from parlai.tasks.wizard_of_internet import constants
  from .mutators import normalize_reply, get_knowledge_appended_context, get_knowledge_sentence_with_special_tokens_only
  from .build import build
  from .constants import FeedbackType, TITLE_PASSAGE_DELIMITER, OK_LABEL, NOT_OK_LABEL
label_desc: Use image node_id 6 for calling the FitsBaseTeacher obj's underlying member method code with example usage: obj._get_perfect_episode(chat, is_training) and returns: perfect_episode,  feedback_examples_with_metadata