o
    i                     @   s~   d dl mZmZmZ d dlZd dlm  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 G dd	 d	eZdS )
    )DictOptionalTupleN)check_argument_types)AbsLM)force_gatherable)AbsESPnetModel)make_pad_maskc                       s   e Zd Zddededef fddZ	ddejd	ejd
ee de	ejejf fddZ
	ddejd	ejdede	ejejf fddZdejd	ejde	ejeeejf ejf fddZdejd	ejdeeejf fddZ  ZS )ESPnetLanguageModelr   lm
vocab_size	ignore_idc                    s8   t  sJ t   || _|d | _|d | _|| _d S )N   )r   super__init__r   soseosr   )selfr   r   r   	__class__ K/home/ubuntu/.local/lib/python3.10/site-packages/espnet2/lm/espnet_model.pyr      s   




zESPnetLanguageModel.__init__Ntexttext_lengths
max_lengthreturnc                 C   s*  | d}|du r|ddd| f }n
|ddd|f }t|ddgd| j}t|ddgd| j}t|D ]\}}| j|||f< q:|d }	| |d\}
}tj	|

d|
jd |
ddd}|du rx|t|	|j
dd n|t|	|d d	|j
dd |
|d}||	fS )
zCompute negative log likelihood(nll)

        Normally, this function is called in batchify_nll.
        Args:
            text: (Batch, Length)
            text_lengths: (Batch,)
            max_lengths: int
        r   Nr   constantnone)	reductiong        )maxlen)sizemaxFpadr   r   	enumerater   r   cross_entropyviewshapemasked_fill_r	   todevice)r   r   r   r   
batch_sizextil	x_lengthsy_nllr   r   r   r4      s&   
$ zESPnetLanguageModel.nlld   r,   c                 C   s   | d}||kr| ||\}}nHg }g }| }d}		 t|	| |}
||	|
ddf }||	|
 }| j|||d\}}|| || |
}	|	|krOnqt|}t|}| d|kscJ | d|kslJ ||fS )a  Compute negative log likelihood(nll) from transformer language model

        To avoid OOM, this fuction seperate the input into batches.
        Then call nll for each batch and combine and return results.
        Args:
            text: (Batch, Length)
            text_lengths: (Batch,)
            batch_size: int, samples each batch contain when computing nll,
                        you may change this to avoid OOM or increase

        r   TN)r   )r!   r4   r"   minappendtorchcat)r   r   r   r,   	total_numr4   r1   nllsr   	start_idxend_idx
batch_textbatch_text_lengths	batch_nllbatch_x_lengthsr   r   r   batchify_nllH   s2   





z ESPnetLanguageModel.batchify_nllc           
      K   sT   |  ||\}}| }| | }t| d}t|||f|j\}}}	|||	fS )N)loss)r4   sumdictdetachr   r+   )
r   r   r   kwargsr4   	y_lengthsntokensrC   statsweightr   r   r   forwardr   s   
zESPnetLanguageModel.forwardc                 K   s   i S Nr   )r   r   r   rG   r   r   r   collect_feats   s   z!ESPnetLanguageModel.collect_feats)r   rM   )r5   )__name__
__module____qualname__r   intr   r8   Tensorr   r   r4   rB   r   strrL   rN   __classcell__r   r   r   r   r
      sH    
1
*
r
   )typingr   r   r   r8   torch.nn.functionalnn
functionalr#   	typeguardr   espnet2.lm.abs_modelr    espnet2.torch_utils.device_funcsr   espnet2.train.abs_espnet_modelr   &espnet.nets.pytorch_backend.nets_utilsr	   r
   r   r   r   r   <module>   s    