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							:					Optional[Any]				,      lowercase_							:					Union[str, Any]=None				,      lowercase_							:					Any=None				,      **lowercase_							:					List[str])		->     int:


   """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:
       _UpperCamelCase				=  [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:
         _UpperCamelCase				=  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:
     _UpperCamelCase				=  [{"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.")

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

   return tqa_pipeline_inputs




@add_end_docstrings(lowerCAmelCase   )
class  _UpperCAmelCase       (			lowerCAmelCase   ):



 '''simple docstring'''




 __A           = '''table,query'''







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


   """simple docstring"""







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

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







 def 						__UpperCAmelCase							(						self							:					Optional[int]				,      **lowercase_							:					Dict)		->     Any:


   """simple docstring"""







   return self.model(**lowercase_)







 def 						__UpperCAmelCase							(						self							:					int				,      **lowercase_							:					Tuple)		->     Optional[Any]:


   """simple docstring"""







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

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

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

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

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

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

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

       all_logits.append(lowercase_)

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

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

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

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

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

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

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

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

         _UpperCamelCase				=  model_labels

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

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

       all_logits.append(lowercase_)

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

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

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

     _UpperCamelCase				=  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]				,      *lowercase_							:					Union[str, Any]				,      **lowercase_							:					Any)		->     Tuple:


   """simple docstring"""







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

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







 def 						__UpperCAmelCase							(						self							:					List[Any]				,      lowercase_							:					List[Any]=None				,      lowercase_							:					Union[str, Any]=None				,      lowercase_							:					Union[str, Any]=None				,      **lowercase_							:					Optional[int])		->     Union[str, Any]:


   """simple docstring"""







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

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







 def 						__UpperCAmelCase							(						self							:					Optional[int]				,      lowercase_							:					List[Any]				,      lowercase_							:					int=None				,      lowercase_							:					List[Any]=True				,      lowercase_							:					List[str]=None)		->     Union[str, Any]:


   """simple docstring"""







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

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







 def 						__UpperCAmelCase							(						self							:					Union[str, Any]				,      lowercase_							:					Union[str, Any]				,      lowercase_							:					str=False)		->     List[Any]:


   """simple docstring"""







   _UpperCamelCase				=  model_inputs.pop("table")

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







 def 						__UpperCAmelCase							(						self							:					Tuple				,      lowercase_							:					Tuple)		->     Optional[int]:


   """simple docstring"""







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

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

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

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





from typing import TYPE_CHECKING

# rely on isort to merge the imports
from ...utils import OptionalDependencyNotAvailable, _LazyModule, is_sentencepiece_available, is_torch_available


lowerCamelCase__   = {
    '''configuration_ernie_m''': ['''ERNIE_M_PRETRAINED_CONFIG_ARCHIVE_MAP''', '''ErnieMConfig'''],
}

try:
   if not is_sentencepiece_available():
      raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
   pass
else:
   lowerCamelCase__   = ['''ErnieMTokenizer''']

try:
   if not is_torch_available():
      raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
   pass
else:
   lowerCamelCase__   = [
       '''ERNIE_M_PRETRAINED_MODEL_ARCHIVE_LIST''',
       '''ErnieMForMultipleChoice''',
       '''ErnieMForQuestionAnswering''',
       '''ErnieMForSequenceClassification''',
       '''ErnieMForTokenClassification''',
       '''ErnieMModel''',
       '''ErnieMPreTrainedModel''',
       '''ErnieMForInformationExtraction''',
   ]


if TYPE_CHECKING:
   from .configuration_ernie_m import ERNIE_M_PRETRAINED_CONFIG_ARCHIVE_MAP, ErnieMConfig

   try:
      if not is_sentencepiece_available():
         raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
      pass
   else:
      from .tokenization_ernie_m import ErnieMTokenizer

   try:
      if not is_torch_available():
         raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
      pass
   else:
      from .modeling_ernie_m import (
          ERNIE_M_PRETRAINED_MODEL_ARCHIVE_LIST,
          ErnieMForInformationExtraction,
          ErnieMForMultipleChoice,
          ErnieMForQuestionAnswering,
          ErnieMForSequenceClassification,
          ErnieMForTokenClassification,
          ErnieMModel,
          ErnieMPreTrainedModel,
      )


else:
   import sys

   lowerCamelCase__   = _LazyModule(__name__, globals()['''__file__'''], _import_structure, module_spec=__spec__)




