class_docstr: Speaker Classifier Teacher.
  
  This teacher is used for the RPA classifier training.
  
  This teacher should NOT be used directly.
class_docstr_tok: ["Speaker","Classifier","Teacher",".","This","teacher","is","used","for","the","RPA","classifier","training",".","This","teacher","should","NOT","be","used","directly","."]
docstr: Construct new episodes from old, LIGHT ones.
  
  enumerate over all possible start and label positions
  
  :param ep:
      episode to explode and build into new eps
  
  :return episodes:
      return a list of episodes after enumerating over possible labels.
docstr_tok: ["Construct","new","episodes","from","old",",","LIGHT","ones",".","enumerate","over","all","possible","start","and","label","positions",":","param","ep",":","episode","to","explode","and","build","into","new","eps",":","return","episodes",":","return","a","list","of","episodes","after","enumerating","over","possible","labels","."]
code: def _build_rpa_episodes(self, ep: List[Message]) -> List[Message]:
      """
      Construct new episodes from old, LIGHT ones.
  
      enumerate over all possible start and label positions
  
      :param ep:
          episode to explode and build into new eps
  
      :return episodes:
          return a list of episodes after enumerating over possible labels.
      """
      episodes = []
      context, characters, utterances = self._explode_episode(
          ep, self.exclude_from_context, self.use_speech_prefix
      )
      candidates = (
          self.candidates
          if self.inline_candidate_type == "all"
          else list(characters.values())
      )
  
      # determine initial start and end indices
      num_utts = self.num_utterances
      if num_utts < 0:
          num_utts = len(utterances) - 1
  
      start_idx, end_idx = (0, num_utts - 1)
  
      # Enumerate over all possible start, end positions
      while end_idx < len(utterances) - 1:
          # Step 0: (maybe) annotate the prior utterances of dialogue
          prev_utts = [
              maybe_annotate(
                  *utt[:-1],
                  self.annotate_speaker,
                  self.speaker_separator,
                  self.speaker_annotation_position,
              )
              for utt in utterances[start_idx:end_idx]
          ]
          if self.include_light_context:
              prev_utts = [context] + prev_utts
  
          # Step 1: enumerate over each successive utterance
          for speaker, label, listener in utterances[end_idx:]:
              # Step 2: determine the label control / task type
              if self.classifier_label_type == "character":
                  speaker_label = (
                      speaker
                      if self.speaker_label_type == "speaker"
                      else listener
                  )
                  label_control = (
                      WHO_AM_I
                      if self.speaker_label_type == "speaker"
                      else WHO_ARE_YOU
                  )
              else:
                  speaker_label = (
                      SELF
                      if speaker == characters["_self_name"]
                      else PARTNER
                  )
                  label_control = WHO_IS_THIS
              # Step 3: Determine what label candidates to use
              if (
                  self.num_train_inline_candidates > 0
                  and DatatypeHelper.is_training(self.datatype)
                  and self.inline_candidate_type == "all"
              ):
                  label_cands = [speaker, listener]
                  while (
                      speaker in label_cands and listener in label_cands
                  ):
                      label_cands = random.sample(
                          candidates,
                          self.num_train_inline_candidates - 2,
                      )
                  label_cands += [speaker, listener]
                  random.shuffle(label_cands)
              else:
                  label_cands = candidates
  
              # Step 4: Build the Message
              if self.left_to_right:
                  label_words = label.split(" ")
                  for i in range(1, len(label_words) + 1):
                      if self.delimit_label_control:
                          text = self.delimiter.join(
                              prev_utts
                              + [
                                  label_control,
                                  " ".join(label_words[:i]),
                              ]
                          )
                      else:
                          text = self.delimiter.join(
                              prev_utts[:-1]
                              + [f"{prev_utts[-1]} {label_control}"]
                              + [" ".join(label_words[:i])]
                          )
                      message = Message(
                          {
                              "text": text,
                              "labels": [speaker_label],
                              "label_candidates": label_cands,
                              "episode_done": True,
                          }
                      )
                      episodes.append([message])
              else:
                  if self.delimit_label_control:
                      text = self.delimiter.join(
                          prev_utts + [label_control, label]
                      )
                  else:
                      text = self.delimiter.join(
                          prev_utts[:-1]
                          + [f"{prev_utts[-1]} {label_control}"]
                          + [label]
                      )
                  message = Message(
                      {
                          "text": text,
                          "labels": [speaker_label],
                          "label_candidates": label_cands,
                          "episode_done": True,
                      }
                  )
                  episodes.append([message])
  
          if start_idx == end_idx:
              # edge case where num_utterances == 1
              break
          else:
              start_idx += 1
              end_idx += 1
  
      return episodes
  
imports: from abc import ABC
  from collections import deque
  import re
  from typing import Optional
  from parlai.core.build_data import modelzoo_path
  from parlai.core.message import Message
  from parlai.core.metrics import AverageMetric
  from parlai.core.opt import Opt
  from parlai.core.params import ParlaiParser
  from parlai.tasks.light_dialog.agents import SimpleMultiTeacher
  from parlai.utils.data import DatatypeHelper
  import parlai.utils.logging
  import copy
  import os
  import random
  import torch
  import torch.nn
  import torch.nn.functional
  from typing import List, Dict, Tuple
  from projects.light_whoami.task.utils import DEFAULT_DELIM, CONTEXT_KEYS, extract_characters, WHO_AM_I, WHO_ARE_YOU, SELF, PARTNER, WHO_IS_THIS, maybe_annotate
  import projects.light_whoami.task.mutators
label_desc: Use image node_id 7 for calling the SpeakerClassifierTeacher obj's underlying member method code with example usage: obj._build_rpa_episodes(ep) and returns: episodes