"""simple docstring"""







import inspect
from typing import Callable, List, Optional, Set, Tuple, Union

import torch
from packaging import version
from safetensors.torch import storage_ptr, storage_size
from torch import nn

from .utils import logging


UpperCamelCase_							:							Tuple				 =		[nn.LayerNorm]

UpperCamelCase_							:							Tuple				 =		logging.get_logger(__name__)

UpperCamelCase_							:							List[Any]				 =		version.parse(version.parse(torch.__version__).base_version)

UpperCamelCase_							:							List[Any]				 =		parsed_torch_version_base >= version.parse("""2.0""")
UpperCamelCase_							:							Dict				 =		parsed_torch_version_base >= version.parse("""1.12""")
UpperCamelCase_							:							Optional[int]				 =		parsed_torch_version_base >= version.parse("""1.11""")
UpperCamelCase_							:							Tuple				 =		parsed_torch_version_base < version.parse("""1.11""")


def 	a__   (		UpperCAmelCase__							:      Any		,      UpperCAmelCase__							:      Dict		,      UpperCAmelCase__							:      Any		,      UpperCAmelCase__							:      Optional[Any]		,      self							:      Optional[Any]      )->						Dict:
						from torch import _softmax_backward_data

						if is_torch_less_than_1_11:
												return _softmax_backward_data(UpperCAmelCase__		,      UpperCAmelCase__		,      parent.dim		,      self      )
						else:
												return _softmax_backward_data(UpperCAmelCase__		,      UpperCAmelCase__		,      parent.dim		,      self.dtype      )


def 	a__   (		UpperCAmelCase__							:      nn.Linear		,      UpperCAmelCase__							:      torch.LongTensor		,      UpperCAmelCase__							:      int = 0      )->						nn.Linear:
						UpperCAmelCase__       						=		index.to(layer.weight.device      )
						UpperCAmelCase__       						=		layer.weight.index_select(UpperCAmelCase__		,      UpperCAmelCase__      ).clone().detach()
						if layer.bias is not None:
												if dim == 1:
																		UpperCAmelCase__       						=		layer.bias.clone().detach()
												else:
																		UpperCAmelCase__       						=		layer.bias[index].clone().detach()
						UpperCAmelCase__       						=		list(layer.weight.size()      )
						UpperCAmelCase__       						=		len(UpperCAmelCase__      )
						UpperCAmelCase__       						=		nn.Linear(new_size[1]		,      new_size[0]		,      bias=layer.bias is not None      ).to(layer.weight.device      )
						UpperCAmelCase__       						=		False
						new_layer.weight.copy_(W.contiguous()      )
						UpperCAmelCase__       						=		True
						if layer.bias is not None:
												UpperCAmelCase__       						=		False
												new_layer.bias.copy_(b.contiguous()      )
												UpperCAmelCase__       						=		True
						return new_layer


class       _lowercase		( nn.Module	):

				def __init__(  self							:     Any							,     _lowercase							:     str							,     _lowercase							:     Any  ):


										'''simple docstring'''
										super().__init__()
										UpperCAmelCase__       						=		nf
										UpperCAmelCase__       						=		nn.Parameter(torch.empty(_lowercase							,     _lowercase  )  )
										UpperCAmelCase__       						=		nn.Parameter(torch.zeros(_lowercase  )  )
										nn.init.normal_(self.weight							,     std=0.02  )

				def 							A			(  self							:     int							,     _lowercase							:     Optional[Any]  ):


										'''simple docstring'''
										UpperCAmelCase__       						=		x.size()[:-1] + (self.nf,)
										UpperCAmelCase__       						=		torch.addmm(self.bias							,     x.view(-1							,     x.size(-1  )  )							,     self.weight  )
										UpperCAmelCase__       						=		x.view(_lowercase  )
										return x


def 	a__   (		UpperCAmelCase__							:      ConvaD		,      UpperCAmelCase__							:      torch.LongTensor		,      UpperCAmelCase__							:      int = 1      )->						ConvaD:
						UpperCAmelCase__       						=		index.to(layer.weight.device      )
						UpperCAmelCase__       						=		layer.weight.index_select(UpperCAmelCase__		,      UpperCAmelCase__      ).clone().detach()
						if dim == 0:
												UpperCAmelCase__       						=		layer.bias.clone().detach()
						else:
												UpperCAmelCase__       						=		layer.bias[index].clone().detach()
						UpperCAmelCase__       						=		list(layer.weight.size()      )
						UpperCAmelCase__       						=		len(UpperCAmelCase__      )
						UpperCAmelCase__       						=		ConvaD(new_size[1]		,      new_size[0]      ).to(layer.weight.device      )
						UpperCAmelCase__       						=		False
						new_layer.weight.copy_(W.contiguous()      )
						UpperCAmelCase__       						=		True
						UpperCAmelCase__       						=		False
						new_layer.bias.copy_(b.contiguous()      )
						UpperCAmelCase__       						=		True
						return new_layer


def 	a__   (		UpperCAmelCase__							:      Union[nn.Linear, ConvaD]		,      UpperCAmelCase__							:      torch.LongTensor		,      UpperCAmelCase__							:      Optional[int] = None      )->						Union[nn.Linear, ConvaD]:
						if isinstance(UpperCAmelCase__		,      nn.Linear      ):
												return prune_linear_layer(UpperCAmelCase__		,      UpperCAmelCase__		,      dim=0 if dim is None else dim      )
						elif isinstance(UpperCAmelCase__		,      UpperCAmelCase__      ):
												return prune_convad_layer(UpperCAmelCase__		,      UpperCAmelCase__		,      dim=1 if dim is None else dim      )
						else:
												raise ValueError(f'Can\'t prune layer of class {layer.__class__}'      )


def 	a__   (		UpperCAmelCase__							:      Callable[..., torch.Tensor]		,      UpperCAmelCase__							:      int		,      UpperCAmelCase__							:      int		,      *UpperCAmelCase__							:      int      )->						torch.Tensor:
						assert len(UpperCAmelCase__      ) > 0, f'{input_tensors} has to be a tuple/list of tensors'

						# inspect.signature exist since python 3.5 and is a python method -> no problem with backward compatibility
						UpperCAmelCase__       						=		len(inspect.signature(UpperCAmelCase__      ).parameters      )
						if num_args_in_forward_chunk_fn != len(UpperCAmelCase__      ):
												raise ValueError(
												    f'forward_chunk_fn expects {num_args_in_forward_chunk_fn} arguments, but only {len(UpperCAmelCase__      )} input '
												    """tensors are given"""      )

						if chunk_size > 0:
												UpperCAmelCase__       						=		input_tensors[0].shape[chunk_dim]
												for input_tensor in input_tensors:
																		if input_tensor.shape[chunk_dim] != tensor_shape:
																								raise ValueError(
																								    f'All input tenors have to be of the same shape: {tensor_shape}, '
																								    f'found shape {input_tensor.shape[chunk_dim]}'      )

												if input_tensors[0].shape[chunk_dim] % chunk_size != 0:
																		raise ValueError(
																		    f'The dimension to be chunked {input_tensors[0].shape[chunk_dim]} has to be a multiple of the chunk '
																		    f'size {chunk_size}'      )

												UpperCAmelCase__       						=		input_tensors[0].shape[chunk_dim] // chunk_size

												# chunk input tensor into tuples
												UpperCAmelCase__       						=		tuple(input_tensor.chunk(UpperCAmelCase__		,      dim=UpperCAmelCase__      ) for input_tensor in input_tensors      )
												# apply forward fn to every tuple
												UpperCAmelCase__       						=		tuple(forward_fn(*UpperCAmelCase__      ) for input_tensors_chunk in zip(*UpperCAmelCase__      )      )
												# concatenate output at same dimension
												return torch.cat(UpperCAmelCase__		,      dim=UpperCAmelCase__      )

						return forward_fn(*UpperCAmelCase__      )


def 	a__   (		UpperCAmelCase__							:      List[int]		,      UpperCAmelCase__							:      int		,      UpperCAmelCase__							:      int		,      UpperCAmelCase__							:      Set[int]      )->						Tuple[Set[int], torch.LongTensor]:
						UpperCAmelCase__       						=		torch.ones(UpperCAmelCase__		,      UpperCAmelCase__      )
						UpperCAmelCase__       						=		set(UpperCAmelCase__      ) - already_pruned_heads  # Convert to set and remove already pruned heads
						for head in heads:
												# Compute how many pruned heads are before the head and move the index accordingly
												UpperCAmelCase__       						=		head - sum(1 if h < head else 0 for h in already_pruned_heads      )
												UpperCAmelCase__       						=		0
						UpperCAmelCase__       						=		mask.view(-1      ).contiguous().eq(1      )
						UpperCAmelCase__       						=		torch.arange(len(UpperCAmelCase__      )      )[mask].long()
						return heads, index


def 	a__   (		*UpperCAmelCase__							:      Union[torch.Tensor, List[torch.Tensor]]		,      UpperCAmelCase__							:      Optional[str] = None      )->						Tuple[torch.Tensor, ...]:
						return torch.meshgrid(*UpperCAmelCase__		,      indexing=UpperCAmelCase__      )







def 	a__   (		UpperCAmelCase__							:      torch.Tensor      )->						Tuple[torch.device, int, int]:
						return tensor.device, storage_ptr(UpperCAmelCase__      ), storage_size(UpperCAmelCase__      )


"""simple docstring"""







import os
import warnings
from pathlib import Path
from typing import Optional, Union

from .dynamic_module_utils import custom_object_save
from .tokenization_utils_base import PreTrainedTokenizerBase
from .utils import PushToHubMixin, copy_func, direct_transformers_import, logging


UpperCamelCase_							:							Optional[int]				 =		logging.get_logger(__name__)

# Dynamically import the Transformers module to grab the attribute classes of the processor form their names.
UpperCamelCase_							:							Optional[Any]				 =		direct_transformers_import(Path(__file__).parent)


UpperCamelCase_							:							Optional[int]				 =		{
    """AutoTokenizer""": """PreTrainedTokenizerBase""",
    """AutoFeatureExtractor""": """FeatureExtractionMixin""",
    """AutoImageProcessor""": """ImageProcessingMixin""",
}


class       _lowercase		( __lowerCamelCase	):
				lowerCamelCase__							=							['feature_extractor', 'tokenizer']
				# Names need to be attr_class for attr in attributes
				lowerCamelCase__							=							None
				lowerCamelCase__							=							None
				lowerCamelCase__							=							None

				def __init__(  self							:     Any							,     *_lowercase							:     Optional[int]							,     **_lowercase							:     int  ):


										'''simple docstring'''
										# Sanitize args and kwargs
										for key in kwargs:
																if key not in self.attributes:
																						raise TypeError(f'Unexpected keyword argument {key}.'  )
										for arg, attribute_name in zip(_lowercase							,     self.attributes  ):
																if attribute_name in kwargs:
																						raise TypeError(f'Got multiple values for argument {attribute_name}.'  )
																else:
																						UpperCAmelCase__       						=		arg

										if len(_lowercase  ) != len(self.attributes  ):
																raise ValueError(
																    f'This processor requires {len(self.attributes  )} arguments: {", ".join(self.attributes  )}. Got '
																    f'{len(_lowercase  )} arguments instead.'  )

										# Check each arg is of the proper class (this will also catch a user initializing in the wrong order)
										for attribute_name, arg in kwargs.items():
																UpperCAmelCase__       						=		getattr(self							,     f'{attribute_name}_class'  )
																# Nothing is ever going to be an instance of "AutoXxx", in that case we check the base class.
																UpperCAmelCase__       						=		AUTO_TO_BASE_CLASS_MAPPING.get(_lowercase							,     _lowercase  )
																if isinstance(_lowercase							,     _lowercase  ):
																						UpperCAmelCase__       						=		tuple(getattr(_lowercase							,     _lowercase  ) for n in class_name if n is not None  )
																else:
																						UpperCAmelCase__       						=		getattr(_lowercase							,     _lowercase  )

																if not isinstance(_lowercase							,     _lowercase  ):
																						raise ValueError(
																						    f'Received a {type(_lowercase  ).__name__} for argument {attribute_name}, but a {class_name} was expected.'  )

																setattr(self							,     _lowercase							,     _lowercase  )

				def __repr__(  self							:     Tuple  ):


										'''simple docstring'''
										UpperCAmelCase__       						=		[f'- {name}: {repr(getattr(self							,     _lowercase  )  )}' for name in self.attributes]
										UpperCAmelCase__       						=		"""\n""".join(_lowercase  )
										return f'{self.__class__.__name__}:\n{attributes_repr}'

				def 							A			(  self							:     Tuple							,     _lowercase							:     Dict							,     _lowercase							:     bool = False							,     **_lowercase							:     List[str]  ):


										'''simple docstring'''
										os.makedirs(_lowercase							,     exist_ok=_lowercase  )

										if push_to_hub:
																UpperCAmelCase__       						=		kwargs.pop("""commit_message"""							,     _lowercase  )
																UpperCAmelCase__       						=		kwargs.pop("""repo_id"""							,     save_directory.split(os.path.sep  )[-1]  )
																UpperCAmelCase__       						=		self._create_repo(_lowercase							,     **_lowercase  )
																UpperCAmelCase__       						=		self._get_files_timestamps(_lowercase  )
										# If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be
										# loaded from the Hub.
										if self._auto_class is not None:
																UpperCAmelCase__       						=		[getattr(self							,     _lowercase  ) for attribute_name in self.attributes]
																UpperCAmelCase__       						=		[(a.init_kwargs if isinstance(_lowercase							,     _lowercase  ) else a) for a in attrs]
																custom_object_save(self							,     _lowercase							,     config=_lowercase  )

										for attribute_name in self.attributes:
																UpperCAmelCase__       						=		getattr(self							,     _lowercase  )
																# Include the processor class in the attribute config so this processor can then be reloaded with the
																# `AutoProcessor` API.
																if hasattr(_lowercase							,     """_set_processor_class"""  ):
																						attribute._set_processor_class(self.__class__.__name__  )
																attribute.save_pretrained(_lowercase  )

										if self._auto_class is not None:
																# We added an attribute to the init_kwargs of the tokenizers, which needs to be cleaned up.
																for attribute_name in self.attributes:
																						UpperCAmelCase__       						=		getattr(self							,     _lowercase  )
																						if isinstance(_lowercase							,     _lowercase  ):
																												del attribute.init_kwargs["auto_map"]

										if push_to_hub:
																self._upload_modified_files(
																    _lowercase							,     _lowercase							,     _lowercase							,     commit_message=_lowercase							,     token=kwargs.get("""use_auth_token"""  )							,     )

				@classmethod
				def 							A			(  cls							:     Dict							,     _lowercase							:     Union[str, os.PathLike]							,     _lowercase							:     Optional[Union[str, os.PathLike]] = None							,     _lowercase							:     bool = False							,     _lowercase							:     bool = False							,     _lowercase							:     Optional[Union[str, bool]] = None							,     _lowercase							:     str = "main"							,     **_lowercase							:     Dict							,     ):


										'''simple docstring'''
										UpperCAmelCase__       						=		cache_dir
										UpperCAmelCase__       						=		force_download
										UpperCAmelCase__       						=		local_files_only
										UpperCAmelCase__       						=		revision

										UpperCAmelCase__       						=		kwargs.pop("""use_auth_token"""							,     _lowercase  )
										if use_auth_token is not None:
																warnings.warn(
																    """The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers."""							,     _lowercase  )
																if token is not None:
																						raise ValueError(
																						    """`token` and `use_auth_token` are both specified. Please set only the argument `token`."""  )
																UpperCAmelCase__       						=		use_auth_token

										if token is not None:
																# change to `token` in a follow-up PR
																UpperCAmelCase__       						=		token

										UpperCAmelCase__       						=		cls._get_arguments_from_pretrained(_lowercase							,     **_lowercase  )
										return cls(*_lowercase  )

				@classmethod
				def 							A			(  cls							:     List[Any]							,     _lowercase							:     Dict="AutoProcessor"  ):


										'''simple docstring'''
										if not isinstance(_lowercase							,     _lowercase  ):
																UpperCAmelCase__       						=		auto_class.__name__

										import transformers.models.auto as auto_module

										if not hasattr(_lowercase							,     _lowercase  ):
																raise ValueError(f'{auto_class} is not a valid auto class.'  )

										UpperCAmelCase__       						=		auto_class

				@classmethod
				def 							A			(  cls							:     Any							,     _lowercase							:     Tuple							,     **_lowercase							:     List[Any]  ):


										'''simple docstring'''
										UpperCAmelCase__       						=		[]
										for attribute_name in cls.attributes:
																UpperCAmelCase__       						=		getattr(cls							,     f'{attribute_name}_class'  )
																if isinstance(_lowercase							,     _lowercase  ):
																						UpperCAmelCase__       						=		tuple(getattr(_lowercase							,     _lowercase  ) if n is not None else None for n in class_name  )
																						UpperCAmelCase__       						=		kwargs.get("""use_fast"""							,     _lowercase  )
																						if use_fast and classes[1] is not None:
																												UpperCAmelCase__       						=		classes[1]
																						else:
																												UpperCAmelCase__       						=		classes[0]
																else:
																						UpperCAmelCase__       						=		getattr(_lowercase							,     _lowercase  )

																args.append(attribute_class.from_pretrained(_lowercase							,     **_lowercase  )  )
										return args

				@property
				def 							A			(  self							:     int  ):


										'''simple docstring'''
										UpperCAmelCase__       						=		getattr(self							,     self.attributes[0]  )
										return getattr(_lowercase							,     """model_input_names"""							,     _lowercase  )
UpperCamelCase_							:							List[Any]				 =		copy_func(ProcessorMixin.push_to_hub)
if ProcessorMixin.push_to_hub.__doc__ is not None:
						UpperCamelCase_							:							Dict				 =		ProcessorMixin.push_to_hub.__doc__.format(
						    object="""processor""", object_class="""AutoProcessor""", object_files="""processor files"""
						)

