




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


UpperCamelCase__  =		5e-5  # larger error tolerance than in our internal tests, to avoid flaky user-facing errors






def       snake_case      (							A    )							->							Tuple:




	'''simple docstring'''


	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        __SCREAMING_SNAKE_CASE							(	lowerCamelCase						):

					@staticmethod
					def 			lowercase_							(       __lowercase      ):







						'''simple docstring'''




						lowerCamelCase_							:	List[Any]							     =							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 			lowercase_							(       __lowercase				, __lowercase      ):







						'''simple docstring'''




						lowerCamelCase_							:	int							     =							set(pt_outputs.keys()      )
						lowerCamelCase_							:	List[str]							     =							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      ):
								lowerCamelCase_							:	Optional[int]							     =							np.max(np.abs(pt_out.numpy() - tf_out.numpy()      )      )
								lowerCamelCase_							:	str							     =							tensor_difference
							else:
								lowerCamelCase_							:	int							     =							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      ):
										lowerCamelCase_							:	Optional[Any]							     =							root_name + pt_item
										lowerCamelCase_							:	Tuple							     =							tf_out[pt_item]
										lowerCamelCase_							:	List[str]							     =							pt_out[pt_item]
									else:
										lowerCamelCase_							:	Dict							     =							root_name + f"[{i}]"
										lowerCamelCase_							:	str							     =							tf_out[i]
									lowerCamelCase_							:	int							     =							_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				, ):







						'''simple docstring'''




						lowerCamelCase_							:	Optional[int]							     =							logging.get_logger('transformers-cli/pt_to_tf'      )
						lowerCamelCase_							:	str							     =							model_name
						lowerCamelCase_							:	Dict							     =							local_dir if local_dir else os.path.join('/tmp'				, __lowercase      )
						lowerCamelCase_							:	Union[str, Any]							     =							max_error
						lowerCamelCase_							:	Optional[Any]							     =							new_weights
						lowerCamelCase_							:	str							     =							no_pr
						lowerCamelCase_							:	List[Any]							     =							push
						lowerCamelCase_							:	List[Any]							     =							extra_commit_description
						lowerCamelCase_							:	Tuple							     =							override_model_class

					def 			lowercase_							(       self				, __lowercase				, __lowercase				, __lowercase      ):







						'''simple docstring'''




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

						lowerCamelCase_							:	Any							     =							type(pt_model.config      )
						if model_config_class in PROCESSOR_MAPPING:
							lowerCamelCase_							:	Any							     =							AutoProcessor.from_pretrained(self._local_dir      )
							if model_config_class in TOKENIZER_MAPPING and processor.tokenizer.pad_token is None:
								lowerCamelCase_							:	int							     =							processor.tokenizer.eos_token
						elif model_config_class in IMAGE_PROCESSOR_MAPPING:
							lowerCamelCase_							:	Tuple							     =							AutoImageProcessor.from_pretrained(self._local_dir      )
						elif model_config_class in FEATURE_EXTRACTOR_MAPPING:
							lowerCamelCase_							:	List[Any]							     =							AutoFeatureExtractor.from_pretrained(self._local_dir      )
						elif model_config_class in TOKENIZER_MAPPING:
							lowerCamelCase_							:	Dict							     =							AutoTokenizer.from_pretrained(self._local_dir      )
							if processor.pad_token is None:
								lowerCamelCase_							:	Optional[Any]							     =							processor.eos_token
						else:
							raise ValueError(f"Unknown data processing type (model config type: {model_config_class})"      )

						lowerCamelCase_							:	List[Any]							     =							set(inspect.signature(pt_model.forward      ).parameters.keys()      )
						lowerCamelCase_							:	str							     =							{}
						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:
							lowerCamelCase_							:	Union[str, Any]							     =							load_dataset('cifar10'				, 'plain_text'				, split='test'      )[:2]['img']
							processor_inputs.update({'images': sample_images}      )
						if "input_features" in model_forward_signature:
							lowerCamelCase_							:	Optional[int]							     =							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:
								lowerCamelCase_							:	int							     =							feature_extractor_signature['padding'].default
								if default_strategy is not False and default_strategy is not None:
									lowerCamelCase_							:	str							     =							default_strategy
								else:
									lowerCamelCase_							:	str							     =							True
							else:
								lowerCamelCase_							:	List[str]							     =							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}      )
						lowerCamelCase_							:	int							     =							processor(**__lowercase				, return_tensors='pt'      )
						lowerCamelCase_							:	Optional[int]							     =							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
						):
							lowerCamelCase_							:	Optional[Any]							     =							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 			lowercase_							(       self      ):







						'''simple docstring'''




						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
						lowerCamelCase_							:	Optional[int]							     =							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
						lowerCamelCase_							:	str							     =							AutoConfig.from_pretrained(self._local_dir      )
						lowerCamelCase_							:	Any							     =							config.architectures
						if self._override_model_class is not None:
							if self._override_model_class.startswith('TF'      ):
								lowerCamelCase_							:	str							     =							[self._override_model_class[2:]]
							else:
								lowerCamelCase_							:	Optional[Any]							     =							[self._override_model_class]
							try:
								lowerCamelCase_							:	int							     =							getattr(import_module('transformers'      )				, architectures[0]      )
							except AttributeError:
								raise ValueError(f"Model class {self._override_model_class} not found in transformers."      )
							try:
								lowerCamelCase_							:	Optional[int]							     =							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
							lowerCamelCase_							:	Optional[Any]							     =							getattr(import_module('transformers'      )				, 'AutoModel'      )
							lowerCamelCase_							:	Optional[Any]							     =							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]}"      )
							lowerCamelCase_							:	Optional[int]							     =							getattr(import_module('transformers'      )				, architectures[0]      )
							try:
								lowerCamelCase_							:	str							     =							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
						lowerCamelCase_							:	Any							     =							tf_class.from_config(__lowercase      )
						lowerCamelCase_							:	List[str]							     =							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
						lowerCamelCase_							:	Optional[Any]							     =							pt_class.from_pretrained(self._local_dir      )
						pt_model.eval()

						lowerCamelCase_     ,    lowerCamelCase_							:	Optional[Any]							     =							self.get_inputs(__lowercase				, __lowercase				, __lowercase      )

						with torch.no_grad():
							lowerCamelCase_							:	List[Any]							     =							pt_model(**__lowercase				, output_hidden_states=__lowercase      )
						del pt_model  # will no longer be used, and may have a large memory footprint

						lowerCamelCase_							:	List[str]							     =							tf_class.from_pretrained(self._local_dir				, from_pt=__lowercase      )
						lowerCamelCase_							:	List[str]							     =							tf_from_pt_model(**__lowercase				, output_hidden_states=__lowercase				, training=__lowercase      )

						# Confirms that cross loading PT weights into TF worked.
						lowerCamelCase_							:	Optional[int]							     =							self.find_pt_tf_differences(__lowercase				, __lowercase      )
						lowerCamelCase_							:	Dict							     =							{k: v for k, v in crossload_differences.items() if 'hidden' not in k}
						lowerCamelCase_							:	Dict							     =							{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\''      )
						lowerCamelCase_							:	Union[str, Any]							     =							max(output_differences.values()      ) if output_differences else 0.0
						lowerCamelCase_							:	Optional[int]							     =							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
						lowerCamelCase_							:	Union[str, Any]							     =							os.path.join(self._local_dir				, __lowercase      )
						lowerCamelCase_							:	List[str]							     =							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

						lowerCamelCase_							:	Tuple							     =							tf_class.from_pretrained(self._local_dir      )
						lowerCamelCase_							:	Tuple							     =							tf_model(**__lowercase				, output_hidden_states=__lowercase      )

						lowerCamelCase_							:	Any							     =							self.find_pt_tf_differences(__lowercase				, __lowercase      )
						lowerCamelCase_							:	Any							     =							{k: v for k, v in conversion_differences.items() if 'hidden' not in k}
						lowerCamelCase_							:	Union[str, Any]							     =							{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\''      )
						lowerCamelCase_							:	Tuple							     =							max(output_differences.values()      ) if output_differences else 0.0
						lowerCamelCase_							:	List[Any]							     =							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]      )      )

						lowerCamelCase_							:	Tuple							     =							'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...'      )
							lowerCamelCase_							:	Any							     =							(
							    '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      ):
								lowerCamelCase_							:	List[str]							     =							[
								    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:
								lowerCamelCase_							:	Any							     =							[CommitOperationAdd(path_in_repo=__lowercase				, path_or_fileobj=__lowercase      )]

							lowerCamelCase_							:	Optional[Any]							     =							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}"      )






def       snake_case      (							A = 998001    )							->							int:




	'''simple docstring'''


	for number in range(n - 1		,     9999		,     -1    ):
		lowerCamelCase_							:	Tuple							     =							str(A    )

		# checks whether 'str_number' is a palindrome.
		if str_number == str_number[::-1]:
			lowerCamelCase_							:	Tuple							     =							999

			# if 'number' is a product of two 3-digit numbers
			# then number is the answer otherwise fetch next number.
			while divisor != 99:
				if (number % divisor == 0) and (len(str(number // divisor    )    ) == 3.0):
					return number
				divisor -= 1
	raise ValueError('That number is larger than our acceptable range.'    )


if __name__ == "__main__":
							print(F'{solution() = }')
