from __future__ import annotations

import copy
import os
import tempfile
from importlib import import_module
from math import isnan

from transformers import is_tf_available
from transformers.models.auto import get_values
from transformers.testing_utils import _tf_gpu_memory_limit, require_tf, slow

from ..test_modeling_tf_common import ids_tensor


if is_tf_available():
     import numpy as np
     import tensorflow as tf

     from transformers import (
         TF_MODEL_FOR_CAUSAL_LM_MAPPING,
         TF_MODEL_FOR_IMAGE_CLASSIFICATION_MAPPING,
         TF_MODEL_FOR_MASKED_LM_MAPPING,
         TF_MODEL_FOR_MULTIPLE_CHOICE_MAPPING,
         TF_MODEL_FOR_NEXT_SENTENCE_PREDICTION_MAPPING,
         TF_MODEL_FOR_PRETRAINING_MAPPING,
         TF_MODEL_FOR_QUESTION_ANSWERING_MAPPING,
         TF_MODEL_FOR_SEQ_TO_SEQ_CAUSAL_LM_MAPPING,
         TF_MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING,
         TF_MODEL_FOR_TOKEN_CLASSIFICATION_MAPPING,
         TFSharedEmbeddings,
     )

     if _tf_gpu_memory_limit is not None:
          _SCREAMING_SNAKE_CASE   		=			tf.config.list_physical_devices("""GPU""")
          for gpu in gpus:
               # Restrict TensorFlow to only allocate x GB of memory on the GPUs
               try:
                    tf.config.set_logical_device_configuration(
                        gpu, [tf.config.LogicalDeviceConfiguration(memory_limit=_tf_gpu_memory_limit)]
                    )
                    _SCREAMING_SNAKE_CASE   		=			tf.config.list_logical_devices("""GPU""")
                    print("""Logical GPUs""", logical_gpus)
               except RuntimeError as e:
                    # Virtual devices must be set before GPUs have been initialized
                    print(e)
@require_tf
class SCREAMING_SNAKE_CASE_		:
   __lowerCAmelCase											=							None
   __lowerCAmelCase											=							()
   __lowerCAmelCase											=							()
   __lowerCAmelCase											=							True
   __lowerCAmelCase											=							True
   __lowerCAmelCase											=							True
   __lowerCAmelCase											=							False







   def 	lowerCamelCase_  (    self	:	Union[str, Any]      ,      lowerCamelCase_	:	int      ,      lowerCamelCase_	:	Tuple      ,      lowerCamelCase_	:	str=False							):





    """simple docstring"""


    UpperCamelCase      =			copy.deepcopy(lowerCamelCase_							)

    if model_class in get_values(lowerCamelCase_							):
     UpperCamelCase      =			{
         k: tf.tile(tf.expand_dims(lowerCamelCase_      ,      1							)      ,      (1, self.model_tester.num_choices) + (1,) * (v.ndim - 1)							)
         if isinstance(lowerCamelCase_      ,      tf.Tensor							) and v.ndim > 0
         else v
         for k, v in inputs_dict.items()
     }

    if return_labels:
     if model_class in get_values(lowerCamelCase_							):
      UpperCamelCase      =			tf.ones(self.model_tester.batch_size      ,      dtype=tf.intaa							)
     elif model_class in get_values(lowerCamelCase_							):
      UpperCamelCase      =			tf.zeros(self.model_tester.batch_size      ,      dtype=tf.intaa							)
      UpperCamelCase      =			tf.zeros(self.model_tester.batch_size      ,      dtype=tf.intaa							)
     elif model_class in [
         *get_values(lowerCamelCase_							),
         *get_values(lowerCamelCase_							),
     ]:
      UpperCamelCase      =			tf.zeros(self.model_tester.batch_size      ,      dtype=tf.intaa							)
     elif model_class in get_values(lowerCamelCase_							):
      UpperCamelCase      =			tf.zeros(self.model_tester.batch_size      ,      dtype=tf.intaa							)
     elif model_class in [
         *get_values(lowerCamelCase_							),
         *get_values(lowerCamelCase_							),
         *get_values(lowerCamelCase_							),
         *get_values(lowerCamelCase_							),
         *get_values(lowerCamelCase_							),
     ]:
      UpperCamelCase      =			tf.zeros(
          (self.model_tester.batch_size, self.model_tester.seq_length)      ,      dtype=tf.intaa							)
    return inputs_dict







   @slow
   def 	lowerCamelCase_  (    self	:	Tuple							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
    for model_class in self.all_model_classes[:2]:
     UpperCamelCase      =			self._prepare_for_class(lowerCamelCase_      ,      lowerCamelCase_							)
     UpperCamelCase      =			model_class(lowerCamelCase_							)

     @tf.function
     def run_in_graph_mode():
      return model(lowerCamelCase_							)

     UpperCamelCase      =			run_in_graph_mode()
     self.assertIsNotNone(lowerCamelCase_							)







   @slow
   def 	lowerCamelCase_  (    self	:	str							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
    for model_class in self.all_model_classes[:2]:
     UpperCamelCase      =			self._prepare_for_class(lowerCamelCase_      ,      lowerCamelCase_							)
     UpperCamelCase      =			model_class(lowerCamelCase_							)

     @tf.function(experimental_compile=lowerCamelCase_							)
     def run_in_graph_mode():
      return model(lowerCamelCase_							)

     UpperCamelCase      =			run_in_graph_mode()
     self.assertIsNotNone(lowerCamelCase_							)







   @slow
   def 	lowerCamelCase_  (    self	:	Any							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
    for model_class in self.all_model_classes[:2]:
     UpperCamelCase      =			model_class(lowerCamelCase_							)
     if getattr(lowerCamelCase_      ,      """hf_compute_loss"""      ,      lowerCamelCase_							):
      # Test that model correctly compute the loss with kwargs
      UpperCamelCase      =			self._prepare_for_class(inputs_dict.copy()      ,      lowerCamelCase_      ,      return_labels=lowerCamelCase_							)
      # Is there a better way to remove these decoder inputs?
      UpperCamelCase      =			{
          key: val
          for key, val in prepared_for_class.items()
          if key not in ("""head_mask""", """decoder_head_mask""", """cross_attn_head_mask""", """decoder_input_ids""")
      }

      UpperCamelCase      =			{
          """labels""",
          """label""",
          """label_ids""",
          """start_positions""",
          """start_position""",
          """end_positions""",
          """end_position""",
          """next_sentence_label""",
      }
      UpperCamelCase      =			possible_label_cols.intersection(set(lowerCamelCase_							)							)
      self.assertGreater(len(lowerCamelCase_							)      ,      0      ,      msg="""No matching label names found!"""							)
      UpperCamelCase      =			{key: val for key, val in prepared_for_class.items() if key in label_names}
      UpperCamelCase      =			{key: val for key, val in prepared_for_class.items() if key not in label_names}
      self.assertGreater(len(lowerCamelCase_							)      ,      0							)

      # Make sure it works with XLA!
      model.compile(optimizer=tf.keras.optimizers.SGD(0.0							)      ,      jit_compile=lowerCamelCase_							)
      # Make sure the model fits without crashing regardless of where we pass the labels
      UpperCamelCase      =			model.fit(
          lowerCamelCase_      ,      validation_data=lowerCamelCase_      ,      steps_per_epoch=1      ,      validation_steps=1      ,      shuffle=lowerCamelCase_      ,      verbose=0      ,      )
      UpperCamelCase      =			history.history["""loss"""][0]
      self.assertTrue(not isnan(lowerCamelCase_							)							)
      UpperCamelCase      =			history.history["""val_loss"""][0]
      self.assertTrue(not isnan(lowerCamelCase_							)							)

      # Now test it with separate labels, to make sure that path works in XLA too.
      UpperCamelCase      =			model_class(lowerCamelCase_							)
      model.compile(optimizer=tf.keras.optimizers.SGD(0.0							)      ,      jit_compile=lowerCamelCase_							)
      UpperCamelCase      =			model.fit(
          lowerCamelCase_      ,      lowerCamelCase_      ,      validation_data=(inputs_minus_labels, labels)      ,      steps_per_epoch=1      ,      validation_steps=1      ,      shuffle=lowerCamelCase_      ,      verbose=0      ,      )

      UpperCamelCase      =			history.history["""loss"""][0]
      self.assertTrue(not isnan(lowerCamelCase_							)							)
      UpperCamelCase      =			history.history["""val_loss"""][0]
      self.assertTrue(not isnan(lowerCamelCase_							)							)







   @slow
   def 	lowerCamelCase_  (    self	:	Tuple							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
    UpperCamelCase      =			True
    UpperCamelCase      =			True

    if hasattr(lowerCamelCase_      ,      """use_cache"""							):
     UpperCamelCase      =			True

    UpperCamelCase      =			getattr(self.model_tester      ,      """encoder_seq_length"""      ,      self.model_tester.seq_length							)
    UpperCamelCase      =			getattr(self.model_tester      ,      """key_length"""      ,      lowerCamelCase_							)

    for model_class in self.all_model_classes[:2]:
     UpperCamelCase      =			self._prepare_for_class(lowerCamelCase_      ,      lowerCamelCase_							)
     UpperCamelCase      =			model_class(lowerCamelCase_							)
     model.build()
     UpperCamelCase      =			len(model(lowerCamelCase_							)							)

     for key in list(class_inputs_dict.keys()							):
      # Remove keys not in the serving signature, as the SavedModel will not be compiled to deal with them
      if key not in model.input_signature:
       del class_inputs_dict[key]
      # Check it's a tensor, in case the inputs dict has some bools in it too
      elif isinstance(class_inputs_dict[key]      ,      tf.Tensor							) and class_inputs_dict[key].dtype.is_integer:
       UpperCamelCase      =			tf.cast(class_inputs_dict[key]      ,      tf.intaa							)

     if set(class_inputs_dict.keys()							) != set(model.input_signature.keys()							):
      continue  # Some models have inputs that the preparation functions don't create, we skip those

     with tempfile.TemporaryDirectory() as tmpdirname:
      model.save_pretrained(lowerCamelCase_      ,      saved_model=lowerCamelCase_							)
      UpperCamelCase      =			os.path.join(lowerCamelCase_      ,      """saved_model"""      ,      """1"""							)
      UpperCamelCase      =			tf.keras.models.load_model(lowerCamelCase_							)
      UpperCamelCase      =			model(lowerCamelCase_							)

      if self.is_encoder_decoder:
       UpperCamelCase      =			outputs["""encoder_hidden_states"""]
       UpperCamelCase      =			outputs["""encoder_attentions"""]
      else:
       UpperCamelCase      =			outputs["""hidden_states"""]
       UpperCamelCase      =			outputs["""attentions"""]

      self.assertEqual(len(lowerCamelCase_							)      ,      lowerCamelCase_							)

      UpperCamelCase      =			getattr(
          self.model_tester      ,      """expected_num_hidden_layers"""      ,      self.model_tester.num_hidden_layers + 1							)

      self.assertEqual(len(lowerCamelCase_							)      ,      lowerCamelCase_							)
      self.assertListEqual(
          list(output_hidden_states[0].shape[-2:]							)      ,      [self.model_tester.seq_length, self.model_tester.hidden_size]      ,      )

      self.assertEqual(len(lowerCamelCase_							)      ,      self.model_tester.num_hidden_layers							)
      self.assertListEqual(
          list(output_attentions[0].shape[-3:]							)      ,      [self.model_tester.num_attention_heads, encoder_seq_length, encoder_key_length]      ,      )







   @slow
   def 	lowerCamelCase_  (    self	:	str							):





    """simple docstring"""


    tf.keras.mixed_precision.set_global_policy("""mixed_float16"""							)

    # try/finally block to ensure subsequent tests run in float32
    try:
     UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
     for model_class in self.all_model_classes[:2]:
      UpperCamelCase      =			self._prepare_for_class(lowerCamelCase_      ,      lowerCamelCase_							)
      UpperCamelCase      =			model_class(lowerCamelCase_							)
      UpperCamelCase      =			model(lowerCamelCase_							)

      self.assertIsNotNone(lowerCamelCase_							)
    finally:
     tf.keras.mixed_precision.set_global_policy("""float32"""							)







   @slow
   def 	lowerCamelCase_  (    self	:	List[str]							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()
    # head_mask and decoder_head_mask has different shapes than other input args
    if "head_mask" in inputs_dict:
     del inputs_dict["head_mask"]
    if "decoder_head_mask" in inputs_dict:
     del inputs_dict["decoder_head_mask"]
    if "cross_attn_head_mask" in inputs_dict:
     del inputs_dict["cross_attn_head_mask"]
    UpperCamelCase      =			{
        module_member
        for model_class in self.all_model_classes
        for module in (import_module(model_class.__module__							),)
        for module_member_name in dir(lowerCamelCase_							)
        if module_member_name.endswith("""MainLayer"""							)
        for module_member in (getattr(lowerCamelCase_      ,      lowerCamelCase_							),)
        if isinstance(lowerCamelCase_      ,      lowerCamelCase_							)
        and tf.keras.layers.Layer in module_member.__bases__
        and getattr(lowerCamelCase_      ,      """_keras_serializable"""      ,      lowerCamelCase_							)
    }

    for main_layer_class in tf_main_layer_classes:
     # T5MainLayer needs an embed_tokens parameter when called without the inputs_embeds parameter
     if "T5" in main_layer_class.__name__:
      # Take the same values than in TFT5ModelTester for this shared layer
      UpperCamelCase      =			TFSharedEmbeddings(self.model_tester.vocab_size      ,      self.model_tester.hidden_size      ,      name="""shared"""							)
      UpperCamelCase      =			False
      UpperCamelCase      =			main_layer_class(lowerCamelCase_      ,      embed_tokens=lowerCamelCase_							)
     else:
      UpperCamelCase      =			main_layer_class(lowerCamelCase_							)

     UpperCamelCase      =			{
         name: tf.keras.Input(tensor.shape[1:]      ,      dtype=tensor.dtype							) for name, tensor in inputs_dict.items()
     }

     if hasattr(self.model_tester      ,      """num_labels"""							):
      UpperCamelCase      =			self.model_tester.num_labels
     else:
      UpperCamelCase      =			2

     UpperCamelCase      =			tf.data.Dataset.from_tensor_slices(
         (inputs_dict, np.ones((self.model_tester.batch_size, self.model_tester.seq_length, num_labels, 1)							))							).batch(1							)

     UpperCamelCase      =			main_layer(lowerCamelCase_							)[0]
     UpperCamelCase      =			tf.keras.layers.Dense(lowerCamelCase_      ,      activation="""softmax"""      ,      name="""outputs"""							)(lowerCamelCase_							)
     UpperCamelCase      =			tf.keras.models.Model(inputs=lowerCamelCase_      ,      outputs=[outputs]							)

     model.compile(loss="""binary_crossentropy"""      ,      optimizer="""adam"""      ,      metrics=["""binary_accuracy"""]							)
     model.fit(lowerCamelCase_      ,      epochs=1							)

     with tempfile.TemporaryDirectory() as tmpdirname:
      UpperCamelCase      =			os.path.join(lowerCamelCase_      ,      """keras_model.h5"""							)
      model.save(lowerCamelCase_							)
      if "T5" in main_layer_class.__name__:
       UpperCamelCase      =			tf.keras.models.load_model(
           lowerCamelCase_      ,      custom_objects={
               main_layer_class.__name__: main_layer_class,
               """TFSharedEmbeddings""": TFSharedEmbeddings,
           }      ,      )
      else:
       UpperCamelCase      =			tf.keras.models.load_model(
           lowerCamelCase_      ,      custom_objects={main_layer_class.__name__: main_layer_class}							)
      assert isinstance(lowerCamelCase_      ,      tf.keras.Model							)
      model(lowerCamelCase_							)







   @slow
   def 	lowerCamelCase_  (    self	:	Optional[int]							):





    """simple docstring"""


    UpperCamelCase     ,    UpperCamelCase      =			self.model_tester.prepare_config_and_inputs_for_common()

    for model_class in self.all_model_classes[:2]:
     UpperCamelCase      =			model_class(lowerCamelCase_							)

     UpperCamelCase      =			copy.deepcopy(lowerCamelCase_							)

     if not self.is_encoder_decoder:
      UpperCamelCase      =			inputs["""input_ids"""]
      del inputs["input_ids"]
     else:
      UpperCamelCase      =			inputs["""input_ids"""]
      UpperCamelCase      =			inputs.get("""decoder_input_ids"""      ,      lowerCamelCase_							)
      del inputs["input_ids"]
      inputs.pop("""decoder_input_ids"""      ,      lowerCamelCase_							)

     if not self.is_encoder_decoder:
      UpperCamelCase      =			model.get_input_embeddings()(lowerCamelCase_							)
     else:
      UpperCamelCase      =			model.get_input_embeddings()(lowerCamelCase_							)
      UpperCamelCase      =			model.get_input_embeddings()(lowerCamelCase_							)

     UpperCamelCase      =			self._prepare_for_class(lowerCamelCase_      ,      lowerCamelCase_							)

     @tf.function
     def run_in_graph_mode():
      return model(lowerCamelCase_							)

     UpperCamelCase      =			run_in_graph_mode()
     self.assertIsNotNone(lowerCamelCase_							)







   def 	lowerCamelCase_  (    self	:	Union[str, Any]      ,      lowerCamelCase_	:	int      ,      lowerCamelCase_	:	List[Any]							):





    """simple docstring"""


    UpperCamelCase      =			[]
    if model.config.bos_token_id is not None:
     special_tokens.append(model.config.bos_token_id							)
    if model.config.pad_token_id is not None:
     special_tokens.append(model.config.pad_token_id							)
    if model.config.eos_token_id is not None:
     special_tokens.append(model.config.eos_token_id							)

    # create random bad tokens that are not special tokens
    UpperCamelCase      =			[]
    while len(lowerCamelCase_							) < num_bad_tokens:
     UpperCamelCase      =			tf.squeeze(ids_tensor((1, 1)      ,      self.model_tester.vocab_size							)      ,      0							).numpy()[0]
     if token not in special_tokens:
      bad_tokens.append(lowerCamelCase_							)
    return bad_tokens







   def 	lowerCamelCase_  (    self	:	Dict      ,      lowerCamelCase_	:	Optional[Any]							):





    """simple docstring"""


    for token_id in output_ids[0].numpy().tolist():
     self.assertGreaterEqual(lowerCamelCase_      ,      0							)
     self.assertLess(lowerCamelCase_      ,      self.model_tester.vocab_size							)







   def 	lowerCamelCase_  (    self	:	Union[str, Any]      ,      lowerCamelCase_	:	Optional[int]      ,      lowerCamelCase_	:	str							):





    """simple docstring"""


    for bad_word_ids in bad_words_ids:
     # for all slices in batch
     for generated_ids_slice in generated_ids:
      # for all word idx
      for i in range(len(lowerCamelCase_							)      ,      len(lowerCamelCase_							)							):
       # if tokens match
       if generated_ids_slice[i - len(lowerCamelCase_							) : i] == bad_word_ids:
        return True
    return False

from typing import TYPE_CHECKING

from ...utils import (
    OptionalDependencyNotAvailable,
    _LazyModule,
    is_torch_available,
)


_SCREAMING_SNAKE_CASE   		=			{
    """configuration_align""": [
        """ALIGN_PRETRAINED_CONFIG_ARCHIVE_MAP""",
        """AlignConfig""",
        """AlignTextConfig""",
        """AlignVisionConfig""",
    ],
    """processing_align""": ["""AlignProcessor"""],
}

try:
     if not is_torch_available():
          raise OptionalDependencyNotAvailable()
except OptionalDependencyNotAvailable:
     pass
else:
     _SCREAMING_SNAKE_CASE   		=			[
         """ALIGN_PRETRAINED_MODEL_ARCHIVE_LIST""",
         """AlignModel""",
         """AlignPreTrainedModel""",
         """AlignTextModel""",
         """AlignVisionModel""",
     ]

if TYPE_CHECKING:
     from .configuration_align import (
         ALIGN_PRETRAINED_CONFIG_ARCHIVE_MAP,
         AlignConfig,
         AlignTextConfig,
         AlignVisionConfig,
     )
     from .processing_align import AlignProcessor

     try:
          if not is_torch_available():
               raise OptionalDependencyNotAvailable()
     except OptionalDependencyNotAvailable:
          pass
     else:
          from .modeling_align import (
              ALIGN_PRETRAINED_MODEL_ARCHIVE_LIST,
              AlignModel,
              AlignPreTrainedModel,
              AlignTextModel,
              AlignVisionModel,
          )

else:
     import sys

     _SCREAMING_SNAKE_CASE   		=			_LazyModule(__name__, globals()["""__file__"""], _import_structure, module_spec=__spec__)
