





from typing import Any, Dict, List, Optional, Tuple, Union

import torch
from torch import nn
from torch.utils.data import DistributedSampler, RandomSampler

from transformers import PreTrainedModel, Trainer, logging
from transformers.integrations import is_fairscale_available
from transformers.models.fsmt.configuration_fsmt import FSMTConfig
from transformers.optimization import (
    Adafactor,
    AdamW,
    get_constant_schedule,
    get_constant_schedule_with_warmup,
    get_cosine_schedule_with_warmup,
    get_cosine_with_hard_restarts_schedule_with_warmup,
    get_linear_schedule_with_warmup,
    get_polynomial_decay_schedule_with_warmup,
)
from transformers.trainer_pt_utils import get_tpu_sampler
from transformers.training_args import ParallelMode
from transformers.utils import is_torch_tpu_available


if is_fairscale_available():
    from fairscale.optim import OSS


__lowerCamelCase       :     Dict   =     logging.get_logger(__name__)

__lowerCamelCase       :     Tuple   =     {
    """linear""": get_linear_schedule_with_warmup,
    """cosine""": get_cosine_schedule_with_warmup,
    """cosine_w_restarts""": get_cosine_with_hard_restarts_schedule_with_warmup,
    """polynomial""": get_polynomial_decay_schedule_with_warmup,
    """constant""": get_constant_schedule,
    """constant_w_warmup""": get_constant_schedule_with_warmup,
}



class 					A__   (       __snake_case			):





      def __init__( self       ,							A_=None       ,							A_=None       ,							*A_       ,							**A_   ):
       '''simple docstring'''




       super().__init__(*A_       ,							**A_   )

       if config is None:
        assert isinstance(self.model       ,							A_   ), (
            "If no `config` is passed the model to be trained has to be of type `PreTrainedModel`, but is"
            F""" {self.model.__class__}"""
        )
        UpperCamelCase	:					Optional[Any]       	=   self.model.config
       else:
        UpperCamelCase	:					int       	=   config

       UpperCamelCase	:					Tuple       	=   data_args
       UpperCamelCase	:					List[str]       	=   self.config.tgt_vocab_size if isinstance(self.config       ,							A_   ) else self.config.vocab_size

       if self.args.label_smoothing != 0 or (self.data_args is not None and self.data_args.ignore_pad_token_for_loss):
        assert self.config.pad_token_id is not None, (
            "Make sure that `config.pad_token_id` is correcly defined when ignoring `pad_token` for loss"
            " calculation or doing label smoothing."
        )

       if self.config.pad_token_id is None and self.config.eos_token_id is not None:
        logger.warning(
            F"""The `config.pad_token_id` is `None`. Using `config.eos_token_id` = {self.config.eos_token_id} for"""
            " padding.."   )

       if self.args.label_smoothing == 0:
        UpperCamelCase	:					Any       	=   torch.nn.CrossEntropyLoss(ignore_index=self.config.pad_token_id   )
       else:
        # dynamically import label_smoothed_nll_loss
        from utils import label_smoothed_nll_loss

        UpperCamelCase	:					Optional[Any]       	=   label_smoothed_nll_loss





      def        __UpperCamelCase( self       ,							A_   ):
       '''simple docstring'''




       if self.optimizer is None:
        UpperCamelCase	:					int       	=   ["bias", "LayerNorm.weight"]
        UpperCamelCase	:					Any       	=   [
            {
                "params": [p for n, p in self.model.named_parameters() if not any(nd in n for nd in no_decay   )],
                "weight_decay": self.args.weight_decay,
            },
            {
                "params": [p for n, p in self.model.named_parameters() if any(nd in n for nd in no_decay   )],
                "weight_decay": 0.0,
            },
        ]
        UpperCamelCase	:					Optional[int]       	=   Adafactor if self.args.adafactor else AdamW
        if self.args.adafactor:
         UpperCamelCase	:					Dict       	=   Adafactor
         UpperCamelCase	:					List[Any]       	=   {"scale_parameter": False, "relative_step": False}
        else:
         UpperCamelCase	:					Optional[int]       	=   AdamW
         UpperCamelCase	:					List[Any]       	=   {
             "betas": (self.args.adam_betaa, self.args.adam_betaa),
             "eps": self.args.adam_epsilon,
         }
        UpperCamelCase	:					Optional[int]       	=   self.args.learning_rate
        if self.sharded_ddp:
         UpperCamelCase	:					Dict       	=   OSS(
             params=A_       ,							optim=A_       ,							**A_       ,							)
        else:
         UpperCamelCase	:					Dict       	=   optimizer_cls(A_       ,							**A_   )

       if self.lr_scheduler is None:
        UpperCamelCase	:					int       	=   self._get_lr_scheduler(A_   )
       else:  # ignoring --lr_scheduler
        logger.warning("scheduler is passed to `Seq2SeqTrainer`, `--lr_scheduler` arg is ignored."   )





      def        __UpperCamelCase( self       ,							A_   ):
       '''simple docstring'''




       UpperCamelCase	:					List[str]       	=   arg_to_scheduler[self.args.lr_scheduler]
       if self.args.lr_scheduler == "constant":
        UpperCamelCase	:					Any       	=   schedule_func(self.optimizer   )
       elif self.args.lr_scheduler == "constant_w_warmup":
        UpperCamelCase	:					List[Any]       	=   schedule_func(self.optimizer       ,							num_warmup_steps=self.args.warmup_steps   )
       else:
        UpperCamelCase	:					str       	=   schedule_func(
            self.optimizer       ,							num_warmup_steps=self.args.warmup_steps       ,							num_training_steps=A_   )
       return scheduler





      def        __UpperCamelCase( self   ):
       '''simple docstring'''




       if isinstance(self.train_dataset       ,							torch.utils.data.IterableDataset   ):
        return None
       elif is_torch_tpu_available():
        return get_tpu_sampler(self.train_dataset   )
       else:
        if self.args.sortish_sampler:
         self.train_dataset.make_sortish_sampler(
             self.args.per_device_train_batch_size       ,							distributed=(self.args.parallel_mode == ParallelMode.DISTRIBUTED)       ,							)

        return (
            RandomSampler(self.train_dataset   )
            if self.args.local_rank == -1
            else DistributedSampler(self.train_dataset   )
        )





      def        __UpperCamelCase( self       ,							A_       ,							A_       ,							A_   ):
       '''simple docstring'''




       if self.args.label_smoothing == 0:
        if self.data_args is not None and self.data_args.ignore_pad_token_for_loss:
         # force training to ignore pad token
         UpperCamelCase	:					List[Any]       	=   model(**A_       ,							use_cache=A_   )[0]
         UpperCamelCase	:					Union[str, Any]       	=   self.loss_fn(logits.view(-1       ,							logits.shape[-1]   )       ,							labels.view(-1   )   )
        else:
         # compute usual loss via models
         UpperCamelCase	,    UpperCamelCase	:					str       	=   model(**A_       ,							labels=A_       ,							use_cache=A_   )[:2]
       else:
        # compute label smoothed loss
        UpperCamelCase	:					Tuple       	=   model(**A_       ,							use_cache=A_   )[0]
        UpperCamelCase	:					List[str]       	=   torch.nn.functional.log_softmax(A_       ,							dim=-1   )
        UpperCamelCase	,    UpperCamelCase	:					Dict       	=   self.loss_fn(A_       ,							A_       ,							self.args.label_smoothing       ,							ignore_index=self.config.pad_token_id   )
       return loss, logits





      def        __UpperCamelCase( self       ,							A_       ,							A_   ):
       '''simple docstring'''




       UpperCamelCase	:					Dict       	=   inputs.pop("labels"   )
       UpperCamelCase	,    UpperCamelCase	:					int       	=   self._compute_loss(A_       ,							A_       ,							A_   )
       return loss





      def        __UpperCamelCase( self       ,							A_       ,							A_       ,							A_       ,							A_ = None       ,							):
       '''simple docstring'''




       UpperCamelCase	:					str       	=   self._prepare_inputs(A_   )

       UpperCamelCase	:					Optional[Any]       	=   {
           "max_length": self.data_args.val_max_target_length
           if self.data_args is not None
           else self.config.max_length,
           "num_beams": self.data_args.eval_beams if self.data_args is not None else self.config.num_beams,
       }

       if self.args.predict_with_generate and not self.args.prediction_loss_only:
        UpperCamelCase	:					Optional[Any]       	=   self.model.generate(
            inputs["input_ids"]       ,							attention_mask=inputs["attention_mask"]       ,							**A_       ,							)
        # in case the batch is shorter than max length, the output should be padded
        if generated_tokens.shape[-1] < gen_kwargs["max_length"]:
         UpperCamelCase	:					Tuple       	=   self._pad_tensors_to_max_len(A_       ,							gen_kwargs["max_length"]   )

       UpperCamelCase	:					List[str]       	=   inputs.pop("labels"   )
       with torch.no_grad():
        # compute loss on predict data
        UpperCamelCase	,    UpperCamelCase	:					str       	=   self._compute_loss(A_       ,							A_       ,							A_   )

       UpperCamelCase	:					Dict       	=   loss.mean().detach()
       if self.args.prediction_loss_only:
        return (loss, None, None)

       UpperCamelCase	:					Optional[int]       	=   generated_tokens if self.args.predict_with_generate else logits

       if labels.shape[-1] < gen_kwargs["max_length"]:
        UpperCamelCase	:					Dict       	=   self._pad_tensors_to_max_len(A_       ,							gen_kwargs["max_length"]   )

       return (loss, logits, labels)





      def        __UpperCamelCase( self       ,							A_       ,							A_   ):
       '''simple docstring'''




       UpperCamelCase	:					Any       	=   self.config.pad_token_id if self.config.pad_token_id is not None else self.config.eos_token_id

       if pad_token_id is None:
        raise ValueError(
            "Make sure that either `config.pad_token_id` or `config.eos_token_id` is defined if tensor has to be"
            F""" padded to `max_length`={max_length}"""   )

       UpperCamelCase	:					List[Any]       	=   pad_token_id * torch.ones(
           (tensor.shape[0], max_length)       ,							dtype=tensor.dtype       ,							device=tensor.device   )
       UpperCamelCase	:					Dict       	=   tensor
       return padded_tensor








"""simple docstring"""





import numpy as np
from nltk.translate import meteor_score

import datasets
from datasets.config import importlib_metadata, version


_SCREAMING_SNAKE_CASE					:				Tuple					    =						version.parse(importlib_metadata.version('''nltk'''))
if NLTK_VERSION >= version.Version('''3.6.4'''):
  from nltk import word_tokenize


_SCREAMING_SNAKE_CASE					:				Tuple					    =						'''\
@inproceedings{banarjee2005,
  title     = {{METEOR}: An Automatic Metric for {MT} Evaluation with Improved Correlation with Human Judgments},
  author    = {Banerjee, Satanjeev  and Lavie, Alon},
  booktitle = {Proceedings of the {ACL} Workshop on Intrinsic and Extrinsic Evaluation Measures for Machine Translation and/or Summarization},
  month     = jun,
  year      = {2005},
  address   = {Ann Arbor, Michigan},
  publisher = {Association for Computational Linguistics},
  url       = {https://www.aclweb.org/anthology/W05-0909},
  pages     = {65--72},
}
'''

_SCREAMING_SNAKE_CASE					:				int					    =						'''\
METEOR, an automatic metric for machine translation evaluation
that is based on a generalized concept of unigram matching between the
machine-produced translation and human-produced reference translations.
Unigrams can be matched based on their surface forms, stemmed forms,
and meanings; furthermore, METEOR can be easily extended to include more
advanced matching strategies. Once all generalized unigram matches
between the two strings have been found, METEOR computes a score for
this matching using a combination of unigram-precision, unigram-recall, and
a measure of fragmentation that is designed to directly capture how
well-ordered the matched words in the machine translation are in relation
to the reference.

METEOR gets an R correlation value of 0.347 with human evaluation on the Arabic
data and 0.331 on the Chinese data. This is shown to be an improvement on
using simply unigram-precision, unigram-recall and their harmonic F1
combination.
'''

_SCREAMING_SNAKE_CASE					:				List[Any]					    =						'''
Computes METEOR score of translated segments against one or more references.
Args:
    predictions: list of predictions to score. Each prediction
        should be a string with tokens separated by spaces.
    references: list of reference for each prediction. Each
        reference should be a string with tokens separated by spaces.
    alpha: Parameter for controlling relative weights of precision and recall. default: 0.9
    beta: Parameter for controlling shape of penalty as a function of fragmentation. default: 3
    gamma: Relative weight assigned to fragmentation penalty. default: 0.5
Returns:
    \'meteor\': meteor score.
Examples:

    >>> meteor = datasets.load_metric(\'meteor\')
    >>> predictions = ["It is a guide to action which ensures that the military always obeys the commands of the party"]
    >>> references = ["It is a guide to action that ensures that the military will forever heed Party commands"]
    >>> results = meteor.compute(predictions=predictions, references=references)
    >>> print(round(results["meteor"], 4))
    0.6944
'''






@datasets.utils.file_utils.add_start_docstrings(_DESCRIPTION  ,      _KWARGS_DESCRIPTION		)
class      a						(					datasets.Metric		):






    def    UpperCamelCase       (       self     :							List[str]					)     ->		List[str]:
      return datasets.MetricInfo(
          description=_DESCRIPTION       ,						citation=_CITATION       ,						inputs_description=_KWARGS_DESCRIPTION       ,						features=datasets.Features(
              {
                  'predictions': datasets.Value('string'       ,						id='sequence'					),
                  'references': datasets.Value('string'       ,						id='sequence'					),
              }					)       ,						codebase_urls=['https://github.com/nltk/nltk/blob/develop/nltk/translate/meteor_score.py']       ,						reference_urls=[
              'https://www.nltk.org/api/nltk.translate.html#module-nltk.translate.meteor_score',
              'https://en.wikipedia.org/wiki/METEOR',
          ]       ,						)






    def    UpperCamelCase       (       self     :							Optional[int]       ,						__SCREAMING_SNAKE_CASE     :							Union[str, Any]					)     ->		Dict:
      import nltk

      nltk.download('wordnet'					)
      if NLTK_VERSION >= version.Version('3.6.5'					):
        nltk.download('punkt'					)
      if NLTK_VERSION >= version.Version('3.6.6'					):
        nltk.download('omw-1.4'					)






    def    UpperCamelCase       (       self     :							Optional[int]       ,						__SCREAMING_SNAKE_CASE     :							Any       ,						__SCREAMING_SNAKE_CASE     :							Any       ,						__SCREAMING_SNAKE_CASE     :							List[Any]=0.9       ,						__SCREAMING_SNAKE_CASE     :							Dict=3       ,						__SCREAMING_SNAKE_CASE     :							Union[str, Any]=0.5					)     ->		int:
      if NLTK_VERSION >= version.Version('3.6.5'					):
        lowerCamelCase_         =						[
            meteor_score.single_meteor_score(
                word_tokenize(__SCREAMING_SNAKE_CASE					)       ,						word_tokenize(__SCREAMING_SNAKE_CASE					)       ,						alpha=__SCREAMING_SNAKE_CASE       ,						beta=__SCREAMING_SNAKE_CASE       ,						gamma=__SCREAMING_SNAKE_CASE					)
            for ref, pred in zip(__SCREAMING_SNAKE_CASE       ,						__SCREAMING_SNAKE_CASE					)
        ]
      else:
        lowerCamelCase_         =						[
            meteor_score.single_meteor_score(__SCREAMING_SNAKE_CASE       ,						__SCREAMING_SNAKE_CASE       ,						alpha=__SCREAMING_SNAKE_CASE       ,						beta=__SCREAMING_SNAKE_CASE       ,						gamma=__SCREAMING_SNAKE_CASE					)
            for ref, pred in zip(__SCREAMING_SNAKE_CASE       ,						__SCREAMING_SNAKE_CASE					)
        ]

      return {"meteor": np.mean(__SCREAMING_SNAKE_CASE					)}




