def read(
            self,
            data_path: str,
            rel2id_path: str,
            rel_info_path: str,
            negative_label: str = "Na",
            train_valid_test_proportion: int = None,
            valid_test_data_size: int = None,
            generate_additional_neg_samples: bool = False,
            num_neg_samples: int = None
    ) -> Dict[str, List[Tuple]]:
        """
        This class processes the DocRED relation extraction dataset (https://arxiv.org/abs/1906.06127v3).
        Args:
            data_path: a path to a folder with dataset files.
            rel2id_path: a path to a file where information about relation to relation id corresponding is stored.
            rel_info_path: a path to a file where information about relations and their real names is stored
            negative_label: a label which will be used as a negative one (by default in DocRED: "Na")
            train_valid_test_proportion: a proportion in which the data will be splitted into train, valid and test sets
            valid_test_data_size: absolute amount of dev & test sets
            generate_additional_neg_samples: boolean; whether to generate additional negative samples or not.
            num_neg_samples: a number of additional negative samples that will be generated for each positive sample.
        Returns:
            DocRED output dictionary in the following format:
            {"data_type":
                List[
                    Tuple(
                        List[
                            List[all tokens of the document],
                            List[
                                List[Tuple(start pos of mention 1 of ent 1, end pos of mention 1 of ent 1), ...],
                                List[Tuple(start position of entity 2, end position of entity 2), ...],
                                List[str(NER tag of entity 1), str(NER tag of entity 2)]
                            ],
                        List(int(one-hot encoded relation label))
                    )
                ]
            }
        """

        with open(str(expand_path(rel2id_path))) as file:
            self.rel2id = json.load(file)
        self.id2rel = {value: key for key, value in self.rel2id.items()}

        with open(str(expand_path(rel_info_path))) as file:
            self.relid2rel = json.load(file)
        self.rel2relid = {value: key for key, value in self.relid2rel.items()}

        self.negative_label = negative_label
        self.if_add_neg_samples = generate_additional_neg_samples
        self.num_neg_samples = num_neg_samples

        if self.if_add_neg_samples and not self.num_neg_samples:
            raise ValueError("Please provide a number of negative samples to be generated!")

        if train_valid_test_proportion and valid_test_data_size:
            raise ValueError(
                f"The train, valid and test splitting should be done either basing on their proportional values to each"
                f"other (train_valid_test_proportion parameter), or on the absolute size of valid and test data "
                f"(valid_test_data_size parameter). They can't be used simultaneously."
            )

        self.train_valid_test_proportion = train_valid_test_proportion
        self.valid_test_data_size = valid_test_data_size

        data_path = Path(data_path).resolve()

        with open(os.path.join(data_path, "train_annotated.json")) as file_ann:
            train_data = json.load(file_ann)

        with open(os.path.join(data_path, "dev.json")) as file:
            valid_data = json.load(file)

        # if you want to use test data from the original docred without labels (e.g. as negatives...),
        # uncomment lines below
        # with open(os.path.join(data_path, "test.json")) as file:
        #     test_data = json.load(file)
        #     test_processed = self.process_docred_file(test_data, neg_samples=None)

        # merge valid and train data and split them again into train, valid & test
        if self.train_valid_test_proportion:
            train_data, test_data, valid_data = self.split_by_relative(list(train_data + valid_data))
        elif self.valid_test_data_size:
            train_data, test_data, valid_data = self.split_by_absolute(list(train_data + valid_data))

        else:
            raise ValueError(
                f"The train, valid and test splitting should be done either basing on their proportional values to each"
                f"other (train_valid_test_proportion parameter), or on the absolute size of valid and test data "
                f"(valid_test_data_size parameter). One of them should be set to the not-None value."
            )

        logger.info("Train data processing...")
        train_data, train_stat = self.process_docred_file(train_data, neg_samples="twice")

        logger.info("Valid data processing...")
        valid_data, valid_stat = self.process_docred_file(valid_data, neg_samples="equal")

        logger.info("Test data processing...")
        test_data, test_stat = self.process_docred_file(test_data, neg_samples="equal")

        self.print_statistics(train_stat, valid_stat, test_stat)

        data = {"train": train_data, "valid": valid_data, "test": test_data}

        return data

        This class processes the DocRED relation extraction dataset (https://arxiv.org/abs/1906.06127v3).
        Args:
            data_path: a path to a folder with dataset files.
            rel2id_path: a path to a file where information about relation to relation id corresponding is stored.
            rel_info_path: a path to a file where information about relations and their real names is stored
            negative_label: a label which will be used as a negative one (by default in DocRED: "Na")
            train_valid_test_proportion: a proportion in which the data will be splitted into train, valid and test sets
            valid_test_data_size: absolute amount of dev & test sets
            generate_additional_neg_samples: boolean; whether to generate additional negative samples or not.
            num_neg_samples: a number of additional negative samples that will be generated for each positive sample.
        Returns:
            DocRED output dictionary in the following format:
            {"data_type":
                List[
                    Tuple(
                        List[
                            List[all tokens of the document],
                            List[
                                List[Tuple(start pos of mention 1 of ent 1, end pos of mention 1 of ent 1), ...],
                                List[Tuple(start position of entity 2, end position of entity 2), ...],
                                List[str(NER tag of entity 1), str(NER tag of entity 2)]
                            ],
                        List(int(one-hot encoded relation label))
                    )
                ]
            }
        
deeppavlov/dataset_readers/docred_reader.py