code: def grouper(iterable, n, worker_id=0, total_workers=1):
      """
      Split an iterable into a list of n-sized chunks. Each element in the chunk is a tuple of (index_num, element).
  
      Example:
  
      >>> list(grouper('ABCDEFG', 3))
      [[(0, 'A'), (1, 'B'), (2, 'C')], [(3, 'D'), (4, 'E'), (5, 'F')], [(6, 'G')]]
  
  
  
      Use with the StreamingDataSilo
  
      When StreamingDataSilo is used with multiple PyTorch DataLoader workers, the generator
      yielding dicts(that gets converted to datasets) is replicated across the workers.
  
      To avoid duplicates, we split the dicts across workers by creating a new generator for
      each worker using this method.
  
      Input --> [dictA, dictB, dictC, dictD, dictE, ...] with total worker=3 and n=2
  
      Output for worker 1: [(dictA, dictB), (dictG, dictH), ...]
      Output for worker 2: [(dictC, dictD), (dictI, dictJ), ...]
      Output for worker 3: [(dictE, dictF), (dictK, dictL), ...]
  
      This method also adds an index number to every dict yielded.
  
      :param iterable: a generator object that yields dicts
      :type iterable: generator
      :param n: the dicts are grouped in n-sized chunks that gets converted to datasets
      :type n: int
      :param worker_id: the worker_id for the PyTorch DataLoader
      :type worker_id: int
      :param total_workers: total number of workers for the PyTorch DataLoader
      :type total_workers: int
      """
  
      # TODO make me comprehensible :)
      def get_iter_start_pos(gen):
          start_pos = worker_id * n
          for i in gen:
              if start_pos:
                  start_pos -= 1
                  continue
              yield i
  
      def filter_elements_per_worker(gen):
          x = n
          y = (total_workers - 1) * n
          for i in gen:
              if x:
                  yield i
                  x -= 1
              else:
                  if y != 1:
                      y -= 1
                      continue
                  else:
                      x = n
                      y = (total_workers - 1) * n
  
      iterable = iter(enumerate(iterable))
      iterable = get_iter_start_pos(iterable)
      if total_workers > 1:
          iterable = filter_elements_per_worker(iterable)
  
      return iter(lambda: list(islice(iterable, n)), [])
  
imports: import hashlib
  import json
  import logging
  import os
  import random
  import tarfile
  import tempfile
  import string
  import uuid
  from contextlib import ExitStack
  from itertools import islice
  from pathlib import Path
  import pandas
  from requests import get
  from tqdm import tqdm
  from typing import List
  from farm.file_utils import http_get
  from farm.modeling.tokenization import tokenize_with_metadata
label_desc: Use image node_id 21 for calling a global function with example usage: grouper(iterable, n, worker_id, total_workers) and returns: iter