o
    ߥiT                     @   s   d dl mZmZ d dlmZ d dlmZmZmZm	Z	 d dl
Z
dZdZG dd deZG d	d
 d
eZG dd dZG dd deZG dd deZG dd deZG dd deZdS )    )ABCabstractmethod)UserDict)IterableListOptionalTupleNag  
    Args:
        input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size * num_beams, sequence_length)`):
            Indices of input sequence tokens in the vocabulary.

            Indices can be obtained using any class inheriting from :class:`~transformers.PretrainedTokenizer`. See
            :meth:`transformers.PreTrainedTokenizer.encode` and :meth:`transformers.PreTrainedTokenizer.__call__` for
            details.

            `What are input IDs? <../glossary.html#input-ids>`__
        next_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, 2 * num_beams)`):
            Current scores of the top :obj:`2 * num_beams` non-finished beam hypotheses.
        next_tokens (:obj:`torch.LongTensor` of shape :obj:`(batch_size, 2 * num_beams)`):
            :obj:`input_ids` of the tokens corresponding to the top :obj:`2 * num_beams` non-finished beam hypotheses.
        next_indices (:obj:`torch.LongTensor` of shape :obj:`(batch_size, 2 * num_beams)`):
            Beam indices indicating to which beam hypothesis the :obj:`next_tokens` correspond.
        pad_token_id (:obj:`int`, `optional`):
            The id of the `padding` token.
        eos_token_id (:obj:`int`, `optional`):
            The id of the `end-of-sequence` token.

    Return:
        :obj:`UserDict`: A dictionary composed of the fields as defined above:

            - **next_beam_scores** (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`) -- Updated
              scores of all non-finished beams.
            - **next_beam_tokens** (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`) -- Next tokens
              to be added to the non-finished beam_hypotheses.
            - **next_beam_indices** (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`) -- Beam indices
              indicating to which beam the next tokens shall be added.

a  
    Args:
        input_ids (:obj:`torch.LongTensor` of shape :obj:`(batch_size * num_beams, sequence_length)`):
            Indices of input sequence tokens in the vocabulary.

            Indices can be obtained using any class inheriting from :class:`~transformers.PretrainedTokenizer`. See
            :meth:`transformers.PreTrainedTokenizer.encode` and :meth:`transformers.PreTrainedTokenizer.__call__` for
            details.

            `What are input IDs? <../glossary.html#input-ids>`__
        final_beam_scores (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`):
            The final scores of all non-finished beams.
        final_beam_tokens (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`):
            The last tokens to be added to the non-finished beam_hypotheses.
        final_beam_indices (:obj:`torch.FloatTensor` of shape :obj:`(batch_size * num_beams)`):
            The beam indices indicating to which beam the :obj:`final_beam_tokens` shall be added.
        pad_token_id (:obj:`int`, `optional`):
            The id of the `padding` token.
        eos_token_id (:obj:`int`, `optional`):
            The id of the `end-of-sequence` token.

    Return:
        :obj:`torch.LongTensor` of shape :obj:`(batch_size * num_return_sequences, sequence_length)`: The generated
        sequences. The second dimension (sequence_length) is either equal to :obj:`max_length` or shorter if all
        batches finished early due to the :obj:`eos_token_id`.

c                   @   sl   e Zd ZdZedejdejdejdejdeej	 f
ddZ
edejdejdejdejdejf
d	d
ZdS )
BeamScorerz
    Abstract base class for all beam scorers that are used for :meth:`~transformers.PretrainedModel.beam_search` and
    :meth:`~transformers.PretrainedModel.beam_sample`.
    	input_idsnext_scoresnext_tokensnext_indicesreturnc                 K      t dNzThis is an abstract method.NotImplementedErrorselfr
   r   r   r   kwargs r   _/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/nlp/mglm/generation_utils.pyprocessY   s   zBeamScorer.processc                 K   r   r   r   r   r   r   r   finalize`   s   zBeamScorer.finalizeN)__name__
__module____qualname____doc__r   torch
LongTensorFloatTensorr   Tensorr   r   r   r   r   r   r	   S   s,    r	   c                   @   s   e Zd ZdZ			ddedededejd	ee d
ee	 dee fddZ
ede	fddZ			d dejdejdejdejdee dee deej fddZ			d dejdejdejdejdee dee deejeej f fddZdS )!BeamSearchScorera  
    :class:`transformers.BeamScorer` implementing standard beam search decoding.

    Adapted in part from `Facebook's XLM beam search code
    <https://github.com/facebookresearch/XLM/blob/9e6f6814d17be4fe5b15f2e6c43eb2b2d76daeb4/src/model/transformer.py#L529>`__.

    Args:
        batch_size (:obj:`int`):
            Batch Size of :obj:`input_ids` for which beam search decoding is run in parallel.
        max_length (:obj:`int`):
            The maximum length of the sequence to be generated.
        num_beams (:obj:`int`):
            Number of beams for beam search.
        device (:obj:`torch.device`):
            Defines the device type (*e.g.*, :obj:`"cpu"` or :obj:`"cuda"`) on which this instance of
            :obj:`BeamSearchScorer` will be allocated.
        length_penalty (:obj:`float`, `optional`, defaults to 1.0):
            Exponential penalty to the length. 1.0 means no penalty. Set to values < 1.0 in order to encourage the
            model to generate shorter sequences, to a value > 1.0 in order to encourage the model to produce longer
            sequences.
        do_early_stopping (:obj:`bool`, `optional`, defaults to :obj:`False`):
            Whether to stop the beam search when at least ``num_beams`` sentences are finished per batch or not.
        num_beam_hyps_to_keep (:obj:`int`, `optional`, defaults to 1):
            The number of beam hypotheses that shall be returned upon calling
            :meth:`~transformer.BeamSearchScorer.finalize`.
          ?F   
batch_size
max_length	num_beamsdevicelength_penaltydo_early_stoppingnum_beam_hyps_to_keepc                    sj   | _ | _| _| _| _| _d _ fddt|D  _t	j
dd t|D t	j jd _d S )NFc                    s$   g | ]}t  j j j jd qS ))r'   r&   r)   early_stopping)BeamHypothesesr'   r&   r)   r*   .0_r   r   r   
<listcomp>   s    z-BeamSearchScorer.__init__.<locals>.<listcomp>c                 S   s   g | ]}d qS )Fr   r.   r   r   r   r2          dtyper(   )r&   r'   r(   r)   r*   r+   _is_initrange
_beam_hypsr   tensorbool_done)r   r%   r&   r'   r(   r)   r*   r+   r   r1   r   __init__   s   

zBeamSearchScorer.__init__r   c                 C   s
   | j  S N)r;   allr1   r   r   r   is_done   s   
zBeamSearchScorer.is_doneNr
   r   r   r   pad_token_ideos_token_idc                    sd  |j d }t| j}	|	|j d | j ksJ t|tr|g}|j}
tj|	| jf|j	|
d}tj|	| jf|j	|
d}tj|	| jf|j	|
d}t
| jD ]\}}| j| rt|| jksbJ d| j|d urj|d usnJ dd||d d f< |||d d f< d||d d f< qJd}t
t|| || || D ]W\}\}} || j   }|d ur| |v r|| jk}|rq|j||  | |ṙ fdd|D nd d n||||f< ||||f< ||||f< |d	7 }|| jkr nq|| jk rtd
| j d||  d| d||  d	| j| p|||   || j|< qJt|d|d|ddS )Nr   r4   z?Batch can only be done if at least {} beams have been generatedzMgenerated beams >= num_beams -> eos_token_id and pad_token have to be definedc                    s   g | ]	}|   g qS r   )itemr/   mem
next_indexr   r   r2      s    z,BeamSearchScorer.process.<locals>.<listcomp>memsr$   zAt most z tokens in z  can be equal to `eos_token_id: z`. Make sure z are corrected.)next_beam_scoresnext_beam_tokensnext_beam_indices)shapelenr8   r'   
isinstanceintr(   r   zerosr5   	enumerater;   formatziprC   addclone
ValueErrorr?   maxr   view)r   r
   r   r   r   r@   rA   rI   cur_lenr%   r(   rJ   rK   rL   	batch_idxbeam_hypbeam_idxbeam_token_rank
next_token
next_scorebatch_beam_idx&is_beam_token_worse_than_top_num_beamsr   rF   r   r      s   






&zBeamSearchScorer.processfinal_beam_scoresfinal_beam_tokensfinal_beam_indicesc                    s  t | j}t| jD ]6\}	}
| j|	 rq
t| jD ]&}|	| j |  |   }|  }|
j||r; fddD nd d qq
||| j	 }g }t| jD ]1\}}
t
|
jdd d}t| j	D ]}| dd  \}t ||| j	| | < ||f qbqPt|  | j}||| j	 |}|  |  kr|d usJ d|| g t|D ]#\}\}}|||d || f< || |k r||||| f< | qrd	 rfd
dtt d	 D nd |fS )Nc                    s   g | ]}| g qS r   r   rD   )ra   r   r   r2     s    z-BeamSearchScorer.finalize.<locals>.<listcomp>rH   c                 S   s   | d S )Nr   r   )xr   r   r   <lambda>  s    z+BeamSearchScorer.finalize.<locals>.<lambda>)keyr$   z `pad_token_id` has to be definedr   c                    s(   g | ] t j fd dD ddqS )c                    s   g | ]}|  qS r   r   rD   ir   r   r2   6  s    z8BeamSearchScorer.finalize.<locals>.<listcomp>.<listcomp>r   )dim)r   cat)r/   rH   ri   r   r2   5  s    )rN   r8   rR   r;   r7   r'   rC   rU   newr+   sortedbeamspopappendminrX   r&   fill_)r   r
   rc   rd   re   r@   rA   rI   r%   r[   r\   beam_idfinal_scorefinal_tokenssent_lengthsbestrj   sorted_hypsjbest_hypsent_max_lendecodedhyporE   r   )ra   rI   r   r      sh   




zBeamSearchScorer.finalize)r#   Fr$   )NNN)r   r   r   r   rP   r   r(   r   floatr:   r<   propertyr?   r   r    r   r!   r   r   r   r   r   r   r   r"   g   st    !
"
Zr"   c                   @   sZ   e Zd ZdedededefddZdd Zdd
ej	defddZ
dededefddZd	S )r-   r'   r&   r)   r,   c                 C   s,   |d | _ || _|| _|| _g | _d| _dS )z7
        Initialize n-best list of hypotheses.
        r$   g    eAN)r&   r)   r,   r'   ro   worst_score)r   r'   r&   r)   r,   r   r   r   r<   >  s   

zBeamHypotheses.__init__c                 C   s
   t | jS )z3
        Number of hypotheses in the list.
        )rN   ro   r1   r   r   r   __len__J  s   
zBeamHypotheses.__len__Nhypsum_logprobsc                 C   s   |t |jd d| j  }t| | jk s|| jkrO| j|||f t| | jkrFtdd t	| jD }| j|d d = |d d | _dS t
|| j| _dS dS )z3
        Add a new hypothesis to the list.
        rB   r$   c                 S   s   g | ]\}\}}}||fqS r   r   )r/   idxsr0   r   r   r   r2   X  s    z&BeamHypotheses.add.<locals>.<listcomp>r   N)rX   rM   r)   rN   r'   r   ro   rq   rn   rR   rr   )r   r   r   rI   scoresorted_next_scoresr   r   r   rU   P  s   zBeamHypotheses.addbest_sum_logprobsrZ   r   c                 C   s8   t | | jk r	dS | jrdS ||| j  }| j|k}|S )z
        If there are enough hypotheses and that none of the hypotheses being generated can become better than the worst
        one in the heap, then we are done with this sentence.
        FT)rN   r'   r,   r)   r   )r   r   rZ   	cur_scoreretr   r   r   r?   `  s   
zBeamHypotheses.is_doner=   )r   r   r   rP   r   r:   r<   r   r   r   rU   r?   r   r   r   r   r-   <  s    
r-   c                   @   ,   e Zd ZdZdejdejdejfddZdS )LogitsProcessorzSAbstract base class for all logit processors that can be applied during generation.r
   scoresr   c                 C   s   t | j d)z#Torch method for processing logits.zH is an abstract class. Only classes inheriting this class can be called.)r   	__class__)r   r
   r   r   r   r   __call__s  s   
zLogitsProcessor.__call__Nr   r   r   r   r   r   r    r   r   r   r   r   r   p  s    r   c                   @   r   )LogitsProcessorListav  
    This class can be used to create a list of :class:`~transformers.LogitsProcessor` or
    :class:`~transformers.LogitsWarper` to subsequently process a :obj:`scores` input tensor. This class inherits from
    list and adds a specific `__call__` method to apply each :class:`~transformers.LogitsProcessor` or
    :class:`~transformers.LogitsProcessor` to the inputs.
    r
   r   r   c                 C   s   | D ]}|||}q|S r=   r   )r   r
   r   	processorr   r   r   r     s   zLogitsProcessorList.__call__Nr   r   r   r   r   r   {  s    r   c                   @   s>   e Zd ZdZdedefddZdejdejdejfd	d
Z	dS )MinLengthLogitsProcessoraU  
    :class:`transformers.LogitsProcessor` enforcing a min-length by setting EOS probability to 0.

    Args:
        min_length (:obj:`int`):
            The minimum length below which the score of :obj:`eos_token_id` is set to :obj:`-float("Inf")`.
        eos_token_id (:obj:`int`):
            The id of the `end-of-sequence` token.
    
min_lengthrA   c                 C   sP   t |tr	|dk rtd| t |tr|dk r td| || _|| _d S )Nr   z2`min_length` has to be a positive integer, but is z4`eos_token_id` has to be a positive integer, but is )rO   rP   rW   r   rA   )r   r   rA   r   r   r   r<     s   
z!MinLengthLogitsProcessor.__init__r
   r   r   c                 C   s0   |j d }|| jk rtd |d d | jf< |S )NrB   inf)rM   r   r   rA   )r   r
   r   rZ   r   r   r   r     s   

z!MinLengthLogitsProcessor.__call__N)
r   r   r   r   rP   r<   r   r   r    r   r   r   r   r   r     s    
r   c                
   @   s^   e Zd ZdZdefddZdejdejdejfdd	Z	d
ej
dededeee  fddZdS )NoRepeatNGramLogitsProcessoraT  
    :class:`transformers.LogitsProcessor` that enforces no repetition of n-grams. See `Fairseq
    <https://github.com/pytorch/fairseq/blob/a07cb6f40480928c9e0548b737aadd36ee66ac76/fairseq/sequence_generator.py#L345>`__.

    Args:
        ngram_size (:obj:`int`):
            All ngrams of size :obj:`ngram_size` can only occur once.
    
ngram_sizec                 C   s*   t |tr	|dkrtd| || _d S )Nr   z;`ngram_size` has to be a strictly positive integer, but is )rO   rP   rW   r   )r   r   r   r   r   r<     s
   
z%NoRepeatNGramLogitsProcessor.__init__r
   r   r   c                 C   sJ   |j d }|j d }| |||}t|D ]\}}td |||f< q|S )Nr   rB   r   )rM   _calc_banned_ngram_tokensrR   r   )r   r
   r   num_batch_hypothesesrZ   banned_batch_tokensrj   banned_tokensr   r   r   r     s   

z%NoRepeatNGramLogitsProcessor.__call__prev_input_ids	num_hyposrZ   c           	         s   d j k rdd t|D S dd t|D t|D ]2}|  | }tfddtj D  D ]}t|dd }||g |d g ||< q7qfdd	  fd
dt|D }|S )z6Copied from fairseq for no_repeat_ngram in beam_searchr$   c                 S   s   g | ]}g qS r   r   r.   r   r   r   r2     r3   zJNoRepeatNGramLogitsProcessor._calc_banned_ngram_tokens.<locals>.<listcomp>c                 S   s   g | ]}i qS r   r   r.   r   r   r   r2     r3   c                    s   g | ]} |d  qS r=   r   )r/   rj   )
gen_tokensr   r   r2     s    NrB   c                    s6    d j  }t| | f  }|  |g S )Nr$   )r   tupletolistget)hypo_idx	start_idx	ngram_idx)rZ   generated_ngramsr   r   r   r   _get_generated_ngrams  s   zUNoRepeatNGramLogitsProcessor._calc_banned_ngram_tokens.<locals>._get_generated_ngramsc                    s   g | ]} |qS r   r   )r/   r   )r   r   r   r2     s    )r   r7   r   rT   r   r   )	r   r   r   rZ   r   generated_ngramngramprev_ngram_tupler   r   )r   rZ   r   r   r   r   r   r     s*   

z6NoRepeatNGramLogitsProcessor._calc_banned_ngram_tokensN)r   r   r   r   rP   r<   r   r   r    r   r!   r   r   r   r   r   r   r   r     s    	

r   )abcr   r   collectionsr   typingr   r   r   r   r   PROCESS_INPUTS_DOCSTRINGFINALIZE_INPUTS_DOCSTRINGr	   r"   r-   r   listr   r   r   r   r   r   r   <module>   s   ! V4!