






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 					__lowercase					(		lowercase_     ):







     '''simple docstring'''




     def __call__( self				:	Optional[Any]       ,		UpperCamelCase_				:	Union[str, Any]=None       ,		UpperCamelCase_				:	Any=None       ,		**UpperCamelCase_				:	List[str] ):


         """simple docstring"""



         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(lowercase_       ,		lowercase_ ) and table.get("""query""" ) is not None and table.get("""table""" ) is not None:
                 __A   			=		[table]
             elif isinstance(lowercase_       ,		lowercase_ ) and len(lowercase_ ) > 0:
                 if not all(isinstance(lowercase_       ,		lowercase_ ) for d in table ):
                     raise ValueError(
                         F"Keyword argument `table` should be a list of dict, but is {(type(lowercase_ ) for d in table)}" )

                 if table[0].get("""query""" ) is not None and table[0].get("""table""" ) is not None:
                     __A   			=		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(lowercase_       ,		lowercase_ ) or isinstance(lowercase_       ,		types.GeneratorType ):
                 return table
             else:
                 raise ValueError(
                     """Invalid input. Keyword argument `table` should be either of type `dict` or `list`, but """
                     F"is {type(lowercase_ )})" )
         else:
             __A   			=		[{"""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.""" )

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

         return tqa_pipeline_inputs


@add_end_docstrings(lowercase_     )
class 					__lowercase					(		lowercase_     ):







     '''simple docstring'''
     SCREAMING_SNAKE_CASE        = "table,query"




     def __init__( self				:	Union[str, Any]       ,		UpperCamelCase_				:	List[Any]=TableQuestionAnsweringArgumentHandler()       ,		*UpperCamelCase_				:	Tuple       ,		**UpperCamelCase_				:	Any ):


         """simple docstring"""



         super().__init__(*lowercase_       ,		**lowercase_ )
         __A   			=		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() ) )

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




     def 						lowerCAmelCase_   ( self				:	Optional[int]       ,		**UpperCamelCase_				:	Dict ):


         """simple docstring"""



         return self.model(**lowercase_ )




     def 						lowerCAmelCase_   ( self				:	int       ,		**UpperCamelCase_				:	Tuple ):


         """simple docstring"""



         if self.framework == "pt":
             __A   			=		[]
             __A   			=		[]
             __A   			=		None
             __A   			=		inputs["""input_ids"""].shape[0]

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

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

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

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

                     __A   			=		torch.from_numpy(lowercase_ ).type(torch.long ).to(self.device )

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

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

                 all_logits.append(lowercase_ )

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

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

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

             __A   			=		torch.cat(tuple(lowercase_ )       ,		0 )

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

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

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

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

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

                     __A   			=		model_labels

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

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

                 all_logits.append(lowercase_ )

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

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

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

             __A   			=		tf.concat(tuple(lowercase_ )       ,		0 )

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




     def __call__( self				:	Union[str, Any]       ,		*UpperCamelCase_				:	Union[str, Any]       ,		**UpperCamelCase_				:	Any ):


         """simple docstring"""



         __A   			=		self._args_parser(*lowercase_       ,		**lowercase_ )

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




     def 						lowerCAmelCase_   ( self				:	List[Any]       ,		UpperCamelCase_				:	List[Any]=None       ,		UpperCamelCase_				:	Union[str, Any]=None       ,		UpperCamelCase_				:	Union[str, Any]=None       ,		**UpperCamelCase_				:	Optional[int] ):


         """simple docstring"""



         __A   			=		{}
         if padding is not None:
             __A   			=		padding
         if truncation is not None:
             __A   			=		truncation

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




     def 						lowerCAmelCase_   ( self				:	Optional[int]       ,		UpperCamelCase_				:	List[Any]       ,		UpperCamelCase_				:	int=None       ,		UpperCamelCase_				:	List[Any]=True       ,		UpperCamelCase_				:	List[str]=None ):


         """simple docstring"""



         if truncation is None:
             if self.type == "tapas":
                 __A   			=		"""drop_rows_to_fit"""
             else:
                 __A   			=		"""do_not_truncate"""

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




     def 						lowerCAmelCase_   ( self				:	Union[str, Any]       ,		UpperCamelCase_				:	Union[str, Any]       ,		UpperCamelCase_				:	str=False ):


         """simple docstring"""



         __A   			=		model_inputs.pop("""table""" )

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





     def 						lowerCAmelCase_   ( self				:	Tuple       ,		UpperCamelCase_				:	Tuple ):


         """simple docstring"""



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

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

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

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





lowerCamelCase__   = '''
# Transformers installation
! pip install transformers datasets
# To install from source instead of the last release, comment the command above and uncomment the following one.
# ! pip install git+https://github.com/huggingface/transformers.git
'''

lowerCamelCase__   = [{'''type''': '''code''', '''content''': INSTALL_CONTENT}]
lowerCamelCase__   = {
    '''{processor_class}''': '''FakeProcessorClass''',
    '''{model_class}''': '''FakeModelClass''',
    '''{object_class}''': '''FakeObjectClass''',
}




