class_docstr: This Blueprint has a subtasks number option to combine multiple conversations into
  "sub-HITs".
  
  It also has options for the onboarding data answers and the annotation bucket
  definitions.
class_docstr_tok: ["This","Blueprint","has","a","subtasks","number","option","to","combine","multiple","conversations","into","''","sub-HITs","''",".","It","also","has","options","for","the","onboarding","data","answers","and","the","annotation","bucket","definitions","."]
docstr: Override this in a subclass if you want to change how data is processed from
  input file before being sent to the frontend.
docstr_tok: ["Override","this","in","a","subclass","if","you","want","to","change","how","data","is","processed","from","input","file","before","being","sent","to","the","frontend","."]
code: def process_data(self, data_dicts, annotation_indices=None):
      """
      Override this in a subclass if you want to change how data is processed from
      input file before being sent to the frontend.
      """
      output = []
      total_annotation_count = 0
      for conv_idx, d in enumerate(data_dicts):
          if annotation_indices:
              total_annotation_count += len(
                  annotation_indices[conv_idx]
              )
              # We only want to show the conversation up to the last
              # utterance we need annotations on, b/c otherwise may confuse
              # or bias the turkers
              if len(annotation_indices[conv_idx]) > 1:
                  logging.info(
                      f"Splitting {len(annotation_indices[conv_idx])} separate problematic utterance "
                      "annotations in the same conversation into two separate conversations for this task. "
                      "This avoids biasing the turkers with utterances that may come after one of the annotations."
                  )
              for a in annotation_indices[conv_idx]:
                  processed_dialog = self._process_conversation(d, [a])
                  output.append(processed_dialog)
          elif self.annotation_last_only:
              # Annotate only the last utterance
              last_idx = len(d["dialog"]) * 2 - 1
              processed_dialog = self._process_conversation(
                  d, annotation_indices=[last_idx]
              )
              total_annotation_count += 1
              output.append(processed_dialog)
          else:
              # Annotate all the model utterances
              total_annotation_count += len(d["dialog"]) / 2
              processed_dialog = self._process_conversation(
                  d, annotation_indices=None
              )
              output.append(processed_dialog)
  
      print(
          f"process_data: Processed {len(data_dicts)} total conversations into {len(output)} "
          f"conversations in the full data with {total_annotation_count} total turn annotations. "
          f"(Does not account for units per assignment value - i.e. multiple annotations.)"
      )
  
      np.random.shuffle(output)
      return output
  
imports: import json
  import logging
  import math
  import os
  import random
  from dataclasses import dataclass, field
  from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING
  import numpy
  from mephisto.operations.registry import register_mephisto_abstraction
  from mephisto.abstractions.blueprint import SharedTaskState
  from mephisto.abstractions.blueprints.static_react_task.static_react_blueprint import StaticReactBlueprint, StaticReactBlueprintArgs
  from omegaconf import DictConfig
label_desc: Use image node_id 3 for calling the TurnAnnotationsStaticBlueprint obj's underlying member method code with example usage: obj.process_data(data_dicts, annotation_indices) and returns: output