o
    ߥih                     @   s   d dl Z d dlZd dlmZmZmZ d dlZd dl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	d
ZG dd de	jZdS )    N)DictListOptional)searchutils)
data_utils)FairseqIncrementalDecoder)NGramRepeatBlock)TensorTc           
      C   s   |  |   d kr|d}|jtjkr|tj}| jd|d }| jddd }|d urA||}|	|d |	|d n
|
d}|
d}|rU| }| }|| dd  }d| | | ||  }	|	|fS )N   dimindexT)r   keepdim              ?)r   	unsqueezedtypetorchint64typegathersumeqmasked_fill_squeezesize)
lprobstargetepsilonignore_indexreducenll_losssmooth_losspad_maskeps_iloss r(   b/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/nlp/canmt/sequence_generator.pylabel_smoothed_nll_loss   s$   



r*   c                       s  e Zd Z																		d. fd	d
	Zdd Ze 		d/deeeee	f f de
e	 de
e fddZ			d0ddZe deeeee	f f deeeee	f   fddZdeeeee	f f fddZdeeeee	f f fddZ			d1deeeee	f f de
e	 de
e	 de
e fddZdedefd d!Zdefd"d#Z	d2ded$eeeee	f   d%ee ded&e
e	 d'efd(d)Zded*ed'ed+edef
d,d-Z  ZS )3SequenceGeneratorr   r      Tr   r   FNc                    sT  t    || _|| _|| _|| _| | _| | _|du r#| n|| _|dur1|	| jhn| jh| _
t|| _|| _t|| jd | _|| _|| _|| _|| _|| _|	| _|
| _|| _|| _d| _|dkrot|| _nd| _|dkszJ d|du rt|n|| _t| jdo| jj| _| j   || _!|| _"| j!dur| j!   dS dS )a{  Generates translations of a given source sentence.

        Args:
            models (List[~fairseq.models.FairseqModel]): ensemble of models,
                currently support fairseq.models.TransformerModel for scripting
            beam_size (int, optional): beam width (default: 1)
            max_len_a/b (int, optional): generate sequences of maximum length
                ax + b, where x is the source length
            max_len (int, optional): the maximum length of the generated output
                (not including end-of-sentence)
            min_len (int, optional): the minimum length of the generated output
                (not including end-of-sentence)
            normalize_scores (bool, optional): normalize scores by the length
                of the output (default: True)
            len_penalty (float, optional): length penalty, where <1.0 favors
                shorter, >1.0 favors longer sentences (default: 1.0)
            unk_penalty (float, optional): unknown word penalty, where <0
                produces more unks, >0 produces fewer (default: 0.0)
            temperature (float, optional): temperature, where values
                >1.0 produce more uniform samples and values <1.0 produce
                sharper samples (default: 1.0)
            match_source_len (bool, optional): outputs should match the source
                length (default: False)
        Nr   g?r   z$--temperature must be greater than 0needs_src_lengths)#super__init__modelrecon_force_decodingtrans_force_decodingtgt_dictpadunkeosunionsymbols_to_strip_from_outputlen
vocab_size	beam_sizemin	max_len_a	max_len_bmin_lenmax_lennormalize_scoreslen_penaltyunk_penaltytemperaturematch_source_lenepsr	   repeat_ngram_blockerr   
BeamSearchhasattrr-   should_set_src_lengthsevallm_model	lm_weight)selfr0   r3   r;   r=   r>   r@   r?   rA   rB   rC   rD   rE   no_repeat_ngram_sizesearch_strategyr6   r8   rL   rM   r1   r2   	__class__r(   r)   r/   .   sT   
/





zSequenceGenerator.__init__c                 C   s   | j   | S N)r0   cuda)rN   r(   r(   r)   rT      s   
zSequenceGenerator.cudasampleprefix_tokens	bos_tokenc                 C   s   | j |||dS )a2  Generate a batch of translations.

        Args:
            sample (dict): batch
            prefix_tokens (torch.LongTensor, optional): force decoder to begin
                with these tokens
            bos_token (int, optional): beginning of sentence token
                (default: self.eos)
        )rW   )	_generate)rN   rU   rV   rW   r(   r(   r)   forward   s   zSequenceGenerator.forwardc              	   c   s"   |D ]}|rt |n|}d|vrq|d }dd | D }|dur(|  t  | |}	W d   n1 s<w   Y  |durQ|tdd |	D  t	|d j
D ]5\}
}t |d j
|
ddf | j}|d	 durt |d	 j
|
ddf | jnd}||||	|
 fV  qXqdS )
zIterate over a batched dataset and yield individual translations.
        Args:
            cuda (bool, optional): use GPU for generation
            timer (StopwatchMeter, optional): time generations
        	net_inputc                 S   s   i | ]\}}|d kr||qS )prev_output_tokensr(   ).0kvr(   r(   r)   
<dictcomp>   s    z:SequenceGenerator.generate_batched_itr.<locals>.<dictcomp>Nc                 s   s     | ]}t |d  d V  qdS )r   tokensN)r9   )r\   hr(   r(   r)   	<genexpr>   s    z9SequenceGenerator.generate_batched_itr.<locals>.<genexpr>id
src_tokensr   )r   move_to_cudaitemsstartr   no_gradgeneratestopr   	enumeratedata	strip_padr4   )rN   data_itrr;   rT   timerrU   sinputencoder_inputhyposirc   srcrefr(   r(   r)   generate_batched_itr   s2   

  z&SequenceGenerator.generate_batched_itrreturnc                 K   s  ddl m} | j|fi |}g }g }tt|D ]}|| d }|d }	||	 |d }
||
 qtdd |D }t|}tt|D ]}|| dd||< || dd||< qG|d ||	| j
}dd	 }t|D ]\}}|||| dt|  qr|}|| j
}| jj|dd
d}|d d }t }|g|d< |g|d< |g|d< g |d< g |d< g |d< | ||}||fS )a  Generate translations. Match the api of other fairseq generators.

        Args:
            models (List[~fairseq.models.FairseqModel]): ensemble of models
            sample (dict): batch
            prefix_tokens (torch.LongTensor, optional): force decoder to begin
                with these tokens
            constraints (torch.LongTensor, optional): force decoder to include
                the list of constraints
            bos_token (int, optional): beginning of sentence token
                (default: self.eos)
        r   )tensorr`   decoder_outc                 s   s    | ]}| d V  qdS )r   N)r   )r\   r^   r(   r(   r)   rb      s    z-SequenceGenerator.generate.<locals>.<genexpr>r   c                 S   s"   |  |   ks
J ||  d S rS   )numelcopy_)ru   dstr(   r(   r)   copy_tensor   s   z/SequenceGenerator.generate.<locals>.copy_tensorTN)encoder_outfull_context_alignment
last_layerr   encoder_padding_maskrd   encoder_embeddingencoder_statessrc_lengths)r   ry   rX   ranger9   appendmaxrollnewfill_r4   rk   r   r0   decoderdict_forward_src)rN   rU   kwargsry   	finalizedtokens_listdecoder_listrt   sentr`   rz   r   
batch_sizeresr~   r^   
tgt_tokensdecoder_padding_maskdecoder_out_redecoder_outsscoresr(   r(   r)   ri      sH   



zSequenceGenerator.generatec                 C   s(  |d }|d }|d }| j |}|d d dd}|d d }d| j _| j j||d d	\}}	}
|
dd}
d
| j _|d}tjt	t	t
ttf   dd t|D }t|D ]6}t|d |  | jkd d }|| |d | d |d  |
| d |d  || || d q[|S )NrZ   rd   r[   r   r   r   r   Fincremental_statesTc                 S   &   g | ]}t jttttf  g qS r(   r   jitannotater   r   strr
   r\   rt   r(   r(   r)   
<listcomp>      z.SequenceGenerator._forward.<locals>.<listcomp>r   )r`   rz   final_encoder_embeddingfinal_encoder_out)r0   forward_encoder	transposehas_incrementalforward_decoderr   r   r   r   r   r   r   r
   r   numpywherecpur6   r   )rN   rU   rZ   rd   r[   encoder_outsr   r   r   avg_attn_scoresr   r   r   rt   eos_idxr(   r(   r)   _forward  s8   
$

zSequenceGenerator._forwardc                 C   s   |d }|d }|d }|d }d| j _| j j||d d\}}}	}
|
d }tj|dd	}|d
 d}|d|d}t||| j| j	dd\}}	|j
d }||d}tj|jddd||d |fdd}|S )NrZ   rd   r   prev_src_tokensFr   r   r   r   sources)r    r!   r"   T)axisr   r   )r   )r0   r   forward_decoder_srcr   log_softmaxviewr   r*   rF   r4   shapereshaper   catr   )rN   r   rU   rZ   rd   r   r[   r   r   _r   logitsr   r   r   r(   r(   r)   r   -  s:   


zSequenceGenerator._forward_srcconstraintsc           4         s
  t jtttttt f f t jtttttt f f i }|d }d|v r?|d }|| j|| j	@ 
 jdd}n
tdt|  | d d \}	}
| j}d}| jrb|  }ntt| j|
 | j | jd }| j|ks{J d| j|}|d	 d
 d
d}|d d
 }t |	ddd|d}||j 
 }| j!||}|d usJ t "|	| |d |# }t "|	| |d |
 $| j	}|d u r| jn||d d d
f< d }t "|	||%d}t jt&t&tttf   dd t'|	D  dd t'|	D }|	}d| }t d
|	| (d)||j }t d
|)||j }d }d }d }d|v rQt*|d trQ|d }n	t d
|	)|}t'|d D ]}|d ur|d ur|t |+ )| }|d|,|(d|  || }| j-|| | j!||}| j.|d d d |d f ||| j/\}} }!|!d
d}!|d
kr|!}"n	t j0|"|!gdd}"t 1t2j3 ||||k< t2j3 |d d | j	f< |d d | j4f  | j58  < ||krt2j3 |d d d | jf< t2j3 |d d | jd d f< |d ur/||dk r/||k r/| 6||||||\}}}n|| jk r@t2j3 |d d | jf< | d urk|d u r[t 7|	| | d|d |}|d d d d |d f 8|  |)|}t 7d
|}#t 7d
|}$| j9r| j:;| | j<d ur| <|||	||}| j:=|||	d| j>||	|dd d d d d |f |d d d |d f |\}%}&}'|'?|}(|&%| j|%t2j3 @ })t 1d
|)|)d d d |f |< t j@|(d d d |f |)d d d |f d}#g }*|#+ d
kr7t j@|%d d d |f |)d d d |f d}$| A||#|$|| ||||||"}*|tB|*8 }|d
ks>J |d
krF n| j:jCrS||krS n||k saJ | d| tB|*d
kr|	tB|* }+t jD|	t jE|&j d},d|,|*< t j|	|&j d@|,}| j:F| |)| })|'| }'|G|+d |'?|}(|%| }%|&| }&|d ur|| }|| }|| }||	d| |+| d}||	d| |+| d}|"H |	d| |+| |"dd}"|d ur ||	d| |+| |dd}|+}	nd }| |)d d d |f  @  |)d d d |f< t ?|))|| |d |)d }-t jI|-|ddd\}.}/|.J|d d d |f }| jKddL sRJ t jM|(d|/d}0t jM|%d|/d}1|0d}0|1d}1t jN|d d d |d f d
|0d|d d d |d f< t jM|&d|/d||	|dd d d d |d f< |d
krt jN|d d d |f d
|0d|d d d |f< t jM|%d|/d||	|dd d d d |f< | j:O|/ |d ur t jN|d d d d d |d f d
|0d|d d d d d |d f< |0}q`t'tB D ]It 1dd   D }t jP|dd\}2}3 fdd|3D  < t jt&tttf     < |   d
 d< |   d
 d< q
 S )NrZ   rd   r   r   z8expected src_tokens or source in net input. input keys:    r   z;min_len cannot be larger than max_len, please adjust these!r   r   r   c                 S   r   r(   r   r   r(   r(   r)   r     r   z/SequenceGenerator._generate.<locals>.<listcomp>c                 S   s   g | ]}d qS )Fr(   r   r(   r(   r)   r     s    rc   )maskz < )r   deviceF)r   )r]   r   largestr   c                 S   s   g | ]
}t |d   qS )score)floatitem)r\   elemr(   r(   r)   r     s    T)
descendingc                    s   g | ]}  | qS r(   r(   )r\   ssir   r   r(   r)   r     s    r   r   )Qr   r   r   r   r   r   r
   ner6   r4   longr   	Exceptionkeysr   r;   rE   r   r   r<   intr=   r>   r@   r?   r0   r   r   aranger   repeattor   reorder_encoder_outzerosr   r   r   r   r   r   type_as
isinstancer{   add_reorder_incremental_stater   rD   r   ry   mathinfr5   rC   _prefix_tokensemptyr|   rJ   r   set_src_lengthsrG   stepr:   addmasked_selectfinalize_hyposr9   stop_on_max_lenonesboolprune_sentencesresize_
contiguoustopkgeanyallr   index_selectupdate_constraintssort)4rN   rU   rV   r   rW   r   rZ   rd   r   bszsrc_lenr;   r@   r   r   r   	new_orderr   r`   attncands_to_ignorefinishednum_remaining_sent	cand_sizebbsz_offsetscand_offsetsreorder_state
batch_idxsoriginal_batch_idxsr   corrr   r   decoder_out_worddecoder_out_tensoreos_bbsz_idx
eos_scorescand_scorescand_indices
cand_beamscand_bbsz_idxeos_maskfinalized_sentsnew_bsz
batch_maskactive_masknew_cands_to_ignoreactive_hyposactive_bbsz_idxactive_scoresr   sorted_scores_indicesr(   r   r)   rX   K  s2   


 


	










 



"


$$









&
"
  

zSequenceGenerator._generater   r;   c                 C   s4  |dd|f  dd|d}|d| d}|| j}	ttj	 
|||	< ||	 d||	  d||	 ||	< || j}
|
 r||
 d||ddddd|d f }|
d|dddf }|| ddd|f }||k sJ | |||}| |||}| |||}|||fS )zHandle prefix tokensNr   r   r   )r   r   r   r   r   r4   r   ry   r   r   r   scatterr   r6   r   r   r   replicate_first_beam)rN   r   r   r   r`   rV   r;   prefix_toksprefix_lprobsprefix_maskr  
first_beameos_mask_batch_dimtarget_prefixr(   r(   r)   r     sD   

z SequenceGenerator._prefix_tokensc                 C   sH   | d||d}|| d d d dd d f ||< | d|dS )Nr   r   )r   r   )rN   ry   r   r;   r(   r(   r)   r    s   "z&SequenceGenerator.replicate_first_beamr   r   r   r@   c              
   C   s  |  |  ks
J |dur|d|}|d|ddd|d f }| j|dd|f< |	durD|	d|ddddd|d f nd}|d|ddd|d f }||dd|f< |ddddf |ddddf  |ddddf< | jr||d | j  }g }d}|D ]}|r|d7 }q|| qi }t| d D ]r}|| }|| }|| }|||  }t|	 d t|	  }||vrd||< | j
r||
| krttj |}t|| |k r|dur|| }ntd}|| || ||td|| |dur|| ng d qg }| D ]5}tt|dd }tt|dd }|| sR| |||t|| |rRd||< || q|S )	a  Finalize hypothesis, store finalized information in `finalized`, and change `finished` accordingly.
        A sentence is finalized when {beam_size} finished items have been collected for it.

        Returns number of sentences (not beam items) being finalized.
        These will be removed from the batch and not processed further.
        Args:
            bbsz_idx (Tensor):
        Nr   r   r   r   r   )r`   r   	attention	alignmentpositional_scoresrz   T)r{   r   r6   rA   rB   r   r   r   r   r   rE   r   ry   r   r   r   r9   r   r   r   r   splitis_finished)rN   r   bbsz_idxr   r`   r   r   r   r;   r   r   r@   rz   decoder_out_clonetokens_clone
attn_clone
pos_scores	cum_unfinprevf
sents_seenrt   idxr   	unfin_idxr   seen	hypo_attnnewly_finishedr(   r(   r)   r     sr    
 8



z SequenceGenerator.finalize_hyposr%  finalized_sent_lenc                 C   s$   ||ksJ ||ks||krdS dS )z
        Check whether decoding for a sentence is finished, which
        occurs when the list of finalized sentences has reached the
        beam size, or when we reach the maximum length.
        TFr(   )rN   r   r%  r@   r)  r;   r(   r(   r)   r  B  s   zSequenceGenerator.is_finished)r   r   r,   r,   r   Tr   r   r   Fr   NNNNr   TF)NN)NFN)NNNrS   )__name__
__module____qualname__r/   rT   r   rh   r   r   r
   r   r   rY   rw   r   ri   r   r   rX   r   r  r   r   r  __classcell__r(   r(   rQ   r)   r+   ,   s    b
#<
&
!
  Y
 	

{r+   )NT)r   systypingr   r   r   r   r   torch.nnnnfairseqr   r   fairseq.datar   fairseq.modelsr   fairseq.ngram_repeat_blockr	   r
   r*   Moduler+   r(   r(   r(   r)   <module>   s   
