






"""simple docstring"""


from copy import deepcopy
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union

import torch
from torch import nn
from torch.utils.data import Dataset

from .deepspeed import is_deepspeed_zeroa_enabled
from .generation.configuration_utils import GenerationConfig
from .trainer import Trainer
from .utils import logging


if TYPE_CHECKING:
   from .data.data_collator import DataCollator
   from .modeling_utils import PreTrainedModel
   from .tokenization_utils_base import PreTrainedTokenizerBase
   from .trainer_callback import TrainerCallback
   from .trainer_utils import EvalPrediction, PredictionOutput
   from .training_args import TrainingArguments


_UpperCamelCase				:    Dict     =						logging.get_logger(__name__)






class 						snake_case  (  snake_case__       ):





    def __init__(							self	:					Optional[int]				,		A	:					Union["PreTrainedModel", nn.Module] = None				,		A	:					"TrainingArguments" = None				,		A	:					Optional["DataCollator"] = None				,		A	:					Optional[Dataset] = None				,		A	:					Optional[Union[Dataset, Dict[str, Dataset]]] = None				,		A	:					Optional["PreTrainedTokenizerBase"] = None				,		A	:					Optional[Callable[[], "PreTrainedModel"]] = None				,		A	:					Optional[Callable[["EvalPrediction"], Dict]] = None				,		A	:					Optional[List["TrainerCallback"]] = None				,		A	:					Tuple[torch.optim.Optimizer, torch.optim.lr_scheduler.LambdaLR] = (None, None)				,		A	:					Optional[Callable[[torch.Tensor, torch.Tensor], torch.Tensor]] = None				,		):


      '''simple docstring'''




      super().__init__(
          model=__UpperCAmelCase				,		args=__UpperCAmelCase				,		data_collator=__UpperCAmelCase				,		train_dataset=__UpperCAmelCase				,		eval_dataset=__UpperCAmelCase				,		tokenizer=__UpperCAmelCase				,		model_init=__UpperCAmelCase				,		compute_metrics=__UpperCAmelCase				,		callbacks=__UpperCAmelCase				,		optimizers=__UpperCAmelCase				,		preprocess_logits_for_metrics=__UpperCAmelCase				,		)

      # Override self.model.generation_config if a GenerationConfig is specified in args.
      # Priority: args.generation_config > model.generation_config > default GenerationConfig.
      if self.args.generation_config is not None:
        a     :			Union[str, Any]				=   self.load_generation_config(self.args.generation_config			)
        a     :			List[Any]				=   gen_config





    @staticmethod
    def 				lowerCamelCase__      (							A	:					Union[str, GenerationConfig]			):


      '''simple docstring'''




      if isinstance(__UpperCAmelCase				,		__UpperCAmelCase			):
        return deepcopy(__UpperCAmelCase			)

      # str or Path
      a     :			Tuple				=   Path(__UpperCAmelCase			) if isinstance(__UpperCAmelCase				,		__UpperCAmelCase			) else gen_config_arg
      a     :			List[str]				=   None

      # Figuring if it is path pointing to a file, pointing to a directory or else a model id or URL
      # This step is required in order to determine config_file_name
      if pretrained_model_name.is_file():
        a     :			Dict				=   pretrained_model_name.name
        a     :			Optional[int]				=   pretrained_model_name.parent
      # dir path
      elif pretrained_model_name.is_dir():
        pass
      # model id or URL
      else:
        a     :			Any				=   gen_config_arg

      a     :			int				=   GenerationConfig.from_pretrained(__UpperCAmelCase				,		__UpperCAmelCase			)
      return gen_config





    def 				lowerCamelCase__      (							self	:					List[str]				,		A	:					Optional[Dataset] = None				,		A	:					Optional[List[str]] = None				,		A	:					str = "eval"				,		**A	:					Any				,		):


      '''simple docstring'''




      a     :			Tuple				=   gen_kwargs.copy()
      if gen_kwargs.get('max_length'			) is None and gen_kwargs.get('max_new_tokens'			) is None:
        a     :			str				=   self.args.generation_max_length
      a     :			List[str]				=   (
          gen_kwargs['num_beams'] if gen_kwargs.get('num_beams'			) is not None else self.args.generation_num_beams
      )
      a     :			int				=   gen_kwargs

      return super().evaluate(__UpperCAmelCase				,		ignore_keys=__UpperCAmelCase				,		metric_key_prefix=__UpperCAmelCase			)





    def 				lowerCamelCase__      (							self	:					Optional[Any]				,		A	:					Dataset				,		A	:					Optional[List[str]] = None				,		A	:					str = "test"				,		**A	:					Union[str, Any]				,		):


      '''simple docstring'''




      a     :			Union[str, Any]				=   gen_kwargs.copy()
      if gen_kwargs.get('max_length'			) is None and gen_kwargs.get('max_new_tokens'			) is None:
        a     :			Dict				=   self.args.generation_max_length
      a     :			Optional[Any]				=   (
          gen_kwargs['num_beams'] if gen_kwargs.get('num_beams'			) is not None else self.args.generation_num_beams
      )
      a     :			List[Any]				=   gen_kwargs

      return super().predict(__UpperCAmelCase				,		ignore_keys=__UpperCAmelCase				,		metric_key_prefix=__UpperCAmelCase			)





    def 				lowerCamelCase__      (							self	:					List[Any]				,		A	:					nn.Module				,		A	:					Dict[str, Union[torch.Tensor, Any]]				,		A	:					bool				,		A	:					Optional[List[str]] = None				,		**A	:					int				,		):


      '''simple docstring'''




      if not self.args.predict_with_generate or prediction_loss_only:
        return super().prediction_step(
            __UpperCAmelCase				,		__UpperCAmelCase				,		prediction_loss_only=__UpperCAmelCase				,		ignore_keys=__UpperCAmelCase			)

      a     :			Union[str, Any]				=   'labels' in inputs
      a     :			List[Any]				=   self._prepare_inputs(__UpperCAmelCase			)

      # XXX: adapt synced_gpus for fairscale as well
      # Priority (handled in generate):
      # gen_kwargs > model.generation_config > default GenerationConfig()

      if len(__UpperCAmelCase			) == 0 and hasattr(self				,		'_gen_kwargs'			):
        a     :			Dict				=   self._gen_kwargs.copy()

      if gen_kwargs.get('max_length'			) is None and gen_kwargs.get('max_new_tokens'			) is None:
        a     :			List[str]				=   self.model.config.max_length
      a     :			Optional[Any]				=   (
          gen_kwargs['num_beams'] if gen_kwargs.get('num_beams'			) is not None else self.model.config.num_beams
      )
      a     :			Any				=   True if is_deepspeed_zeroa_enabled() else False
      a     :			str				=   (
          gen_kwargs['synced_gpus'] if gen_kwargs.get('synced_gpus'			) is not None else default_synced_gpus
      )

      # If the `decoder_input_ids` was created from `labels`, evict the former, so that the model can freely generate
      # (otherwise, it would continue generating from the padded `decoder_input_ids`)
      if (
          "labels" in inputs
          and "decoder_input_ids" in inputs
          and inputs["labels"].shape == inputs["decoder_input_ids"].shape
      ):
        a     :			Optional[int]				=   {k: v for k, v in inputs.items() if k != 'decoder_input_ids'}
      a     :			Optional[Any]				=   self.model.generate(**__UpperCAmelCase				,		**__UpperCAmelCase			)

      # Temporary hack to ensure the generation config is not initialized for each iteration of the evaluation loop
      # TODO: remove this hack when the legacy code that initializes generation_config from a model config is
      # removed in https://github.com/huggingface/transformers/blob/98d88b23f54e5a23e741833f1e973fdf600cc2c5/src/transformers/generation/utils.py#L1183
      if self.model.generation_config._from_model_config:
        a     :			int				=   False

      # Retrieves GenerationConfig from model.generation_config
      a     :			int				=   self.model.generation_config
      # in case the batch is shorter than max length, the output should be padded
      if generated_tokens.shape[-1] < gen_config.max_length:
        a     :			List[Any]				=   self._pad_tensors_to_max_len(__UpperCAmelCase				,		gen_config.max_length			)
      elif gen_config.max_new_tokens is not None and generated_tokens.shape[-1] < gen_config.max_new_tokens + 1:
        a     :			List[str]				=   self._pad_tensors_to_max_len(__UpperCAmelCase				,		gen_config.max_new_tokens + 1			)

      with torch.no_grad():
        if has_labels:
          with self.compute_loss_context_manager():
            a     :			Any				=   model(**__UpperCAmelCase			)
          if self.label_smoother is not None:
            a     :			Union[str, Any]				=   self.label_smoother(__UpperCAmelCase				,		inputs['labels']			).mean().detach()
          else:
            a     :			Tuple				=   (outputs['loss'] if isinstance(__UpperCAmelCase				,		__UpperCAmelCase			) else outputs[0]).mean().detach()
        else:
          a     :			Optional[Any]				=   None

      if self.args.prediction_loss_only:
        return loss, None, None

      if has_labels:
        a     :			List[Any]				=   inputs['labels']
        if labels.shape[-1] < gen_config.max_length:
          a     :			Any				=   self._pad_tensors_to_max_len(__UpperCAmelCase				,		gen_config.max_length			)
        elif gen_config.max_new_tokens is not None and labels.shape[-1] < gen_config.max_new_tokens + 1:
          a     :			Tuple				=   self._pad_tensors_to_max_len(__UpperCAmelCase				,		gen_config.max_new_tokens + 1			)
      else:
        a     :			Tuple				=   None

      return loss, generated_tokens, labels





    def 				lowerCamelCase__      (							self	:					List[Any]				,		A	:					Tuple				,		A	:					str			):


      '''simple docstring'''




      if self.tokenizer is not None and hasattr(self.tokenizer				,		'pad_token_id'			):
        # If PAD token is not defined at least EOS token has to be defined
        a     :			Optional[int]				=   (
            self.tokenizer.pad_token_id if self.tokenizer.pad_token_id is not None else self.tokenizer.eos_token_id
        )
      else:
        if self.model.config.pad_token_id is not None:
          a     :			int				=   self.model.config.pad_token_id
        else:
          raise ValueError('Pad_token_id must be set in the configuration of the model, in order to pad tensors'			)

      a     :			Union[str, Any]				=   pad_token_id * torch.ones(
          (tensor.shape[0], max_length)				,		dtype=tensor.dtype				,		device=tensor.device			)
      a     :			Tuple				=   tensor
      return padded_tensor









def        __a     (    lowerCAmelCase_   :					int				)      -> int:






						'''simple docstring'''



						if number != int(lowerCAmelCase_				):
												raise ValueError("""factorial() only accepts integral values"""				)
						if number < 0:
												raise ValueError("""factorial() not defined for negative values"""				)
						UpperCAmelCase_=   1
						for i in range(1			,number + 1				):
												value *= i
						return value



def        __a     (    lowerCAmelCase_   :					int				)      -> int:






						'''simple docstring'''



						if not isinstance(lowerCAmelCase_			,lowerCAmelCase_				):
												raise ValueError("""factorial() only accepts integral values"""				)
						if n < 0:
												raise ValueError("""factorial() not defined for negative values"""				)
						return 1 if n == 0 or n == 1 else n * factorial(n - 1				)


if __name__ == "__main__":
	import doctest

	doctest.testmod()

	__A				    =						int(input('''Enter a positive integer: ''').strip() or 0)
	print(f'factorial{n} is {factorial(n)}')




