






"""simple docstring"""




import time
import warnings
from abc import ABC
from copy import deepcopy
from typing import Optional

import torch

from ..utils import add_start_docstrings, logging


_snake_case        =  logging.get_logger(__name__)


_snake_case        =  r'\n    Args:\n        input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):\n            Indices of input sequence tokens in the vocabulary.\n\n            Indices can be obtained using [`AutoTokenizer`]. See [`PreTrainedTokenizer.encode`] and\n            [`PreTrainedTokenizer.__call__`] for details.\n\n            [What are input IDs?](../glossary#input-ids)\n        scores (`torch.FloatTensor` of shape `(batch_size, config.vocab_size)`):\n            Prediction scores of a language modeling head. These can be scores for each vocabulary token before SoftMax\n            or scores for each vocabulary token after SoftMax.\n        kwargs (`Dict[str, Any]`, *optional*):\n            Additional stopping criteria specific kwargs.\n\n    Return:\n        `bool`. `False` indicates we should continue, `True` indicates we should stop.\n\n'






class 			UpperCamelCase     (      A_ ):


 @add_start_docstrings(snake_case__				)
 def __call__(	self						:		List[Any]				,		UpperCAmelCase__						:		torch.LongTensor				,		UpperCAmelCase__						:		torch.FloatTensor				,		**UpperCAmelCase__						:		List[Any]				)   ->			bool:
   raise NotImplementedError("""StoppingCriteria needs to be subclassed"""				)







class 			UpperCamelCase     (      A_ ):


 def __init__(	self						:		str				,		UpperCAmelCase__						:		int				,		UpperCAmelCase__						:		Optional[int] = None				)   ->			int:
   _a    :			Any			 =      max_length
   _a    :			int			 =      max_position_embeddings







 @add_start_docstrings(snake_case__				)
 def __call__(	self						:		int				,		UpperCAmelCase__						:		torch.LongTensor				,		UpperCAmelCase__						:		torch.FloatTensor				,		**UpperCAmelCase__						:		Any				)   ->			bool:
   _a    :			Tuple			 =      input_ids.shape[-1]
   _a    :			Optional[Any]			 =      cur_len >= self.max_length
   if self.max_position_embeddings is not None and not is_done and cur_len >= self.max_position_embeddings:
     logger.warning_once(
         """This is a friendly reminder - the current text generation call will exceed the model's predefined """
         f"""maximum length ({self.max_position_embeddings}). Depending on the model, you may observe """
         """exceptions, performance degradation, or nothing at all."""				)
   return is_done







class 			UpperCamelCase     (      A_ ):


 def __init__(	self						:		List[str]				,		UpperCAmelCase__						:		int				,		UpperCAmelCase__						:		int				)   ->			Dict:
   warnings.warn(
       """The class `MaxNewTokensCriteria` is deprecated. """
       f"""Please use `MaxLengthCriteria(max_length={start_length + max_new_tokens})` """
       """with `max_length = start_length + max_new_tokens` instead."""				,		snake_case__				,		)
   _a    :			int			 =      start_length
   _a    :			str			 =      max_new_tokens
   _a    :			int			 =      start_length + max_new_tokens







 @add_start_docstrings(snake_case__				)
 def __call__(	self						:		str				,		UpperCAmelCase__						:		torch.LongTensor				,		UpperCAmelCase__						:		torch.FloatTensor				,		**UpperCAmelCase__						:		Dict				)   ->			bool:
   return input_ids.shape[-1] >= self.max_length







class 			UpperCamelCase     (      A_ ):


 def __init__(	self						:		List[str]				,		UpperCAmelCase__						:		float				,		UpperCAmelCase__						:		Optional[float] = None				)   ->			List[Any]:
   _a    :			Union[str, Any]			 =      max_time
   _a    :			List[str]			 =      time.time() if initial_timestamp is None else initial_timestamp







 @add_start_docstrings(snake_case__				)
 def __call__(	self						:		int				,		UpperCAmelCase__						:		torch.LongTensor				,		UpperCAmelCase__						:		torch.FloatTensor				,		**UpperCAmelCase__						:		Optional[int]				)   ->			bool:
   return time.time() - self.initial_timestamp > self.max_time







class 			UpperCamelCase     (      A_ ):


 @add_start_docstrings(snake_case__				)
 def __call__(	self						:		Tuple				,		UpperCAmelCase__						:		torch.LongTensor				,		UpperCAmelCase__						:		torch.FloatTensor				,		**UpperCAmelCase__						:		Union[str, Any]				)   ->			bool:
   return any(criteria(snake_case__				,		snake_case__				) for criteria in self				)







 @property
 def _lowercase      (	self						:		str				)   ->			Optional[int]:


   for stopping_criterium in self:
     if isinstance(snake_case__				,		snake_case__				):
       return stopping_criterium.max_length
     elif isinstance(snake_case__				,		snake_case__				):
       return stopping_criterium.max_length
   return None







def      lowerCAmelCase__	(	UpperCamelCase__	,  UpperCamelCase__							):



  '''simple docstring'''
  _a    :			Union[str, Any]			 =      stopping_criteria.max_length
  _a    :			List[str]			 =      deepcopy(__lowerCamelCase							)
  if stopping_max_length is not None and stopping_max_length != max_length:
    warnings.warn("""You set different `max_length` for stopping criteria and `max_length` parameter"""	,  __lowerCamelCase							)
  elif stopping_max_length is None:
    new_stopping_criteria.append(MaxLengthCriteria(max_length=__lowerCamelCase							)							)
  return new_stopping_criteria



import os
from argparse import ArgumentParser, Namespace

from ..data import SingleSentenceClassificationProcessor as Processor
from ..pipelines import TextClassificationPipeline
from ..utils import is_tf_available, is_torch_available, logging
from . import BaseTransformersCLICommand


if not is_tf_available() and not is_torch_available():
   raise RuntimeError("""At least one of PyTorch or TensorFlow 2.0+ should be installed to use CLI training""")

# TF training parameters
__lowerCamelCase				=			False
__lowerCamelCase				=			False


def      UpperCamelCase   (       __lowerCamelCase	:					Namespace       ):
       return TrainCommand(__lowerCamelCase       )






class     UpperCAmelCase						(		A_					):



   @staticmethod
   def 							_SCREAMING_SNAKE_CASE  (snake_case__						:   ArgumentParser					)						->      int:


          '''simple docstring'''


          snake_case			:  Any     							= parser.add_parser("train"       ,		help="CLI tool to train a model on a task."					)

          train_parser.add_argument(
              "--train_data"       ,		type=snake_case__       ,		required=snake_case__       ,		help="path to train (and optionally evaluation) dataset as a csv with tab separated labels and sentences."       ,		)
          train_parser.add_argument(
              "--column_label"       ,		type=snake_case__       ,		default=0       ,		help="Column of the dataset csv file with example labels."					)
          train_parser.add_argument(
              "--column_text"       ,		type=snake_case__       ,		default=1       ,		help="Column of the dataset csv file with example texts."					)
          train_parser.add_argument(
              "--column_id"       ,		type=snake_case__       ,		default=2       ,		help="Column of the dataset csv file with example ids."					)
          train_parser.add_argument(
              "--skip_first_row"       ,		action="store_true"       ,		help="Skip the first row of the csv file (headers)."					)

          train_parser.add_argument("--validation_data"       ,		type=snake_case__       ,		default=""       ,		help="path to validation dataset."					)
          train_parser.add_argument(
              "--validation_split"       ,		type=snake_case__       ,		default=0.1       ,		help="if validation dataset is not provided, fraction of train dataset to use as validation dataset."       ,		)

          train_parser.add_argument("--output"       ,		type=snake_case__       ,		default="./"       ,		help="path to saved the trained model."					)

          train_parser.add_argument(
              "--task"       ,		type=snake_case__       ,		default="text_classification"       ,		help="Task to train the model on."					)
          train_parser.add_argument(
              "--model"       ,		type=snake_case__       ,		default="bert-base-uncased"       ,		help="Model's name or path to stored model."					)
          train_parser.add_argument("--train_batch_size"       ,		type=snake_case__       ,		default=32       ,		help="Batch size for training."					)
          train_parser.add_argument("--valid_batch_size"       ,		type=snake_case__       ,		default=64       ,		help="Batch size for validation."					)
          train_parser.add_argument("--learning_rate"       ,		type=snake_case__       ,		default=3e-5       ,		help="Learning rate."					)
          train_parser.add_argument("--adam_epsilon"       ,		type=snake_case__       ,		default=1e-08       ,		help="Epsilon for Adam optimizer."					)
          train_parser.set_defaults(func=snake_case__					)



   def __init__(self						:   List[Any]       ,		snake_case__						:   Namespace					)						->      Tuple:


          '''simple docstring'''


          snake_case			:  Any     							= logging.get_logger("transformers-cli/training"					)

          snake_case			:  List[Any]     							= "tf" if is_tf_available() else "torch"

          os.makedirs(args.output       ,		exist_ok=snake_case__					)
          snake_case			:  Any     							= args.output

          snake_case			:  List[Any]     							= args.column_label
          snake_case			:  Tuple     							= args.column_text
          snake_case			:  str     							= args.column_id

          self.logger.info(f"""Loading {args.task} pipeline for {args.model}"""					)
          if args.task == "text_classification":
                 snake_case			:  Optional[int]     							= TextClassificationPipeline.from_pretrained(args.model					)
          elif args.task == "token_classification":
                 raise NotImplementedError
          elif args.task == "question_answering":
                 raise NotImplementedError

          self.logger.info(f"""Loading dataset from {args.train_data}"""					)
          snake_case			:  Tuple     							= Processor.create_from_csv(
              args.train_data       ,		column_label=args.column_label       ,		column_text=args.column_text       ,		column_id=args.column_id       ,		skip_first_row=args.skip_first_row       ,		)
          snake_case			:  Optional[Any]     							= None
          if args.validation_data:
                 self.logger.info(f"""Loading validation dataset from {args.validation_data}"""					)
                 snake_case			:  Dict     							= Processor.create_from_csv(
                     args.validation_data       ,		column_label=args.column_label       ,		column_text=args.column_text       ,		column_id=args.column_id       ,		skip_first_row=args.skip_first_row       ,		)

          snake_case			:  Union[str, Any]     							= args.validation_split
          snake_case			:  Optional[Any]     							= args.train_batch_size
          snake_case			:  List[str]     							= args.valid_batch_size
          snake_case			:  List[Any]     							= args.learning_rate
          snake_case			:  List[Any]     							= args.adam_epsilon



   def 							_SCREAMING_SNAKE_CASE  (self						:   int					)						->      List[str]:


          '''simple docstring'''


          if self.framework == "tf":
                 return self.run_tf()
          return self.run_torch()



   def 							_SCREAMING_SNAKE_CASE  (self						:   Tuple					)						->      Optional[Any]:


          '''simple docstring'''


          raise NotImplementedError



   def 							_SCREAMING_SNAKE_CASE  (self						:   Optional[Any]					)						->      Tuple:


          '''simple docstring'''


          self.pipeline.fit(
              self.train_dataset       ,		validation_data=self.valid_dataset       ,		validation_split=self.validation_split       ,		learning_rate=self.learning_rate       ,		adam_epsilon=self.adam_epsilon       ,		train_batch_size=self.train_batch_size       ,		valid_batch_size=self.valid_batch_size       ,		)

          # Save trained pipeline
          self.pipeline.save_pretrained(self.output					)





