"""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 					UpperCAmelCase		(lowerCAmelCase__						):



    """simple docstring"""

    def __call__(     self					,    _UpperCAmelCase=None					,    _UpperCAmelCase=None					,    **_UpperCAmelCase							):
       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__:     Any      =   [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__:     Dict      =   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__:     Union[str, Any]      =   [{"""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__:     List[str]      =   pd.DataFrame(tqa_pipeline_input['''table''']							)

       return tqa_pipeline_inputs



@add_end_docstrings(lowerCAmelCase__						)
class 					UpperCAmelCase		(lowerCAmelCase__						):



    """simple docstring"""

    _UpperCAmelCase			:Tuple							=				"table,query"






    def __init__(     self					,    _UpperCAmelCase=TableQuestionAnsweringArgumentHandler()					,    *_UpperCAmelCase					,    **_UpperCAmelCase							):
       super().__init__(*_lowerCamelCase					,    **_lowerCamelCase							)
       lowercase__:     int      =   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__:     List[Any]      =   bool(getattr(self.model.config					,    '''aggregation_labels'''					,    _lowerCamelCase							)							) and bool(
           getattr(self.model.config					,    '''num_aggregation_labels'''					,    _lowerCamelCase							)							)
       lowercase__:     Union[str, Any]      =   """tapas""" if hasattr(self.model.config					,    '''aggregation_labels'''							) else None






    def _snake_case    (     self					,    **_UpperCAmelCase							):
       return self.model(**_lowerCamelCase							)






    def _snake_case    (     self					,    **_UpperCAmelCase							):

       if self.framework == "pt":
          lowercase__:     Optional[Any]      =   []
          lowercase__:     Union[str, Any]      =   []
          lowercase__:     Union[str, Any]      =   None
          lowercase__:     List[str]      =   inputs["""input_ids"""].shape[0]

          lowercase__:     Optional[Any]      =   inputs["""input_ids"""].to(self.device							)
          lowercase__:     List[Any]      =   inputs["""attention_mask"""].to(self.device							)
          lowercase__:     Dict      =   inputs["""token_type_ids"""].to(self.device							)
          lowercase__:     Optional[int]      =   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__:     int      =   token_type_ids_example[:, 3]  # shape (seq_len,)
                lowercase__:     List[str]      =   np.zeros_like(prev_labels_example.cpu().numpy()							)  # shape (seq_len,)

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

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

                lowercase__:     List[str]      =   torch.from_numpy(_lowerCamelCase							).type(torch.long							).to(self.device							)

             lowercase__:     Optional[int]      =   input_ids[index]
             lowercase__:     Any      =   attention_mask[index]  # shape (seq_len,)
             lowercase__:     str      =   token_type_ids[index]  # shape (seq_len, 7)
             lowercase__:     Any      =   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__:     List[str]      =   outputs.logits

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

             all_logits.append(_lowerCamelCase							)

             lowercase__:     List[Any]      =   torch.distributions.Bernoulli(logits=_lowerCamelCase							)
             lowercase__:     str      =   dist_per_token.probs * attention_mask_example.type(torch.floataa							).to(
                 dist_per_token.probs.device							)

             lowercase__:     List[Any]      =   collections.defaultdict(_lowerCamelCase							)
             for i, p in enumerate(probabilities.squeeze().tolist()							):
                lowercase__:     Optional[Any]      =   token_type_ids_example[:, 0].tolist()[i]
                lowercase__:     Tuple      =   token_type_ids_example[:, 1].tolist()[i] - 1
                lowercase__:     List[str]      =   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__:     int      =   {key: np.array(coords_to_probs[key]							).mean() > 0.5 for key in coords_to_probs}

          lowercase__:     Optional[Any]      =   torch.cat(tuple(_lowerCamelCase							)					,    0							)

          return (logits_batch,) if not self.aggregate else (logits_batch, torch.cat(tuple(_lowerCamelCase							)					,    0							))
       else:
          lowercase__:     Optional[int]      =   []
          lowercase__:     Tuple      =   []
          lowercase__:     List[str]      =   None
          lowercase__:     Union[str, Any]      =   inputs["""input_ids"""].shape[0]

          lowercase__:     Dict      =   inputs["""input_ids"""]
          lowercase__:     Tuple      =   inputs["""attention_mask"""]
          lowercase__:     Tuple      =   inputs["""token_type_ids"""].numpy()
          lowercase__:     Dict      =   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__:     int      =   token_type_ids_example[:, 3]  # shape (seq_len,)
                lowercase__:     List[Any]      =   np.zeros_like(_lowerCamelCase					,    dtype=np.intaa							)  # shape (seq_len,)

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

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

                lowercase__:     Dict      =   model_labels

             lowercase__:     int      =   input_ids[index]
             lowercase__:     int      =   attention_mask[index]  # shape (seq_len,)
             lowercase__:     Any      =   token_type_ids[index]  # shape (seq_len, 7)
             lowercase__:     Optional[int]      =   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__:     Dict      =   outputs.logits

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

             all_logits.append(_lowerCamelCase							)

             lowercase__:     List[str]      =   tfp.distributions.Bernoulli(logits=_lowerCamelCase							)
             lowercase__:     Dict      =   dist_per_token.probs_parameter() * tf.cast(_lowerCamelCase					,    tf.floataa							)

             lowercase__:     int      =   collections.defaultdict(_lowerCamelCase							)
             lowercase__:     List[Any]      =   token_type_ids_example
             for i, p in enumerate(tf.squeeze(_lowerCamelCase							).numpy().tolist()							):
                lowercase__:     Optional[int]      =   token_type_ids_example[:, 0].tolist()[i]
                lowercase__:     Dict      =   token_type_ids_example[:, 1].tolist()[i] - 1
                lowercase__:     str      =   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__:     Dict      =   {key: np.array(coords_to_probs[key]							).mean() > 0.5 for key in coords_to_probs}

          lowercase__:     Tuple      =   tf.concat(tuple(_lowerCamelCase							)					,    0							)

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






    def __call__(     self					,    *_UpperCAmelCase					,    **_UpperCAmelCase							):
       lowercase__:     str      =   self._args_parser(*_lowerCamelCase					,    **_lowerCamelCase							)

       lowercase__:     Any      =   super().__call__(_lowerCamelCase					,    **_lowerCamelCase							)
       if len(_lowerCamelCase							) == 1:
          return results[0]
       return results






    def _snake_case    (     self					,    _UpperCAmelCase=None					,    _UpperCAmelCase=None					,    _UpperCAmelCase=None					,    **_UpperCAmelCase							):
       lowercase__:     Optional[Any]      =   {}
       if padding is not None:
          lowercase__:     Optional[Any]      =   padding
       if truncation is not None:
          lowercase__:     Optional[Any]      =   truncation

       lowercase__:     List[str]      =   {}
       if sequential is not None:
          lowercase__:     str      =   sequential
       return preprocess_params, forward_params, {}






    def _snake_case    (     self					,    _UpperCAmelCase					,    _UpperCAmelCase=None					,    _UpperCAmelCase=True					,    _UpperCAmelCase=None							):

       if truncation is None:
          if self.type == "tapas":
             lowercase__:     Dict      =   """drop_rows_to_fit"""
          else:
             lowercase__:     Optional[int]      =   """do_not_truncate"""

       lowercase__:     Optional[int]      =   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__:     Optional[Any]      =   self.tokenizer(_lowerCamelCase					,    _lowerCamelCase					,    return_tensors=self.framework					,    truncation=_lowerCamelCase					,    padding=_lowerCamelCase							)
       lowercase__:     Optional[int]      =   table
       return inputs






    def _snake_case    (     self					,    _UpperCAmelCase					,    _UpperCAmelCase=False							):
       lowercase__:     Tuple      =   model_inputs.pop('''table'''							)

       if self.type == "tapas":
          if sequential:
             lowercase__:     Dict      =   self.sequential_inference(**_lowerCamelCase							)
          else:
             lowercase__:     Tuple      =   self.batch_inference(**_lowerCamelCase							)
       else:
          lowercase__:     Optional[Any]      =   self.model.generate(**_lowerCamelCase							)
       lowercase__:     int      =   {"""model_inputs""": model_inputs, """table""": table, """outputs""": outputs}
       return model_outputs






    def _snake_case    (     self					,    _UpperCAmelCase							):
       lowercase__:     str      =   model_outputs["""model_inputs"""]
       lowercase__:     Optional[Any]      =   model_outputs["""table"""]
       lowercase__:     Any      =   model_outputs["""outputs"""]
       if self.type == "tapas":
          if self.aggregate:
             lowercase__:     Optional[Any]      =   outputs[:2]
             lowercase__:     List[str]      =   self.tokenizer.convert_logits_to_predictions(_lowerCamelCase					,    _lowerCamelCase					,    _lowerCamelCase							)
             lowercase__:     Optional[int]      =   predictions
             lowercase__:     int      =   {i: self.model.config.aggregation_labels[pred] for i, pred in enumerate(_lowerCamelCase							)}

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

             answers.append(_lowerCamelCase							)
          if len(_lowerCamelCase							) == 0:
             raise PipelineException('''Empty answer'''							)
       else:
          lowercase__:     Optional[int]      =   [{"""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"""






def SCREAMING_SNAKE_CASE__    (     __UpperCAmelCase				)						->						int:
   if not isinstance(__UpperCAmelCase ,					__UpperCAmelCase				):
      lowercase__:     Optional[int]      =   F"""Input value of [number={number}] must be an integer"""
      raise TypeError(__UpperCAmelCase				)
   if number < 1:
      raise ValueError('''Input must be a positive integer'''				)
   return number * (2 * number - 1)


if __name__ == "__main__":
       import doctest

       doctest.testmod()
