


'''simple docstring'''






import unittest
from pathlib import Path
from tempfile import NamedTemporaryFile, TemporaryDirectory

from transformers import BertConfig, BertTokenizerFast, FeatureExtractionPipeline
from transformers.convert_graph_to_onnx import (
    convert,
    ensure_valid_input,
    generate_identified_filename,
    infer_shapes,
    quantize,
)
from transformers.testing_utils import require_tf, require_tokenizers, require_torch, slow
class 						__UpperCamelCase	:





							def 		a__   (  self		:Optional[int]  ,_UpperCamelCase		:Dict  ,_UpperCamelCase		:Optional[Any]  ,_UpperCamelCase		:Tuple			):
									return None





class 						__UpperCamelCase	:





							def 		a__   (  self		:Optional[int]  ,_UpperCamelCase		:List[str]  ,_UpperCamelCase		:List[Any]  ,_UpperCamelCase		:List[str]  ,_UpperCamelCase		:Tuple			):
									return None





class 						__UpperCamelCase	(						unittest.TestCase							):
							lowercase			:		str   		=  [
							    # (model_name, model_kwargs)
							    ('bert-base-cased', {}),
							    ('gpt2', {'use_cache': False}),  # We don't support exporting GPT2 past keys anymore
							]





							@require_tf
							@slow
							def 		a__   (  self		:int			):
									for model, model_kwargs in OnnxExportTestCase.MODEL_TO_TEST:
											self._test_export(_UpperCamelCase  ,"""tf"""  ,1_2  ,**_UpperCamelCase			)





							@require_torch
							@slow
							def 		a__   (  self		:Union[str, Any]			):
									for model, model_kwargs in OnnxExportTestCase.MODEL_TO_TEST:
											self._test_export(_UpperCamelCase  ,"""pt"""  ,1_2  ,**_UpperCamelCase			)





							@require_torch
							@slow
							def 		a__   (  self		:int			):
									from transformers import BertModel

									snake_case_		:							Optional[Any]			       =						["""[UNK]""", """[SEP]""", """[CLS]""", """[PAD]""", """[MASK]""", """some""", """other""", """words"""]
									with NamedTemporaryFile(mode="""w+t"""			) as vocab_file:
											vocab_file.write("""\n""".join(_UpperCamelCase			)			)
											vocab_file.flush()
											snake_case_		:							List[Any]			       =						BertTokenizerFast(vocab_file.name			)

									with TemporaryDirectory() as bert_save_dir:
											snake_case_		:							int			       =						BertModel(BertConfig(vocab_size=len(_UpperCamelCase			)			)			)
											model.save_pretrained(_UpperCamelCase			)
											self._test_export(_UpperCamelCase  ,"""pt"""  ,1_2  ,_UpperCamelCase			)





							@require_tf
							@slow
							def 		a__   (  self		:str			):
									for model, model_kwargs in OnnxExportTestCase.MODEL_TO_TEST:
											snake_case_		:							Optional[Any]			       =						self._test_export(_UpperCamelCase  ,"""tf"""  ,1_2  ,**_UpperCamelCase			)
											snake_case_		:							Any			       =						quantize(Path(_UpperCamelCase			)			)

											# Ensure the actual quantized model is not bigger than the original one
											if quantized_path.stat().st_size >= Path(_UpperCamelCase			).stat().st_size:
													self.fail("""Quantized model is bigger than initial ONNX model"""			)





							@require_torch
							@slow
							def 		a__   (  self		:List[str]			):
									for model, model_kwargs in OnnxExportTestCase.MODEL_TO_TEST:
											snake_case_		:							List[str]			       =						self._test_export(_UpperCamelCase  ,"""pt"""  ,1_2  ,**_UpperCamelCase			)
											snake_case_		:							Tuple			       =						quantize(_UpperCamelCase			)

											# Ensure the actual quantized model is not bigger than the original one
											if quantized_path.stat().st_size >= Path(_UpperCamelCase			).stat().st_size:
													self.fail("""Quantized model is bigger than initial ONNX model"""			)





							def 		a__   (  self		:Optional[Any]  ,_UpperCamelCase		:List[Any]  ,_UpperCamelCase		:Dict  ,_UpperCamelCase		:int  ,_UpperCamelCase		:Dict=None  ,**_UpperCamelCase		:str			):
									try:
											# Compute path
											with TemporaryDirectory() as tempdir:
													snake_case_		:							List[str]			       =						Path(_UpperCamelCase			).joinpath("""model.onnx"""			)

											# Remove folder if exists
											if path.parent.exists():
													path.parent.rmdir()

											# Export
											convert(_UpperCamelCase  ,_UpperCamelCase  ,_UpperCamelCase  ,_UpperCamelCase  ,_UpperCamelCase  ,**_UpperCamelCase			)

											return path
									except Exception as e:
											self.fail(_UpperCamelCase			)





							@require_torch
							@require_tokenizers
							@slow
							def 		a__   (  self		:str			):
									from transformers import BertModel

									snake_case_		:							List[Any]			       =						BertModel(BertConfig.from_pretrained("""lysandre/tiny-bert-random"""			)			)
									snake_case_		:							Tuple			       =						BertTokenizerFast.from_pretrained("""lysandre/tiny-bert-random"""			)
									self._test_infer_dynamic_axis(_UpperCamelCase  ,_UpperCamelCase  ,"""pt"""			)





							@require_tf
							@require_tokenizers
							@slow
							def 		a__   (  self		:List[str]			):
									from transformers import TFBertModel

									snake_case_		:							int			       =						TFBertModel(BertConfig.from_pretrained("""lysandre/tiny-bert-random"""			)			)
									snake_case_		:							Optional[int]			       =						BertTokenizerFast.from_pretrained("""lysandre/tiny-bert-random"""			)
									self._test_infer_dynamic_axis(_UpperCamelCase  ,_UpperCamelCase  ,"""tf"""			)





							def 		a__   (  self		:Union[str, Any]  ,_UpperCamelCase		:Dict  ,_UpperCamelCase		:List[Any]  ,_UpperCamelCase		:Optional[int]			):
									snake_case_		:							int			       =						FeatureExtractionPipeline(_UpperCamelCase  ,_UpperCamelCase			)

									snake_case_		:							str			       =						["""input_ids""", """token_type_ids""", """attention_mask""", """output_0""", """output_1"""]
									snake_case_       ,      snake_case_       ,      snake_case_       ,      snake_case_		:							Dict			       =						infer_shapes(_UpperCamelCase  ,_UpperCamelCase			)

									# Assert all variables are present
									self.assertEqual(len(_UpperCamelCase			)  ,len(_UpperCamelCase			)			)
									self.assertTrue(all(var_name in shapes for var_name in variable_names			)			)
									self.assertSequenceEqual(variable_names[:3]  ,_UpperCamelCase			)
									self.assertSequenceEqual(variable_names[3:]  ,_UpperCamelCase			)

									# Assert inputs are {0: batch, 1: sequence}
									for var_name in ["input_ids", "token_type_ids", "attention_mask"]:
											self.assertDictEqual(shapes[var_name]  ,{0: """batch""", 1: """sequence"""}			)

									# Assert outputs are {0: batch, 1: sequence} and {0: batch}
									self.assertDictEqual(shapes["""output_0"""]  ,{0: """batch""", 1: """sequence"""}			)
									self.assertDictEqual(shapes["""output_1"""]  ,{0: """batch"""}			)





							def 		a__   (  self		:List[str]			):
									snake_case_		:							Union[str, Any]			       =						["""input_ids""", """attention_mask""", """token_type_ids"""]
									snake_case_		:							List[str]			       =						{"""input_ids""": [1, 2, 3, 4], """attention_mask""": [0, 0, 0, 0], """token_type_ids""": [1, 1, 1, 1]}
									snake_case_       ,      snake_case_		:							int			       =						ensure_valid_input(FuncContiguousArgs()  ,_UpperCamelCase  ,_UpperCamelCase			)

									# Should have exactly the same number of args (all are valid)
									self.assertEqual(len(_UpperCamelCase			)  ,3			)

									# Should have exactly the same input names
									self.assertEqual(set(_UpperCamelCase			)  ,set(_UpperCamelCase			)			)

									# Parameter should be reordered according to their respective place in the function:
									# (input_ids, token_type_ids, attention_mask)
									self.assertEqual(_UpperCamelCase  ,(tokens["""input_ids"""], tokens["""token_type_ids"""], tokens["""attention_mask"""])			)

									# Generated args are interleaved with another args (for instance parameter "past" in GPT2)
									snake_case_       ,      snake_case_		:							Any			       =						ensure_valid_input(FuncNonContiguousArgs()  ,_UpperCamelCase  ,_UpperCamelCase			)

									# Should have exactly the one arg (all before the one not provided "some_other_args")
									self.assertEqual(len(_UpperCamelCase			)  ,1			)
									self.assertEqual(len(_UpperCamelCase			)  ,1			)

									# Should have only "input_ids"
									self.assertEqual(inputs_args[0]  ,tokens["""input_ids"""]			)
									self.assertEqual(ordered_input_names[0]  ,"""input_ids"""			)





							def 		a__   (  self		:Union[str, Any]			):
									snake_case_		:							Optional[Any]			       =						generate_identified_filename(Path("""/home/something/my_fake_model.onnx"""			)  ,"""-test"""			)
									self.assertEqual("""/home/something/my_fake_model-test.onnx"""  ,generated.as_posix()			)



'''simple docstring'''






import logging

import torch
from torch import nn
from torch.nn import CrossEntropyLoss, MSELoss

from transformers.file_utils import add_start_docstrings, add_start_docstrings_to_model_forward
from transformers.models.bert.modeling_bert import (
    BERT_INPUTS_DOCSTRING,
    BERT_START_DOCSTRING,
    BertEncoder,
    BertModel,
    BertPreTrainedModel,
)


__A	:	Any     =     logging.getLogger(__name__)
class 						__UpperCamelCase	(						lowercase__							):





							def 		a__   (  self		:int  ,_UpperCamelCase		:Union[str, Any]  ,_UpperCamelCase		:Optional[Any]  ,_UpperCamelCase		:List[Any]=None  ,_UpperCamelCase		:Any=None			):
									snake_case_		:							List[str]			       =						self.layer[current_layer](_UpperCamelCase  ,_UpperCamelCase  ,head_mask[current_layer]			)

									snake_case_		:							Tuple			       =						layer_outputs[0]

									return hidden_states





@add_start_docstrings(
    'The bare Bert Model transformer with PABEE outputting raw hidden-states without any specific head on top.'						,  lowercase__						,  )
class 						__UpperCamelCase	(						lowercase__							):





							def __init__(  self		:Dict  ,_UpperCamelCase		:Optional[Any]			):
									super().__init__(_UpperCamelCase			)

									snake_case_		:							List[Any]			       =						BertEncoderWithPabee(_UpperCamelCase			)

									self.init_weights()
									snake_case_		:							int			       =						0
									snake_case_		:							Optional[Any]			       =						0
									snake_case_		:							Any			       =						0

									snake_case_		:							str			       =						0





							def 		a__   (  self		:Tuple  ,_UpperCamelCase		:int			):
									snake_case_		:							Optional[Any]			       =						threshold





							def 		a__   (  self		:Optional[Any]  ,_UpperCamelCase		:Union[str, Any]			):
									snake_case_		:							str			       =						patience





							def 		a__   (  self		:Optional[int]			):
									snake_case_		:							List[str]			       =						0
									snake_case_		:							List[Any]			       =						0





							def 		a__   (  self		:List[Any]			):
									snake_case_		:							str			       =						self.inference_layers_num / self.inference_instances_num
									snake_case_		:							List[str]			       =						(
									    F'''*** Patience = {self.patience} Avg. Inference Layers = {avg_inf_layers:.2f} Speed Up ='''
									    F''' {1 - avg_inf_layers / self.config.num_hidden_layers:.2f} ***'''
									)
									print(_UpperCamelCase			)





							@add_start_docstrings_to_model_forward(_UpperCamelCase			)
							def 		a__   (  self		:Optional[Any]  ,_UpperCamelCase		:Any=None  ,_UpperCamelCase		:List[str]=None  ,_UpperCamelCase		:Any=None  ,_UpperCamelCase		:Optional[int]=None  ,_UpperCamelCase		:Optional[int]=None  ,_UpperCamelCase		:int=None  ,_UpperCamelCase		:Optional[int]=None  ,_UpperCamelCase		:Any=None  ,_UpperCamelCase		:int=None  ,_UpperCamelCase		:Union[str, Any]=None  ,_UpperCamelCase		:int=False  ,):

									if input_ids is not None and inputs_embeds is not None:
											raise ValueError("""You cannot specify both input_ids and inputs_embeds at the same time"""			)
									elif input_ids is not None:
											snake_case_		:							Any			       =						input_ids.size()
									elif inputs_embeds is not None:
											snake_case_		:							Union[str, Any]			       =						inputs_embeds.size()[:-1]
									else:
											raise ValueError("""You have to specify either input_ids or inputs_embeds"""			)

									snake_case_		:							Tuple			       =						input_ids.device if input_ids is not None else inputs_embeds.device

									if attention_mask is None:
											snake_case_		:							Any			       =						torch.ones(_UpperCamelCase  ,device=_UpperCamelCase			)
									if token_type_ids is None:
											snake_case_		:							str			       =						torch.zeros(_UpperCamelCase  ,dtype=torch.long  ,device=_UpperCamelCase			)

									# We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]
									# ourselves in which case we just need to make it broadcastable to all heads.
									snake_case_		:							torch.Tensor			       =						self.get_extended_attention_mask(_UpperCamelCase  ,_UpperCamelCase  ,_UpperCamelCase			)

									# If a 2D ou 3D attention mask is provided for the cross-attention
									# we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length]
									if self.config.is_decoder and encoder_hidden_states is not None:
											snake_case_       ,      snake_case_       ,      snake_case_		:							List[Any]			       =						encoder_hidden_states.size()
											snake_case_		:							str			       =						(encoder_batch_size, encoder_sequence_length)
											if encoder_attention_mask is None:
													snake_case_		:							List[str]			       =						torch.ones(_UpperCamelCase  ,device=_UpperCamelCase			)
											snake_case_		:							Optional[Any]			       =						self.invert_attention_mask(_UpperCamelCase			)
									else:
											snake_case_		:							List[str]			       =						None

									# Prepare head mask if needed
									# 1.0 in head_mask indicate we keep the head
									# attention_probs has shape bsz x n_heads x N x N
									# input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]
									# and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]
									snake_case_		:							List[Any]			       =						self.get_head_mask(_UpperCamelCase  ,self.config.num_hidden_layers			)

									snake_case_		:							Dict			       =						self.embeddings(
									    input_ids=_UpperCamelCase  ,position_ids=_UpperCamelCase  ,token_type_ids=_UpperCamelCase  ,inputs_embeds=_UpperCamelCase			)
									snake_case_		:							Optional[int]			       =						embedding_output

									if self.training:
											snake_case_		:							Any			       =						[]
											for i in range(self.config.num_hidden_layers			):
													snake_case_		:							Any			       =						self.encoder.adaptive_forward(
													    _UpperCamelCase  ,current_layer=_UpperCamelCase  ,attention_mask=_UpperCamelCase  ,head_mask=_UpperCamelCase			)

													snake_case_		:							Dict			       =						self.pooler(_UpperCamelCase			)
													snake_case_		:							str			       =						output_layers[i](output_dropout(_UpperCamelCase			)			)
													res.append(_UpperCamelCase			)
									elif self.patience == 0:  # Use all layers for inference
											snake_case_		:							List[str]			       =						self.encoder(
											    _UpperCamelCase  ,attention_mask=_UpperCamelCase  ,head_mask=_UpperCamelCase  ,encoder_hidden_states=_UpperCamelCase  ,encoder_attention_mask=_UpperCamelCase  ,)
											snake_case_		:							int			       =						self.pooler(encoder_outputs[0]			)
											snake_case_		:							Tuple			       =						[output_layers[self.config.num_hidden_layers - 1](_UpperCamelCase			)]
									else:
											snake_case_		:							Any			       =						0
											snake_case_		:							List[str]			       =						None
											snake_case_		:							Any			       =						0
											for i in range(self.config.num_hidden_layers			):
													calculated_layer_num += 1
													snake_case_		:							Dict			       =						self.encoder.adaptive_forward(
													    _UpperCamelCase  ,current_layer=_UpperCamelCase  ,attention_mask=_UpperCamelCase  ,head_mask=_UpperCamelCase			)

													snake_case_		:							Union[str, Any]			       =						self.pooler(_UpperCamelCase			)
													snake_case_		:							Optional[Any]			       =						output_layers[i](_UpperCamelCase			)
													if regression:
															snake_case_		:							Union[str, Any]			       =						logits.detach()
															if patient_result is not None:
																	snake_case_		:							Union[str, Any]			       =						patient_result.detach()
															if (patient_result is not None) and torch.abs(patient_result - labels			) < self.regression_threshold:
																	patient_counter += 1
															else:
																	snake_case_		:							Union[str, Any]			       =						0
													else:
															snake_case_		:							Any			       =						logits.detach().argmax(dim=1			)
															if patient_result is not None:
																	snake_case_		:							str			       =						patient_result.detach().argmax(dim=1			)
															if (patient_result is not None) and torch.all(labels.eq(_UpperCamelCase			)			):
																	patient_counter += 1
															else:
																	snake_case_		:							List[str]			       =						0

													snake_case_		:							List[Any]			       =						logits
													if patient_counter == self.patience:
															break
											snake_case_		:							int			       =						[patient_result]
											self.inference_layers_num += calculated_layer_num
											self.inference_instances_num += 1

									return res





@add_start_docstrings(
    'Bert Model transformer with PABEE and a sequence classification/regression head on top (a linear layer on top of\n    the pooled output) e.g. for GLUE tasks. '						,  lowercase__						,  )
class 						__UpperCamelCase	(						lowercase__							):





							def __init__(  self		:Tuple  ,_UpperCamelCase		:List[str]			):
									super().__init__(_UpperCamelCase			)
									snake_case_		:							List[str]			       =						config.num_labels

									snake_case_		:							Dict			       =						BertModelWithPabee(_UpperCamelCase			)
									snake_case_		:							List[str]			       =						nn.Dropout(config.hidden_dropout_prob			)
									snake_case_		:							str			       =						nn.ModuleList(
									    [nn.Linear(config.hidden_size  ,self.config.num_labels			) for _ in range(config.num_hidden_layers			)]			)

									self.init_weights()





							@add_start_docstrings_to_model_forward(_UpperCamelCase			)
							def 		a__   (  self		:Union[str, Any]  ,_UpperCamelCase		:Tuple=None  ,_UpperCamelCase		:Dict=None  ,_UpperCamelCase		:Union[str, Any]=None  ,_UpperCamelCase		:Union[str, Any]=None  ,_UpperCamelCase		:Tuple=None  ,_UpperCamelCase		:int=None  ,_UpperCamelCase		:Union[str, Any]=None  ,):
									snake_case_		:							int			       =						self.bert(
									    input_ids=_UpperCamelCase  ,attention_mask=_UpperCamelCase  ,token_type_ids=_UpperCamelCase  ,position_ids=_UpperCamelCase  ,head_mask=_UpperCamelCase  ,inputs_embeds=_UpperCamelCase  ,output_dropout=self.dropout  ,output_layers=self.classifiers  ,regression=self.num_labels == 1  ,)

									snake_case_		:							Optional[int]			       =						(logits[-1],)

									if labels is not None:
											snake_case_		:							Optional[Any]			       =						None
											snake_case_		:							Optional[int]			       =						0
											for ix, logits_item in enumerate(_UpperCamelCase			):
													if self.num_labels == 1:
															#  We are doing regression
															snake_case_		:							Dict			       =						MSELoss()
															snake_case_		:							List[str]			       =						loss_fct(logits_item.view(-1			)  ,labels.view(-1			)			)
													else:
															snake_case_		:							Any			       =						CrossEntropyLoss()
															snake_case_		:							str			       =						loss_fct(logits_item.view(-1  ,self.num_labels			)  ,labels.view(-1			)			)
													if total_loss is None:
															snake_case_		:							str			       =						loss
													else:
															total_loss += loss * (ix + 1)
													total_weights += ix + 1
											snake_case_		:							str			       =						(total_loss / total_weights,) + outputs

									return outputs