code: def make_batchset(
      data,
      batch_size=0,
      max_length_in=float("inf"),
      max_length_out=float("inf"),
      num_batches=0,
      min_batch_size=1,
      shortest_first=False,
      batch_sort_key="input",
      swap_io=False,
      mt=False,
      count="auto",
      batch_bins=0,
      batch_frames_in=0,
      batch_frames_out=0,
      batch_frames_inout=0,
      iaxis=0,
      oaxis=0,
  ):
      """Make batch set from json dictionary
  
      if utts have "category" value,
  
          >>> data = {'utt1': {'category': 'A', 'input': ...},
          ...         'utt2': {'category': 'B', 'input': ...},
          ...         'utt3': {'category': 'B', 'input': ...},
          ...         'utt4': {'category': 'A', 'input': ...}}
          >>> make_batchset(data, batchsize=2, ...)
          [[('utt1', ...), ('utt4', ...)], [('utt2', ...), ('utt3': ...)]]
  
      Note that if any utts doesn't have "category",
      perform as same as batchfy_by_{count}
  
      :param Dict[str, Dict[str, Any]] data: dictionary loaded from data.json
      :param int batch_size: maximum number of sequences in a minibatch.
      :param int batch_bins: maximum number of bins (frames x dim) in a minibatch.
      :param int batch_frames_in:  maximum number of input frames in a minibatch.
      :param int batch_frames_out: maximum number of output frames in a minibatch.
      :param int batch_frames_out: maximum number of input+output frames in a minibatch.
      :param str count: strategy to count maximum size of batch.
          For choices, see espnet.asr.batchfy.BATCH_COUNT_CHOICES
  
      :param int max_length_in: maximum length of input to decide adaptive batch size
      :param int max_length_out: maximum length of output to decide adaptive batch size
      :param int num_batches: # number of batches to use (for debug)
      :param int min_batch_size: minimum batch size (for multi-gpu)
      :param bool shortest_first: Sort from batch with shortest samples
          to longest if true, otherwise reverse
      :param str batch_sort_key: how to sort data before creating minibatches
          ["input", "output", "shuffle"]
      :param bool swap_io: if True, use "input" as output and "output"
          as input in `data` dict
      :param bool mt: if True, use 0-axis of "output" as output and 1-axis of "output"
          as input in `data` dict
      :param int iaxis: dimension to access input
          (for ASR, TTS iaxis=0, for MT iaxis="1".)
      :param int oaxis: dimension to access output (for ASR, TTS, MT oaxis=0,
          reserved for future research, -1 means all axis.)
      :return: List[List[Tuple[str, dict]]] list of batches
      """
  
      # check args
      if count not in BATCH_COUNT_CHOICES:
          raise ValueError(
              f"arg 'count' ({count}) should be one of {BATCH_COUNT_CHOICES}"
          )
      if batch_sort_key not in BATCH_SORT_KEY_CHOICES:
          raise ValueError(
              f"arg 'batch_sort_key' ({batch_sort_key}) should be "
              f"one of {BATCH_SORT_KEY_CHOICES}"
          )
  
      # TODO(karita): remove this by creating converter from ASR to TTS json format
      batch_sort_axis = 0
      if swap_io:
          # for TTS
          ikey = "output"
          okey = "input"
          if batch_sort_key == "input":
              batch_sort_key = "output"
          elif batch_sort_key == "output":
              batch_sort_key = "input"
      elif mt:
          # for MT
          ikey = "output"
          okey = "output"
          batch_sort_key = "output"
          batch_sort_axis = 1
          assert iaxis == 1
          assert oaxis == 0
          # NOTE: input is json['output'][1] and output is json['output'][0]
      else:
          ikey = "input"
          okey = "output"
  
      if count == "auto":
          if batch_size != 0:
              count = "seq"
          elif batch_bins != 0:
              count = "bin"
          elif (
              batch_frames_in != 0
              or batch_frames_out != 0
              or batch_frames_inout != 0
          ):
              count = "frame"
          else:
              raise ValueError(
                  f"cannot detect `count` manually set one of {BATCH_COUNT_CHOICES}"
              )
          logging.info(f"count is auto detected as {count}")
  
      if count != "seq" and batch_sort_key == "shuffle":
          raise ValueError(
              "batch_sort_key=shuffle is only available if batch_count=seq"
          )
  
      category2data = {}  # Dict[str, dict]
      for k, v in data.items():
          category2data.setdefault(v.get("category"), {})[k] = v
  
      batches_list = []  # List[List[List[Tuple[str, dict]]]]
      for d in category2data.values():
          if batch_sort_key == "shuffle":
              batches = batchfy_shuffle(
                  d,
                  batch_size,
                  min_batch_size,
                  num_batches,
                  shortest_first,
              )
              batches_list.append(batches)
              continue
  
          # sort it by input lengths (long to short)
          sorted_data = sorted(
              d.items(),
              key=lambda data: int(
                  data[1][batch_sort_key][batch_sort_axis]["shape"][0]
              ),
              reverse=not shortest_first,
          )
          logging.info("# utts: " + str(len(sorted_data)))
          if count == "seq":
              batches = batchfy_by_seq(
                  sorted_data,
                  batch_size=batch_size,
                  max_length_in=max_length_in,
                  max_length_out=max_length_out,
                  min_batch_size=min_batch_size,
                  shortest_first=shortest_first,
                  ikey=ikey,
                  iaxis=iaxis,
                  okey=okey,
                  oaxis=oaxis,
              )
          if count == "bin":
              batches = batchfy_by_bin(
                  sorted_data,
                  batch_bins=batch_bins,
                  min_batch_size=min_batch_size,
                  shortest_first=shortest_first,
                  ikey=ikey,
                  okey=okey,
              )
          if count == "frame":
              batches = batchfy_by_frame(
                  sorted_data,
                  max_frames_in=batch_frames_in,
                  max_frames_out=batch_frames_out,
                  max_frames_inout=batch_frames_inout,
                  min_batch_size=min_batch_size,
                  shortest_first=shortest_first,
                  ikey=ikey,
                  okey=okey,
              )
          batches_list.append(batches)
  
      if len(batches_list) == 1:
          batches = batches_list[0]
      else:
          # Concat list. This way is faster than "sum(batch_list, [])"
          batches = list(itertools.chain(*batches_list))
  
      # for debugging
      if num_batches > 0:
          batches = batches[:num_batches]
      logging.info("# minibatches: " + str(len(batches)))
  
      # batch: List[List[Tuple[str, dict]]]
      return batches
  
imports: import itertools
  import logging
  import numpy
label_desc: Use image node_id 5 for calling a global function with example usage: make_batchset(data, batch_size, max_length_in, max_length_out, num_batches, min_batch_size, shortest_first, batch_sort_key, swap_io, mt, count, batch_bins, batch_frames_in, batch_frames_out, batch_frames_inout, iaxis, oaxis) and returns: batches