text: import os
  import ujson
  
  from functools import partial
  from colbert.utils.utils import print_message
  from colbert.modeling.tokenization import QueryTokenizer, DocTokenizer, tensorize_triples
  
  from colbert.utils.runs import Run
  
  
  class EagerBatcher():
      def __init__(self, args, rank=0, nranks=1):
          self.rank, self.nranks = rank, nranks
          self.bsize, self.accumsteps = args.bsize, args.accumsteps
  
          self.query_tokenizer = QueryTokenizer(args.query_maxlen)
          self.doc_tokenizer = DocTokenizer(args.doc_maxlen)
          self.tensorize_triples = partial(tensorize_triples, self.query_tokenizer, self.doc_tokenizer)
  
          self.triples_path = args.triples
          self._reset_triples()
  
      def _reset_triples(self):
          self.reader = open(self.triples_path, mode='r', encoding="utf-8")
          self.position = 0
  
      def __iter__(self):
          return self
  
      def __next__(self):
          queries, positives, negatives = [], [], []
  
          for line_idx, line in zip(range(self.bsize * self.nranks), self.reader):
              if (self.position + line_idx) % self.nranks != self.rank:
                  continue
  
              query, pos, neg = line.strip().split('\t')
  
              queries.append(query)
              positives.append(pos)
              negatives.append(neg)
  
          self.position += line_idx + 1
  
          if len(queries) < self.bsize:
              raise StopIteration
  
          return self.collate(queries, positives, negatives)
  
      def collate(self, queries, positives, negatives):
          assert len(queries) == len(positives) == len(negatives) == self.bsize
  
          return self.tensorize_triples(queries, positives, negatives, self.bsize // self.accumsteps)
  
      def skip_to_batch(self, batch_idx, intended_batch_size):
          self._reset_triples()
  
          Run.warn(f'Skipping to batch #{batch_idx} (with intended_batch_size = {intended_batch_size}) for training.')
  
          _ = [self.reader.readline() for _ in range(batch_idx * intended_batch_size)]
  
          return None
  