o
    }oi&                     @   s   d dl mZmZmZmZ d dlZd dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d	gZd
d ZG dd	 d	e	ZdS )    )LiteralOptionalSequenceUnionN)_bleu_score_compute)SacreBLEUScore)AbstractCTCDecoding)AbstractMultiTaskDecoding)AbstractRNNTDecoding)loggingBLEUc                 C   s6   t t| j}| j|g|d |  ||d d    S )N   )listrangendimpermute)tensor	dim_indexall_dims r   U/home/ubuntu/.local/lib/python3.10/site-packages/nemo/collections/asr/metrics/bleu.pymove_dimension_to_the_front   s   (r   c                       s   e Zd ZU dZdZeed< 								dd	eee	e
f d
ed dededeee  def fddZ		d dejdejdejdejdeej deej f fddZd! fdd	Zdd Z  ZS )"r   a	  
    This metric computes numerator, denominator, hypotheses lengths, and target lengths for Overall Bilingual Evaluation Understudy (BLEU)
    between prediction and reference texts. When doing distributed training/evaluation the result of
    ``res=BLEU.(predictions, predictions_lengths, targets, target_lengths)``
    calls will be all-reduced between all workers using SUM operations.

    If used with PytorchLightning LightningModule, include bleu_num bleur_den, bleu_pred_len, and bleu_target_len values inside
    validation_step results. Then aggregate (sum) then at the end of validation epoch to correctly compute validation BLEUR.

    Example:
        def validation_step(self, batch, batch_idx):
            ...
            bleu_values = self.bleu(predictions, predictions_len, transcript, transcript_len)
            self.val_outputs = {'val_loss': loss_value, **bleu_values}
            return self.val_outputs

        def on_validation_epoch_end(self):
            ...
            bleu_num = torch.stack([x['val_wer_num'] for x in self.val_outputs]).sum()
            bleu_denom = torch.stack([x['val_wer_denom'] for x in self.val_outputs]).sum()
            bleu_num = torch.stack([x[f"val_bleu_num"] for x in outputs]).sum(dim=0)
            bleu_denom = torch.stack([x[f"val_bleu_denom"] for x in outputs]).sum(dim=0)

            val_bleu = {"val_bleu": self.bleu._compute_bleu(bleu_pred_len, bleu_target_len, bleu_num, bleu_denom)}
            tensorboard_logs.update(val_bleu)

            self.val_outputs.clear()  # free memory
            return {'val_loss': val_loss_mean, 'log': tensorboard_logs}

    Args:
        decoding: An instance of CTCDecoding, RNNTDecoding, or MultiTaskDecoding.
        tokenize: Desired tokenizer for BLEU evaluation. (Depending on language, this will drastically affect BLEU score.)
        n_gram: Maximum number of n_grams to compute BLEU values over. Max: 4.
        lowercase: Whether to lowercase all inputs.
        weights: List of float values to weight each n_gram score.
        log_prediction: Whether to log a single decoded sample per call.
        batch_dim_index: Index corresponding to batch dimension. (For RNNT.)
        dist_dync_on_step: Whether to perform reduction on forward pass of metric.

    Returns:
        res: a tuple of 3 zero dimensional float32 ``torch.Tensor` objects: a WER score, a sum of Levenstein's
            distances for all prediction - reference pairs, total number of words in all references.
    Tfull_state_update13a   FNr   decodingtokenize)noner   zhintlcharn_gram	lowercaseweightssmoothc
           
         s   t  j||||||	d | _d  _t jtr  fdd _n&t jtr. fdd _nt jtr< fdd _n
tdt	 j | _
| _| _d S )N)r   r!   r"   r#   r$   dist_sync_on_stepc                    s    j j| |dS )N)encoder_outputencoded_lengths)r   rnnt_decoder_predictions_tensorpredictionspredictions_lengthspredictions_mask	input_idstargetsselfr   r   <lambda>i   s    zBLEU.__init__.<locals>.<lambda>c                    s    j j| | jdS )N)decoder_outputsdecoder_lengthsfold_consecutive)r   ctc_decoder_predictions_tensorr4   r)   r/   r   r   r1   m   s
    c                    s    j j| ||ddS )NF)encoder_hidden_statesencoder_input_maskdecoder_input_idsreturn_hypotheses)r   decode_predictions_tensor)r*   prediction_lengthsr,   r-   r.   r/   r   r   r1   s   s    z-WER metric does not support decoding of type )super__init__r   decode
isinstancer
   r   r	   	TypeErrortyper   log_predictionbatch_dim_index)
r0   r   r   r!   r"   r#   r$   rB   rC   r%   	__class__r/   r   r=   R   s(   
zBLEU.__init__r*   r+   r.   targets_lengthsr,   r-   c                    s  g }t  O |  }|  }	| jdkrt|	| j}	t|	jd D ]}
||
  }|	|
 d| 	 
 }| j|}|| q%| |||||}W d   n1 sXw   Y  | jrytd td|d   td|d   t dd |D |g dS )a  
        Updates metric state.
        Args:
            predictions: an integer torch.Tensor of shape ``[Batch, Time, {Vocabulary}]`` (if ``batch_dim_index == 0``) or
                ``[Time, Batch]`` (if ``batch_dim_index == 1``)
            predictions_lengths: an integer torch.Tensor of shape ``[Batch]``
            targets: an integer torch.Tensor of shape ``[Batch, Time]`` (if ``batch_dim_index == 0``) or
                ``[Time, Batch]`` (if ``batch_dim_index == 1``)
            target_lengths: an integer torch.Tensor of shape ``[Batch]``
            predictions_mask: a bool torch.Tensor of shape ``[Batch, Time]`` (if ``batch_dim_index == 0``) or
                ``[Time, Batch]`` (if ``batch_dim_index == 1``). Required for MultiTaskDecoding.
            input_ids: an int torch.Tensor of shape ``[Batch, Time]`` (if ``batch_dim_index == 0``) or
                ``[Time, Batch]`` (if ``batch_dim_index == 1``). Required for MultiTaskDecoding.
        r   N
z
reference:z
predicted:c                 S   s   g | ]}|j qS r   )text).0hr   r   r   
<listcomp>   s    zBLEU.update.<locals>.<listcomp>)torchno_gradlongcpurC   r   r   shapeitemnumpytolistr   decode_tokens_to_strappendr>   rB   r   infor<   update)r0   r*   r+   r.   rF   r,   r-   
referencestgt_lenths_cpu_tensortargets_cpu_tensorindtgt_lentarget	reference
hypothesesrD   r   r   rW      s(   


zBLEU.update c                    s   t   }|r@| d| || d| | j  | d| | j  | d| | j  | d| | j  iS | d| |iS )a  
        Returns BLEU values and component metrics.

        Args:
            return_all_metrics: bool flag. On True, BLEU and composite metrics returned. If False, returns
                only BLEU. Default: True.
            prefix: str to prepend to metric value keys.
            suffix: str to append to metric value keys.

        Returns:
            Dict: key-value pairs of BLEU metrics and values. Keys are prepended and appended with prefix
                and suffix flags, respectively.
        bleubleu_pred_lenbleu_target_lenbleu_num
bleu_denom)r<   compute	preds_lendetachfloat
target_len	numeratordenominator)r0   return_all_metricsprefixsuffixra   rD   r   r   rf      s   
zBLEU.computec                 C   s   t ||||| j| j| jS )N)r   r!   r#   r$   )r0   r+   rF   rk   rl   r   r   r   _compute_bleu   s   zBLEU._compute_bleu)r   r   FNFTr   F)NN)Tr`   r`   )__name__
__module____qualname____doc__r   bool__annotations__r   r   r
   r	   r   intr   r   ri   r=   rL   TensorrW   rf   rp   __classcell__r   r   rD   r   r   #   sR   
 ,
4/)typingr   r   r   r   rL   !torchmetrics.functional.text.bleur   torchmetrics.textr   2nemo.collections.asr.parts.submodules.ctc_decodingr   8nemo.collections.asr.parts.submodules.multitask_decodingr	   3nemo.collections.asr.parts.submodules.rnnt_decodingr
   
nemo.utilsr   __all__r   r   r   r   r   r   <module>   s   