o
    wiO                     @   s  d dl Z d dlZd dlmZ d dlmZmZmZmZm	Z	m
Z
 d dlZd dlmZmZ d dlmZmZmZ d dlmZmZ d dlmZmZmZmZmZ d dlmZ d d	lmZ d d
l m!Z! d dl"m#Z#m$Z$m%Z% zd dl&Z'dZ(W n e)e*fy{   dZ(Y nw zd dl+m,Z,m-Z-m.Z. dZ/W n e)e*fy   dZ/Y nw zd dl0m1Z1 d dl2m3Z3 dZ4W n e)e*fy   dZ4Y nw dZ5eG dd dZ6e6dde(e5dde6ddde/e!dde6ddddddde6ddde/e!dde6ddddd dde6d!d"e4edde6d#d"e4edde6d$dde/e!d%e6d&dddd'd%d(	Z7e7d e7d)< d*d+ Z8	d;d,e9d-e	ee9ef  d.ed/e	e
e9  d0ee9ef f
d1d2Z:d0e9fd3d4Z;d;d,e9d5e<d6e=d0ej>j?fd7d8Z@G d9d: d:eZAdS )<    N)	dataclass)AnyCallableDictListOptionalSet)
DictConfig	OmegaConf)MultiblankRNNTLossPytorchRNNTLossPytorchTDTLossPytorch)Loss	typecheck)
LabelsTypeLengthsTypeLogprobsTypeLossType
NeuralType)numba_utils)K2_INSTALLATION_MESSAGE)NUMBA_INSTALLATION_MESSAGE)logginglogging_modemodel_utilsTF)MultiblankRNNTLossNumbaRNNTLossNumbaTDTLossNumba)GraphRnntLoss)GraphWTransducerLosszCould not import `warprnnt_pytorch`.
Please visit https://github.com/HawkAaron/warp-transducer and follow the steps in the readme to build and install the pytorch bindings for RNNT Loss, or use the provided docker container that supports RNN-T loss.c                   @   sR   e Zd ZU eed< eed< dZeed< dZeed< dZe	e ed< d	Z
eed
< dS )RNNTLossConfig	loss_namelib_nameFis_available installation_msgNmin_versionTforce_float32)__name__
__module____qualname__str__annotations__r#   boolr%   r&   r   r'    r.   r.   ]/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/nemo/collections/asr/losses/rnnt.pyr    M   s   
 r    warprnntwarprnnt_pytorch)r!   r"   r#   r%   r'   warprnnt_numbanumbaz0.53.0)r!   r"   r&   r#   r%   r'   pytorchtorchz0.0zPPure Pytorch implementation of RNN-T loss. Slow and for debugging purposes only.multiblank_rnntz[Pure Pytorch implementation of Multiblank RNN-T loss. Slow and for debugging purposes only.graph_w_transducerk2
graph_rnnttdt)r!   r"   r&   r#   r%   tdt_pytorchzNPure Pytorch implementation of TDT loss. Slow and for debugging purposes only.)	r0   r2   r4   r6   multiblank_rnnt_pytorchr7   r9   r:   r;   defaultc                 C   s*   t |dkrtd|  d|  d S d S )Nr   zLoss function `z\` was provided with following additional kwargs,
however they were ignored as it is unused.
)lenr   warning)r!   kwargsr.   r.   r/   _warn_unused_additional_kwargs   s   rA   r!   r@   init_methodignore_paramsreturnc           	      C   s   |si S t t|j dh }|dur||8 }t }t }| D ]\}}||vr0|||< q#|||< q#t|dkr@t| | |S )af  
    Cleans kwargs for the given loss function. Warn if there are unused kwargs.

    Args:
        loss_name: name of the loss function
        kwargs: kwargs to clean
        init_method: LossClass.__init__ method
        ignore_params: set of argument names for init_method to ignore

    Returns:
        only used kwargs for the given `init_method`
    selfNr   )	setinspect	signature
parameterskeysdictitemsr>   rA   )	r!   r@   rB   rC   init_paramsunused_kwargsused_kwargskeyvaluer.   r.   r/   _clean_kwargs   s   


rR   c                   C   s
   t d jS )Nr=   )RNNT_LOSS_RESOLVERr!   r.   r.   r.   r/   resolve_rnnt_default_loss_name   s   
rT   	blank_idxloss_kwargsc              	   C   s6  t t }| |vrtd|  d| dd t D }t|  }|js5dt |  d|j }t||jd urWt	j
|j|jtjd\}}|du rW| d	|j }t||d u r]i n|}t|trktj|d
d}| dkrr|j} 	 | dkrtj|dd}t| | |S | dkrt  |_|dd}	|dd}
t|d|	|
d}t| | |S | dkrt|dd}t| | |S | dkr|dd}	|dd}
|dd }|dd}t||d|	|
|d}t| | |S | dkr|dd }|dd}t||d|d}t| | |S | dkr=|dd}	|dd}
|dd }|dd}|dd}t||d|	|
||d }t| | |S | d!kr]|dd }|dd}t ||d|d"}t| | |S | d#krwt!| |t"j#d$hd%}t"d)d$|i|}|S | d&krt!| |t$j#d$hd%}t$d)d$|i|}|S td'|  d(| )*NzProvided `loss_name` z' not in list of available RNNT losses 
c                 S   s   i | ]
\}}|j r||qS r.   )r#   ).0nameconfigr.   r.   r/   
<dictcomp>   s    z%resolve_rnnt_loss.<locals>.<dictcomp>zInstalled RNNT losses are : z.
****************************************************************
To install the selected loss function, please follow the steps below:
)checked_versionoperatorFz
****************************************************************
To update the selected loss function, please follow the steps below:
T)resolver=   r0   none)blank	reductionr2   fastemit_lambdag        clampg      )r_   r`   ra   rb   r4   r6   big_blank_durationssigma)r_   rc   r`   ra   rb   rd   r<   )r_   rc   r`   rd   r:   	durationsomega)r_   re   r`   ra   rb   rd   rf   r;   )r_   re   r`   rd   r9   r_   )rC   r7   zInvalid value of `loss_name`: z. Allowed loss names are :r.   )%listrS   rJ   
ValueErrorrL   r#   r%   ImportErrorr&   r   check_lib_versionr"   r\   geRuntimeError
isinstancer	   r
   to_containerr!   r0   RNNTLossrA   r   is_numba_cuda_fp16_supportedr'   popr   r   r   r   r   r   rR   r   __init__r   )r!   rU   rV   loss_function_namesall_available_lossesloss_configmsgver_matched	loss_funcra   rb   rc   rd   re   rf   r.   r.   r/   resolve_rnnt_loss   s   



H
?
;
,

$

	


	
ry   c                       sV   e Zd Zedd Zedd Zdded	ef fd
dZdd Ze	 dd Z
  ZS )ro   c                 C   s6   t dt t dt t tdt t tdt dS )z-Input types definitions for CTCLoss.
        )BTr{   D)rz   r{   rz   )	log_probstargetsinput_lengthstarget_lengths)r   r   r   tupler   rE   r.   r.   r/   input_typesN  s
   

zRNNTLoss.input_typesc                 C   s   dt t diS )zYOutput types definitions for CTCLoss.
        loss:
            NeuralType(None)
        loss)elements_type)r   r   r   r.   r.   r/   output_typesY  s   zRNNTLoss.output_types
mean_batchr=   Nr`   r!   c                    sR   t t|   |dvrtd|| _|| _t|| j|d| _t| j	| _
d| _dS )ab  
        RNN-T Loss function based on https://github.com/HawkAaron/warp-transducer.
        Optionally, can utilize a numba implementation of the same loss without having to compile the loss,
        albiet there is a small speed penalty for JIT numba compile.

        Note:
            Requires Numba 0.53.0 or later to be installed to use this loss function.

        Losses can be selected via the config, and optionally be passed keyword arguments as follows.

        Examples:
            .. code-block:: yaml

                model:  # RNNT Model config
                    ...
                    loss:
                        loss_name: "warprnnt_numba"
                        warprnnt_numba_kwargs:
                            fastemit_lambda: 0.0

        Warning:
            In the case that GPU memory is exhausted in order to compute RNNTLoss, it might cause
            a core dump at the cuda level with the following error message.

            ```
                ...
                costs = costs.to(acts.device)
            RuntimeError: CUDA error: an illegal memory access was encountered
            terminate called after throwing an instance of 'c10::Error'
            ```

            Please kill all remaining python processes after this point, and use a smaller batch size
            for train, validation and test sets so that CUDA memory is not exhausted.

        Args:
            num_classes: Number of target classes for the joint network to predict.
                In all cases (conventional RNNT, multi-blank RNNT, and TDT model), this equals the token-id
                for the standard "blank" symbol. In particular, say V is the number of non-blank tokens in
                the vocabulary, then in the case of,
                standard RNNT: num_classes = V
                multiblank RNNT: num_classes = V + number-big-blanks (since we store big-blanks before
                                 standard blank, and the standard blank is the last symbol in the vocab)
                TDT: num_classes = V. Note, V here does not include any of the "duration outputs".

            reduction: Type of reduction to perform on loss. Possible values are 
                `mean_batch`, 'mean_volume`, `mean`, `sum` or None.
                `None` will return a torch vector comprising the individual loss values of the batch.
                `mean_batch` will average the losses in the batch
                `mean` will divide each loss by the target length and then average
                `mean_volume` will add up all the losses and divide by sum of target lengths

            loss_name: String that is resolved into an RNNT loss function. Available list of losses
                is ininitialized in `RNNT_LOSS_RESOLVER` dictionary.

            loss_kwargs: Optional Dict of (str, value) pairs that are passed to the instantiated loss
                function.
        )Nmeansumr   mean_volumez?`reduction` must be one of [mean, sum, mean_batch, mean_volume])rU   rV   FN)superro   rr   rh   _blankr`   ry   _lossrS   r'   _force_float32_fp16_compat_checked)rE   num_classesr`   r!   rV   	__class__r.   r/   rr   a  s   :
zRNNTLoss.__init__c                 C   s   t |trt|d}t|d}| jdkr| }|S | jdkr+t|| }|S | jdkr6| }|S | jdkrC| |  }|S )Nr   r   r   r   r   )rm   r   r5   catr`   r   divr   )rE   lossesr   r.   r.   r/   reduce  s   




zRNNTLoss.reducec                 C   s>  |  }|  }|  }| }| }| jst rn3| jrO|jtjkrO|jtjkrH| j	sHtjdd\}}t
jd|j d| tjd d| _	|}	| }~	|jd |kr`|jdd|d }| sh| }|jd |kry|jdd|d }| jj}
d | j_| j||||d	}|
| j_| jd ur| ||}~~~~|S )
NT)return_reasonz'Provided RNNT Joint tensor is of dtype zy, but RNNT loss could not be calculated in fp16 due to following reason stated below. Loss will be calculated in fp32. 

)mode   r   )dimstartlength)actslabelsact_lens
label_lens)longmaxr   r   rp   dtyper5   float32float16r   r   r?   r   ONCEfloatshapenarrow
contiguousis_contiguousr   r`   r   )rE   r}   r~   r   r   max_logit_lenmax_targets_len_reasonlogits_origloss_reductionr   r.   r.   r/   forward  sJ   

zRNNTLoss.forward)r   r=   N)r(   r)   r*   propertyr   r   r+   rr   r   r   r   __classcell__r.   r.   r   r/   ro   M  s    


Ero   )N)BrG   r\   dataclassesr   typingr   r   r   r   r   r   r5   	omegaconfr	   r
   (nemo.collections.asr.losses.rnnt_pytorchr   r   r   nemo.core.classesr   r   nemo.core.neural_typesr   r   r   r   r   nemo.core.utilsr   nemo.core.utils.k2_utilsr   nemo.core.utils.numba_utilsr   
nemo.utilsr   r   r   r1   r0   WARP_RNNT_AVAILABLEri   ModuleNotFoundError*nemo.collections.asr.parts.numba.rnnt_lossr   r   r   NUMBA_RNNT_AVAILABLE.nemo.collections.asr.parts.k2.graph_transducerr   *nemo.collections.asr.parts.k2.w_transducerr   K2_AVAILABLEWARP_RNNT_INSTALLATION_MESSAGEr    rS   rA   r+   rR   rT   intrK   nnModulery   ro   r.   r.   r.   r/   <module>   s    	F



  