o
    iS                     @   s   d dl Z d dlZd dlZd dlmZ d dlmZ d dlZd dl	Z	d dl
Z
d dlm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mZmZmZ d dlmZ e eZ G dd de
j!j"Z#dS )    N)chain)Path)convert_float_to_float16)RepeatedCompositeFieldContainer)
ModelProtoValueInfoProto)	OnnxModel)PastKeyValuesHelper)WhisperConfig)convert_inputs_for_ortget_model_dynamic_axesget_sample_decoder_inputsgroup_past_key_values)InferenceSessionc                       s  e Zd ZdZd5dedejjdede	f fddZ
				d6d
ejdejd	B deeej  d	B fddZ				d6d
ejdejd	B deeej  d	B fddZ				d6d
ejdejd	B deeej  d	B fddZdd Zdd Zdd Zd5de	de	de	fddZd7dede	d e	fd!d"Zd5d#ed e	fd$d%Zdefd&d'Zdede	fd(d)Z	*			*		*d8d+ed,ed-e	d.e	de	de	d/e	d0e	fd1d2Zd+ed,ede	de	fd3d4Z  ZS )9WhisperDecoderz/A Whisper decoder with optional past key valuesFconfigmodel
model_implno_beam_search_opc                    s   t    || _|j| _|| _|| _|dkrd n|jj| _|dkr#d n|j| _|dkr-|nd | _| jj	| _	| jj
| _| jj| j | _d S NZopenai)super__init__r   devicer   r   r   decoderproj_outmax_source_positionsZdecoder_attention_heads	num_headsZd_model	head_size)selfr   r   r   r   	__class__ q/home/kim/smarthome/.venv/lib/python3.10/site-packages/onnxruntime/transformers/models/whisper/whisper_decoder.pyr   %   s   


zWhisperDecoder.__init__Ndecoder_input_idsencoder_hidden_statespast_key_valuesc           	      C   sJ   | j |||dd}| |j}|j}|d u r||fS t|\}}||fS )NT)r$   	input_idsr%   Z	use_cache)r   r   Zlast_hidden_stater%   r	   Zgroup_by_self_and_cross)	r   r#   r$   r%   Zoutputslogitspresent_key_valuespresent_selfpresent_crossr!   r!   r"   
hf_forward4   s   zWhisperDecoder.hf_forwardc                    s&  i }|d ur`t |\}}dd |D }dd |D }dd |D }dd |D }t jjjD ]0\}}|d|  ||jj< |d| d  ||jj< |d|  ||jj< |d| d  ||jj< q/ j	 \}	}
 jj|||d}|d ur jjjD ]0}t
j||jj |	|jj gdd	 |	|jj< t
j||jj |	|jj gdd	 |	|jj< qyg g }} jjjD ]*}||	|jj  ||	|jj  |d u r||	|jj  ||	|jj  q fd
d|D } fdd|D }|
D ]}|  q|d u rt|| t|d }||fS ||fS )Nc                 S      g | ]}| d dqS       	transpose.0Zpast_kvr!   r!   r"   
<listcomp>Z       z.WhisperDecoder.oai_forward.<locals>.<listcomp>c                 S   *   g | ]}| g |jd d dR qS Nr/   reshapeshaper2   r!   r!   r"   r4   [      * c                 S   r,   r-   r0   r2   r!   r!   r"   r4   \   r5   c                 S   r6   r7   r9   r2   r!   r!   r"   r4   ]   r<   r/   r.   )xZxakv_cache)dimc                    8   g | ]}| g |jd d d jR ddqS Nr/   r8   r.   r:   r;   r   r1   r3   Z
present_kvr   r!   r"   r4          *c                    r@   rA   rB   rC   rD   r!   r"   r4      rE   )r   	enumerater   r   blocksZattnkeyvalueZ
cross_attnZinstall_kv_cache_hookstorchcatdetachappendremover	   Zgroup_by_layerlen)r   r#   r$   r%   Zpast_kv_cacheself_attn_kv_cachescross_attn_kv_cachesidxblockr>   hooksr'   r)   r*   hookr(   r!   rD   r"   oai_forwardP   s`   






zWhisperDecoder.oai_forwardc                 C   s&   | j dkr| |||S | |||S r   )r   rV   r+   )r   r#   r$   r%   r!   r!   r"   forward   s   
zWhisperDecoder.forwardc                 C   s>   | j r	ddg}|S ddgttdd t| jjD }|S )Nr&   r$   c                 s   4    | ]}d | d| d| d| fV  qdS )Zpast_key_self_Zpast_value_self_Zpast_key_cross_Zpast_value_cross_Nr!   r3   ir!   r!   r"   	<genexpr>   s
    "
z-WhisperDecoder.input_names.<locals>.<genexpr>
first_passlistr   from_iterableranger   Zdecoder_layers)r   input_namesr!   r!   r"   ra      s   


zWhisperDecoder.input_namesc                 C   sZ   | j rdgttdd t| jjD }|S dgttdd t| jjD }|S )Nr'   c                 s   rX   )present_key_self_present_value_self_Zpresent_key_cross_Zpresent_value_cross_Nr!   rY   r!   r!   r"   r[      s    
z.WhisperDecoder.output_names.<locals>.<genexpr>c                 s   s$    | ]}d | d| fV  qdS )rb   rc   Nr!   rY   r!   r!   r"   r[      s    
r\   )r   output_namesr!   r!   r"   rd      s&   



zWhisperDecoder.output_namesc                 C   s*   t | j||}d|v r| js|d d= |S )Nr&   r.   )r   r   r   )r   ra   rd   dynamic_axesr!   r!   r"   re      s   
zWhisperDecoder.dynamic_axesuse_fp16_inputsuse_int32_inputsreturn_dictc              	   C   sn   t | j| jd| jrdnd| jrdnd||d}|r!| jr|d= |S | jr,|d |d fS |d |d |d fS )	Nr/   r      r.   )Z
batch_sizepast_sequence_lengthsequence_lengthZuse_fp16Z	use_int32r%   r#   r$   )r   r   r   r]   )r   rf   rg   rh   inputsr!   r!   r"   rl      s*   	zWhisperDecoder.inputsiois_cross	is_outputc                 C   s   |j jjjd }d|jv r|  | j|_|j jjjd }d|jv r4|  |r-| j|_n|r1dnd|_|j jjjd }d|jv rI|  | j	|_|S )Nr.   Z_dim_r/   Ztotal_sequence_lengthrj      )
typeZtensor_typer;   r?   Z	dim_paramZClearr   Z	dim_valuer   r   )r   rm   rn   ro   r   rk   r   r!   r!   r"   fix_key_value_cache_dims   s   



z'WhisperDecoder.fix_key_value_cache_dimsio_listc                 C   s   g }g }g }|D ]D}d|j vrd|j vr|| qd|j v r6| j|d|d}| jr0|| q|| q| j|d|d}| jrG|| q|| q| jsV||| 7 }|S )NZpastZpresentr   F)rn   ro   T)namerM   rr   r   )r   rs   ro   Zreordered_iorP   rQ   rm   Znew_ior!   r!   r"   fix_io  s$   
zWhisperDecoder.fix_ioc                 C   s   | j |jjdd}t|jjdkr|jj  t|jjdks|jj| | j |jjdd}t|jjdkrE|jj  t|jjdks7|jj| |S )NF)ro   r   T)ru   graphinputrO   popextendoutput)r   r   Zreordered_inputsZreordered_outputsr!   r!   r"   fix_inputs_and_outputs0  s   z%WhisperDecoder.fix_inputs_and_outputsc                 C   s   | j dkr|rt|}|S r   )r   r   )r   r   rf   r!   r!   r"   fix_layernorm_weights>  s   z$WhisperDecoder.fix_layernorm_weightsTonnx_model_pathproviderverboseuse_external_data_formatuse_encoder_hidden_statesuse_kv_cache_inputsc	                 C   s*  |o| | _ | o
|| _| j s| jsJ d| j||d}	|  }
|  }| |
|}t|jjddd t	
 J}tj|d}t|jjddd |rO|n|}tjj| |	|d|
||dd|d
 tj||d}| |}| ||}tj|||dd	 W d
   n1 sw   Y  | |||| d
S )al  Export decoder to ONNX

        Args:
            onnx_model_path (str): path to save ONNX model
            provider (str): provider to use for verifying parity on ONNX model
            verbose (bool, optional): print verbose information. Defaults to True.
            use_external_data_format (bool, optional): use external data format or not. Defaults to False.
            use_fp16_inputs (bool, optional): use float16 inputs for the KV caches. Defaults to False.
            use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids. Defaults to True.
            use_encoder_hidden_states (bool, optional): use encoder_hidden_states as model input for decoder-init/decoder-without-past models. Defaults to False.
            use_kv_cache_inputs (bool, optional): use KV caches as model inputs for decoder-with-past models. Defaults to True.
        zVOnly one of `use_encoder_hidden_states` and `use_kv_cache_inputs` can be true at once.)rf   rg   T)parentsexist_okzdecoder.onnx   )	argsfZexport_paramsra   rd   re   Zopset_versionZdo_constant_foldingr   )Zload_external_data)Zsave_as_external_dataZall_tensors_to_one_fileN)r]   Z
later_passrl   ra   rd   re   r   parentmkdirtempfileTemporaryDirectoryospathjoinrJ   onnxZexportZ
load_modelr{   r|   r   saveverify_onnx)r   r}   r~   r   r   rf   rg   r   r   rl   ra   rd   re   Ztmp_dir_nameZtemp_onnx_model_pathZout_pathr   r!   r!   r"   export_onnxJ  sJ   $

zWhisperDecoder.export_onnxc                 C   sJ  | j ||dd}g }| jr:| jd
i |}||d     |d D ]}|D ]}	||	    q*q&n'| jd
i |}||d     |d D ]}
||
    qSt||gd}|dt	||}z-t
|  D ]#\}}t|| ||  }td| d td	t|  qxW dS    Y dS )aw  Verify ONNX model outputs and PyTorch model outputs match

        Args:
            onnx_model_path (str): path to save ONNX model
            provider (str): execution provider for ONNX model
            use_fp16_inputs (bool, optional): use float16 inputs for the KV caches
            use_int32_inputs (bool, optional): use int32 inputs for the decoder_input_ids
        T)rf   rg   rh   r   r.   )	providersNz
Comparing z...z
Max diff: r!   )rl   r]   rW   rM   rL   cpunumpyr   runr   rF   rd   npabsloggerwarningmax)r   r}   r~   rf   rg   rl   Z
pt_outputsoutZpresent_key_value_layerZpresent_key_valueZpresent_self_key_valuesessZort_outputsrZ   Zoutput_namediffr!   r!   r"   r     s0   zWhisperDecoder.verify_onnx)F)NN)FF)TFFTFT)__name__
__module____qualname____doc__r
   rJ   nnModulestrboolr   ZTensorr^   tupler+   rV   rW   ra   rd   re   rl   r   rr   r   ru   r   r{   r|   r   r   __classcell__r!   r!   r   r"   r   "   s    $

]

	
Qr   )$loggingr   r   	itertoolsr   pathlibr   r   r   r   rJ   Zfloat16r   Z#google.protobuf.internal.containersr   r   r   Z
onnx_modelr   Zpast_helperr	   Ztransformersr
   Zwhisper_inputsr   r   r   r   Zonnxruntimer   	getLoggerr   r   r   r   r   r!   r!   r!   r"   <module>   s$   
