class_docstr: Data source for DPR (https://github.com/facebookresearch/DPR).
  
  Expects multiline json for lazy loading and improved memory usage.
  The original DPR files can be converted to multiline json using `jq -c .[]`
class_docstr_tok: ["Data","source","for","DPR","(","https",":","\/\/github.com\/facebookresearch\/DPR",")",".","Expects","multiline","json","for","lazy","loading","and","improved","memory","usage",".","The","original","DPR","files","can","be","converted","to","multiline","json","using","`","jq","-c",".","[","]","`"]
code: def process_file(self, fname, is_train):
      if not fname:
          print("File path is either empty or None. Not unflattening.")
          return
      if not PathManager.exists(fname):
          print(f"{fname} does not exist. Not unflattening.")
          return
  
      for row in self.read_file(fname):
          question = row["question"]
          positive_ctx = combine_title_text_id(
              row["positive_ctxs"][0], self.use_title
          )
  
          negative_ctxs = [
              combine_title_text_id(ctx, self.use_title)
              for ctx in row["negative_ctxs"]
          ]
  
          if not negative_ctxs and row.get("distant_negatives"):
              # use distant_negatives in case we don't have hard negatives
              # it's better to have at least one negative for training
              negative_ctxs = [
                  combine_title_text_id(ctx, self.use_title)
                  for ctx in row["distant_negatives"]
              ]
  
          if is_train:
              random.shuffle(negative_ctxs)
              if isinstance(question, list):
                  # We can have a list of questions in the training data.
                  # This is to account for paraphrases. We randomly sample a single paraphrases
                  # in every epoch. Thus, with enough epochs all questions should be tried.
                  question = question[
                      random.randint(0, len(question) - 1)
                  ]
          else:
              # for non training runs, always take the num_negative_ctxs without shuffling
              # this makes the evaluation and test sets deterministic
              negative_ctxs = negative_ctxs[: self.num_negative_ctxs]
  
          num_negative_ctx = min(
              self.num_negative_ctxs, len(negative_ctxs)
          )
          yield {
              "question": question,
              "positive_ctx": positive_ctx,
              "negative_ctxs": negative_ctxs,
              "label": "1",  # Make LabelTensorizer.initialize() happy.
              "num_negative_ctx": num_negative_ctx,
          }
  
file_path: pytext/pytext/data/sources/dense_retrieval.py
imports: import json
  import random
  from typing import List, Optional
  from pytext.data.sources.data_source import DataSource, generator_property
  from pytext.utils.file_io import PathManager
label_desc: Use image node_id 7 for calling the DenseRetrievalDataSource obj's underlying member method code with example usage: obj.process_file(fname, is_train) without return types