o
    wi4                     @   s   d dl mZ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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Zdd Zdd ZG dd deZdS )    )LiteralOptionalSequence	TypeAliasUnionN)CutSet)MixedCut)_bleu_score_compute_bleu_score_update)SacreBLEUScore)AbstractCTCDecoding)AbstractMultiTaskDecoding)AbstractRNNTDecoding)loggingBLEUbleu_tokenizerc                    s   dd   fdd| D S )z~
    Helper function for multi tokenizer BLEU evaluation.
    Looks for `bleu_tokenizer` property to pass to BLEU metric.
    c                 S   s   | j tS N)customgetBLEU_TOKENIZER)c r   ^/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/nemo/collections/asr/metrics/bleu.py	_get_lang(   s   z1_get_bleu_tokenizers_from_cuts.<locals>._get_langc                    s(   g | ]}t |tr |jn |qS r   )
isinstancer   first_non_padding_cut).0r   r   r   r   
<listcomp>-   s   ( z2_get_bleu_tokenizers_from_cuts.<locals>.<listcomp>r   )cutsr   r   r   _get_bleu_tokenizers_from_cuts"   s   r    c                 C   s6   t t| j}| j|g|d |  ||d d    S )N   )listrangendimpermute)tensor	dim_indexall_dimsr   r   r   _move_dimension_to_the_front0   s   (r)   c                       s   e Zd ZU dZdZeed< ed Ze	ed< 										
		d&de
eeef dedededeee  d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 dee fddZd( fdd	Zd d! Zd)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_bleu_num'] for x in self.val_outputs]).sum()
            bleu_denom = torch.stack([x['val_bleu_denom'] for x in self.val_outputs]).sum()
            bleu_pred_len = torch.stack([x['val_bleu_pred_len'] for x in self.val_outputs]).sum()
            bleu_target_len = torch.stack([x['val_bleu_target_len'] for x in self.val_outputs]).sum()
            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: Decoder instance (CTCDecoding, RNNTDecoding, or MultiTaskDecoding) for converting model outputs to text.
        tokenize: Tokenizer name for BLEU evaluation (affects BLEU score based on language/tokenization).
        n_gram: Maximum n-gram order for BLEU calculation (default: 4).
        lowercase: If True, lowercases all input texts before evaluation.
        weights: Optional sequence of float weights for each n-gram order.
        smooth: If True, applies smoothing to BLEU calculation.
        check_cuts_for_tokenizers: If True, will inspect cuts for a `BLEU_TOKENIZERS` attribute for 'on the fly' changes to tokenizer (see `cuts` argument in `update`).
        log_prediction: If True, logs the first reference and prediction in each batch.
        batch_dim_index: Index of the batch dimension in input tensors.
        dist_sync_on_step: If True, synchronizes metric state across distributed workers on each step.

    Returns:
        Dictionary containing BLEU score and component statistics (numerator, denominator, prediction_lengths, target_lengths).
    Tfull_state_update)	none13azhintlcharzja-mecabzko-mecab	flores101	flores200SacreBLEUTokenr,      FNr   decodingr   n_gram	lowercaseweightssmoothcheck_cuts_for_bleu_tokenizersc              	      sD   || _ |	| _|
| _|| _|   || _t j|||||||d d S )N)tokenizer5   r6   r7   r8   dist_sync_on_stepsync_on_compute)log_predictionfold_consecutivebatch_dim_indexr4   _init_decode
check_cutssuper__init__)selfr4   r   r5   r6   r7   r8   r9   r=   r>   r?   r;   r<   kwargs	__class__r   r   rC   f   s   
zBLEU.__init__predictionspredictions_lengthstargetstargets_lengthspredictions_mask	input_idsr   c                 K   s~  d}	| j r"t||jd ksJ dt| d|jd  dt|}	t  | dkr5| ||||ng }
| jdkrBt	|| j}|
  }|
  }t|D ]Z\}}|| d|  }| j|}|	rl|	| nd}t|
| jg|gg| j| j| j| j| j| |\| _| _|
r| jr|dkrtd td|  td|
| j  qRW d   dS 1 sw   Y  dS )	aT  
        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.
            cuts: a CutSet of ``length == batch size``. If `self.check_cuts`, inspects each element
                for SacreBLEU tokenizer type for corresponding element in batch. If a sequence element is ``None``,
                the initial tokenizer type from ``BLEU.__init__`` is used. If ``cuts == None`` then all elements
                in batch are tokenized with initial tokenizer type.
        Nr   z?BLEU metrics configured for multiple tokenizers, but got only 'z' samples for 'z' predictions.
zBLEU reference:zBLEU predicted:)rA   lenshaper    torchno_gradnumeldecoder?   r)   longcpu	enumeratetolistr4   decode_ids_to_strr
   text	numeratordenominator	preds_len
target_lenr5   _get_tokenizerr=   r   info)rD   rH   rI   rJ   rK   rL   rM   r   rE   
tokenizers
hypothesestargets_cpu_tensortgt_lenths_cpu_tensoridxtgt_lentarget	referencetokr   r   r   update   sH   




"zBLEU.update c                    sz   t   }|r6| 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.

        Returns:
            Dict: key-value pairs of BLEU metrics and values. Keys are prepended with prefix flag.
        bleubleu_pred_lenbleu_target_lenbleu_num
bleu_denom)rB   computer]   detachfloatr^   r[   r\   )rD   return_all_metricsprefixrl   rF   r   r   rq      s   


zBLEU.computec                 C   s   t ||||| j| j| jS r   )r	   r5   r7   r8   )rD   rI   rK   r[   r\   r   r   r   _compute_bleu   s   zBLEU._compute_bleuc                    s`    j r|d u r
 jS | jjvrtd| d jj  dt j jj|  fddS )Nz"Sample passed BLEU tokenizer key 'z ' but BLEU config only support ''c                    s    j |  j j S r   )	tokenizer_lowerr6   split)linerD   tokenizer_fnr   r   <lambda>   s    z%BLEU._get_tokenizer.<locals>.<lambda>)rA   rx   _TOKENIZE_FNKeyErrorkeysgetattr)rD   r:   r   r|   r   r_      s   zBLEU._get_tokenizerc                    st   d  _ t jtr fdd _ d S t jtr! fdd _ d S t jtr0 fdd _ d S tdt j )Nc                    s    j j| |dS )N)encoder_outputencoded_lengths)r4   rnnt_decoder_predictions_tensorrH   rI   rL   rM   rD   r   r   r~     s    z#BLEU._init_decode.<locals>.<lambda>c                    s    j j| | jdS )N)decoder_outputsdecoder_lengthsr>   )r4   ctc_decoder_predictions_tensorr>   r   r   r   r   r~   	  s
    c                    s    j j| ||ddS )NF)encoder_hidden_statesencoder_input_maskdecoder_input_idsreturn_hypotheses)r4   decode_predictions_tensor)rH   prediction_lengthsrL   rM   r   r   r   r~     s    z.BLEU metric does not support decoding of type )rT   r   r4   r   r   r   	TypeErrortyper   r   r   r   r@     s   zBLEU._init_decode)r,   r3   FNFFFTr   FT)NNN)Trk   r   )__name__
__module____qualname____doc__r*   bool__annotations__r   r2   r   r   r   r   r   intr   r   rs   rC   rQ   Tensorr   rj   rq   rv   r_   r@   __classcell__r   r   rF   r   r   5   sl   
 +
(
G
)typingr   r   r   r   r   rQ   lhotser   
lhotse.cutr   !torchmetrics.functional.text.bleur	   r
   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   r   r   <module>   s   