


import collections
from typing import List, Optional, Union

from ...tokenization_utils_base import BatchEncoding
from ...utils import TensorType, add_end_docstrings, add_start_docstrings, logging
from ..bert.tokenization_bert import BertTokenizer


_lowercase     							=						logging.get_logger(__name__)

_lowercase     							=						{'''vocab_file''': '''vocab.txt''', '''tokenizer_file''': '''tokenizer.json'''}

_lowercase     							=						{
    '''vocab_file''': {
        '''facebook/dpr-ctx_encoder-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-ctx_encoder-single-nq-base/resolve/main/vocab.txt'''
        ),
        '''facebook/dpr-ctx_encoder-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-ctx_encoder-multiset-base/resolve/main/vocab.txt'''
        ),
    },
    '''tokenizer_file''': {
        '''facebook/dpr-ctx_encoder-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-ctx_encoder-single-nq-base/resolve/main/tokenizer.json'''
        ),
        '''facebook/dpr-ctx_encoder-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-ctx_encoder-multiset-base/resolve/main/tokenizer.json'''
        ),
    },
}
_lowercase     							=						{
    '''vocab_file''': {
        '''facebook/dpr-question_encoder-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-question_encoder-single-nq-base/resolve/main/vocab.txt'''
        ),
        '''facebook/dpr-question_encoder-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-question_encoder-multiset-base/resolve/main/vocab.txt'''
        ),
    },
    '''tokenizer_file''': {
        '''facebook/dpr-question_encoder-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-question_encoder-single-nq-base/resolve/main/tokenizer.json'''
        ),
        '''facebook/dpr-question_encoder-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-question_encoder-multiset-base/resolve/main/tokenizer.json'''
        ),
    },
}
_lowercase     							=						{
    '''vocab_file''': {
        '''facebook/dpr-reader-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-reader-single-nq-base/resolve/main/vocab.txt'''
        ),
        '''facebook/dpr-reader-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-reader-multiset-base/resolve/main/vocab.txt'''
        ),
    },
    '''tokenizer_file''': {
        '''facebook/dpr-reader-single-nq-base''': (
            '''https://huggingface.co/facebook/dpr-reader-single-nq-base/resolve/main/tokenizer.json'''
        ),
        '''facebook/dpr-reader-multiset-base''': (
            '''https://huggingface.co/facebook/dpr-reader-multiset-base/resolve/main/tokenizer.json'''
        ),
    },
}

_lowercase     							=						{
    '''facebook/dpr-ctx_encoder-single-nq-base''': 5_12,
    '''facebook/dpr-ctx_encoder-multiset-base''': 5_12,
}
_lowercase     							=						{
    '''facebook/dpr-question_encoder-single-nq-base''': 5_12,
    '''facebook/dpr-question_encoder-multiset-base''': 5_12,
}
_lowercase     							=						{
    '''facebook/dpr-reader-single-nq-base''': 5_12,
    '''facebook/dpr-reader-multiset-base''': 5_12,
}


_lowercase     							=						{
    '''facebook/dpr-ctx_encoder-single-nq-base''': {'''do_lower_case''': True},
    '''facebook/dpr-ctx_encoder-multiset-base''': {'''do_lower_case''': True},
}
_lowercase     							=						{
    '''facebook/dpr-question_encoder-single-nq-base''': {'''do_lower_case''': True},
    '''facebook/dpr-question_encoder-multiset-base''': {'''do_lower_case''': True},
}
_lowercase     							=						{
    '''facebook/dpr-reader-single-nq-base''': {'''do_lower_case''': True},
    '''facebook/dpr-reader-multiset-base''': {'''do_lower_case''': True},
}
class 				__A					( __snake_case      ):
			UpperCamelCase					:List[Any]     =			VOCAB_FILES_NAMES
			UpperCamelCase					:List[str]     =			CONTEXT_ENCODER_PRETRAINED_VOCAB_FILES_MAP
			UpperCamelCase					:List[Any]     =			CONTEXT_ENCODER_PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
			UpperCamelCase					:str     =			CONTEXT_ENCODER_PRETRAINED_INIT_CONFIGURATION







class 				__A					( __snake_case      ):
			UpperCamelCase					:Optional[int]     =			VOCAB_FILES_NAMES
			UpperCamelCase					:Union[str, Any]     =			QUESTION_ENCODER_PRETRAINED_VOCAB_FILES_MAP
			UpperCamelCase					:str     =			QUESTION_ENCODER_PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
			UpperCamelCase					:Dict     =			QUESTION_ENCODER_PRETRAINED_INIT_CONFIGURATION







_lowercase     							=						collections.namedtuple(
    '''DPRSpanPrediction''', ['''span_score''', '''relevance_score''', '''doc_id''', '''start_index''', '''end_index''', '''text''']
)

_lowercase     							=						collections.namedtuple('''DPRReaderOutput''', ['''start_logits''', '''end_logits''', '''relevance_logits'''])


_lowercase     							=						r'''\n    Return a dictionary with the token ids of the input strings and other information to give to `.decode_best_spans`.\n    It converts the strings of a question and different passages (title and text) in a sequence of IDs (integers),\n    using the tokenizer and vocabulary. The resulting `input_ids` is a matrix of size `(n_passages, sequence_length)`\n    with the format:\n\n    ```\n    [CLS] <question token ids> [SEP] <titles ids> [SEP] <texts ids>\n    ```\n\n    Args:\n        questions (`str` or `List[str]`):\n            The questions to be encoded. You can specify one question for many passages. In this case, the question\n            will be duplicated like `[questions] * n_passages`. Otherwise you have to specify as many questions as in\n            `titles` or `texts`.\n        titles (`str` or `List[str]`):\n            The passages titles to be encoded. This can be a string or a list of strings if there are several passages.\n        texts (`str` or `List[str]`):\n            The passages texts to be encoded. This can be a string or a list of strings if there are several passages.\n        padding (`bool`, `str` or [`~utils.PaddingStrategy`], *optional*, defaults to `False`):\n            Activates and controls padding. Accepts the following values:\n\n            - `True` or `\'longest\'`: Pad to the longest sequence in the batch (or no padding if only a single sequence\n              if provided).\n            - `\'max_length\'`: Pad to a maximum length specified with the argument `max_length` or to the maximum\n              acceptable input length for the model if that argument is not provided.\n            - `False` or `\'do_not_pad\'` (default): No padding (i.e., can output a batch with sequences of different\n              lengths).\n        truncation (`bool`, `str` or [`~tokenization_utils_base.TruncationStrategy`], *optional*, defaults to `False`):\n            Activates and controls truncation. Accepts the following values:\n\n            - `True` or `\'longest_first\'`: Truncate to a maximum length specified with the argument `max_length` or to\n              the maximum acceptable input length for the model if that argument is not provided. This will truncate\n              token by token, removing a token from the longest sequence in the pair if a pair of sequences (or a batch\n              of pairs) is provided.\n            - `\'only_first\'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum\n              acceptable input length for the model if that argument is not provided. This will only truncate the first\n              sequence of a pair if a pair of sequences (or a batch of pairs) is provided.\n            - `\'only_second\'`: Truncate to a maximum length specified with the argument `max_length` or to the maximum\n              acceptable input length for the model if that argument is not provided. This will only truncate the\n              second sequence of a pair if a pair of sequences (or a batch of pairs) is provided.\n            - `False` or `\'do_not_truncate\'` (default): No truncation (i.e., can output batch with sequence lengths\n              greater than the model maximum admissible input size).\n        max_length (`int`, *optional*):\n                Controls the maximum length to use by one of the truncation/padding parameters.\n\n                If left unset or set to `None`, this will use the predefined model maximum length if a maximum length\n                is required by one of the truncation/padding parameters. If the model has no specific maximum input\n                length (like XLNet) truncation/padding to a maximum length will be deactivated.\n        return_tensors (`str` or [`~utils.TensorType`], *optional*):\n                If set, will return tensors instead of list of python integers. Acceptable values are:\n\n                - `\'tf\'`: Return TensorFlow `tf.constant` objects.\n                - `\'pt\'`: Return PyTorch `torch.Tensor` objects.\n                - `\'np\'`: Return Numpy `np.ndarray` objects.\n        return_attention_mask (`bool`, *optional*):\n            Whether or not to return the attention mask. If not set, will return the attention mask according to the\n            specific tokenizer\'s default, defined by the `return_outputs` attribute.\n\n            [What are attention masks?](../glossary#attention-mask)\n\n    Returns:\n        `Dict[str, List[List[int]]]`: A dictionary with the following keys:\n\n        - `input_ids`: List of token ids to be fed to a model.\n        - `attention_mask`: List of indices specifying which tokens should be attended to by the model.\n    '''
@add_start_docstrings(__snake_case      )
class 				__A					:





			def __call__(self							,    __magic_name__							,    __magic_name__ = None							,    __magic_name__ = None							,    __magic_name__ = False							,    __magic_name__ = False							,    __magic_name__ = None							,    __magic_name__ = None							,    __magic_name__ = None							,    **__magic_name__							,    ):


						if titles is None and texts is None:
									return super().__call__(
									    __UpperCamelCase							,    padding=__UpperCamelCase							,    truncation=__UpperCamelCase							,    max_length=__UpperCamelCase							,    return_tensors=__UpperCamelCase							,    return_attention_mask=__UpperCamelCase							,    **__UpperCamelCase							,    )
						elif titles is None or texts is None:
									lowerCamelCase__ :      str								=		titles if texts is None else texts
									return super().__call__(
									    __UpperCamelCase							,    __UpperCamelCase							,    padding=__UpperCamelCase							,    truncation=__UpperCamelCase							,    max_length=__UpperCamelCase							,    return_tensors=__UpperCamelCase							,    return_attention_mask=__UpperCamelCase							,    **__UpperCamelCase							,    )
						lowerCamelCase__ :      Union[str, Any]								=		titles if not isinstance(__UpperCamelCase							,    __UpperCamelCase				) else [titles]
						lowerCamelCase__ :      Tuple								=		texts if not isinstance(__UpperCamelCase							,    __UpperCamelCase				) else [texts]
						lowerCamelCase__ :      List[str]								=		len(__UpperCamelCase				)
						lowerCamelCase__ :      Dict								=		questions if not isinstance(__UpperCamelCase							,    __UpperCamelCase				) else [questions] * n_passages
						if len(__UpperCamelCase				) != len(__UpperCamelCase				):
									raise ValueError(
									    f"There should be as many titles than texts but got {len(__UpperCamelCase				)} titles and {len(__UpperCamelCase				)} texts."				)
						lowerCamelCase__ :      Optional[Any]								=		super().__call__(__UpperCamelCase							,    __UpperCamelCase							,    padding=__UpperCamelCase							,    truncation=__UpperCamelCase				)["""input_ids"""]
						lowerCamelCase__ :      Optional[int]								=		super().__call__(__UpperCamelCase							,    add_special_tokens=__UpperCamelCase							,    padding=__UpperCamelCase							,    truncation=__UpperCamelCase				)["""input_ids"""]
						lowerCamelCase__ :      Dict								=		{
						    """input_ids""": [
						        (encoded_question_and_title + encoded_text)[:max_length]
						        if max_length is not None and truncation
						        else encoded_question_and_title + encoded_text
						        for encoded_question_and_title, encoded_text in zip(__UpperCamelCase							,    __UpperCamelCase				)
						    ]
						}
						if return_attention_mask is not False:
									lowerCamelCase__ :      Optional[Any]								=		[]
									for input_ids in encoded_inputs["input_ids"]:
												attention_mask.append([int(input_id != self.pad_token_id				) for input_id in input_ids]				)
									lowerCamelCase__ :      Optional[int]								=		attention_mask
						return self.pad(__UpperCamelCase							,    padding=__UpperCamelCase							,    max_length=__UpperCamelCase							,    return_tensors=__UpperCamelCase				)





			def        _snake_case    (self							,    __magic_name__							,    __magic_name__							,    __magic_name__ = 16							,    __magic_name__ = 64							,    __magic_name__ = 4							,    ):
						lowerCamelCase__ :      Union[str, Any]								=		reader_input["""input_ids"""]
						lowerCamelCase__							,lowerCamelCase__							,lowerCamelCase__ :      Dict								=		reader_output[:3]
						lowerCamelCase__ :      Tuple								=		len(__UpperCamelCase				)
						lowerCamelCase__ :      int								=		sorted(range(__UpperCamelCase				)							,    reverse=__UpperCamelCase							,    key=relevance_logits.__getitem__				)
						lowerCamelCase__ :      Optional[int]								=		[]
						for doc_id in sorted_docs:
									lowerCamelCase__ :      Tuple								=		list(input_ids[doc_id]				)
									# assuming question & title information is at the beginning of the sequence
									lowerCamelCase__ :      Optional[int]								=		sequence_ids.index(self.sep_token_id							,    2				) + 1  # second sep id
									if sequence_ids[-1] == self.pad_token_id:
												lowerCamelCase__ :      Dict								=		sequence_ids.index(self.pad_token_id				)
									else:
												lowerCamelCase__ :      Union[str, Any]								=		len(__UpperCamelCase				)

									lowerCamelCase__ :      Tuple								=		self._get_best_spans(
									    start_logits=start_logits[doc_id][passage_offset:sequence_len]							,    end_logits=end_logits[doc_id][passage_offset:sequence_len]							,    max_answer_length=__UpperCamelCase							,    top_spans=__UpperCamelCase							,    )
									for start_index, end_index in best_spans:
												start_index += passage_offset
												end_index += passage_offset
												nbest_spans_predictions.append(
												    DPRSpanPrediction(
												        span_score=start_logits[doc_id][start_index] + end_logits[doc_id][end_index]							,    relevance_score=relevance_logits[doc_id]							,    doc_id=__UpperCamelCase							,    start_index=__UpperCamelCase							,    end_index=__UpperCamelCase							,    text=self.decode(sequence_ids[start_index : end_index + 1]				)							,    )				)
									if len(__UpperCamelCase				) >= num_spans:
												break
						return nbest_spans_predictions[:num_spans]





			def        _snake_case    (self							,    __magic_name__							,    __magic_name__							,    __magic_name__							,    __magic_name__							,    ):
						lowerCamelCase__ :      int								=		[]
						for start_index, start_score in enumerate(__UpperCamelCase				):
									for answer_length, end_score in enumerate(end_logits[start_index : start_index + max_answer_length]				):
												scores.append(((start_index, start_index + answer_length), start_score + end_score)				)
						lowerCamelCase__ :      Union[str, Any]								=		sorted(__UpperCamelCase							,    key=lambda __magic_name__				: x[1]							,    reverse=__UpperCamelCase				)
						lowerCamelCase__ :      Union[str, Any]								=		[]
						for (start_index, end_index), score in scores:
									if start_index > end_index:
												raise ValueError(f"Wrong span indices: [{start_index}:{end_index}]"				)
									lowerCamelCase__ :      Union[str, Any]								=		end_index - start_index + 1
									if length > max_answer_length:
												raise ValueError(f"Span is too long: {length} > {max_answer_length}"				)
									if any(
									    start_index <= prev_start_index <= prev_end_index <= end_index
									    or prev_start_index <= start_index <= end_index <= prev_end_index
									    for (prev_start_index, prev_end_index) in chosen_span_intervals				):
												continue
									chosen_span_intervals.append((start_index, end_index)				)

									if len(__UpperCamelCase				) == top_spans:
												break
						return chosen_span_intervals







@add_end_docstrings(__snake_case      )
class 				__A					( __snake_case					, __snake_case      ):
			UpperCamelCase					:Tuple     =			VOCAB_FILES_NAMES
			UpperCamelCase					:List[str]     =			READER_PRETRAINED_VOCAB_FILES_MAP
			UpperCamelCase					:List[str]     =			READER_PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES
			UpperCamelCase					:Dict     =			READER_PRETRAINED_INIT_CONFIGURATION
			UpperCamelCase					:str     =			['''input_ids''', '''attention_mask''']








import numpy as np
from nltk.translate import meteor_score

import datasets
from datasets.config import importlib_metadata, version


_lowercase     							=						version.parse(importlib_metadata.version('''nltk'''))
if NLTK_VERSION >= version.Version('''3.6.4'''):
				from nltk import word_tokenize


_lowercase     							=						'''\
@inproceedings{banarjee2005,
  title     = {{METEOR}: An Automatic Metric for {MT} Evaluation with Improved Correlation with Human Judgments},
  author    = {Banerjee, Satanjeev  and Lavie, Alon},
  booktitle = {Proceedings of the {ACL} Workshop on Intrinsic and Extrinsic Evaluation Measures for Machine Translation and/or Summarization},
  month     = jun,
  year      = {2005},
  address   = {Ann Arbor, Michigan},
  publisher = {Association for Computational Linguistics},
  url       = {https://www.aclweb.org/anthology/W05-0909},
  pages     = {65--72},
}
'''

_lowercase     							=						'''\
METEOR, an automatic metric for machine translation evaluation
that is based on a generalized concept of unigram matching between the
machine-produced translation and human-produced reference translations.
Unigrams can be matched based on their surface forms, stemmed forms,
and meanings; furthermore, METEOR can be easily extended to include more
advanced matching strategies. Once all generalized unigram matches
between the two strings have been found, METEOR computes a score for
this matching using a combination of unigram-precision, unigram-recall, and
a measure of fragmentation that is designed to directly capture how
well-ordered the matched words in the machine translation are in relation
to the reference.

METEOR gets an R correlation value of 0.347 with human evaluation on the Arabic
data and 0.331 on the Chinese data. This is shown to be an improvement on
using simply unigram-precision, unigram-recall and their harmonic F1
combination.
'''

_lowercase     							=						'''
Computes METEOR score of translated segments against one or more references.
Args:
    predictions: list of predictions to score. Each prediction
        should be a string with tokens separated by spaces.
    references: list of reference for each prediction. Each
        reference should be a string with tokens separated by spaces.
    alpha: Parameter for controlling relative weights of precision and recall. default: 0.9
    beta: Parameter for controlling shape of penalty as a function of fragmentation. default: 3
    gamma: Relative weight assigned to fragmentation penalty. default: 0.5
Returns:
    \'meteor\': meteor score.
Examples:

    >>> meteor = datasets.load_metric(\'meteor\')
    >>> predictions = ["It is a guide to action which ensures that the military always obeys the commands of the party"]
    >>> references = ["It is a guide to action that ensures that the military will forever heed Party commands"]
    >>> results = meteor.compute(predictions=predictions, references=references)
    >>> print(round(results["meteor"], 4))
    0.6944
'''
@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION					, _KWARGS_DESCRIPTION      )
class 				__A					( datasets.Metric      ):





			def        _snake_case    (self				):
						return datasets.MetricInfo(
						    description=_DESCRIPTION							,    citation=_CITATION							,    inputs_description=_KWARGS_DESCRIPTION							,    features=datasets.Features(
						        {
						            """predictions""": datasets.Value("""string"""							,    id="""sequence"""				),
						            """references""": datasets.Value("""string"""							,    id="""sequence"""				),
						        }				)							,    codebase_urls=["""https://github.com/nltk/nltk/blob/develop/nltk/translate/meteor_score.py"""]							,    reference_urls=[
						        """https://www.nltk.org/api/nltk.translate.html#module-nltk.translate.meteor_score""",
						        """https://en.wikipedia.org/wiki/METEOR""",
						    ]							,    )





			def        _snake_case    (self							,    __magic_name__				):
						import nltk

						nltk.download("""wordnet"""				)
						if NLTK_VERSION >= version.Version("""3.6.5"""				):
									nltk.download("""punkt"""				)
						if NLTK_VERSION >= version.Version("""3.6.6"""				):
									nltk.download("""omw-1.4"""				)





			def        _snake_case    (self							,    __magic_name__							,    __magic_name__							,    __magic_name__=0.9							,    __magic_name__=3							,    __magic_name__=0.5				):
						if NLTK_VERSION >= version.Version("""3.6.5"""				):
									lowerCamelCase__ :      List[str]								=		[
									    meteor_score.single_meteor_score(
									        word_tokenize(__magic_name__				)							,    word_tokenize(__magic_name__				)							,    alpha=__magic_name__							,    beta=__magic_name__							,    gamma=__magic_name__				)
									    for ref, pred in zip(__magic_name__							,    __magic_name__				)
									]
						else:
									lowerCamelCase__ :      int								=		[
									    meteor_score.single_meteor_score(__magic_name__							,    __magic_name__							,    alpha=__magic_name__							,    beta=__magic_name__							,    gamma=__magic_name__				)
									    for ref, pred in zip(__magic_name__							,    __magic_name__				)
									]

						return {"meteor": np.mean(__magic_name__				)}



