o
    ;ήc!                     @   sh   d dl mZ d dl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 eeZG dd deZdS )	    )	getLoggerN)Fusion)FusionUtils)TensorProtohelpernumpy_helper)	OnnxModelc                       s:   e Zd ZdZdedef fddZdd Zdd	 Z  Z	S )
FusionGptAttentionNoPastz
    Fuse GPT-2 Attention without past state into one Attention node.
    This does not support attention_mask graph input right now.
    model	num_headsc                    s   t  |ddd || _d S )N	AttentionLayerNormalizationzwithout past)super__init__r   )selfr
   r   	__class__ \/tmp/pip-target-vg8gfxp4/lib/python/onnxruntime/transformers/fusion_gpt_attention_no_past.pyr      s   
z!FusionGptAttentionNoPast.__init__c           	      C   s   | j d}tjd||jd |jd g|d g|d}d|_|jtd| j	tddg tjd	|d |jd g|d
 g|d d}tjd|d
 |jd g|g|d d}| j
|||g | j| j|j< | j| j|j< | j| j|j< d S )Nr         _output)inputsoutputsnamezcom.microsoftr   unidirectionalMatMul_matmul_output_matmulAdd_add)r
   create_node_namer   	make_nodeinputdomain	attributeextendmake_attributer   nodes_to_addthis_graph_namenode_name_to_graph_namer   )	r   gemmgemm_qkvr#   outputattention_node_nameattention_nodematmul_nodeadd_noder   r   r   create_attention_node   s:   
z.FusionGptAttentionNoPast.create_attention_nodec           (      C   sB  g }| j j|g dg d||d}|d u rd S |\}}}}	}
}}|jd|d   }| j |g dg d}|d u r@td d S |\}}}}}}| j |d|}|d u sY|jd	kri|jd
kritd|j  d S ||jvrz||jvrztd d S | j |g dg d}|d ur|\}}}}}| j |g dg d}|d u rtd d S |d }||krtd d S n| j |g dg d}|d ur|\}}}}| j |g dg d}|d u rtd d S |d }||krtd d S nG| j |g dg d}|d u rtd d S |\}}}}}| j |g dg d}|d u r,td d S |d }||kr<td d S | j |g dg d} | d u rTtd d S | \}!}"}#||#kretd d S | j |g dg d }$|$d u r}td! d S |$\}%}&}'||'krtd" d S | |||jd |jd  d#| _	d S )$N)r   ReshapeGemmr3   r3   	Transposer   )r   Nr   r   r   r   r   )output_name_to_nodereturn_indicer   r   )r5   r3   Splitr3   r4   r3   )r   r   r   r   r   r   z&fuse_attention: failed to match v pathr   r   z)failed to get layernorm before gemm. Got z4Add and LayerNormalization shall have one same input)SoftmaxSubMulDivr   )r   r   r   r   r   )
r;   r:   Slicer=   	Unsqueezer:   Squeezer=   Shaper<   )
r   r   r   r   r   r   r   r   r   r   z)fuse_attention: failed to match mask pathz-fuse_attention: skip since div_qk != div_mask)r9   Wherer<   r   )r   r   r   r   )	Castr=   r=   r>   r:   r?   r=   r@   r<   )	r   r   r   r   r   r   r   r   r   )r9   r   r;   r<   r   z'fuse_attention: failed to match qk path)r=   r=   r>   r?   r=   r@   r<   )r   r   r   r   r   r   r   )r5   r3   r8   )r   r   r   z&fuse_attention: failed to match q pathz-fuse_attention: skip since split_v != split_q)r   r   r   z&fuse_attention: failed to match k pathz-fuse_attention: skip since split_v != split_kT)
r
   match_parent_pathr#   loggerdebug
get_parentop_typer-   r2   prune_graph)(r   normalize_nodeinput_name_to_nodesr6   r7   	qkv_nodesadd_qkvreshape_qkvr,   	reshape_1	reshape_2transpose_qkv
matmul_qkvanother_inputv_nodestranspose_v	reshape_vsplit_vreshape_after_gemmr+   reshape_before_gemmlayernorm_before_attentionqk_nodes
softmax_qksub_qkmul_qkdiv_qk	matmul_qk
mask_nodesdiv_maskwhere_qkadd_qkq_nodestranspose_q	reshape_qsplit_qk_nodestranspose_k	reshape_ksplit_kr   r   r   fuse>   s   	

























zFusionGptAttentionNoPast.fuse)
__name__
__module____qualname____doc__r   intr   r2   rm   __classcell__r   r   r   r   r	      s
    #r	   )loggingr   numpynpfusion_baser   fusion_utilsr   onnxr   r   r   
onnx_modelr   rn   rE   r	   r   r   r   r   <module>   s   