
"""simple docstring"""






import collections
import types

import numpy as np

from ..utils import (
    add_end_docstrings,
    is_tensorflow_probability_available,
    is_tf_available,
    is_torch_available,
    requires_backends,
)
from .base import PIPELINE_INIT_ARGS, ArgumentHandler, Dataset, Pipeline, PipelineException


if is_torch_available():
					import torch

					from ..models.auto.modeling_auto import (
					    MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING,
					    MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING,
					)

if is_tf_available() and is_tensorflow_probability_available():
					import tensorflow as tf
					import tensorflow_probability as tfp

					from ..models.auto.modeling_tf_auto import (
					    TF_MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING,
					    TF_MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING,
					)

class 				__a    (   __a					):



							'''simple docstring'''







							def __call__(    self     ,						_lowerCamelCase=None     ,						_lowerCamelCase=None     ,						**_lowerCamelCase					) ->       Optional[int]:




										'''simple docstring'''
										# Returns tqa_pipeline_inputs of shape:
										# [
										#   {"table": pd.DataFrame, "query": List[str]},
										#   ...,
										#   {"table": pd.DataFrame, "query" : List[str]}
										# ]
										requires_backends(self     ,						"pandas"					)
										import pandas as pd

										if table is None:
													raise ValueError("Keyword argument `table` cannot be None."					)
										elif query is None:
													if isinstance(_lowerCamelCase     ,						_lowerCamelCase					) and table.get("query"					) is not None and table.get("table"					) is not None:
																__lowercase						      =					[table]
													elif isinstance(_lowerCamelCase     ,						_lowerCamelCase					) and len(_lowerCamelCase					) > 0:
																if not all(isinstance(_lowerCamelCase     ,						_lowerCamelCase					) for d in table					):
																			raise ValueError(
																			    f'''Keyword argument `table` should be a list of dict, but is {(type(_lowerCamelCase					) for d in table)}'''					)

																if table[0].get("query"					) is not None and table[0].get("table"					) is not None:
																			__lowercase						      =					table
																else:
																			raise ValueError(
																			    "If keyword argument `table` is a list of dictionaries, each dictionary should have a `table`"
																			    f''' and `query` key, but only dictionary has keys {table[0].keys()} `table` and `query` keys.'''					)
													elif Dataset is not None and isinstance(_lowerCamelCase     ,						_lowerCamelCase					) or isinstance(_lowerCamelCase     ,						types.GeneratorType					):
																return table
													else:
																raise ValueError(
																    "Invalid input. Keyword argument `table` should be either of type `dict` or `list`, but "
																    f'''is {type(_lowerCamelCase					)})'''					)
										else:
													__lowercase						      =					[{"table": table, "query": query}]

										for tqa_pipeline_input in tqa_pipeline_inputs:
													if not isinstance(tqa_pipeline_input["table"]     ,						pd.DataFrame					):
																if tqa_pipeline_input["table"] is None:
																			raise ValueError("Table cannot be None."					)

																__lowercase						      =					pd.DataFrame(tqa_pipeline_input["table"]					)

										return tqa_pipeline_inputs





@add_end_docstrings(__a					)
class 				__a    (   __a					):



							'''simple docstring'''







							_lowerCamelCase				: Union[str, Any]					      =      """table,query"""
							def __init__(    self     ,						_lowerCamelCase=TableQuestionAnsweringArgumentHandler()     ,						*_lowerCamelCase     ,						**_lowerCamelCase					) ->       List[Any]:




										'''simple docstring'''
										super().__init__(*_lowerCamelCase     ,						**_lowerCamelCase					)
										__lowercase						      =					args_parser

										self.check_model_type(
										    dict(
										        TF_MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING.items()
										        + TF_MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING.items()					)
										    if self.framework == "tf"
										    else dict(
										        MODEL_FOR_TABLE_QUESTION_ANSWERING_MAPPING.items() + MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING.items()					)					)

										__lowercase						      =					bool(getattr(self.model.config     ,						"aggregation_labels"     ,						_lowerCamelCase					)					) and bool(
										    getattr(self.model.config     ,						"num_aggregation_labels"     ,						_lowerCamelCase					)					)
										__lowercase						      =					"tapas" if hasattr(self.model.config     ,						"aggregation_labels"					) else None
							def      SCREAMING_SNAKE_CASE	(    self     ,						**_lowerCamelCase					) ->       str:




										'''simple docstring'''
										return self.model(**_lowerCamelCase					)
							def      SCREAMING_SNAKE_CASE	(    self     ,						**_lowerCamelCase					) ->       Tuple:




										'''simple docstring'''
										if self.framework == "pt":
													__lowercase						      =					[]
													__lowercase						      =					[]
													__lowercase						      =					None
													__lowercase						      =					inputs["input_ids"].shape[0]

													__lowercase						      =					inputs["input_ids"].to(self.device					)
													__lowercase						      =					inputs["attention_mask"].to(self.device					)
													__lowercase						      =					inputs["token_type_ids"].to(self.device					)
													__lowercase						      =					None

													for index in range(_lowerCamelCase					):
																# If sequences have already been processed, the token type IDs will be created according to the previous
																# answer.
																if prev_answers is not None:
																			__lowercase						      =					token_type_ids_example[:, 3]  # shape (seq_len,)
																			__lowercase						      =					np.zeros_like(prev_labels_example.cpu().numpy()					)  # shape (seq_len,)

																			__lowercase						      =					token_type_ids[index]  # shape (seq_len, 7)
																			for i in range(model_labels.shape[0]					):
																						__lowercase						      =					token_type_ids_example[:, 0].tolist()[i]
																						__lowercase						      =					token_type_ids_example[:, 1].tolist()[i] - 1
																						__lowercase						      =					token_type_ids_example[:, 2].tolist()[i] - 1

																						if row_id >= 0 and col_id >= 0 and segment_id == 1:
																									__lowercase						      =					int(prev_answers[(col_id, row_id)]					)

																			__lowercase						      =					torch.from_numpy(_lowerCamelCase					).type(torch.long					).to(self.device					)

																__lowercase						      =					input_ids[index]
																__lowercase						      =					attention_mask[index]  # shape (seq_len,)
																__lowercase						      =					token_type_ids[index]  # shape (seq_len, 7)
																__lowercase						      =					self.model(
																    input_ids=input_ids_example.unsqueeze(0					)     ,						attention_mask=attention_mask_example.unsqueeze(0					)     ,						token_type_ids=token_type_ids_example.unsqueeze(0					)     ,						)
																__lowercase						      =					outputs.logits

																if self.aggregate:
																			all_aggregations.append(outputs.logits_aggregation					)

																all_logits.append(_lowerCamelCase					)

																__lowercase						      =					torch.distributions.Bernoulli(logits=_lowerCamelCase					)
																__lowercase						      =					dist_per_token.probs * attention_mask_example.type(torch.floataa					).to(
																    dist_per_token.probs.device					)

																__lowercase						      =					collections.defaultdict(_lowerCamelCase					)
																for i, p in enumerate(probabilities.squeeze().tolist()					):
																			__lowercase						      =					token_type_ids_example[:, 0].tolist()[i]
																			__lowercase						      =					token_type_ids_example[:, 1].tolist()[i] - 1
																			__lowercase						      =					token_type_ids_example[:, 2].tolist()[i] - 1
																			if col >= 0 and row >= 0 and segment_id == 1:
																						coords_to_probs[(col, row)].append(_lowerCamelCase					)

																__lowercase						      =					{key: np.array(coords_to_probs[key]					).mean() > 0.5 for key in coords_to_probs}

													__lowercase						      =					torch.cat(tuple(_lowerCamelCase					)     ,						0					)

													return (logits_batch,) if not self.aggregate else (logits_batch, torch.cat(tuple(_lowerCamelCase					)     ,						0					))
										else:
													__lowercase						      =					[]
													__lowercase						      =					[]
													__lowercase						      =					None
													__lowercase						      =					inputs["input_ids"].shape[0]

													__lowercase						      =					inputs["input_ids"]
													__lowercase						      =					inputs["attention_mask"]
													__lowercase						      =					inputs["token_type_ids"].numpy()
													__lowercase						      =					None

													for index in range(_lowerCamelCase					):
																# If sequences have already been processed, the token type IDs will be created according to the previous
																# answer.
																if prev_answers is not None:
																			__lowercase						      =					token_type_ids_example[:, 3]  # shape (seq_len,)
																			__lowercase						      =					np.zeros_like(_lowerCamelCase     ,						dtype=np.intaa					)  # shape (seq_len,)

																			__lowercase						      =					token_type_ids[index]  # shape (seq_len, 7)
																			for i in range(model_labels.shape[0]					):
																						__lowercase						      =					token_type_ids_example[:, 0].tolist()[i]
																						__lowercase						      =					token_type_ids_example[:, 1].tolist()[i] - 1
																						__lowercase						      =					token_type_ids_example[:, 2].tolist()[i] - 1

																						if row_id >= 0 and col_id >= 0 and segment_id == 1:
																									__lowercase						      =					int(prev_answers[(col_id, row_id)]					)

																			__lowercase						      =					model_labels

																__lowercase						      =					input_ids[index]
																__lowercase						      =					attention_mask[index]  # shape (seq_len,)
																__lowercase						      =					token_type_ids[index]  # shape (seq_len, 7)
																__lowercase						      =					self.model(
																    input_ids=np.expand_dims(_lowerCamelCase     ,						axis=0					)     ,						attention_mask=np.expand_dims(_lowerCamelCase     ,						axis=0					)     ,						token_type_ids=np.expand_dims(_lowerCamelCase     ,						axis=0					)     ,						)
																__lowercase						      =					outputs.logits

																if self.aggregate:
																			all_aggregations.append(outputs.logits_aggregation					)

																all_logits.append(_lowerCamelCase					)

																__lowercase						      =					tfp.distributions.Bernoulli(logits=_lowerCamelCase					)
																__lowercase						      =					dist_per_token.probs_parameter() * tf.cast(_lowerCamelCase     ,						tf.floataa					)

																__lowercase						      =					collections.defaultdict(_lowerCamelCase					)
																__lowercase						      =					token_type_ids_example
																for i, p in enumerate(tf.squeeze(_lowerCamelCase					).numpy().tolist()					):
																			__lowercase						      =					token_type_ids_example[:, 0].tolist()[i]
																			__lowercase						      =					token_type_ids_example[:, 1].tolist()[i] - 1
																			__lowercase						      =					token_type_ids_example[:, 2].tolist()[i] - 1
																			if col >= 0 and row >= 0 and segment_id == 1:
																						coords_to_probs[(col, row)].append(_lowerCamelCase					)

																__lowercase						      =					{key: np.array(coords_to_probs[key]					).mean() > 0.5 for key in coords_to_probs}

													__lowercase						      =					tf.concat(tuple(_lowerCamelCase					)     ,						0					)

													return (logits_batch,) if not self.aggregate else (logits_batch, tf.concat(tuple(_lowerCamelCase					)     ,						0					))
							def __call__(    self     ,						*_lowerCamelCase     ,						**_lowerCamelCase					) ->       str:




										'''simple docstring'''
										__lowercase						      =					self._args_parser(*_lowerCamelCase     ,						**_lowerCamelCase					)

										__lowercase						      =					super().__call__(_lowerCamelCase     ,						**_lowerCamelCase					)
										if len(_lowerCamelCase					) == 1:
													return results[0]
										return results
							def      SCREAMING_SNAKE_CASE	(    self     ,						_lowerCamelCase=None     ,						_lowerCamelCase=None     ,						_lowerCamelCase=None     ,						**_lowerCamelCase					) ->       List[str]:




										'''simple docstring'''
										__lowercase						      =					{}
										if padding is not None:
													__lowercase						      =					padding
										if truncation is not None:
													__lowercase						      =					truncation

										__lowercase						      =					{}
										if sequential is not None:
													__lowercase						      =					sequential
										return preprocess_params, forward_params, {}
							def      SCREAMING_SNAKE_CASE	(    self     ,						_lowerCamelCase     ,						_lowerCamelCase=None     ,						_lowerCamelCase=True     ,						_lowerCamelCase=None					) ->       Tuple:




										'''simple docstring'''
										if truncation is None:
													if self.type == "tapas":
																__lowercase						      =					"drop_rows_to_fit"
													else:
																__lowercase						      =					"do_not_truncate"

										__lowercase      ,				__lowercase						      =					pipeline_input["table"], pipeline_input["query"]
										if table.empty:
													raise ValueError("table is empty"					)
										if query is None or query == "":
													raise ValueError("query is empty"					)
										__lowercase						      =					self.tokenizer(_lowerCamelCase     ,						_lowerCamelCase     ,						return_tensors=self.framework     ,						truncation=_lowerCamelCase     ,						padding=_lowerCamelCase					)
										__lowercase						      =					table
										return inputs
							def      SCREAMING_SNAKE_CASE	(    self     ,						_lowerCamelCase     ,						_lowerCamelCase=False					) ->       Any:




										'''simple docstring'''
										__lowercase						      =					model_inputs.pop("table"					)

										if self.type == "tapas":
													if sequential:
																__lowercase						      =					self.sequential_inference(**_lowerCamelCase					)
													else:
																__lowercase						      =					self.batch_inference(**_lowerCamelCase					)
										else:
													__lowercase						      =					self.model.generate(**_lowerCamelCase					)
										__lowercase						      =					{"model_inputs": model_inputs, "table": table, "outputs": outputs}
										return model_outputs





							def      SCREAMING_SNAKE_CASE	(    self     ,						_lowerCamelCase					) ->       int:




										'''simple docstring'''
										__lowercase						      =					model_outputs["model_inputs"]
										__lowercase						      =					model_outputs["table"]
										__lowercase						      =					model_outputs["outputs"]
										if self.type == "tapas":
													if self.aggregate:
																__lowercase      ,				__lowercase						      =					outputs[:2]
																__lowercase						      =					self.tokenizer.convert_logits_to_predictions(_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase					)
																__lowercase      ,				__lowercase						      =					predictions
																__lowercase						      =					{i: self.model.config.aggregation_labels[pred] for i, pred in enumerate(_lowerCamelCase					)}

																__lowercase						      =					self.model.config.no_aggregation_label_index
																__lowercase						      =					{
																    i: aggregators[i] + " > " for i, pred in enumerate(_lowerCamelCase					) if pred != no_agg_label_index
																}
													else:
																__lowercase						      =					outputs[0]
																__lowercase						      =					self.tokenizer.convert_logits_to_predictions(_lowerCamelCase     ,						_lowerCamelCase					)
																__lowercase						      =					predictions[0]
																__lowercase						      =					{}
																__lowercase						      =					{}
													__lowercase						      =					[]
													for index, coordinates in enumerate(_lowerCamelCase					):
																__lowercase						      =					[table.iat[coordinate] for coordinate in coordinates]
																__lowercase						      =					aggregators.get(_lowerCamelCase     ,						""					)
																__lowercase						      =					aggregators_prefix.get(_lowerCamelCase     ,						""					)
																__lowercase						      =					{
																    "answer": aggregator_prefix + ", ".join(_lowerCamelCase					),
																    "coordinates": coordinates,
																    "cells": [table.iat[coordinate] for coordinate in coordinates],
																}
																if aggregator:
																			__lowercase						      =					aggregator

																answers.append(_lowerCamelCase					)
													if len(_lowerCamelCase					) == 0:
																raise PipelineException("Empty answer"					)
										else:
													__lowercase						      =					[{"answer": answer} for answer in self.tokenizer.batch_decode(_lowerCamelCase     ,						skip_special_tokens=_lowerCamelCase					)]

										return answers if len(_lowerCamelCase					) > 1 else answers[0]







"""simple docstring"""






import datasets

from .evaluate import (
    apply_no_ans_threshold,
    find_all_best_thresh,
    get_raw_scores,
    make_eval_dict,
    make_qid_to_has_ans,
    merge_eval,
)


_lowercase							 =							'''\
@inproceedings{Rajpurkar2016SQuAD10,
  title={SQuAD: 100, 000+ Questions for Machine Comprehension of Text},
  author={Pranav Rajpurkar and Jian Zhang and Konstantin Lopyrev and Percy Liang},
  booktitle={EMNLP},
  year={2016}
}
'''

_lowercase							 =							'''
This metric wrap the official scoring script for version 2 of the Stanford Question
Answering Dataset (SQuAD).

Stanford Question Answering Dataset (SQuAD) is a reading comprehension dataset, consisting of questions posed by
crowdworkers on a set of Wikipedia articles, where the answer to every question is a segment of text, or span,
from the corresponding reading passage, or the question might be unanswerable.

SQuAD2.0 combines the 100,000 questions in SQuAD1.1 with over 50,000 unanswerable questions
written adversarially by crowdworkers to look similar to answerable ones.
To do well on SQuAD2.0, systems must not only answer questions when possible, but also
determine when no answer is supported by the paragraph and abstain from answering.
'''

_lowercase							 =							'''
Computes SQuAD v2 scores (F1 and EM).
Args:
    predictions: List of triple for question-answers to score with the following elements:
        - the question-answer \'id\' field as given in the references (see below)
        - the text of the answer
        - the probability that the question has no answer
    references: List of question-answers dictionaries with the following key-values:
            - \'id\': id of the question-answer pair (see above),
            - \'answers\': a list of Dict {\'text\': text of the answer as a string}
    no_answer_threshold: float
        Probability threshold to decide that a question has no answer.
Returns:
    \'exact\': Exact match (the normalized answer exactly match the gold answer)
    \'f1\': The F-score of predicted tokens versus the gold answer
    \'total\': Number of score considered
    \'HasAns_exact\': Exact match (the normalized answer exactly match the gold answer)
    \'HasAns_f1\': The F-score of predicted tokens versus the gold answer
    \'HasAns_total\': Number of score considered
    \'NoAns_exact\': Exact match (the normalized answer exactly match the gold answer)
    \'NoAns_f1\': The F-score of predicted tokens versus the gold answer
    \'NoAns_total\': Number of score considered
    \'best_exact\': Best exact match (with varying threshold)
    \'best_exact_thresh\': No-answer probability threshold associated to the best exact match
    \'best_f1\': Best F1 (with varying threshold)
    \'best_f1_thresh\': No-answer probability threshold associated to the best F1
Examples:

    >>> predictions = [{\'prediction_text\': \'1976\', \'id\': \'56e10a3be3433e1400422b22\', \'no_answer_probability\': 0.}]
    >>> references = [{\'answers\': {\'answer_start\': [97], \'text\': [\'1976\']}, \'id\': \'56e10a3be3433e1400422b22\'}]
    >>> squad_v2_metric = datasets.load_metric("squad_v2")
    >>> results = squad_v2_metric.compute(predictions=predictions, references=references)
    >>> print(results)
    {\'exact\': 100.0, \'f1\': 100.0, \'total\': 1, \'HasAns_exact\': 100.0, \'HasAns_f1\': 100.0, \'HasAns_total\': 1, \'best_exact\': 100.0, \'best_exact_thresh\': 0.0, \'best_f1\': 100.0, \'best_f1_thresh\': 0.0}
'''

@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION				,      _KWARGS_DESCRIPTION					)
class 				__a    (   datasets.Metric					):



							'''simple docstring'''







							def      SCREAMING_SNAKE_CASE	(    self					) ->       Tuple:




										'''simple docstring'''
										return datasets.MetricInfo(
										    description=_DESCRIPTION     ,						citation=_CITATION     ,						inputs_description=_KWARGS_DESCRIPTION     ,						features=datasets.Features(
										        {
										            "predictions": {
										                "id": datasets.Value("string"					),
										                "prediction_text": datasets.Value("string"					),
										                "no_answer_probability": datasets.Value("float32"					),
										            },
										            "references": {
										                "id": datasets.Value("string"					),
										                "answers": datasets.features.Sequence(
										                    {"text": datasets.Value("string"					), "answer_start": datasets.Value("int32"					)}					),
										            },
										        }					)     ,						codebase_urls=["https://rajpurkar.github.io/SQuAD-explorer/"]     ,						reference_urls=["https://rajpurkar.github.io/SQuAD-explorer/"]     ,						)





							def      SCREAMING_SNAKE_CASE	(    self     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase=1.0					) ->       Tuple:




										'''simple docstring'''
										__lowercase						      =					{p["id"]: p["no_answer_probability"] for p in predictions}
										__lowercase						      =					[{"paragraphs": [{"qas": references}]}]
										__lowercase						      =					{p["id"]: p["prediction_text"] for p in predictions}

										__lowercase						      =					make_qid_to_has_ans(_lowerCamelCase					)  # maps qid to True/False
										__lowercase						      =					[k for k, v in qid_to_has_ans.items() if v]
										__lowercase						      =					[k for k, v in qid_to_has_ans.items() if not v]

										__lowercase      ,				__lowercase						      =					get_raw_scores(_lowerCamelCase     ,						_lowerCamelCase					)
										__lowercase						      =					apply_no_ans_threshold(_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase					)
										__lowercase						      =					apply_no_ans_threshold(_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase					)
										__lowercase						      =					make_eval_dict(_lowerCamelCase     ,						_lowerCamelCase					)

										if has_ans_qids:
													__lowercase						      =					make_eval_dict(_lowerCamelCase     ,						_lowerCamelCase     ,						qid_list=_lowerCamelCase					)
													merge_eval(_lowerCamelCase     ,						_lowerCamelCase     ,						"HasAns"					)
										if no_ans_qids:
													__lowercase						      =					make_eval_dict(_lowerCamelCase     ,						_lowerCamelCase     ,						qid_list=_lowerCamelCase					)
													merge_eval(_lowerCamelCase     ,						_lowerCamelCase     ,						"NoAns"					)
										find_all_best_thresh(_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase     ,						_lowerCamelCase					)
										return dict(_lowerCamelCase					)





