



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    (    snake_case_					):





   def __call__(						self							,  _lowerCAmelCase=None							,  _lowerCAmelCase=None							,  **_lowerCAmelCase      ):
         # 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:
                     _lowerCAmelCase			      =	[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:
                           _lowerCAmelCase			      =	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:
               _lowerCAmelCase			      =	[{'''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.'''      )

                     _lowerCAmelCase			      =	pd.DataFrame(tqa_pipeline_input['''table''']      )

         return tqa_pipeline_inputs






@add_end_docstrings(snake_case_					)
class 		UpperCAmelCase    (    snake_case_					):
   SCREAMING_SNAKE_CASE__					      =  '''table,query'''





   def __init__(						self							,  _lowerCAmelCase=TableQuestionAnsweringArgumentHandler()							,  *_lowerCAmelCase							,  **_lowerCAmelCase      ):
         super().__init__(*_lowerCAmelCase							,  **_lowerCAmelCase      )
         _lowerCAmelCase			      =	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()      )      )

         _lowerCAmelCase			      =	bool(getattr(self.model.config							,  '''aggregation_labels'''							,  _lowerCAmelCase      )      ) and bool(
             getattr(self.model.config							,  '''num_aggregation_labels'''							,  _lowerCAmelCase      )      )
         _lowerCAmelCase			      =	'''tapas''' if hasattr(self.model.config							,  '''aggregation_labels'''      ) else None





   def 						__lowerCAmelCase				(						self							,  **_lowerCAmelCase      ):
         return self.model(**_lowerCAmelCase      )





   def 						__lowerCAmelCase				(						self							,  **_lowerCAmelCase      ):
         if self.framework == "pt":
               _lowerCAmelCase			      =	[]
               _lowerCAmelCase			      =	[]
               _lowerCAmelCase			      =	None
               _lowerCAmelCase			      =	inputs['''input_ids'''].shape[0]

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

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

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

                           _lowerCAmelCase			      =	torch.from_numpy(_lowerCAmelCase      ).type(torch.long      ).to(self.device      )

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

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

                     all_logits.append(_lowerCAmelCase      )

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

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

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

               _lowerCAmelCase			      =	torch.cat(tuple(_lowerCAmelCase      )							,  0      )

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

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

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

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

                           _lowerCAmelCase			      =	model_labels

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

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

                     all_logits.append(_lowerCAmelCase      )

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

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

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

               _lowerCAmelCase			      =	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      ):
         _lowerCAmelCase			      =	self._args_parser(*_lowerCAmelCase							,  **_lowerCAmelCase      )

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





   def 						__lowerCAmelCase				(						self							,  _lowerCAmelCase=None							,  _lowerCAmelCase=None							,  _lowerCAmelCase=None							,  **_lowerCAmelCase      ):
         _lowerCAmelCase			      =	{}
         if padding is not None:
               _lowerCAmelCase			      =	padding
         if truncation is not None:
               _lowerCAmelCase			      =	truncation

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





   def 						__lowerCAmelCase				(						self							,  _lowerCAmelCase							,  _lowerCAmelCase=None							,  _lowerCAmelCase=True							,  _lowerCAmelCase=None      ):
         if truncation is None:
               if self.type == "tapas":
                     _lowerCAmelCase			      =	'''drop_rows_to_fit'''
               else:
                     _lowerCAmelCase			      =	'''do_not_truncate'''

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





   def 						__lowerCAmelCase				(						self							,  _lowerCAmelCase							,  _lowerCAmelCase=False      ):
         _lowerCAmelCase			      =	model_inputs.pop('''table'''      )

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





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

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

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

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




def 				UpperCAmelCase__		(					_SCREAMING_SNAKE_CASE :						float  ,					_SCREAMING_SNAKE_CASE :						float					)->float:
      _lowerCAmelCase			      =	float()
      try:
            _lowerCAmelCase			      =	mass * acceleration
      except Exception:
            return -0.0
      return force


if __name__ == "__main__":
    import doctest

    # run doctest
    doctest.testmod()

    # demo
    UpperCAmelCase_          =				12.5
    UpperCAmelCase_          =				1_0
    UpperCAmelCase_          =				newtons_second_law_of_motion(mass, acceleration)
    print("The force is ", force, "N")