
'''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 			lowerCAmelCase__ (							UpperCamelCase							):



  '''simple docstring'''






  def __call__(self	:			Optional[Any]						,			lowerCAmelCase_	:			List[Any]=None						,			lowerCAmelCase_	:			Any=None						,			**lowerCAmelCase_	:			List[Any]     ) ->							Union[str, Any]:
        # 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:
                    snake_case_    							=				[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:
                          snake_case_    							=				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:
              snake_case_    							=				[{"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."     )

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

        return tqa_pipeline_inputs



@add_end_docstrings(UpperCamelCase							)
class 			lowerCAmelCase__ (							UpperCamelCase							):



  '''simple docstring'''






  _UpperCamelCase							=			'table,query'

  def __init__(self	:			Union[str, Any]						,			lowerCAmelCase_	:			Any=TableQuestionAnsweringArgumentHandler()						,			*lowerCAmelCase_	:			Tuple						,			**lowerCAmelCase_	:			str     ) ->							Optional[Any]:
        super().__init__(*lowerCAmelCase_						,			**lowerCAmelCase_     )
        snake_case_    							=				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()     )     )

        snake_case_    							=				bool(getattr(self.model.config						,			"aggregation_labels"						,			lowerCAmelCase_     )     ) and bool(
            getattr(self.model.config						,			"num_aggregation_labels"						,			lowerCAmelCase_     )     )
        snake_case_    							=				"tapas" if hasattr(self.model.config						,			"aggregation_labels"     ) else None

  def 		_lowerCamelCase						(self	:			Optional[int]						,			**lowerCAmelCase_	:			Tuple     ) ->							Union[str, Any]:
        return self.model(**lowerCAmelCase_     )

  def 		_lowerCamelCase						(self	:			List[str]						,			**lowerCAmelCase_	:			str     ) ->							Dict:
        if self.framework == "pt":
              snake_case_    							=				[]
              snake_case_    							=				[]
              snake_case_    							=				None
              snake_case_    							=				inputs["input_ids"].shape[0]

              snake_case_    							=				inputs["input_ids"].to(self.device     )
              snake_case_    							=				inputs["attention_mask"].to(self.device     )
              snake_case_    							=				inputs["token_type_ids"].to(self.device     )
              snake_case_    							=				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:
                          snake_case_    							=				token_type_ids_example[:, 3]  # shape (seq_len,)
                          snake_case_    							=				np.zeros_like(prev_labels_example.cpu().numpy()     )  # shape (seq_len,)

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

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

                          snake_case_    							=				torch.from_numpy(lowerCAmelCase_     ).type(torch.long     ).to(self.device     )

                    snake_case_    							=				input_ids[index]
                    snake_case_    							=				attention_mask[index]  # shape (seq_len,)
                    snake_case_    							=				token_type_ids[index]  # shape (seq_len, 7)
                    snake_case_    							=				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     )						,			)
                    snake_case_    							=				outputs.logits

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

                    all_logits.append(lowerCAmelCase_     )

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

                    snake_case_    							=				collections.defaultdict(lowerCAmelCase_     )
                    for i, p in enumerate(probabilities.squeeze().tolist()     ):
                          snake_case_    							=				token_type_ids_example[:, 0].tolist()[i]
                          snake_case_    							=				token_type_ids_example[:, 1].tolist()[i] - 1
                          snake_case_    							=				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_     )

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

              snake_case_    							=				torch.cat(tuple(lowerCAmelCase_     )						,			0     )

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

              snake_case_    							=				inputs["input_ids"]
              snake_case_    							=				inputs["attention_mask"]
              snake_case_    							=				inputs["token_type_ids"].numpy()
              snake_case_    							=				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:
                          snake_case_    							=				token_type_ids_example[:, 3]  # shape (seq_len,)
                          snake_case_    							=				np.zeros_like(lowerCAmelCase_						,			dtype=np.intaa     )  # shape (seq_len,)

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

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

                          snake_case_    							=				model_labels

                    snake_case_    							=				input_ids[index]
                    snake_case_    							=				attention_mask[index]  # shape (seq_len,)
                    snake_case_    							=				token_type_ids[index]  # shape (seq_len, 7)
                    snake_case_    							=				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     )						,			)
                    snake_case_    							=				outputs.logits

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

                    all_logits.append(lowerCAmelCase_     )

                    snake_case_    							=				tfp.distributions.Bernoulli(logits=lowerCAmelCase_     )
                    snake_case_    							=				dist_per_token.probs_parameter() * tf.cast(lowerCAmelCase_						,			tf.floataa     )

                    snake_case_    							=				collections.defaultdict(lowerCAmelCase_     )
                    snake_case_    							=				token_type_ids_example
                    for i, p in enumerate(tf.squeeze(lowerCAmelCase_     ).numpy().tolist()     ):
                          snake_case_    							=				token_type_ids_example[:, 0].tolist()[i]
                          snake_case_    							=				token_type_ids_example[:, 1].tolist()[i] - 1
                          snake_case_    							=				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_     )

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

              snake_case_    							=				tf.concat(tuple(lowerCAmelCase_     )						,			0     )

              return (logits_batch,) if not self.aggregate else (logits_batch, tf.concat(tuple(lowerCAmelCase_     )						,			0     ))

  def __call__(self	:			Dict						,			*lowerCAmelCase_	:			Dict						,			**lowerCAmelCase_	:			Union[str, Any]     ) ->							str:
        snake_case_    							=				self._args_parser(*lowerCAmelCase_						,			**lowerCAmelCase_     )

        snake_case_    							=				super().__call__(lowerCAmelCase_						,			**lowerCAmelCase_     )
        if len(lowerCAmelCase_     ) == 1:
              return results[0]
        return results

  def 		_lowerCamelCase						(self	:			Optional[Any]						,			lowerCAmelCase_	:			List[str]=None						,			lowerCAmelCase_	:			List[str]=None						,			lowerCAmelCase_	:			Tuple=None						,			**lowerCAmelCase_	:			Dict     ) ->							List[Any]:
        snake_case_    							=				{}
        if padding is not None:
              snake_case_    							=				padding
        if truncation is not None:
              snake_case_    							=				truncation

        snake_case_    							=				{}
        if sequential is not None:
              snake_case_    							=				sequential
        return preprocess_params, forward_params, {}

  def 		_lowerCamelCase						(self	:			Tuple						,			lowerCAmelCase_	:			str						,			lowerCAmelCase_	:			List[Any]=None						,			lowerCAmelCase_	:			Any=True						,			lowerCAmelCase_	:			List[Any]=None     ) ->							int:
        if truncation is None:
              if self.type == "tapas":
                    snake_case_    							=				"drop_rows_to_fit"
              else:
                    snake_case_    							=				"do_not_truncate"

        snake_case_							,						snake_case_    							=				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"     )
        snake_case_    							=				self.tokenizer(lowerCAmelCase_						,			lowerCAmelCase_						,			return_tensors=self.framework						,			truncation=lowerCAmelCase_						,			padding=lowerCAmelCase_     )
        snake_case_    							=				table
        return inputs

  def 		_lowerCamelCase						(self	:			Optional[Any]						,			lowerCAmelCase_	:			List[Any]						,			lowerCAmelCase_	:			List[Any]=False     ) ->							Tuple:
        snake_case_    							=				model_inputs.pop("table"     )

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


  def 		_lowerCamelCase						(self	:			Tuple						,			lowerCAmelCase_	:			List[Any]     ) ->							Any:
        snake_case_    							=				model_outputs["model_inputs"]
        snake_case_    							=				model_outputs["table"]
        snake_case_    							=				model_outputs["outputs"]
        if self.type == "tapas":
              if self.aggregate:
                    snake_case_							,						snake_case_    							=				outputs[:2]
                    snake_case_    							=				self.tokenizer.convert_logits_to_predictions(lowerCAmelCase_						,			lowerCAmelCase_						,			lowerCAmelCase_     )
                    snake_case_							,						snake_case_    							=				predictions
                    snake_case_    							=				{i: self.model.config.aggregation_labels[pred] for i, pred in enumerate(lowerCAmelCase_     )}

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

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

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





from sklearn.metrics import mean_absolute_error

import datasets


a					:				Optional[Any]       =      '\\n@article{scikit-learn,\n title={Scikit-learn: Machine Learning in {P}ython},\n author={Pedregosa, F. and Varoquaux, G. and Gramfort, A. and Michel, V.\n         and Thirion, B. and Grisel, O. and Blondel, M. and Prettenhofer, P.\n         and Weiss, R. and Dubourg, V. and Vanderplas, J. and Passos, A. and\n         Cournapeau, D. and Brucher, M. and Perrot, M. and Duchesnay, E.},\n journal={Journal of Machine Learning Research},\n volume={12},\n pages={2825--2830},\n year={2011}\n}\n'

a					:				int       =      '\\nMean Absolute Error (MAE) is the mean of the magnitude of difference between the predicted and actual\nvalues.\n'


a					:				Any       =      '\nArgs:\n    predictions: array-like of shape (n_samples,) or (n_samples, n_outputs)\n        Estimated target values.\n    references: array-like of shape (n_samples,) or (n_samples, n_outputs)\n        Ground truth (correct) target values.\n    sample_weight: array-like of shape (n_samples,), default=None\n        Sample weights.\n    multioutput: {"raw_values", "uniform_average"} or array-like of shape (n_outputs,), default="uniform_average"\n        Defines aggregating of multiple output values. Array-like value defines weights used to average errors.\n\n                 "raw_values" : Returns a full set of errors in case of multioutput input.\n\n                 "uniform_average" : Errors of all outputs are averaged with uniform weight.\n\nReturns:\n    mae : mean absolute error.\n        If multioutput is "raw_values", then mean absolute error is returned for each output separately. If multioutput is "uniform_average" or an ndarray of weights, then the weighted average of all output errors is returned.\n        MAE output is non-negative floating point. The best value is 0.0.\nExamples:\n\n    >>> mae_metric = datasets.load_metric("mae")\n    >>> predictions = [2.5, 0.0, 2, 8]\n    >>> references = [3, -0.5, 2, 7]\n    >>> results = mae_metric.compute(predictions=predictions, references=references)\n    >>> print(results)\n    {\'mae\': 0.5}\n\n    If you\'re using multi-dimensional lists, then set the config as follows :\n\n    >>> mae_metric = datasets.load_metric("mae", "multilist")\n    >>> predictions = [[0.5, 1], [-1, 1], [7, -6]]\n    >>> references = [[0, 2], [-1, 2], [8, -5]]\n    >>> results = mae_metric.compute(predictions=predictions, references=references)\n    >>> print(results)\n    {\'mae\': 0.75}\n    >>> results = mae_metric.compute(predictions=predictions, references=references, multioutput=\'raw_values\')\n    >>> print(results)\n    {\'mae\': array([0.5, 1. ])}\n'

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

       def 					UpperCAmelCase					(      self       ):






        '''simple docstring'''






        return datasets.MetricInfo(
            description=_DESCRIPTION						,    citation=_CITATION						,    inputs_description=_KWARGS_DESCRIPTION						,    features=datasets.Features(self._get_feature_types()       )						,    reference_urls=[
                '''https://scikit-learn.org/stable/modules/generated/sklearn.metrics.mean_absolute_error.html'''
            ]						,    )

       def 					UpperCAmelCase					(      self       ):






        '''simple docstring'''






        if self.config_name == "multilist":
         return {
             "predictions": datasets.Sequence(datasets.Value('''float'''       )       ),
             "references": datasets.Sequence(datasets.Value('''float'''       )       ),
         }
        else:
         return {
             "predictions": datasets.Value('''float'''       ),
             "references": datasets.Value('''float'''       ),
         }



       def 					UpperCAmelCase					(      self						,    a__						,    a__						,    a__=None						,    a__="uniform_average"       ):






        '''simple docstring'''






        snake_case :			str							=   mean_absolute_error(a__						,    a__						,    sample_weight=a__						,    multioutput=a__       )

        return {"mae": mae_score}






