+
    9i&Q                     x    ^ RI Ht ^ RIt^ RIHt ^ RIHt ^ RIH	t	H
t
Ht ^ RIHt ]! ]4      t ! R R]4      tR# )	    )	getLoggerN)Fusion)NumpyHelper)	NodeProtohelpernumpy_helper)	OnnxModelc                      a a ] tR t^t oRtV3R lV 3R lltV3R lR ltV3R lR ltR tRV3R	 lR
 llt	V3R lR lt
R tR tV3R lR ltRR ltV3R lR ltRtVtV ;t# )FusionMultiHeadAttentionSam2zA
Fuse MultiHeadAttention subgraph of Segment Anything v2 (SAM2).
c                ,   < V ^8  d   QhRS[ RS[RS[/# )   modelhidden_size	num_heads)r	   int)format__classdict__s   "l/var/www/html/photoedit/myenv/lib/python3.14/site-packages/onnxruntime/transformers/fusion_attention_sam2.py__annotate__)FusionMultiHeadAttentionSam2.__annotate__   s)     ( (( ( 	(    c                `   < \         SV `  VR R.4       W n        W0n        RV n        RV n        R# )MultiHeadAttentionLayerNormalizationTN)super__init__r   r   num_heads_warninghidden_size_warning)selfr   r   r   	__class__s   &&&&r   r   %FusionMultiHeadAttentionSam2.__init__   s8     	 47K6LM&" "&#' r   c                &   < V ^8  d   QhRS[ RS[/# )r   	reshape_qreturnr   r   )r   r   s   "r   r   r   #   s      y S r   c                B   ^ pV P                   P                  VP                  ^,          4      pVeN   \        V\        P
                  4      '       d.   \        VP                  4      ^.8X  d   \        V^,          4      p\        V\        4      '       d
   V^ 8  d   V# ^ # )Detect num_heads from a reshape node.

Args:
    reshape_q (NodeProto): reshape node for Q
Returns:
    int: num_heads, or 0 if not found
)	r   get_constant_valueinput
isinstancenpndarraylistshaper   )r   r#   r   shape_values   &&  r   get_decoder_num_heads2FusionMultiHeadAttentionSam2.get_decoder_num_heads#   s     	 jj33IOOA4FG"+rzz22tK<M<M7NSTRU7UA/	i%%)a-r   c                &   < V ^8  d   QhRS[ RS[/# )r   
reshape_inr$   r%   )r   r   s   "r   r   r   8   s      	 c r   c                   ^ pV P                   P                  VP                  ^,          4      pVeO   \        V\        P
                  4      '       d.   \        VP                  4      ^.8X  d   \        V^,          4      pMV P                   P                  VR^4      pVe   \        VP                  4      ^8X  d~   V P                   P                  VP                  ^,          4      pVeN   \        V\        P
                  4      '       d.   \        VP                  4      ^.8X  d   \        V^ ,          4      p\        V\        4      '       d
   V^ 8  d   V# ^ # )r'   Concat)r   r(   r)   r*   r+   r,   r-   r.   r   match_parentlen)r   r3   r   r/   concat_shapes   &&   r   get_encoder_num_heads2FusionMultiHeadAttentionSam2.get_encoder_num_heads8   s
    	jj33J4D4DQ4GH"+rzz22tK<M<M7NSTRU7UA/	::22:xKL'C0B0B,Cq,H"jj;;L<N<Nq<QR*!+rzz::tKDUDU?V[\Z]?]$'A$7	i%%)a-r   c                    V P                   P                  VP                  ^,          4      pV'       d(   \        P                  ! V4      P
                  ^ ,          # ^ # )zDetect hidden_size from LayerNormalization node.
Args:
    layernorm_node (NodeProto): LayerNormalization node before Q, K and V
Returns:
    int: hidden_size, or 0 if not found
)r   get_initializerr)   r   to_arrayr.   )r   layernorm_nodelayernorm_biass   && r   get_hidden_size,FusionMultiHeadAttentionSam2.get_hidden_sizeT   sE     33N4H4H4KL''7==a@@r   c          
      H   < V ^8  d   QhRS[ RS[ RS[RS[S[S[3,          /# )r   r#   r>   
is_encoderr$   )r   booltupler   )r   r   s   "r   r   r   a   s5     "& "&""&4="&KO"&	sCx"&r   c                L   V'       d   V P                  V4      pMV P                  V4      pV^ 8:  d   V P                  pV P                  ^ 8  dP   W@P                  8w  d@   V P                  '       d.   \        P                  RV P                   RV R24       RV n        V P                  V4      pV^ 8:  d   V P                  pV P                  ^ 8  dP   WPP                  8w  d@   V P                  '       d.   \        P                  RV P                   RV R24       RV n        WE3# )zDetect num_heads and hidden_size.

Args:
    reshape_q (NodeProto): reshape node for Q
    layernorm_node (NodeProto): LayerNormalization node before Q, K, V
Returns:
    Tuple[int, int]: num_heads and hidden_size
z--num_heads is z. Detected value is z. Using detected value.Fz--hidden_size is )	r9   r0   r   r   loggerwarningr@   r   r   )r   r#   r>   rC   r   r   s   &&&&  r   get_num_heads_and_hidden_size:FusionMultiHeadAttentionSam2.get_num_heads_and_hidden_sizea   s    229=I229=I>I>>A)~~"=%%%0@@TU^T__vwx).&**>:!**KaK3C3C$C''''(8(8'99Mk]Zqr ,1(%%r   c                d   < V ^8  d   QhRS[ RS[ RS[ RS[ RS[ RS[ RS[RS[R	S[R
S[ R,          /
# )r   q_matmulq_addk_matmulk_addv_matmulv_addr   r   outputr$   N)r   r   str)r   r   s   "r   r   r      st     > >> > 	>
 > > > > > > 
T	>r   c
           
     6   V^ 8  d+   W,          ^ 8w  d   \         P                  RV RV 24       R# V P                  P                  VP                  ^,          4      p
V P                  P                  VP                  ^,          4      pV P                  P                  VP                  ^,          4      pV
'       d   V'       d	   V'       g   R# \
        P                  ! V
4      p\
        P                  ! V4      p\
        P                  ! V4      p\         P                  RVP                   RVP                   RVP                   RV 24       V P                  P                  R4      pVP                  ^ ,          VP                  ^ ,          VP                  ^ ,          .p\        P                  ! RVV	.VR	7      pR
Vn        VP                  P                  \        P                  ! RV4      .4       RP!                  R4      pV P#                  V4       V# )a  Create an Attention node.

Args:
    q_matmul (NodeProto): MatMul node in fully connection for Q
    q_add (NodeProto): Add bias node in fully connection for Q
    k_matmul (NodeProto): MatMul node in fully connection for K
    k_add (NodeProto): Add bias node in fully connection for K
    v_matmul (NodeProto): MatMul node in fully connection for V
    v_add (NodeProto): Add bias node in fully connection for V
    num_heads (int): number of attention heads. If a model is pruned, it is the number of heads after pruning.
    hidden_size (int): hidden dimension. If a model is pruned, it is the hidden dimension after pruning.
    output (str): output name

Returns:
    Union[NodeProto, None]: the node created or None if failed.
zinput hidden size z# is not a multiple of num of heads Nzqw=z kw=z vw=z hidden_size=r   inputsoutputsnamecom.microsoftr   MultiHeadAttention ({})zcross attention)rG   debugr   r<   r)   r   r=   r.   create_node_namerR   r   	make_nodedomain	attributeextendmake_attributer   increase_counter)r   rL   rM   rN   rO   rP   rQ   r   r   rR   q_weightk_weightv_weightqwkwvwattention_node_nameattention_inputsattention_nodecounter_names   &&&&&&&&&&          r   create_attention_node2FusionMultiHeadAttentionSam2.create_attention_node   s   8 ? 7A=LL-k]:]^g]hij::--hnnQ.?@::--hnnQ.?@::--hnnQ.?@X(!!(+!!(+!!(+s288*D
$rxxjk][\"jj99:NO LLOLLOLLO
  )) #H$	
 !0  '')>)>{I)V(WX0778IJl+r   c                   V P                  WV4      '       d   R # V P                  V4      pVf^   VP                  ^ ,          V9  d   R # W1P                  ^ ,          ,          pVP                  R8w  d   R # V P                  V4      pVf   R # Vw	  rgrrrpTpV P	                  WR4      w  ppV^ 8:  d   \
        P                  R4       R # V P                  V	V
VVVVVVVP                  ^ ,          R7	      pVf   R # V P                  P                  V4       V P                  V P                  VP                  &   V P                  P                  W.4       RV n        R # )NAddF*fuse_attention: failed to detect num_heads)rR   T)fuse_sam_encoder_patternmatch_attention_subgraphr)   op_typerI   rG   r[   rm   rR   nodes_to_addappendthis_graph_namenode_name_to_graph_namerX   nodes_to_remover`   prune_graph)r   normalize_nodeinput_name_to_nodesoutput_name_to_node	match_qkvskip_addreshape_qkvtranspose_qkvr#   matmul_qadd_qmatmul_kadd_kmatmul_vadd_vattention_last_nodeq_num_headsq_hidden_sizenew_nodes   &&&&               r   fuse!FusionMultiHeadAttentionSam2.fuse   sb   ((Nabb11.A	##A&.AA*+?+?+BCH5(55h?I cl`I%[`)%)%G%G	ch%i"]!LLEF --&--a0 . 

   *6:6J6J$$X]]3##%8$HI  r   c           	        V P                   P                  V. R	O. R
O4      pVf   R# Vw   r4rVV P                   P                  V. RO. RO4      pVf   \        P                  R4       R# Vw   r8p	V P                   P                  VRR.^ ^ .4      p
V
e   V
w  rM\        P                  R4       R# V P                   P                  V. RO. RO4      pVf   \        P                  R4       R# Vw  rpppV P                   P                  V. RO. RO4      pVf   \        P                  R4       R# Vw  p pppV P                   P                  V. RO. RO4      pVe   VR,          V8w  d   \        P                  R4       R# WEVVVVVW3	# )z.Match Q, K and V paths exported by PyTorch 2.*MatMulNz&fuse_attention: failed to match v pathSoftmaxz'fuse_attention: failed to match qk pathz&fuse_attention: failed to match q pathz&fuse_attention: failed to match k pathz*fuse_attention: failed to match mul_q pathrp   r   Reshape	Transposer   )NNNr   r   )r   r   rp   r   )   r   r   N)Mulr   r   rp   r   )r   Nr   r   N)r   Nr   r   N)SqrtDivr   CastSliceShaper   r   )Nr   r   r   r   r   r   r   r   match_parent_pathrG   r[   )r   node_after_output_projection	qkv_nodes_r   r   
matmul_qkvv_nodesr   r   qk_nodes_softmax_qk	matmul_qkq_nodesmul_q_transpose_qr#   r   r   k_nodes_mul_kr   r   mul_q_nodess   &&                      r   rs   5FusionMultiHeadAttentionSam2.match_attention_subgraph   s   JJ00(?$
	 9B6AM**..z;dfuv?LLAB")Ah:://
Y<QTUWXSYZ'/$[)LLBC**..GI^
 ?LLAB<C9i**..GI^
 ?LLAB*1'Auh jj22U'

 +b/Y">LLEF9hxQVX`ggr   c                    < V ^8  d   QhRS[ /# )r   r$   )rD   )r   r   s   "r   r   r   1  s     B Bdh Br   c                   V P                   P                  V. RO. RO4      pVf"   V P                   P                  V. RO. RO4      pVf    V P                   P                  VR .^ .4      pVf   R# VR,          pT P                  T\        V4      ^8X  d   ^MRR7      pVf   R# Vw  rxrr\        P
                  ! V
R4      p\        V\        4      '       d
   V. RO8w  d   R# \        P
                  ! VR4      p\        V\        4      '       d
   V. RO8w  d   R# \        P
                  ! VR4      p\        V\        4      '       d
   V. RO8w  d   R# V P                   P                  V	. RO. RO4      pVf   R# Vw  pppV P                  VVR4      w  ppV^ 8:  d   \        P                  R4       R# RpV P                   P                  V4      pVfW   \        P                  ! \        P                  ! . ROR	R
7      VR7      pV P                   P!                  VV P"                  4       V P                   P%                  R4      p\&        P(                  ! RV
P*                  ^ ,          V.V
P*                  ^ ,          R,           .VR7      pV P,                  P/                  V4       V P"                  V P0                  VP2                  &   T
pVP*                  ^ ,          VP*                  ^ &   VP*                  ^ ,          R,           VP4                  ^ &   \        P                  RV: RV: 24       V P7                  VVVV4      pVf   R# \        V P                   P9                  W4      4      ^8X  g   Q hVP4                  ^ ,          VP*                  ^ &   V P,                  P/                  V4       V P"                  V P0                  VP2                  &   V P:                  P=                  V.4       RV n        R# )rp   r   NF)input_indexpermTrq   bsnh_to_bsd_reshape_dimsint64)dtype)rX   _BSDrU   _BNSHzFound MHA: q_num_heads=z q_hidden_size=)rp   r   r   r   r   Nr   r   )rp   r   r   r   r   r   )r   Nr   r   r   r   r   )r   r   r      )r   r   r   r   )r   rp   r   )r   r   N)r   r   r   ) r   r   $match_sam_encoder_attention_subgraphr7   r	   get_node_attributer*   r-   rI   rG   r[   r<   r   
from_arrayr+   arrayadd_initializerrw   r\   r   r]   r)   ru   rv   rx   rX   rR   create_mha_nodeget_childrenry   r`   rz   )r   r{   r|   r}   nodesr   matched_sdpareshape_outtranspose_out	split_qkvtranspose_qtranspose_ktranspose_vpermutation_qpermutation_kpermutation_vinput_projection_nodesr3   add_in	matmul_inr   r   new_dims_namenew_dimsreshape_q_namer#   transpose_k_bnshr   s   &&&&                        r   rr   5FusionMultiHeadAttentionSam2.fuse_sam_encoder_pattern1  s   < 

,,6

 =JJ00L%E
 =JJ00E
 =',Ry$@@(3u:?aPT A 
 WcTIK "44[&I=$//M\4Q "44[&I=$//M\4Q "44[&I=$//M\4Q!%!=!=("

 ")(>%
FI%)%G%G
Tbdh%i"]!LLEF 3::--m<#..rxx
'/RYfgHJJ&&x1E1EF44Y?$$%%a(-8 &&q)F23	
	 	  +7;7K7K$$Y^^4 '$/$5$5a$8q!%0%6%6q%9G%C"/;.0@-1ABC ''	
  4::**=NOSTTTT'q1!  *6:6J6J$$X]]3##]O4  r   c           	        V P                   P                  V. ROVRR^ ^ .4      pVf   R# Vw   rErgV P                   P                  V. R	O. R
O4      pVf   \        P                  R4       R# Vw  rrV P                   P                  VRR.^ ^ .4      pVe   Vw  rM\        P                  R4       R# V P                   P                  V. RO. RO4      pVf=   V P                   P                  V. RO. RO4      pVf   \        P                  R4       R# VR,          V
8w  d   R# V^,          pV P                   P                  V. RO. RO4      pVf   \        P                  R4       R# VR,          V
8w  d   R# Vw  ppppWVV
VVV	3# )z%Match SDPA pattern in SAM2 enconder.*r   Nzfailed to match v pathr   zfailed to match qk pathzfailed to match q pathzfailed to match k pathr   )r   SqueezeSplitr   )r   r   r   r   )r   r   r   r   r   )	r   r   r   r   MaxPoolr   r   r   r   )	r   Nr   r   r   r   r   r   r   r   )r   Nr   r   r   )r   r   r   	out_nodesr   r   r   matmul_qk_vr   r   r   r   r   r   r   r   r   r   mul_kr   
_squeeze_ks   &&&                  r   r   AFusionMultiHeadAttentionSam2.match_sam_encoder_attention_subgraph  s    JJ00(?$a+
	 :C7AM **..{<hjvw?LL123:0:://i=RUVXYTZ['/$[)LL23**..y:bdst?jj22s.G
 562;)#aj**..y:bdst?LL122;)#.5+Z9k;P[[[r   c          
      8   < V ^8  d   QhRS[ RS[ RS[ RS[RS[ /# )r   r#   r   r   r   r$   r%   )r   r   s   "r   r   r     s=     ) )) ) 	)
 ) 
)r   c                   V P                   P                  R4      pVP                  ^ ,          VP                  ^ ,          VP                  ^ ,          .pVR,           p\        P                  ! RVV.VR7      pRVn        VP                  P                  \        P                  ! RV4      .4       RP                  R4      p	V P                  V	4       V# )a  Create a MultiHeadAttention node for SAM2 encoder.

Args:
    reshape_q (NodeProto): Reshape node for Q, output is 3D BxSxNH format
    transpose_k (NodeProto): Transpose node for K, output is BNSH format
    transpose_v (NodeProto): Transpose node for V, output is BNSH format
    num_heads (int): number of attention heads. If a model is pruned, it is the number of heads after pruning.

Returns:
    NodeProto: the MultiHeadAttention node created.
r   _outrU   rY   r   rZ   zself attention)r   r\   rR   r   r]   r^   r_   r`   ra   r   rb   )
r   r#   r   r   r   ri   rV   rR   rk   rl   s
   &&&&&     r   r   ,FusionMultiHeadAttentionSam2.create_mha_node  s    & #jj99:NO Qq!q!
 %v-)) H$	
 !0  '')>)>{I)V(WX0778HIl+r   )r   r   r   r   rz   )F)N)__name__
__module____qualname____firstlineno____doc__r   r0   r9   r@   rI   rm   r   rs   rr   r   r   __static_attributes____classdictcell____classcell__)r    r   s   @@r   r   r      ss     ( ( * 8"& "&H> >@0 d5htB BH5\n) ) )r   r   )loggingr   numpyr+   fusion_baser   fusion_utilsr   onnxr   r   r   
onnx_modelr	   r   rG   r    r   r   <module>r      s4   
    $ 0 0  	8	E6 Er   