






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







		'''simple docstring'''



		def __call__(							self       ,	_UpperCamelCase=None       ,	_UpperCamelCase=None       ,	**_UpperCamelCase     )			->							Any:
							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(_UpperCamelCase       ,	_UpperCamelCase     ) and table.get('query'     ) is not None and table.get('table'     ) is not None:
																	UpperCAmelCase_					:   Tuple   =		[table]
												elif isinstance(_UpperCamelCase       ,	_UpperCamelCase     ) and len(_UpperCamelCase     ) > 0:
																	if not all(isinstance(_UpperCamelCase       ,	_UpperCamelCase     ) for d in table     ):
																						raise ValueError(
																						    f"Keyword argument `table` should be a list of dict, but is {(type(_UpperCamelCase     ) for d in table)}"     )

																	if table[0].get('query'     ) is not None and table[0].get('table'     ) is not None:
																						UpperCAmelCase_					:   int   =		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(_UpperCamelCase       ,	_UpperCamelCase     ) or isinstance(_UpperCamelCase       ,	types.GeneratorType     ):
																	return table
												else:
																	raise ValueError(
																	    'Invalid input. Keyword argument `table` should be either of type `dict` or `list`, but '
																	    f"is {type(_UpperCamelCase     )})"     )
							else:
												UpperCAmelCase_					:   Dict   =		[{"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_					:   Tuple   =		pd.DataFrame(tqa_pipeline_input['table']     )

							return tqa_pipeline_inputs





@add_end_docstrings(lowerCamelCase_    )
class 						lowerCamelCase   (lowerCamelCase_    ):







		'''simple docstring'''



		_snake_case					:					List[Any] 		=						"""table,query"""



		def __init__(							self       ,	_UpperCamelCase=TableQuestionAnsweringArgumentHandler()       ,	*_UpperCamelCase       ,	**_UpperCamelCase     )			->							Optional[int]:
							super().__init__(*_UpperCamelCase       ,	**_UpperCamelCase     )
							UpperCAmelCase_					:   Optional[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()     )     )

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



		def       __UpperCAmelCase    (							self       ,	**_UpperCamelCase     )			->							Tuple:
							return self.model(**_UpperCamelCase     )



		def       __UpperCAmelCase    (							self       ,	**_UpperCamelCase     )			->							Optional[Any]:







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

												UpperCAmelCase_					:   int   =		inputs["input_ids"].to(self.device     )
												UpperCAmelCase_					:   str   =		inputs["attention_mask"].to(self.device     )
												UpperCAmelCase_					:   Optional[Any]   =		inputs["token_type_ids"].to(self.device     )
												UpperCAmelCase_					:   List[str]   =		None

												for index in range(_UpperCamelCase     ):
																	# 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_					:   Tuple   =		token_type_ids_example[:, 3]  # shape (seq_len,)
																						UpperCAmelCase_					:   str   =		np.zeros_like(prev_labels_example.cpu().numpy()     )  # shape (seq_len,)

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

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

																						UpperCAmelCase_					:   Any   =		torch.from_numpy(_UpperCamelCase     ).type(torch.long     ).to(self.device     )

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

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

																	all_logits.append(_UpperCamelCase     )

																	UpperCAmelCase_					:   Optional[Any]   =		torch.distributions.Bernoulli(logits=_UpperCamelCase     )
																	UpperCAmelCase_					:   Union[str, Any]   =		dist_per_token.probs * attention_mask_example.type(torch.floataa     ).to(
																	    dist_per_token.probs.device     )

																	UpperCAmelCase_					:   int   =		collections.defaultdict(_UpperCamelCase     )
																	for i, p in enumerate(probabilities.squeeze().tolist()     ):
																						UpperCAmelCase_					:   str   =		token_type_ids_example[:, 0].tolist()[i]
																						UpperCAmelCase_					:   Union[str, Any]   =		token_type_ids_example[:, 1].tolist()[i] - 1
																						UpperCAmelCase_					:   List[Any]   =		token_type_ids_example[:, 2].tolist()[i] - 1
																						if col >= 0 and row >= 0 and segment_id == 1:
																											coords_to_probs[(col, row)].append(_UpperCamelCase     )

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

												UpperCAmelCase_					:   Optional[int]   =		torch.cat(tuple(_UpperCamelCase     )       ,	0     )

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

												UpperCAmelCase_					:   Tuple   =		inputs["input_ids"]
												UpperCAmelCase_					:   Optional[int]   =		inputs["attention_mask"]
												UpperCAmelCase_					:   Dict   =		inputs["token_type_ids"].numpy()
												UpperCAmelCase_					:   Dict   =		None

												for index in range(_UpperCamelCase     ):
																	# 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_					:   Optional[int]   =		token_type_ids_example[:, 3]  # shape (seq_len,)
																						UpperCAmelCase_					:   Optional[int]   =		np.zeros_like(_UpperCamelCase       ,	dtype=np.intaa     )  # shape (seq_len,)

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

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

																						UpperCAmelCase_					:   Tuple   =		model_labels

																	UpperCAmelCase_					:   List[Any]   =		input_ids[index]
																	UpperCAmelCase_					:   List[str]   =		attention_mask[index]  # shape (seq_len,)
																	UpperCAmelCase_					:   Union[str, Any]   =		token_type_ids[index]  # shape (seq_len, 7)
																	UpperCAmelCase_					:   List[Any]   =		self.model(
																	    input_ids=np.expand_dims(_UpperCamelCase       ,	axis=0     )       ,	attention_mask=np.expand_dims(_UpperCamelCase       ,	axis=0     )       ,	token_type_ids=np.expand_dims(_UpperCamelCase       ,	axis=0     )       ,	)
																	UpperCAmelCase_					:   str   =		outputs.logits

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

																	all_logits.append(_UpperCamelCase     )

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

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

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

												UpperCAmelCase_					:   str   =		tf.concat(tuple(_UpperCamelCase     )       ,	0     )

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



		def __call__(							self       ,	*_UpperCamelCase       ,	**_UpperCamelCase     )			->							int:
							UpperCAmelCase_					:   Optional[Any]   =		self._args_parser(*_UpperCamelCase       ,	**_UpperCamelCase     )

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



		def       __UpperCAmelCase    (							self       ,	_UpperCamelCase=None       ,	_UpperCamelCase=None       ,	_UpperCamelCase=None       ,	**_UpperCamelCase     )			->							Tuple:
							UpperCAmelCase_					:   Optional[Any]   =		{}
							if padding is not None:
												UpperCAmelCase_					:   List[Any]   =		padding
							if truncation is not None:
												UpperCAmelCase_					:   int   =		truncation

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



		def       __UpperCAmelCase    (							self       ,	_UpperCamelCase       ,	_UpperCamelCase=None       ,	_UpperCamelCase=True       ,	_UpperCamelCase=None     )			->							Optional[Any]:







							if truncation is None:
												if self.type == "tapas":
																	UpperCAmelCase_					:   List[Any]   =		"drop_rows_to_fit"
												else:
																	UpperCAmelCase_					:   Union[str, Any]   =		"do_not_truncate"

							UpperCAmelCase_					:   Dict   =		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_					:   Union[str, Any]   =		self.tokenizer(_UpperCamelCase       ,	_UpperCamelCase       ,	return_tensors=self.framework       ,	truncation=_UpperCamelCase       ,	padding=_UpperCamelCase     )
							UpperCAmelCase_					:   Optional[int]   =		table
							return inputs



		def       __UpperCAmelCase    (							self       ,	_UpperCamelCase       ,	_UpperCamelCase=False     )			->							List[str]:
							UpperCAmelCase_					:   Dict   =		model_inputs.pop('table'     )

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



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

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

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

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














from typing import TYPE_CHECKING

from ...utils import _LazyModule


__UpperCAmelCase										=		{'tokenization_phobert': ['PhobertTokenizer']}


if TYPE_CHECKING:
		from .tokenization_phobert import PhobertTokenizer

else:
		import sys

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






