o
    ߥi!                     @   s   d dl mZmZ d dlZd dl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mZmZ d dlmZ d	gZejeje	jd
G dd	 d	eeZdddZdd Zdd ZdS )    )AnyDictN)PreTrainedModel)
TaskModels)MODELS)SingleBackboneTaskModelBase)
OutputKeysTextGenerationModelOutputTokenGeneratorOutput)TasksModelForTextGeneration)module_namec                       sR   e Zd Zdef fddZdeeejf f fddZddd	Z	dddZ
  ZS )r   	model_dirc                    sv   t  j|g|R i | d|v r|d | _| | j | | j | jddr9| j	
 }| j }|j|_dS dS )zinitialize the text generation model from the `model_dir` path.

        Args:
            model_dir (str): the model path.
        base_model_prefixshared_embeddingFN)super__init___base_model_prefixbuild_backbonebackbone_cfg
build_headhead_cfgconfiggetbackboneget_input_embeddingsheadget_output_embeddingsweight)selfr   argskwargsinput_embeddingsoutput_embeddings	__class__ e/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/nlp/task_models/text_generation.pyr      s   


zModelForTextGeneration.__init__returnc                    s\   | tjd }t |}|d }| j|}d }|d ur(||tj< | ||}t||dS )Nr   )logitsloss)popr   LABELSr   forwardr   compute_lossr	   )r   inputslabelsbackbone_outputshidden_statesr)   r*   r$   r&   r'   r-   (   s   
zModelForTextGeneration.forwardNc                 K   s   |r|d d df  d}|dd }|dd }|d ur@|d u r@| dd }||dkd |r?|d d df  d}nd }|||d||dS )Nattention_maskposition_ids   r   	use_cache)	input_idspast_key_valuesr7   r5   r4   )	unsqueezer   longcumsummasked_fill_)r   r8   pastr!   r4   r5   r&   r&   r'   prepare_inputs_for_generation6   s"   z4ModelForTextGeneration.prepare_inputs_for_generation      ?c              	   K   s  t |tr	|d n|}|dd| jv r| jjnd}|dd| jv r&| jjnd}|d| jj}|d}|dtj	|dg|j
d	}	|	  }
|}|
|krVtd
||d }|dkrutj|||j
d	 }tj||fdd}| jj}tj|tj|j
d}t Y t|
|D ]K}|d d d |f }| |dj}|d d dd d f }t||||| jjd}|	|k}|| |||f< ||k | @ }||B }t|}|r nqW d    n1 sw   Y  |d d d |d f }t|dS )Nr8   top_kr6   top_p        
max_lengthr   prompt_length)devicezcontext length too larger3   dim)dtyperF   )r8   )rA   rB   temperature
vocab_size)	sequences)
isinstancer   r+   r   rA   rB   rD   sizetorchtensorrF   minitem
ValueErrorzerosr;   cateos_token_iduint8no_gradranger)   sampler   rK   byteallr
   )r   r/   rJ   r!   tokensrA   rB   rD   
batch_sizelengthsmin_prompt_lengthmax_sequence_length
pad_lengthpadstermination_idis_generation_donecontext_length
tokens2user)   last_token_logits
new_samplestarted
done_tokendoner&   r&   r'   generateN   sr   


	

"
zModelForTextGeneration.generate)N)r@   )__name__
__module____qualname__strr   r   npndarrayr-   r?   rm   __classcell__r&   r&   r$   r'   r      s
    
rC   r@   c                 C   s   | j dks	J d|dkr|dksJ dtj| dd}nQ|  } |dkr*| | |dkrM|dk || dks=J d	|rG||k sGJ d
t| | n|dkr^|dksYJ dt| | | jdd}tj	|dd
d}|rztj|d|d d}|S )a9   Sample and generate a token.
    Note: logits has the dimension [b, v] where b is the batch size
          and v is the vocabulary size.
    If vocab_size is provided, we will make sure the sample that is
    generated is in [0, vocab-size). This will avoid out of vocabulary
    generations due to padding.
       z*expected the logits to be of [b, v] shape.r6   rC   z+cannot set both greedy and top-p samplings.r3   rG   r@   z top-k is larger than logit size.z top-k is larger than vocab size.ztop-p should be in (0, 1].)num_samplesr   )rQ   max)ndimrO   argmaxclonediv_rN   !modify_logits_for_top_k_filtering!modify_logits_for_top_p_filteringsoftmaxmultinomialviewclamp)r)   rA   rB   rJ   rK   samplesprobsr&   r&   r'   rZ      s*   


rZ   c                 C   s,   | t | |d d k }| |td dS )z-Set the logits for none top-k values to -inf.r   ).r3   N-InfN)rO   topkr=   float)r)   rA   filter_r&   r&   r'   r|      s   r|   c                 C   s   t j| dd\}}|jddjdd}||k}|ddddf  |ddddf< d|d< |d||}| |td	 dS )
z-Set the logits for none top-p values to -inf.T)
descendingr3   rG   Nr6   r   ).r   r   )rO   sortr~   r<   rz   scatterr=   r   )r)   rB   sorted_logitssorted_indicescumulative_probsr   r&   r&   r'   r}      s   (r}   )r   rC   r@   N)typingr   r   numpyrr   rO   transformers.modeling_utilsr   modelscope.metainfor   modelscope.models.builderr   ,modelscope.models.nlp.task_models.task_modelr   modelscope.outputsr   r	   r
   modelscope.utils.constantr   __all__register_moduletext_generationr   rZ   r|   r}   r&   r&   r&   r'   <module>   s$    
0