


import gc
import unittest

import numpy as np
import torch
from transformers import CLIPTextConfig, CLIPTextModel, CLIPTextModelWithProjection, CLIPTokenizer

from diffusers import (
    AutoencoderKL,
    DiffusionPipeline,
    EulerDiscreteScheduler,
    StableDiffusionXLPipeline,
    UNetaDConditionModel,
)
from diffusers.utils import slow, torch_device
from diffusers.utils.testing_utils import enable_full_determinism, require_torch_gpu

from ..pipeline_params import TEXT_TO_IMAGE_BATCH_PARAMS, TEXT_TO_IMAGE_IMAGE_PARAMS, TEXT_TO_IMAGE_PARAMS
from ..test_pipelines_common import PipelineLatentTesterMixin, PipelineTesterMixin


enable_full_determinism()




class 			lowercase_				(lowercase__			,				lowercase__			,				unittest.TestCase      ):
				snake_case  						=StableDiffusionXLPipeline
				snake_case  						=TEXT_TO_IMAGE_PARAMS
				snake_case  						=TEXT_TO_IMAGE_BATCH_PARAMS
				snake_case  						=TEXT_TO_IMAGE_IMAGE_PARAMS
				snake_case  						=TEXT_TO_IMAGE_IMAGE_PARAMS





				def 	__UpperCamelCase						(							self)     ->   Union[str, Any]:
											torch.manual_seed(0)
											a__     						=UNetaDConditionModel(
											    block_out_channels=(32, 64)					,     layers_per_block=2					,     sample_size=32					,     in_channels=4					,     out_channels=4					,     down_block_types=('DownBlock2D', 'CrossAttnDownBlock2D')					,     up_block_types=('CrossAttnUpBlock2D', 'UpBlock2D')					,     attention_head_dim=(2, 4)					,     use_linear_projection=lowercase_					,     addition_embed_type='text_time'					,     addition_time_embed_dim=8					,     transformer_layers_per_block=(1, 2)					,     projection_class_embeddings_input_dim=80					,     cross_attention_dim=64					,     )
											a__     						=EulerDiscreteScheduler(
											    beta_start=0.0_00_85					,     beta_end=0.0_12					,     steps_offset=1					,     beta_schedule='scaled_linear'					,     timestep_spacing='leading'					,     )
											torch.manual_seed(0)
											a__     						=AutoencoderKL(
											    block_out_channels=[32, 64]					,     in_channels=3					,     out_channels=3					,     down_block_types=['DownEncoderBlock2D', 'DownEncoderBlock2D']					,     up_block_types=['UpDecoderBlock2D', 'UpDecoderBlock2D']					,     latent_channels=4					,     sample_size=128					,     )
											torch.manual_seed(0)
											a__     						=CLIPTextConfig(
											    bos_token_id=0					,     eos_token_id=2					,     hidden_size=32					,     intermediate_size=37					,     layer_norm_eps=1e-05					,     num_attention_heads=4					,     num_hidden_layers=5					,     pad_token_id=1					,     vocab_size=1000					,     hidden_act='gelu'					,     projection_dim=32					,     )
											a__     						=CLIPTextModel(lowercase_)
											a__     						=CLIPTokenizer.from_pretrained('hf-internal-testing/tiny-random-clip'					,     local_files_only=lowercase_)

											a__     						=CLIPTextModelWithProjection(lowercase_)
											a__     						=CLIPTokenizer.from_pretrained('hf-internal-testing/tiny-random-clip'					,     local_files_only=lowercase_)

											a__     						={
											    'unet': unet,
											    'scheduler': scheduler,
											    'vae': vae,
											    'text_encoder': text_encoder,
											    'tokenizer': tokenizer,
											    'text_encoder_2': text_encoder_a,
											    'tokenizer_2': tokenizer_a,
											    # "safety_checker": None,
											    # "feature_extractor": None,
											}
											return components





				def 	__UpperCamelCase						(							self					,     lowercase_					,     lowercase_=0)     ->   int:
											if str(lowercase_).startswith('mps'):
																		a__     						=torch.manual_seed(lowercase_)
											else:
																		a__     						=torch.Generator(device=lowercase_).manual_seed(lowercase_)
											a__     						={
											    'prompt': 'A painting of a squirrel eating a burger',
											    'generator': generator,
											    'num_inference_steps': 2,
											    'guidance_scale': 5.0,
											    'output_type': 'numpy',
											}
											return inputs





				def 	__UpperCamelCase						(							self)     ->   Optional[Any]:
											a__     						='cpu'  # ensure determinism for the device-dependent torch.Generator
											a__     						=self.get_dummy_components()
											a__     						=StableDiffusionXLPipeline(**lowercase_)
											a__     						=sd_pipe.to(lowercase_)
											sd_pipe.set_progress_bar_config(disable=lowercase_)

											a__     						=self.get_dummy_inputs(lowercase_)
											a__     						=sd_pipe(**lowercase_).images
											a__     						=image[0, -3:, -3:, -1]

											assert image.shape == (1, 64, 64, 3)
											a__     						=np.array([0.58_73, 0.61_28, 0.47_97, 0.51_22, 0.56_74, 0.46_39, 0.52_27, 0.51_49, 0.47_47])

											assert np.abs(image_slice.flatten() - expected_slice).max() < 1e-2





				def 	__UpperCamelCase						(							self)     ->   str:
											a__     						=self.get_dummy_components()
											a__     						=StableDiffusionXLPipeline(**lowercase_)
											a__     						=sd_pipe.to(lowercase_)
											a__     						=sd_pipe.to(lowercase_)
											sd_pipe.set_progress_bar_config(disable=lowercase_)

											# forward without prompt embeds
											a__     						=self.get_dummy_inputs(lowercase_)
											a__     						=3 * ['this is a negative prompt']
											a__     						=negative_prompt
											a__     						=3 * [inputs['prompt']]

											a__     						=sd_pipe(**lowercase_)
											a__     						=output.images[0, -3:, -3:, -1]

											# forward with prompt embeds
											a__     						=self.get_dummy_inputs(lowercase_)
											a__     						=3 * ['this is a negative prompt']
											a__     						=3 * [inputs.pop('prompt')]

											(
											    (
											    a__    
											)						,    (
											    a__    
											)						,    (
											    a__    
											)						,    (
											    a__    
											)						,        
											)     						=sd_pipe.encode_prompt(lowercase_					,     negative_prompt=lowercase_)

											a__     						=sd_pipe(
											    **lowercase_					,     prompt_embeds=lowercase_					,     negative_prompt_embeds=lowercase_					,     pooled_prompt_embeds=lowercase_					,     negative_pooled_prompt_embeds=lowercase_					,     )
											a__     						=output.images[0, -3:, -3:, -1]

											# make sure that it's equal
											assert np.abs(image_slice_a.flatten() - image_slice_a.flatten()).max() < 1e-4





				def 	__UpperCamelCase						(							self)     ->   str:
											super().test_attention_slicing_forward_pass(expected_max_diff=3e-3)





				def 	__UpperCamelCase						(							self)     ->   Union[str, Any]:
											super().test_inference_batch_single_identical(expected_max_diff=3e-3)







@slow
@require_torch_gpu
class 			lowercase_				(unittest.TestCase      ):





				def 	__UpperCamelCase						(							self)     ->   Dict:
											super().tearDown()
											gc.collect()
											torch.cuda.empty_cache()





				def 	__UpperCamelCase						(							self					,     lowercase_					,     lowercase_="cpu"					,     lowercase_=torch.floataa					,     lowercase_=0)     ->   Dict:
											a__     						=torch.Generator(device=lowercase_).manual_seed(lowercase_)
											a__     						=np.random.RandomState(lowercase_).standard_normal((1, 4, 64, 64))
											a__     						=torch.from_numpy(lowercase_).to(device=lowercase_					,     dtype=lowercase_)
											a__     						={
											    'prompt': 'a photograph of an astronaut riding a horse',
											    'latents': latents,
											    'generator': generator,
											    'num_inference_steps': 3,
											    'guidance_scale': 7.5,
											    'output_type': 'numpy',
											}
											return inputs





				def 	__UpperCamelCase						(							self)     ->   List[str]:
											a__     						=DiffusionPipeline.from_pretrained('stabilityai/stable-diffusion-2-base')
											pipe.to(lowercase_)
											pipe.set_progress_bar_config(disable=lowercase_)

											a__     						=self.get_inputs(lowercase_)
											a__     						=pipe(**lowercase_).images
											a__     						=image[0, -3:, -3:, -1].flatten()

											assert image.shape == (1, 512, 512, 3)
											a__     						=np.array([0.4_94_93, 0.4_78_96, 0.4_07_98, 0.5_42_14, 0.5_32_12, 0.4_82_02, 0.4_76_56, 0.4_63_29, 0.4_85_06])
											assert np.abs(image_slice - expected_slice).max() < 7e-3





import inspect
import os
from argparse import ArgumentParser, Namespace
from importlib import import_module

import huggingface_hub
import numpy as np
from packaging import version

from .. import (
    FEATURE_EXTRACTOR_MAPPING,
    IMAGE_PROCESSOR_MAPPING,
    PROCESSOR_MAPPING,
    TOKENIZER_MAPPING,
    AutoConfig,
    AutoFeatureExtractor,
    AutoImageProcessor,
    AutoProcessor,
    AutoTokenizer,
    is_datasets_available,
    is_tf_available,
    is_torch_available,
)
from ..utils import TF2_WEIGHTS_INDEX_NAME, TF2_WEIGHTS_NAME, logging
from . import BaseTransformersCLICommand


if is_tf_available():
	import tensorflow as tf

	tf.config.experimental.enable_tensor_float_aa_execution(False)

if is_torch_available():
	import torch

if is_datasets_available():
	from datasets import load_dataset


_lowerCAmelCase:	Optional[Any]      							=					5e-5  # larger error tolerance than in our internal tests, to avoid flaky user-facing errors






def      _lowercase(				__a							:	Namespace    ):
							return PTtoTFCommand(
							    args.model_name						,    args.local_dir						,    args.max_error						,    args.new_weights						,    args.no_pr						,    args.push						,    args.extra_commit_description						,    args.override_model_class						,    )







class 			lowercase_				(lowercase__      ):





				@staticmethod
				def 	__UpperCamelCase						(							lowercase_)     ->   int:
											a__     						=parser.add_parser(
											    'pt-to-tf'					,     help=(
											        'CLI tool to run convert a transformers model from a PyTorch checkpoint to a TensorFlow checkpoint.'
											        ' Can also be used to validate existing weights without opening PRs, with --no-pr.'
											    )					,     )
											train_parser.add_argument(
											    '--model-name'					,     type=lowercase_					,     required=lowercase_					,     help='The model name, including owner/organization, as seen on the hub.'					,     )
											train_parser.add_argument(
											    '--local-dir'					,     type=lowercase_					,     default=''					,     help='Optional local directory of the model repository. Defaults to /tmp/{model_name}'					,     )
											train_parser.add_argument(
											    '--max-error'					,     type=lowercase_					,     default=lowercase_					,     help=(
											        F"""Maximum error tolerance. Defaults to {MAX_ERROR}. This flag should be avoided, use at your own risk."""
											    )					,     )
											train_parser.add_argument(
											    '--new-weights'					,     action='store_true'					,     help='Optional flag to create new TensorFlow weights, even if they already exist.'					,     )
											train_parser.add_argument(
											    '--no-pr'					,     action='store_true'					,     help='Optional flag to NOT open a PR with converted weights.')
											train_parser.add_argument(
											    '--push'					,     action='store_true'					,     help='Optional flag to push the weights directly to `main` (requires permissions)'					,     )
											train_parser.add_argument(
											    '--extra-commit-description'					,     type=lowercase_					,     default=''					,     help='Optional additional commit description to use when opening a PR (e.g. to tag the owner).'					,     )
											train_parser.add_argument(
											    '--override-model-class'					,     type=lowercase_					,     default=lowercase_					,     help='If you think you know better than the auto-detector, you can specify the model class here. '
											    'Can be either an AutoModel class or a specific model class like BertForSequenceClassification.'					,     )
											train_parser.set_defaults(func=lowercase_)





				@staticmethod
				def 	__UpperCamelCase						(							lowercase_					,     lowercase_)     ->   Optional[int]:
											a__     						=set(pt_outputs.keys())
											a__     						=set(tf_outputs.keys())
											if pt_out_attrs != tf_out_attrs:
																		raise ValueError(
																		    F"""The model outputs have different attributes, aborting. (Pytorch: {pt_out_attrs}, TensorFlow:"""
																		    F""" {tf_out_attrs})""")

											# 2. For each output attribute, computes the difference
											def _find_pt_tf_differences(lowercase_					,     lowercase_					,     lowercase_					,     lowercase_=""):
																		# If the current attribute is a tensor, it is a leaf and we make the comparison. Otherwise, we will dig in
																		# recursivelly, keeping the name of the attribute.
																		if isinstance(lowercase_					,     torch.Tensor):
																									a__     						=np.max(np.abs(pt_out.numpy() - tf_out.numpy()))
																									a__     						=tensor_difference
																		else:
																									a__     						=attr_name
																									for i, pt_item in enumerate(lowercase_):
																																# If it is a named attribute, we keep the name. Otherwise, just its index.
																																if isinstance(lowercase_					,     lowercase_):
																																							a__     						=root_name + pt_item
																																							a__     						=tf_out[pt_item]
																																							a__     						=pt_out[pt_item]
																																else:
																																							a__     						=root_name + F"""[{i}]"""
																																							a__     						=tf_out[i]
																																a__     						=_find_pt_tf_differences(lowercase_					,     lowercase_					,     lowercase_					,     lowercase_)

																		return differences

											return _find_pt_tf_differences(lowercase_					,     lowercase_					,     {})





				def __init__(							self					,     lowercase_					,     lowercase_					,     lowercase_					,     lowercase_					,     lowercase_					,     lowercase_					,     lowercase_					,     lowercase_					,     *lowercase_					,     )     ->   str:
											a__     						=logging.get_logger('transformers-cli/pt_to_tf')
											a__     						=model_name
											a__     						=local_dir if local_dir else os.path.join('/tmp'					,     lowercase_)
											a__     						=max_error
											a__     						=new_weights
											a__     						=no_pr
											a__     						=push
											a__     						=extra_commit_description
											a__     						=override_model_class





				def 	__UpperCamelCase						(							self					,     lowercase_					,     lowercase_					,     lowercase_)     ->   List[Any]:

											def _get_audio_input():
																		a__     						=load_dataset('hf-internal-testing/librispeech_asr_dummy'					,     'clean'					,     split='validation')
																		a__     						=ds.sort('id').select(range(2))[:2]['audio']
																		a__     						=[x['array'] for x in speech_samples]
																		return raw_samples

											a__     						=type(pt_model.config)
											if model_config_class in PROCESSOR_MAPPING:
																		a__     						=AutoProcessor.from_pretrained(self._local_dir)
																		if model_config_class in TOKENIZER_MAPPING and processor.tokenizer.pad_token is None:
																									a__     						=processor.tokenizer.eos_token
											elif model_config_class in IMAGE_PROCESSOR_MAPPING:
																		a__     						=AutoImageProcessor.from_pretrained(self._local_dir)
											elif model_config_class in FEATURE_EXTRACTOR_MAPPING:
																		a__     						=AutoFeatureExtractor.from_pretrained(self._local_dir)
											elif model_config_class in TOKENIZER_MAPPING:
																		a__     						=AutoTokenizer.from_pretrained(self._local_dir)
																		if processor.pad_token is None:
																									a__     						=processor.eos_token
											else:
																		raise ValueError(F"""Unknown data processing type (model config type: {model_config_class})""")

											a__     						=set(inspect.signature(pt_model.forward).parameters.keys())
											a__     						={}
											if "input_ids" in model_forward_signature:
																		processor_inputs.update(
																		    {
																		        'text': ['Hi there!', 'I am a batch with more than one row and different input lengths.'],
																		        'padding': True,
																		        'truncation': True,
																		    })
											if "pixel_values" in model_forward_signature:
																		a__     						=load_dataset('cifar10'					,     'plain_text'					,     split='test')[:2]['img']
																		processor_inputs.update({'images': sample_images})
											if "input_features" in model_forward_signature:
																		a__     						=inspect.signature(processor.feature_extractor).parameters
																		# Pad to the largest input length by default but take feature extractor default
																		# padding value if it exists e.g. "max_length" and is not False or None
																		if "padding" in feature_extractor_signature:
																									a__     						=feature_extractor_signature['padding'].default
																									if default_strategy is not False and default_strategy is not None:
																																a__     						=default_strategy
																									else:
																																a__     						=True
																		else:
																									a__     						=True
																		processor_inputs.update({'audio': _get_audio_input(), 'padding': padding_strategy})
											if "input_values" in model_forward_signature:  # Wav2Vec2 audio input
																		processor_inputs.update({'audio': _get_audio_input(), 'padding': True})
											a__     						=processor(**lowercase_					,     return_tensors='pt')
											a__     						=processor(**lowercase_					,     return_tensors='tf')

											# Extra input requirements, in addition to the input modality
											if (
											    config.is_encoder_decoder
											    or (hasattr(lowercase_					,     'encoder') and hasattr(lowercase_					,     'decoder'))
											    or "decoder_input_ids" in tf_dummy_inputs
											):
																		a__     						=np.asarray([[1], [1]]					,     dtype=lowercase_) * (pt_model.config.decoder_start_token_id or 0)
																		pt_input.update({'decoder_input_ids': torch.tensor(lowercase_)})
																		tf_input.update({'decoder_input_ids': tf.convert_to_tensor(lowercase_)})

											return pt_input, tf_input





				def 	__UpperCamelCase						(							self)     ->   str:
											# hub version 0.9.0 introduced the possibility of programmatically opening PRs with normal write tokens.
											if version.parse(huggingface_hub.__version__) < version.parse('0.9.0'):
																		raise ImportError(
																		    'The huggingface_hub version must be >= 0.9.0 to use this command. Please update your huggingface_hub'
																		    ' installation.')
											else:
																		from huggingface_hub import Repository, create_commit
																		from huggingface_hub._commit_api import CommitOperationAdd

											# Fetch remote data
											a__     						=Repository(local_dir=self._local_dir					,     clone_from=self._model_name)

											# Load config and get the appropriate architecture -- the latter is needed to convert the head's weights
											a__     						=AutoConfig.from_pretrained(self._local_dir)
											a__     						=config.architectures
											if self._override_model_class is not None:
																		if self._override_model_class.startswith('TF'):
																									a__     						=[self._override_model_class[2:]]
																		else:
																									a__     						=[self._override_model_class]
																		try:
																									a__     						=getattr(import_module('transformers')					,     architectures[0])
																		except AttributeError:
																									raise ValueError(F"""Model class {self._override_model_class} not found in transformers.""")
																		try:
																									a__     						=getattr(import_module('transformers')					,     'TF' + architectures[0])
																		except AttributeError:
																									raise ValueError(F"""TF model class TF{self._override_model_class} not found in transformers.""")
											elif architectures is None:  # No architecture defined -- use auto classes
																		a__     						=getattr(import_module('transformers')					,     'AutoModel')
																		a__     						=getattr(import_module('transformers')					,     'TFAutoModel')
																		self._logger.warning('No detected architecture, using AutoModel/TFAutoModel')
											else:  # Architecture defined -- use it
																		if len(lowercase_) > 1:
																									raise ValueError(F"""More than one architecture was found, aborting. (architectures = {architectures})""")
																		self._logger.warning(F"""Detected architecture: {architectures[0]}""")
																		a__     						=getattr(import_module('transformers')					,     architectures[0])
																		try:
																									a__     						=getattr(import_module('transformers')					,     'TF' + architectures[0])
																		except AttributeError:
																									raise AttributeError(F"""The TensorFlow equivalent of {architectures[0]} doesn't exist in transformers.""")

        # Check the TF dummy inputs to see what keys we need in the forward pass
											a__     						=tf_class.from_config(lowercase_)
											a__     						=tf_from_pt_model.dummy_inputs

											del tf_from_pt_model  # Try to keep only one model in memory at a time

											# Load the model and get some basic inputs
											a__     						=pt_class.from_pretrained(self._local_dir)
											pt_model.eval()

											a__						,    a__     						=self.get_inputs(lowercase_					,     lowercase_					,     lowercase_)

											with torch.no_grad():
																		a__     						=pt_model(**lowercase_					,     output_hidden_states=lowercase_)
											del pt_model  # will no longer be used, and may have a large memory footprint

											a__     						=tf_class.from_pretrained(self._local_dir					,     from_pt=lowercase_)
											a__     						=tf_from_pt_model(**lowercase_					,     output_hidden_states=lowercase_					,     training=lowercase_)

											# Confirms that cross loading PT weights into TF worked.
											a__     						=self.find_pt_tf_differences(lowercase_					,     lowercase_)
											a__     						={k: v for k, v in crossload_differences.items() if 'hidden' not in k}
											a__     						={k: v for k, v in crossload_differences.items() if 'hidden' in k}
											if len(lowercase_) == 0 and architectures is not None:
																		raise ValueError(
																		    F"""Something went wrong -- the config file has architectures ({architectures}), but no model head"""
																		    ' output was found. All outputs start with \'hidden\'')
											a__     						=max(output_differences.values()) if output_differences else 0.0
											a__     						=max(hidden_differences.values())
											if max_crossload_output_diff > self._max_error or max_crossload_hidden_diff > self._max_error:
																		raise ValueError(
																		    'The cross-loaded TensorFlow model has different outputs, something went wrong!\n'
																		    + F"""\nList of maximum output differences above the threshold ({self._max_error}):\n"""
																		    + '\n'.join([F"""{k}: {v:.3e}""" for k, v in output_differences.items() if v > self._max_error])
																		    + F"""\n\nList of maximum hidden layer differences above the threshold ({self._max_error}):\n"""
																		    + '\n'.join([F"""{k}: {v:.3e}""" for k, v in hidden_differences.items() if v > self._max_error]))

											# Save the weights in a TF format (if needed) and confirms that the results are still good
											a__     						=os.path.join(self._local_dir					,     lowercase_)
											a__     						=os.path.join(self._local_dir					,     lowercase_)
											if (not os.path.exists(lowercase_) and not os.path.exists(lowercase_)) or self._new_weights:
																		tf_from_pt_model.save_pretrained(self._local_dir)
											del tf_from_pt_model  # will no longer be used, and may have a large memory footprint

											a__     						=tf_class.from_pretrained(self._local_dir)
											a__     						=tf_model(**lowercase_					,     output_hidden_states=lowercase_)

											a__     						=self.find_pt_tf_differences(lowercase_					,     lowercase_)
											a__     						={k: v for k, v in conversion_differences.items() if 'hidden' not in k}
											a__     						={k: v for k, v in conversion_differences.items() if 'hidden' in k}
											if len(lowercase_) == 0 and architectures is not None:
																		raise ValueError(
																		    F"""Something went wrong -- the config file has architectures ({architectures}), but no model head"""
																		    ' output was found. All outputs start with \'hidden\'')
											a__     						=max(output_differences.values()) if output_differences else 0.0
											a__     						=max(hidden_differences.values())
											if max_conversion_output_diff > self._max_error or max_conversion_hidden_diff > self._max_error:
																		raise ValueError(
																		    'The converted TensorFlow model has different outputs, something went wrong!\n'
																		    + F"""\nList of maximum output differences above the threshold ({self._max_error}):\n"""
																		    + '\n'.join([F"""{k}: {v:.3e}""" for k, v in output_differences.items() if v > self._max_error])
																		    + F"""\n\nList of maximum hidden layer differences above the threshold ({self._max_error}):\n"""
																		    + '\n'.join([F"""{k}: {v:.3e}""" for k, v in hidden_differences.items() if v > self._max_error]))

											a__     						='Update TF weights' if self._new_weights else 'Add TF weights'
											if self._push:
																		repo.git_add(auto_lfs_track=lowercase_)
																		repo.git_commit(lowercase_)
																		repo.git_push(blocking=lowercase_)  # this prints a progress bar with the upload
																		self._logger.warning(F"""TF weights pushed into {self._model_name}""")
											elif not self._no_pr:
																		self._logger.warning('Uploading the weights into a new PR...')
																		a__     						=(
																		    'Model converted by the [`transformers`\' `pt_to_tf`'
																		    ' CLI](https://github.com/huggingface/transformers/blob/main/src/transformers/commands/pt_to_tf.py). '
																		    'All converted model outputs and hidden layers were validated against its PyTorch counterpart.\n\n'
																		    F"""Maximum crossload output difference={max_crossload_output_diff:.3e}; """
																		    F"""Maximum crossload hidden layer difference={max_crossload_hidden_diff:.3e};\n"""
																		    F"""Maximum conversion output difference={max_conversion_output_diff:.3e}; """
																		    F"""Maximum conversion hidden layer difference={max_conversion_hidden_diff:.3e};\n"""
																		)
																		if self._max_error > MAX_ERROR:
																									commit_descrition += (
																									    F"""\n\nCAUTION: The maximum admissible error was manually increased to {self._max_error}!"""
																									)
																		if self._extra_commit_description:
																									commit_descrition += "\n\n" + self._extra_commit_description

																		# sharded model -> adds all related files (index and .h5 shards)
																		if os.path.exists(lowercase_):
																									a__     						=[
																									    CommitOperationAdd(path_in_repo=lowercase_					,     path_or_fileobj=lowercase_)
																									]
																									for shard_path in tf.io.gfile.glob(self._local_dir + '/tf_model-*.h5'):
																																operations += [
																																    CommitOperationAdd(path_in_repo=os.path.basename(lowercase_)					,     path_or_fileobj=lowercase_)
																																]
																		else:
																									a__     						=[CommitOperationAdd(path_in_repo=lowercase_					,     path_or_fileobj=lowercase_)]

																		a__     						=create_commit(
																		    repo_id=self._model_name					,     operations=lowercase_					,     commit_message=lowercase_					,     commit_description=lowercase_					,     repo_type='model'					,     create_pr=lowercase_					,     ).pr_url
																		self._logger.warning(F"""PR open in {hub_pr_url}""")

