Ë
    éÓ^jZë  ã                   ó®  — d Z ddlZddlmZ ddlmZmZmZmZm	Z	m
Z
mZmZ ddlZddlmZ ddlmc mZ ddlmZmZ ddlmZmZmZmZmZ ddlmZ dd	lmZ dd
l m!Z!m"Z" ddl#m$Z$m%Z% ddl&m'Z' ddgZ( G d„ dejR                  «      Z*dejV                  dejV                  fd„Z,	 dRdejV                  dejV                  dejV                  de-dejV                  f
d„Z.	 	 dSdejV                  dejV                  dejV                  de-de-dejV                  fd„Z/ G d„ dejR                  «      Z0 G d„ dejR                  «      Z1 G d„ dejR                  «      Z2 G d „ d!ejR                  «      Z3 G d"„ d#ejR                  «      Z4 G d$„ d%ejR                  «      Z5 G d&„ dejR                  «      Z6 G d'„ dejR                  «      Z7dTd)ejR                  d*e8d+e9ddfd,„Z:dTd-e8d+e9defd.„Z;d/ee8ejV                  f   d0e6dee8ejV                  f   fd1„Z<d/ee8ejV                  f   d0ddee8ejV                  f   fd2„Z=dUd4e8d5e9de6fd6„Z>dUd4e8d5e9de7fd7„Z?dVd8e8dee8ef   fd9„Z@ e$ e@d:d;d<¬=«       e@d>d;d<¬=«       e@d?d<¬@«       e@dAd<¬@«      dBœ«      ZA eBdCdDdEdFdGd3d(¬H«      ZC eBdIdJdDdKdLd(¬M«      ZDe%dUd5e9de7fdN„«       ZEe%dUd5e9de6fdO„«       ZFe%dUd5e9de7fdP„«       ZGe%dUd5e9de6fdQ„«       ZHy)WaM  Gemma4 Vision Transformer

Vision encoder from Google's Gemma 4 multimodal model.
Custom ViT with 2D RoPE, Gated MLP, QKV normalization, and 4-norm sandwich blocks.

Paper: https://ai.google.dev/gemma/docs/core/model_card_4
Reference impl: https://github.com/huggingface/transformers (Gemma4VisionModel)

Copyright 2025 Yonghye Kwon
é    N)Úpartial)ÚAnyÚCallableÚDictÚListÚOptionalÚSetÚTupleÚUnion)ÚIMAGENET_DEFAULT_MEANÚIMAGENET_DEFAULT_STD)ÚRmsNormÚDropPathÚ	to_2tupleÚtrunc_normal_tf_Úuse_fused_attné   )Úbuild_model_with_cfg)Úfeature_take_indices)Ú
checkpointÚnamed_apply)Úgenerate_default_cfgsÚregister_model)Úbatch_patchifyÚGemma4VitEncoderÚGemma4VitClassifierc            	       ó|   ‡ — e Zd ZdZ	 	 	 ddedededdfˆ fd„Zdd„Zd	ej                  dej                  fd
„Z
ˆ xZS )ÚGemma4ClippableLinearzÜLinear layer with optional input/output clamping.

    Used in Gemma4 E4B variant where clamp values are finite and affect output.
    When use_clipped=False, behaves as a standard nn.Linear (no buffers registered).
    NÚin_featuresÚout_featuresÚuse_clippedÚreturnc                 óÄ  •— ||dœ}t         ‰| �  «        || _        t        j                  ||fddi|¤Ž| _        |r¥| j                  dt        j                  di |¤Ž«       | j                  dt        j                  di |¤Ž«       | j                  dt        j                  di |¤Ž«       | j                  dt        j                  di |¤Ž«       | j                  «        y y )	N©ÚdeviceÚdtypeÚbiasFÚ	input_minÚ	input_maxÚ
output_minÚ
output_max)© )
ÚsuperÚ__init__r!   ÚnnÚLinearÚlinearÚregister_bufferÚtorchÚemptyÚreset_parameters)Úselfr   r    r!   r%   r&   ÚddÚ	__class__s          €úa/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/timm/models/gemma4_vit.pyr.   zGemma4ClippableLinear.__init__'   sÂ   ø€ ð ¨Ñ/ˆÜ‰ÑÔØ&ˆÔÜ—i‘i ¨\ÑLÀÐLÈÑLˆŒÙØ× Ñ  ¬e¯k©kÑ.CÀÑ.CÔDØ× Ñ  ¬e¯k©kÑ.CÀÑ.CÔDØ× Ñ  ¬u¯{©{Ñ/DÀÑ/DÔEØ× Ñ  ¬u¯{©{Ñ/DÀÑ/DÔEà×!Ñ!Õ#ð ó    c                 óB  — | j                   r“| j                  j                  t        d«       «       | j                  j                  t        d«      «       | j
                  j                  t        d«       «       | j                  j                  t        d«      «       y y )NÚinf)r!   r(   Úfill_Úfloatr)   r*   r+   ©r6   s    r9   r5   z&Gemma4ClippableLinear.reset_parameters;   sn   € ð ×ÒØ�N‰N× Ñ ¤%¨£, Ô/Ø�N‰N× Ñ ¤ u£Ô.Ø�O‰O×!Ñ!¤5¨£< -Ô0Ø�O‰O×!Ñ!¤%¨£,Õ/ð	 r:   Úxc                 ó  — | j                   r+t        j                  || j                  | j                  «      }| j                  |«      }| j                   r+t        j                  || j                  | j                  «      }|S ©N)r!   r3   Úclampr(   r)   r1   r*   r+   ©r6   r@   s     r9   ÚforwardzGemma4ClippableLinear.forwardD   sZ   € Ø×ÒÜ—‘˜A˜tŸ~™~¨t¯~©~Ó>ˆAØ�K‰K˜‹NˆØ×ÒÜ—‘˜A˜tŸ™°·±Ó@ˆAØˆr:   )FNN©r"   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚintÚboolr.   r5   r3   ÚTensorrE   Ú__classcell__©r8   s   @r9   r   r       s^   ø„ ñð !&ØØñ$àð$ð ð$ð ð	$ð 
õ$ó(0ð˜Ÿ™ð ¨%¯,©,÷ r:   r   r@   r"   c                 óš   — | dd| j                   d   dz  …f   }| d| j                   d   dz  d…f   }t        j                  | |fd¬«      S )z*Rotates half the hidden dims of the input..Néÿÿÿÿé   ©Údim)Úshaper3   Úcat)r@   Úx1Úx2s      r9   Úrotate_halfrY   M   sZ   € à	
ˆ3Ð"�!—'‘'˜"‘+ Ñ"Ð"Ð"Ñ	#€BØ	
ˆ3�—‘˜‘˜qÑ Ñ"Ð"Ñ	#€BÜ�9‰9�r�c˜2�Y BÔ'Ð'r:   ÚcosÚsinÚunsqueeze_dimc                 ón   — |j                  |«      }|j                  |«      }| |z  t        | «      |z  z   S )z0Apply rotary position embedding to input tensor.)Ú	unsqueezerY   )r@   rZ   r[   r\   s       r9   Úapply_rotary_pos_embr_   T   s8   € ð �-‰-˜Ó
&€CØ
�-‰-˜Ó
&€CØ�‰Gœ A›¨Ñ,Ñ-Ð-r:   Úndimc           	      óf  — | j                   d   }d|d|z  z  z  }|g|z  }t        j                  | |d¬«      }t        j                  ||d¬«      }	t        j                  ||d¬«      }
t        |«      D �cg c]  }t	        ||   |	|   |
|   |¬«      ‘Œ }}t        j
                  |d¬«      S c c}w )z•Apply multidimensional RoPE to input tensor.

    Splits input along head_dim into ndim parts, applies RoPE to each,
    then concatenates back.
    rQ   rR   rS   )r\   )rU   r3   ÚsplitÚranger_   rV   )r@   rZ   r[   r`   r\   Únum_input_channelsÚnum_rotated_channels_per_dimÚsplit_sizesÚx_partsÚ	cos_partsÚ	sin_partsÚkÚy_partss                r9   Úapply_multidimensional_roperl   `   s¿   € ð Ÿ™ ™ÐØ#$Ð(:¸qÀ4¹xÑ(HÑ#IÐ Ø/Ð0°4Ñ7€Kä�k‰k˜!˜[¨bÔ1€GÜ—‘˜C °"Ô5€IÜ—‘˜C °"Ô5€Iô lqÐquÓkvöØfgÔ˜W Q™Z¨°1©°yÀ±|ÐS`Öað€Gð ô �9‰9�W "Ô%Ð%ùòs   Á6B.c                   ó¾   ‡ — e Zd ZdZ	 	 	 ddededdfˆ fd„Zdd„Zdd„Zdd	„Z	d
e
j                  de
j                  dee
j                  e
j                  f   fd„Zˆ xZS )ÚGemma4RotaryEmbedding2Dz´2D Rotary Position Embedding for Gemma4 vision encoder.

    Computes RoPE independently for each spatial dimension (x, y),
    using theta=100.0 and the partitioned head_dim.
    NÚhead_dimÚ
rope_thetar"   c                 óÞ   •— t         ‰| �  «        || _        || _        |dz  dz  }| j	                  dt        j                  ||t
        j                  ¬«      d¬«       | j                  «        y )NrR   Úinv_freqr$   F)Ú
persistent)	r-   r.   ro   rp   r2   r3   r4   r>   Ú_init_buffers)r6   ro   rp   r%   r&   Ú	num_freqsr8   s         €r9   r.   z Gemma4RotaryEmbedding2D.__init__�   si   ø€ ô 	‰ÑÔØ ˆŒØ$ˆŒð  ‘] qÑ(ˆ	Ø×ÑØÜ�K‰K˜	¨&¼¿¹ÔDØð 	ô 	
ð 	×ÑÕr:   c           	      óö   — | j                   dz  }d| j                  t        j                  d|dt        j                  | j
                  j                  ¬«      |z  z  z  }| j
                  j                  |«       y)z.Compute and fill non-persistent buffer values.rR   ç      ð?r   ©r&   r%   N)ro   rp   r3   Úaranger>   rr   r%   Úcopy_)r6   Úspatial_dimrr   s      r9   rt   z%Gemma4RotaryEmbedding2D._init_buffers—   sc   € à—m‘m qÑ(ˆØØ�O‰OÜ—‘˜Q ¨Q´e·k±kÈ$Ï-É-×J^ÑJ^Ô_ÐbmÑmñoñ
ˆð 	�‰×Ñ˜HÕ%r:   c                 ó$   — | j                  «        y rB   ©rt   r?   s    r9   r5   z(Gemma4RotaryEmbedding2D.reset_parameters    s   € Ø×ÑÕr:   c                 ó$   — | j                  «        y)z"Initialize non-persistent buffers.Nr}   r?   s    r9   Úinit_non_persistent_buffersz3Gemma4RotaryEmbedding2D.init_non_persistent_buffers£   s   € à×ÑÕr:   r@   Úposition_idsc                 ó\  — t        j                  «       5  | j                  ddd…df   j                  «       j	                  |j
                  d   dd«      j                  |j                  «      }g }g }t        d«      D ]°  }|dd…dd…|f   }|dd…ddd…f   j                  «       }|j                  «       |j                  «       z  j                  dd«      }	t        j                  |	|	fd¬«      }
|j                  |
j                  «       «       |j                  |
j                  «       «       Œ² t        j                  |d¬«      j                  |j                  ¬«      }t        j                  |d¬«      j                  |j                  ¬«      }ddd«       ||fS # 1 sw Y   fS xY w)zü
        Args:
            x: Hidden states tensor, used only for dtype/device.
            position_ids: (B, N, 2) Gemma4-internal ``(x, y)`` patch coords.

        Returns:
            cos, sin: (B, N, head_dim) tensors for RoPE application.
        Nr   rQ   r   rR   rS   )r&   )r3   Úno_gradrr   r>   ÚexpandrU   Útor%   rc   Ú	transposerV   ÚappendrZ   r[   r&   )r6   r@   r€   Úinv_freq_expandedÚall_cosÚall_sinÚiÚdim_posÚdim_pos_expandedÚfreqsÚembrZ   r[   s                r9   rE   zGemma4RotaryEmbedding2D.forward§   sq  € ô  �]‰]‹_ñ 	?Ø $§¡¨d²A°t¨mÑ <× BÑ BÓ D× KÑ KÈL×L^ÑL^Ð_`ÑLaÐceÐghÓ i× lÑ lÐmn×muÑmuÓ vÐà*,ˆGØ*,ˆGÜ˜1“Xò *�Ø&¢qª!¨Q wÑ/�Ø#*ª1¨d²A¨:Ñ#6×#<Ñ#<Ó#>Ð à*×0Ñ0Ó2Ð5E×5KÑ5KÓ5MÑM×XÑXÐYZÐ\]Ó^�Ü—i‘i ¨ °BÔ7�Ø—‘˜sŸw™w›yÔ)Ø—‘˜sŸw™w›yÕ)ð*ô —)‘)˜G¨Ô,×/Ñ/°a·g±gÐ/Ó>ˆCÜ—)‘)˜G¨Ô,×/Ñ/°a·g±gÐ/Ó>ˆC÷	?ð  �Cˆxˆ÷!	?ð  �Cˆxˆús   •E>FÆF+)ç      Y@NNrF   )rG   rH   rI   rJ   rK   r>   r.   rt   r5   r   r3   rM   r
   rE   rN   rO   s   @r9   rn   rn   z   s~   ø„ ñð !&ØØñàðð ðð 
õó,&óóð à�|‰|ð ð  Ÿ,™,ð ð 
ˆu�|‰|˜UŸ\™\Ð)Ñ	*÷	 r:   rn   c                   óê  ‡ — e Zd ZdZ	 	 	 	 	 	 ddeeeeef   f   dedededdf
ˆ fd„Zdd	„Zd
ededede	j                  dee	j                  e	j                  f   f
d„Zde	j                  de	j                  de	j                  fd„Z	 	 ddee	j                  eee	j                  f   f   dee	j                     dee	j                     dee	j                  e	j                  e	j                  f   fd„Zˆ xZS )ÚGemma4PatchEmbeduï  Linear patch embedding with a 2D position-embedding table.

    Unlike the standard ViT PatchEmbed (Conv2d), Gemma4 uses a Linear projection
    on flattened patches plus a separate 2D position-embedding table applied via
    one-hot lookup. Inputs may be supplied as:

      * ``(B, C, H, W)`` raw images â€” patchified inline in P-P-C flat order.
      * ``(B, N, P*P*C)`` pre-patchified P-P-C patches (NaFlex loader output).
      * ``(B, N, Ph, Pw, C)`` pre-patchified unflattened patches.
      * ``dict`` with keys ``patches`` / ``patch_coord`` / ``patch_valid``.

    All input-dispatch logic is owned by this module; the parent model simply
    calls ``self.patch_embed(x, patch_coord, patch_valid)`` and unpacks the
    returned tensors.
    NÚ
patch_sizeÚin_chansÚ	embed_dimÚposition_embedding_sizer"   c                 óN  •— ||dœ}t         ‰
| �  «        t        |«      | _        || _        || _        | j                  \  }}	t        j                  ||z  |	z  |fddi|¤Ž| _        t        j                  t        j                  d||fi |¤Ž«      | _        | j                  «        y )Nr$   r'   FrR   )r-   r.   r   r’   r”   r•   r/   r0   Ú
input_projÚ	Parameterr3   r4   Úposition_embedding_tabler5   )r6   r’   r“   r”   r•   r%   r&   r7   ÚphÚpwr8   s             €r9   r.   zGemma4PatchEmbed.__init__Û   s�   ø€ ð ¨Ñ/ˆÜ‰ÑÔÜ# JÓ/ˆŒØ"ˆŒØ'>ˆÔ$à—‘‰ˆˆBÜŸ)™) H¨r¡M°BÑ$6¸	ÑTÈÐTÐQSÑTˆŒÜ(*¯©Ü�K‰K˜Ð2°IÑDÀÑDó)
ˆÔ%ð 	×ÑÕr:   c                 ó2   — t        | j                  d¬«       y )Nç{®Gáz”?©Ústd)r   r™   r?   s    r9   r5   z!Gemma4PatchEmbed.reset_parametersò   s   € Ü˜×6Ñ6¸DÖAr:   Ú
batch_sizeÚpHÚpWr%   c                 óž  — t        j                  ||¬«      }t        j                  ||¬«      }t        j                  ||d¬«      \  }}t        j                  |j	                  «       |j	                  «       gd¬«      }	|	j                  d«      j                  |dd«      }	t        j                  |||z  t         j                  |¬«      }
|	|
fS )z:Row-major grid coords in external NaFlex ``(y, x)`` order.)r%   Úij)ÚindexingrQ   rS   r   rx   )	r3   ry   ÚmeshgridÚstackÚflattenr^   rƒ   ÚonesrL   )r6   r    r¡   r¢   r%   ÚysÚxsÚgrid_yÚgrid_xÚpatch_coordÚpatch_valids              r9   Ú_default_patch_coordz%Gemma4PatchEmbed._default_patch_coordõ   s£   € ô �\‰\˜" VÔ,ˆÜ�\‰\˜" VÔ,ˆÜŸ™¨¨B¸Ô>‰ˆ�Ü—k‘k 6§>¡>Ó#3°V·^±^Ó5EÐ"FÈBÔOˆØ!×+Ñ+¨AÓ.×5Ñ5°jÀ"ÀbÓIˆÜ—j‘j ¨R°"©W¼E¿J¹JÈvÔVˆØ˜KÐ'Ð'r:   r€   Úpadding_positionsc                 óT  — |j                  d¬«      }t        j                  || j                  ¬«      }|j	                  dddd«      j                  | j                  «      }|| j                  z  }|j                  d¬«      }t        j                  |j                  d«      d	|«      }|S )
zšCompute position embeddings via one-hot matmul against the 2D table.

        ``position_ids`` follows the Gemma4-internal ``(x, y)`` convention.
        r   ©Úmin©Únum_classesrR   r   é   rS   rQ   ç        )rC   ÚFÚone_hotr•   Úpermuter„   r™   Úsumr3   Úwherer^   )r6   r€   r±   Úclamped_positionsrº   Úposition_embeddingss         r9   Ú_position_embeddingsz%Gemma4PatchEmbed._position_embeddings  s£   € ð )×.Ñ.°1Ð.Ó5ÐÜ—)‘)Ð-¸4×;WÑ;WÔXˆØ—/‘/ ! Q¨¨1Ó-×0Ñ0°×1NÑ1NÓOˆà%¨×(EÑ(EÑEÐØ1×5Ñ5¸!Ð5Ó<ÐÜ#Ÿk™kØ×'Ñ'¨Ó+¨SÐ2Eó
Ðð #Ð"r:   r@   r®   r¯   c                 ó¶  — t        |t        «      r)|j                  d|«      }|j                  d|«      }|d   }| j                  \  }}|j                  dk(  rO|j
                  \  }}}}	|€'| j                  |||z  |	|z  |j                  «      \  }}t        |||fdd¬«      \  }}nÊ|j                  dk(  rA|j                  d	d
ddd«      j                  |j
                  d	   |j
                  d
   d«      }nz|j                  dk(  rR|j
                  \  }}
}|||z  z  }|j                  ||
|||«      j                  d	d
ddd«      j                  ||
|«      }nt        d|j                  › d�«      ‚|€t        d«      ‚|€f|dk(  j                  d¬«      }|j                  «       r| }n=t        j                   |j
                  dd t        j"                  |j                  ¬«      }d|dz
  z  }| j%                  |j'                  | j$                  j(                  j*                  «      «      }|j-                  d¬«      }| }|| j/                  ||«      z   }|||fS )aÅ  Normalize inputs, patchify / project / position-embed.

        Accepts external NaFlex ``patch_coord`` (y, x) / ``patch_valid`` inputs
        and returns the internal (x, y) form used by the rest of the model.

        Returns:
            embeddings: (B, N, embed_dim) patch embeddings with position info added.
            position_ids: (B, N, 2) Gemma4-internal (x, y) coords.
            padding_positions: (B, N) True for padding tokens.
        r®   r¯   Úpatchesé   NF)ÚpadÚchannels_lasté   r   r   rR   r·   rQ   z&Expected input ndim in (3, 4, 5); got ú.z1patch_coord is required for pre-patchified input.rS   rx   ç      à?)rQ   )Údims)Ú
isinstanceÚdictÚgetr’   r`   rU   r°   r%   r   r»   ÚreshapeÚviewÚ
ValueErrorÚallÚanyr3   r©   rL   r—   r„   Úweightr&   ÚfliprÀ   )r6   r@   r®   r¯   rš   r›   ÚBÚ_ÚHÚWÚNÚPPCÚCÚsentinelr€   r±   s                   r9   rE   zGemma4PatchEmbed.forward  sS  € ô  �aœÔØŸ%™% ¨{Ó;ˆKØŸ%™% ¨{Ó;ˆKØ�)‘ˆAà—‘‰ˆˆBØ�6‰6�QŠ;àŸ™‰JˆAˆq�!�QØÐ"Ø+/×+DÑ+DÀQÈÈRÉÐQRÐVXÑQXÐZ[×ZbÑZbÓ+cÑ(�˜[Ü! ! b¨" X°5ÈÔN‰DˆA‰qØ�V‰V�qŠ[ð —	‘	˜!˜Q  1 aÓ(×0Ñ0°·±¸±¸Q¿W¹WÀQ¹ZÈÓL‰AØ�V‰V�qŠ[ð Ÿ™‰IˆAˆq�#Ø˜˜R™Ñ ˆAØ—‘�q˜!˜R  QÓ'×/Ñ/°°1°a¸¸AÓ>×FÑFÀqÈ!ÈSÓQ‰AäØ8¸¿¹¸ÀÐBóð ð ÐÜÐPÓQÐQàÐØ# rÑ)×.Ñ.°2Ð.Ó6ˆHØ�|‰|Œ~Ø'˜i‘ä#Ÿj™jØ×%Ñ% b qÐ)´·±ÀK×DVÑDVô�ð
 ��S‘‰MˆØ�O‰O˜AŸD™D §¡×!7Ñ!7×!=Ñ!=Ó>Ó?ˆð #×'Ñ'¨UÐ'Ó3ˆØ(˜LÐØ�×)Ñ)¨,Ð8IÓJÑJˆà�,Ð 1Ð1Ð1r:   )é   r·   é   é (  NNrF   ©NN)rG   rH   rI   rJ   r   rK   r
   r.   r5   r3   r%   rM   r°   rÀ   r   Ústrr   rE   rN   rO   s   @r9   r‘   r‘   Ê   s_  ø„ ñð$ 79ØØ Ø+0ØØñ à˜c 5¨¨c¨¡?Ð2Ñ3ð ð ð ð ð	 ð
 &)ð ð 
õ ó.Bð(àð(ð ð(ð ð	(ð
 —L‘Lð(ð 
ˆu�|‰|˜UŸ\™\Ð)Ñ	*ó(ð #àŸ,™,ð#ð  %Ÿ|™|ð#ð 
�‰ó	#ð. 37Ø26ñ	@2à�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ð@2ð " %§,¡,Ñ/ð@2ð " %§,¡,Ñ/ð	@2ð
 
ˆu�|‰|˜UŸ\™\¨5¯<©<Ð7Ñ	8÷@2r:   r‘   c                   ó&  ‡ — e Zd ZU dZej
                  j                  e   ed<   	 	 	 	 	 	 	 	 	 dde	de	de	de
e	   ded	ed
ededdfˆ fd„Z	 ddej                  dej                  dej                  de
ej                     dej                  f
d„Zˆ xZS )ÚGemma4Attentiona  Gemma4 Vision Attention with QKV normalization and 2D RoPE.

    Key features:
    - Separate Q, K, V projections (not fused)
    - RMSNorm on Q, K (with scale) and V (without scale)
    - 2D RoPE applied after normalization
    - Attention scale = 1.0 (since QK are normalized)
    Ú
fused_attnNrT   Ú	num_headsro   Únum_kv_headsÚ	attn_dropÚ	proj_dropÚnorm_epsÚuse_clipped_linearsr"   c                 ód  •— |	|
dœ}t         ‰| �  «        || _        || _        |xs || _        || j                  z  | _        t        «       | _        t        |||z  fd|i|¤Ž| _	        t        || j                  |z  fd|i|¤Ž| _
        t        || j                  |z  fd|i|¤Ž| _        t        ||z  |fd|i|¤Ž| _        t        |f|ddœ|¤Ž| _        t        |f|ddœ|¤Ž| _        t        |f|ddœ|¤Ž| _        t#        j$                  |«      | _        t#        j$                  |«      | _        y )Nr$   r!   T©ÚepsÚaffineF)r-   r.   rä   ro   rå   Únum_kv_groupsr   rã   r   Úq_projÚk_projÚv_projÚo_projr   Úq_normÚk_normÚv_normr/   ÚDropoutræ   rç   )r6   rT   rä   ro   rå   ræ   rç   rè   ré   r%   r&   r7   r8   s               €r9   r.   zGemma4Attention.__init__h  sB  ø€ ð ¨Ñ/ˆÜ‰ÑÔØ"ˆŒØ ˆŒØ(Ò5¨IˆÔØ&¨$×*;Ñ*;Ñ;ˆÔÜ(Ó*ˆŒä+¨C°¸XÑ1EÑmÐSfÐmÐjlÑmˆŒÜ+¨C°×1BÑ1BÀXÑ1MÑuÐ[nÐuÐrtÑuˆŒÜ+¨C°×1BÑ1BÀXÑ1MÑuÐ[nÐuÐrtÑuˆŒÜ+¨I¸Ñ,@À#ÑmÐSfÐmÐjlÑmˆŒä˜hÐH¨H¸TÑHÀRÑHˆŒÜ˜hÐH¨H¸TÑHÀRÑHˆŒä˜hÐI¨H¸UÑIÀbÑIˆŒäŸ™ IÓ.ˆŒÜŸ™ IÓ.ˆ�r:   r@   Úrope_cosÚrope_sinÚ	attn_maskc                 óº  — |j                   \  }}}| j                  |«      j                  ||| j                  | j                  «      }| j                  |«      j                  ||| j                  | j                  «      }	| j                  |«      j                  ||| j                  | j                  «      }
| j                  |«      }| j                  |	«      }	| j                  |
«      }
t        |||dd¬«      }t        |	||dd¬«      }	|j                  dd«      }|	j                  dd«      }	|
j                  dd«      }
| j                  dkD  r:|	j                  | j                  d¬«      }	|
j                  | j                  d¬«      }
| j                  r>t!        j"                  ||	|
|| j$                  r| j&                  j(                  ndd¬«      }nD||	j                  dd	«      z  }|�||z   }|j+                  d	¬«      }| j'                  |«      }||
z  }|j                  dd«      j-                  ||d	«      }| j/                  |«      }| j1                  |«      }|S )
NrR   )r`   r\   r   rS   r¸   rw   )rù   Ú	dropout_pÚscaleéþÿÿÿrQ   )rU   rï   rÎ   rä   ro   rð   rå   rñ   ró   rô   rõ   rl   r…   rî   Úrepeat_interleaverã   r¹   Úscaled_dot_product_attentionÚtrainingræ   ÚpÚsoftmaxrÍ   rò   rç   )r6   r@   r÷   rø   rù   rÔ   rØ   rÚ   Úqrj   ÚvÚattns               r9   rE   zGemma4Attention.forwardŠ  s  € ð —'‘'‰ˆˆ1ˆaà�K‰K˜‹N×Ñ  1 d§n¡n°d·m±mÓDˆØ�K‰K˜‹N×Ñ  1 d×&7Ñ&7¸¿¹ÓGˆØ�K‰K˜‹N×Ñ  1 d×&7Ñ&7¸¿¹ÓGˆð �K‰K˜‹NˆØ�K‰K˜‹NˆØ�K‰K˜‹Nˆô (¨¨8°XÀAÐUVÔWˆÜ'¨¨8°XÀAÐUVÔWˆð �K‰K˜˜1ÓˆØ�K‰K˜˜1ÓˆØ�K‰K˜˜1Óˆð ×Ñ Ò!Ø×#Ñ# D×$6Ñ$6¸AÐ#Ó>ˆAØ×#Ñ# D×$6Ñ$6¸AÐ#Ó>ˆAà�?Š?Ü×.Ñ.ØØØØ#Ø.2¯mªm˜$Ÿ.™.×*Ò*ÀØô‰Að �q—{‘{ 2 rÓ*Ñ*ˆDØÐ$Ø˜iÑ'�Ø—<‘< B�<Ó'ˆDØ—>‘> $Ó'ˆDØ�q‘ˆAà�K‰K˜˜1Ó×%Ñ% a¨¨BÓ/ˆØ�K‰K˜‹NˆØ�N‰N˜1ÓˆØˆr:   )	é   é@   Nr¸   r¸   ç�íµ ÷Æ°>FNNrB   )rG   rH   rI   rJ   r3   ÚjitÚFinalrL   Ú__annotations__rK   r   r>   r.   rM   rE   rN   rO   s   @r9   râ   râ   \  sï   ø… ñð —	‘	—‘ Ñ%Ó%ð
  ØØ*.Ø"Ø"Ø"Ø(-ØØñ /àð /ð ð /ð ð	 /ð
 # 3™-ð /ð ð /ð ð /ð ð /ð "&ð /ð 
õ /ðN 15ñ5à�|‰|ð5ð —l‘lð5ð —l‘lð	5ð
   §¡Ñ-ð5ð 
�‰÷5r:   râ   c                   ó†   ‡ — e Zd ZdZ	 	 	 	 	 ddededee   dededdfˆ fd	„Z	d
e
j                  de
j                  fd„Zˆ xZS )ÚGemma4GatedMlpz�Gated MLP for Gemma4 Vision Encoder.

    Uses GELUTanh activation: output = down_proj(gelu_tanh(gate_proj(x)) * up_proj(x))
    Nr   Úhidden_featuresÚ	act_layerÚdropré   r"   c                 ó   •— ||dœ}t         ‰	| �  «        t        ||fd|i|¤Ž| _        t        ||fd|i|¤Ž| _        t        ||fd|i|¤Ž| _        |� |«       nt        j                  d¬«      | _        t        j                  |«      | _
        y )Nr$   r!   Útanh©Úapproximate)r-   r.   r   Ú	gate_projÚup_projÚ	down_projr/   ÚGELUÚactrö   r  )
r6   r   r  r  r  ré   r%   r&   r7   r8   s
            €r9   r.   zGemma4GatedMlp.__init__È  s’   ø€ ð ¨Ñ/ˆÜ‰ÑÔÜ.¨{¸OÑsÐYlÐsÐprÑsˆŒÜ,¨[¸/ÑqÐWjÐqÐnpÑqˆŒÜ.¨ÀÑsÐYlÐsÐprÑsˆŒØ"+Ð"7‘9”;¼R¿W¹WÐQWÔ=XˆŒÜ—J‘J˜tÓ$ˆ�	r:   r@   c           	      ó¢   — | j                  | j                  | j                  | j                  |«      «      | j	                  |«      z  «      «      S rB   )r  r  r  r  r  rD   s     r9   rE   zGemma4GatedMlp.forwardÚ  s:   € Ø�y‰y˜Ÿ™¨¯©°·±ÀÓ1BÓ(CÀdÇlÁlÐSTÃoÑ(UÓVÓWÐWr:   )Nr¸   FNN)rG   rH   rI   rJ   rK   r   r   r>   rL   r.   r3   rM   rE   rN   rO   s   @r9   r  r  Â  s{   ø„ ñð -1ØØ(-ØØñ%àð%ð !ð%ð   Ñ)ð	%ð
 ð%ð "&ð%ð 
õ%ð$X˜Ÿ™ð X¨%¯,©,÷ Xr:   r  c                   óþ   ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 ddededededee   ded	ed
ededee   deddfˆ fd„Z		 dde
j                  de
j                  de
j                  dee
j                     de
j                  f
d„Zˆ xZS )ÚGemma4Blocka  Gemma4 Vision Encoder Block with 4-norm sandwich pattern.

    Unlike standard ViT (pre-norm with 2 norms), Gemma4 uses:
    - input_layernorm (norm1) + post_attention_layernorm (norm2)
    - pre_feedforward_layernorm (norm3) + post_feedforward_layernorm (norm4)
    NrT   rä   ro   Úintermediate_sizerå   rè   ræ   rç   Ú	drop_pathr  ré   r"   c                 ó~  •— ||dœ}t         ‰| �  «        t        |fd|i|¤Ž| _        t	        d||||||||dœ|¤Ž| _        t        |fd|i|¤Ž| _        t        |fd|i|¤Ž| _        t        d|||
|dœ|¤Ž| _	        t        |fd|i|¤Ž| _
        |	dkD  rt        |	«      | _        y t        j                  «       | _        y )Nr$   rì   )rT   rä   ro   rå   ræ   rç   rè   ré   )r   r  r  ré   r¸   r,   )r-   r.   r   Únorm1râ   r  Únorm2Únorm3r  ÚmlpÚnorm4r   r/   ÚIdentityr  )r6   rT   rä   ro   r  rå   rè   ræ   rç   r  r  ré   r%   r&   r7   r8   s                  €r9   r.   zGemma4Block.__init__æ  sî   ø€ ð  ¨Ñ/ˆÜ‰ÑÔÜ˜SÑ5 hÐ5°"Ñ5ˆŒ
Ü#ð 

ØØØØ%ØØØØ 3ñ

ð ñ

ˆŒ	ô ˜SÑ5 hÐ5°"Ñ5ˆŒ
Ü˜SÑ5 hÐ5°"Ñ5ˆŒ
Ü!ð 
ØØ-ØØ 3ñ	
ð
 ñ
ˆŒô ˜SÑ5 hÐ5°"Ñ5ˆŒ
Ø09¸C²œ )Ó,ˆ�ÄRÇ[Á[Ã]ˆ�r:   r@   r÷   rø   rù   c                 ó2  — |}| j                  |«      }| j                  ||||¬«      }| j                  |«      }|| j                  |«      z   }|}| j	                  |«      }| j                  |«      }| j                  |«      }|| j                  |«      z   }|S )N©rù   )r   r  r!  r  r"  r#  r$  )r6   r@   r÷   rø   rù   Úresiduals         r9   rE   zGemma4Block.forward  s’   € ð ˆØ�J‰J�q‹MˆØ�I‰I�a˜ 8°yˆIÓAˆØ�J‰J�q‹MˆØ�t—~‘~ aÓ(Ñ(ˆð ˆØ�J‰J�q‹MˆØ�H‰H�Q‹KˆØ�J‰J�q‹MˆØ�t—~‘~ aÓ(Ñ(ˆØˆr:   )	Nr  r¸   r¸   r¸   NFNNrB   )rG   rH   rI   rJ   rK   r   r>   r   rL   r.   r3   rM   rE   rN   rO   s   @r9   r  r  Þ  s
  ø„ ñð +/Ø"Ø"Ø"Ø"Ø,0Ø(-ØØñ(Sàð(Sð ð(Sð ð	(Sð
  #ð(Sð # 3™-ð(Sð ð(Sð ð(Sð ð(Sð ð(Sð   Ñ)ð(Sð "&ð(Sð 
õ(Sð^ 15ñà�|‰|ðð —l‘lðð —l‘lð	ð
   §¡Ñ-ðð 
�‰÷r:   r  c            
       ó"  ‡ — e Zd ZdZddedefˆ fd„Zdej                  dej                  deej                  ej                  f   fd„Z	dej                  dej                  d	ej                  deej                  ej                  f   fd
„Z
ˆ xZS )ÚGemma4VisionPooleru·   Spatial pooling for Gemma4 vision encoder output.

    Pools patches by averaging within kÃ—k grid cells based on position coordinates.
    Output is scaled by sqrt(hidden_size).
    Úhidden_sizeÚpooling_kernel_sizec                 óR   •— t         ‰| �  «        || _        |dz  | _        || _        y )NrÈ   )r-   r.   r+  Úroot_hidden_sizer,  )r6   r+  r,  r8   s      €r9   r.   zGemma4VisionPooler.__init__.  s+   ø€ Ü‰ÑÔØ&ˆÔØ +¨SÑ 0ˆÔØ#6ˆÕ r:   Úhidden_statesr€   r"   c           	      ón  — |j                   d   }| j                  }||z  }||z  dk7  rt        d|› d|› d|› d�«      ‚||z  }|j                  d¬«      }|d   j	                  d	d
¬«      d   dz   }t        j                  ||d¬«      }	|	d   ||z  |	d   z  z   }	t        j                  |	j                  «       |«      j                  «       |z  }
|
j                  dd«      |j                  «       z  }t        j                  |
dk(  j                  d¬«      «      }|j                  |j                  «      |fS )u@  2D spatial pooling on a ``k Ã— k`` grid (k = ``self.pooling_kernel_size``).

        ``N`` patches are binned into ``k^2``-sized cells, so the pool requires
        ``N % k^2 == 0`` (caller ensures both grid dims divide by k upstream).
        ``position_ids`` follows the Gemma4-internal ``(x, y)`` convention.
        r   r   zCannot pool z tokens with k=z: N must be divisible by k^2=z.. Both grid dimensions must be divisible by k.r³   ©.r   rQ   T©rT   ÚkeepdimÚfloor)Úrounding_mode©.r   rR   rS   )rU   r,  rÏ   rC   Úmaxr3   Údivr¹   rº   Úlongr>   r…   Úlogical_notrÐ   r„   r&   )r6   r/  r€   rØ   rj   Ú	k_squaredÚoutput_lengthr¾   Úmax_xÚkernel_idxsÚweightsÚoutputÚmasks                r9   Ú_avg_pool_by_positionsz)Gemma4VisionPooler._avg_pool_by_positions4  sY  € ð ×Ñ Ñ"ˆØ×$Ñ$ˆØ˜‘Eˆ	Øˆy‰=˜AÒÜØ˜q˜c °°Ð3PÐQZÐP[ð \?ð @óð ð ˜Y™ˆà(×.Ñ.°1Ð.Ó5ÐØ! &Ñ)×-Ñ-°"¸dÐ-ÓCÀAÑFÈÑJˆÜ—i‘iÐ 1°1ÀGÔLˆØ! &Ñ)¨U°a©Z¸;ÀvÑ;NÑ,NÑNˆä—)‘)˜K×,Ñ,Ó.°Ó>×DÑDÓFÈÑRˆØ×"Ñ" 1 aÓ(¨=×+>Ñ+>Ó+@Ñ@ˆÜ× Ñ  '¨Q¡,×!3Ñ!3¸Ð!3Ó!:Ó;ˆØ�y‰y˜×,Ñ,Ó-¨tÐ3Ð3r:   r±   c                 ó”   — |j                  |j                  d«      d«      }| j                  ||«      \  }}|| j                  z  }||fS )u  Spatial pool with ``pooling_kernel_size Ã— pooling_kernel_size`` cells.

        Args:
            hidden_states: (B, N, D) encoder output.
            position_ids: (B, N, 2) Gemma4-internal ``(x, y)`` coords.
            padding_positions: (B, N) True for padding tokens.

        Returns:
            pooled hidden states (B, N // k^2, D) and validity mask (B, N // k^2).
        rQ   r¸   )Úmasked_fillr^   rB  r.  )r6   r/  r€   r±   Úpooler_masks        r9   rE   zGemma4VisionPooler.forwardS  sV   € ð" &×1Ñ1Ð2C×2MÑ2MÈbÓ2QÐSVÓWˆØ%)×%@Ñ%@ÀÐP\Ó%]Ñ"ˆ�{Ø%¨×(=Ñ(=Ñ=ˆØ˜kÐ)Ð)r:   )r·   )rG   rH   rI   rJ   rK   r.   r3   rM   r
   rB  rE   rN   rO   s   @r9   r*  r*  '  sŸ   ø„ ññ7 Cð 7¸cõ 7ð4à Ÿ<™<ð4ð  Ÿ,™,ð4ð 
ˆu�|‰|˜UŸ\™\Ð)Ñ	*ó	4ð>*à Ÿ<™<ð*ð  Ÿ,™,ð*ð  %Ÿ|™|ð	*ð
 
ˆu�|‰|˜UŸ\™\Ð)Ñ	*÷*r:   r*  c            -       ó&  ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d<deeeeef   f   dededededed	ed
edee   dede	de	dedede
de
de	de	de	dee   deddf,ˆ fd„Zej                  j                  d=dede
ddfd„«       Zej                  j                  dee   fd„«       Zej                  j                  deeef   fd„«       Zej                  j                  d>de
deeef   fd „«       Zej                  j                  d?d!e
ddfd"„«       Zej                  j                  d?d#e
ddfd$„«       Zd%ej2                  ddfd&„Z	 	 d@d%ej2                  d'ej2                  d(ej2                  d)eeeej2                  gdf      d*ee   dej2                  fd+„Z	 	 d@d%eej2                  eeej2                  f   f   d,eej2                     d-eej2                     dej2                  fd.„Zd>d%ej2                  d/e
dej2                  fd0„Z	 	 d@d%eej2                  eeej2                  f   f   d,eej2                     d-eej2                     dej2                  fd1„Z	 	 	 	 	 	 	 	 dAd%eej2                  eeej2                  f   f   d,eej2                     d-eej2                     d2eeeee   f      d3e
d4e
d5ed6e
d7e
deeej2                     eej2                  eej2                     f   eeef   f   fd8„Z 	 	 	 dBd2eeee   f   d9e
d:e
dee   fd;„Z!ˆ xZ"S )Cr   u#  Gemma4 Vision Encoder.

    The pure encoder from Google's Gemma 4 multimodal model. Custom ViT with 2D
    RoPE, gated MLP, QKV normalization, and 4-norm sandwich blocks.

    When ``standardize=True`` (31B variant), ``std_bias/std_scale`` are applied
    after the soft-token pooler (original contract). Other pool modes don't apply it.
    Output shape depends on ``global_pool``:

    - ``'soft'`` (default): spatial ``kÃ—k`` pooler + ``âˆšD`` scale + optional
      standardization. Output ``(B, num_soft_tokens, embed_dim)``
    - ``'avg'``: masked mean over patch tokens; skips the pooler's ``âˆšD`` scale
      and standardization. Output ``(B, embed_dim)``.
    - ``'none'`` / ``''``: no pool â€” returns raw patch tokens
      ``(B, N, embed_dim)``. Useful for building custom pool heads.
    NÚimg_sizer’   r“   Úglobal_poolr”   Údepthrä   ro   rå   r  rè   rp   r•   r,  Ústandardizeré   Úproj_drop_rateÚattn_drop_rateÚdrop_path_rater  Úweight_initr"   c                 óX  •— ||dœ}t         ‰| �  «        |dv s
J d|›�«       ‚|| _        |x| _        x| _        | _        d| _        d| _        d| _        d| _	        t        |«      | _        || _        || _        |xs t        t        j                   d¬«      }t#        d| j                  |||d	œ|¤Ž| _        t'        d||d
œ|¤Ž| _        t+        j,                  d||«      D �cg c]  }|j/                  «       ‘Œ }}t        j0                  t3        |«      D �cg c]  }t5        d||||	|
|||||   ||dœ|¤Ž‘Œ c}«      | _        t9        ||¬«      | _        |rM| j=                  dt+        j>                  |fi |¤Ž«       | j=                  dt+        j>                  |fi |¤Ž«       nd | _         d | _!        tE        | j                  «      }t3        |«      D �cg c]  }tG        ||d|› �¬«      ‘Œ c}| _$        |dk(  rdn|| _%        |dk7  r| jM                  d¬«       y y c c}w c c}w c c}w )Nr$   )ÚsoftÚavgÚnoneÚ z>global_pool must be one of 'soft', 'avg', 'none' (or ''); got r   ÚNLCFr  r  )r’   r“   r”   r•   )ro   rp   )rT   rä   ro   rå   r  rè   ræ   rç   r  r  ré   )r+  r,  Ústd_biasÚ	std_scaleúblocks.)Únum_chsÚ	reductionÚmoduleÚskipÚreset©Úneeds_resetr,   )'r-   r.   rH  Únum_featuresÚhead_hidden_sizer”   r¶   Ú
output_fmtÚnum_prefix_tokensÚgrad_checkpointingr   r’   r,  ré   r   r/   r  r‘   Úpatch_embedrn   Ú
rotary_embr3   ÚlinspaceÚitemÚ
ModuleListrc   r  Úblocksr*  Úpoolerr2   r4   rU  rV  r7  rË   Úfeature_infoÚweight_init_modeÚinit_weights)r6   rG  r’   r“   rH  r”   rI  rä   ro   rå   r  rè   rp   r•   r,  rJ  ré   rK  rL  rM  r  rN  r%   r&   r7   r@   ÚdprrŠ   Ú_redr8   s                                €r9   r.   zGemma4VitEncoder.__init__|  so  ø€ ð4 ¨Ñ/ˆÜ‰ÑÔØÐ9Ñ9ð 	]ØLÈ[ÈOÐ\ó	]Ð9à&ˆÔØENÐNˆÔÐN˜DÔ1°D´NàˆÔð  ˆŒØ!"ˆÔØ"'ˆÔô $ JÓ/ˆŒØ#6ˆÔ Ø#6ˆÔ àÒE¤¬¯©¸fÔ!Eˆ	ô ,ð 
Ø—‘ØØØ$;ñ	
ð
 ñ
ˆÔô 2ð 
ØØ!ñ
ð ñ
ˆŒô "'§¡°°>À5Ó!IÖJ˜Aˆq�v‰v�xÐJˆÐJÜ—m‘mô ˜5“\ö%
ð ô ð ØØ#Ø!Ø)Ø"3Ø!Ø(Ø(Ø˜a™&Ø#Ø$7ñð óò%
ó ˆŒô& )Ø!Ø 3ô
ˆŒñ Ø× Ñ  ¬U¯[©[¸Ñ-IÀbÑ-IÔJØ× Ñ  ¬e¯k©k¸)Ñ.JÀrÑ.JÕKà ˆDŒMØ!ˆDŒNô
 �4—?‘?Ó#ˆÜdiÐjoÓdpÖqÐ_`œT¨)¸tÈgÐVWÐUXÈMÖZÒqˆÔà+6¸&Ò+@¡ÀkˆÔà˜&Ò Ø×Ñ¨%ÐÕ0ð !ùòW Kùò%
ùòL rs   Ã#HÄ!H"ÇH'Úmoder^  c                 ó2  — |xs | j                   }|dv sJ ‚| j                  �)t        j                  j	                  | j                  «       | j
                  �)t        j                  j                  | j
                  «       t        t        ||¬«      | «       y)a§  Initialize model weights.

        Args:
            mode: Init mode. '' applies trunc-normal-TF Linear init; 'reset'
                only calls ``reset_parameters`` on each sub-module.
            needs_reset: If True, call ``reset_parameters`` on modules that
                have one (for post-``to_empty()`` reinit). Set to False during
                ``__init__`` since modules already self-initialize there.
        )rS  r\  Nr]  )	rl  rU  r/   ÚinitÚzeros_rV  Úones_r   Úget_init_weights_gemma4_vit©r6   rp  r^  s      r9   rm  zGemma4VitEncoder.init_weightsë  ss   € ð Ò,�t×,Ñ,ˆØ�}Ñ$Ð$Ð$ð �=‰=Ð$Ü�G‰G�N‰N˜4Ÿ=™=Ô)Ø�>‰>Ð%Ü�G‰G�M‰M˜$Ÿ.™.Ô)äÔ/°À+ÔNÐPTÕUr:   c                 ó   — dhS )Nz$patch_embed.position_embedding_tabler,   r?   s    r9   Úno_weight_decayz Gemma4VitEncoder.no_weight_decay  s   € à6Ð7Ð7r:   c                 ó   — | j                   S ©zHReturn the 2-tuple patch size. For NaFlex dataloader / transform wiring.)r’   r?   s    r9   Úget_patch_sizezGemma4VitEncoder.get_patch_size  s   € ð �‰Ðr:   Úcoarsec                 ó    — t        dddg¬«      S )Nz^patch_embed|^rotary_emb)z^blocks\.(\d+)N)z^pooler|^std_)iŸ† ©Ústemri  ©rË   ©r6   r|  s     r9   Úgroup_matcherzGemma4VitEncoder.group_matcher  s   € äØ,Ø-Ð/KÐLô
ð 	
r:   Úenablec                 ó   — || _         y rB   )rc  ©r6   rƒ  s     r9   Úset_grad_checkpointingz'Gemma4VitEncoder.set_grad_checkpointing  s
   € à"(ˆÕr:   Úenabledc                 ó^   — | j                  «       D ]  }t        |t        «      sŒ||_        Œ y)aŸ  Toggle the ``Gemma4ClippableLinear`` clamp ops.

        Gemma4's pretrained E4B checkpoint ships finite clamp buffers on every
        projection, which can saturate and stall gradient flow during classifier
        fine-tuning. Setting ``enabled=False`` skips both the input and output
        clamps in the forward pass (buffers are left untouched so the call is
        reversible and checkpoint-safe).
        N)ÚmodulesrÊ   r   r!   )r6   r‡  Úmods      r9   Úset_clamp_enabledz"Gemma4VitEncoder.set_clamp_enabled  s+   € ð —<‘<“>ò 	*ˆCÜ˜#Ô4Õ5Ø")�•ñ	*r:   r@   c                 ó  — |j                   dk7  s| j                  dk7  ry|j                  dd \  }}| j                  \  }}| j                  }||z  ||z  }}||z  dk7  s||z  dk7  rt        d|› d|› d|› d|› d	|› d|› d
�«      ‚y)zäWhen using the soft-token pooler, raw-image H/W must divide
        by ``patch_size * pooling_kernel_size`` so the pool cell grid is integral.
        Pre-patchified / NaFlex inputs are assumed to be conformant already.
        rÃ   rP  Nrý   r   zImage size (z, z=) must be divisible by (patch_size * pooling_kernel_size) = (z3) when global_pool='soft'. Resize to multiples of (z#), or use global_pool='avg'/'none'.)r`   rH  rU   r’   r,  rÏ   )	r6   r@   rÖ   r×   rš   r›   rj   Úcell_hÚcell_ws	            r9   Ú_assert_raw_img_conformantz+Gemma4VitEncoder._assert_raw_img_conformant$  s¹   € ð
 �6‰6�QŠ;˜$×*Ñ*¨fÒ4ØØ�w‰w�r�sˆ|‰ˆˆ1Ø—‘‰ˆˆBØ×$Ñ$ˆØ˜a™  a¡�ˆØˆv‰:˜Š?˜a &™j¨AšoÜØ˜q˜c  A 3ð '9Ø9?¸ÀÀ6À(ð K+Ø+1¨(°"°V°HÐ<_ðaóð ð .r:   r€   r±   Úblock_callbackÚmax_block_indexc                 ó.  — |j                   dd \  }}| j                  ||«      \  }}	d}
|j                  «       rUt        j                  |dd||j
                  |j                  ¬«      }
|
j                  |dd…dddd…f   t        d«      «       |€| j                  }n| j                  d|dz    }t        |«      D ]W  \  }}| j                  r.t        j                  j                  «       st        ||||	|
«      }n ||||	|
¬«      }|€ŒO |||«       ŒY |S )z?RoPE + transformer-block pipeline over already-embedded tokens.NrR   r   r$   z-infr'  )rU   re  rÑ   r3   Úzerosr%   r&   Úmasked_fill_r>   ri  Ú	enumeraterc  r	  Úis_scriptingr   )r6   r@   r€   r±   r�  r‘  rÔ   rØ   r÷   rø   rù   ri  rŠ   Úblks                 r9   Ú_encodezGemma4VitEncoder._encode6  s  € ð �w‰w�r˜ˆ{‰ˆˆ1Ø!Ÿ_™_¨Q°Ó=Ñˆ�(à,0ˆ	Ø× Ñ Ô"äŸ™ A q¨!¨Q°q·x±xÀqÇwÁwÔOˆIØ×"Ñ"Ð#4²Q¸¸dÂAÐ5EÑ#FÌÈfËÔVàÐ"Ø—[‘[‰Fà—[‘[Ð!5 /°AÑ"5Ð6ˆFä Ó'ò 	%‰FˆAˆsØ×&Ò&¬u¯y©y×/EÑ/EÔ/GÜ˜s A x°¸9ÓE‘á˜˜8 X¸ÔC�ØÑ)Ù˜q !Õ$ð	%ð ˆr:   r®   r¯   c                 ó¢   — | j                  t        |t        «      s|n|d   «       | j                  |||«      \  }}}| j	                  |||«      S )z9Raw patch tokens pre-pool. Returns ``(B, N, embed_dim)``.rÂ   )r�  rÊ   rË   rd  r˜  )r6   r@   r®   r¯   r€   r±   s         r9   Úforward_featuresz!Gemma4VitEncoder.forward_featuresW  sQ   € ð 	×'Ñ'´¸A¼tÔ1D©È!ÈIÉ,ÔWØ-1×-=Ñ-=¸aÀÈkÓ-ZÑ*ˆˆ<Ð*Ø�|‰|˜A˜|Ð->Ó?Ð?r:   Ú
pre_logitsc                 ó   — t        d«      ‚)Nz;Gemma4VitEncoder does not support classification use cases.)ÚNotImplementedError)r6   r@   r›  s      r9   Úforward_headzGemma4VitEncoder.forward_headb  s   € Ü!Ð"_Ó`Ð`r:   c                 óZ  — | j                  t        |t        «      s|n|d   «       | j                  |||«      \  }}}| j	                  |||«      }| j
                  dk(  r@| j                  |||«      \  }}| j                  �|| j                  z
  | j                  z  }|S | j
                  dk(  r||j                  «       rZ|j                  |j                  d«      d«      }|j                  d¬«      | j                  dd¬	«      j                  d¬
«      z  }|S |j                  d¬«      }|S )u  Encode + apply the configured pool.

        Output shape depends on ``self.global_pool``:
          ``'soft'`` â†’ ``(B, num_soft_tokens, D)``
          ``'avg'``  â†’ ``(B, D)``
          ``'none'`` â†’ ``(B, N, D)`` (raw patch tokens, identical to forward_features)
        rÂ   rP  rQ  rQ   r¸   r   rS   Tr2  r³   )r�  rÊ   rË   rd  r˜  rH  rj  rU  rV  rÑ   rD  r^   r¼   rC   Úmean)r6   r@   r®   r¯   r€   r±   rÕ   s          r9   rE   zGemma4VitEncoder.forwarde  s+  € ð 	×'Ñ'´¸A¼tÔ1D©È!ÈIÉ,ÔWØ-1×-=Ñ-=¸aÀÈkÓ-ZÑ*ˆˆ<Ð*Ø�L‰L˜˜LÐ*;Ó<ˆà×Ñ˜vÒ%Ø—;‘;˜q ,Ð0AÓB‰DˆAˆqà�}‰}Ð(Ø˜Ÿ™Ñ&¨$¯.©.Ñ8�ð ˆð ×Ñ Ò&à ×$Ñ$Ô&Ø—M‘MÐ"3×"=Ñ"=¸bÓ"AÀ3ÓG�Ø—E‘E˜a�E“LÐ%6Ð$6×#;Ñ#;ÀÈ4Ð#;Ó#P×#VÑ#VÐ[\Ð#VÓ#]Ñ]�ð
 ˆð —F‘F˜q�F“M�ð ˆr:   ÚindicesÚnormÚ
stop_earlyra  Úintermediates_onlyÚoutput_dictc
           	      ój  ‡‡— |dv sJ ‚|dk(  }
t        t        | j                  «      |«      \  Š}t        |t        «      s|n|d   }|j
                  }| j                  |«       | j                  |||«      \  }}}g Šdt        dt        j                  ddfˆˆfd„}d}|r t        j                  j                  «       s|}| j                  |||||¬	«      }|
r»|d
k7  rt        d«      ‚|j                  d   }t        |d   j!                  «       j#                  «       «      dz   }t        |d   j!                  «       j#                  «       «      dz   }‰D �cg c]6  }|j%                  |||d«      j'                  dddd«      j)                  «       ‘Œ8 c}Š|	rd‰i}|s||d<   | |d<   |S |r‰S |‰fS c c}w )a  Forward features returning intermediates.

        Args:
            x: Input tensor ``(B, C, H, W)`` or NaFlex pre-patchified tensor/dict.
            patch_coord: ``(B, N, 2)`` patch coords in NaFlex external (y, x) convention.
            patch_valid: ``(B, N)`` boolean mask, True for valid tokens.
            indices: Block indices to return intermediates for.
            norm: Not used (no final norm in Gemma4 encoder).
            stop_early: Stop iterating after last needed intermediate.
            output_fmt: Output format ('NCHW' or 'NLC'). NCHW requires a fixed full grid.
            intermediates_only: Only return intermediate features.
            output_dict: Return a dict matching the NaFlexVit intermediates contract:
                'image_intermediates' (+ 'image_features' unless ``intermediates_only``) and
                'patch_valid' aligned with the token sequence (all-True for dense image input;
                gemma4 has no patch dropout, so it always equals the input validity).
        )ÚNCHWrT  r§  rÂ   rŠ   Úyr"   Nc                 ó2   •— | ‰v r‰j                  |«       y y rB   )r†   )rŠ   r¨  ÚintermediatesÚtake_indicess     €€r9   Ú_cbz3Gemma4VitEncoder.forward_intermediates.<locals>._cb®  s   ø€ Ø�LÑ Ø×$Ñ$ QÕ'ð !r:   )r�  r‘  rÃ   z:output_fmt='NCHW' requires a raw image (B, C, H, W) input.r   r1  r   r6  rQ   r·   rR   Úimage_intermediatesÚimage_featuresr¯   )r   Úlenri  rÊ   rË   r`   r�  rd  rK   r3   rM   r	  r–  r˜  rÏ   rU   r7  rg  rÍ   r»   Ú
contiguous)r6   r@   r®   r¯   r¡  r¢  r£  ra  r¤  r¥  rÍ   Ú	max_indexÚrawÚraw_input_ndimr€   r±   r¬  r‘  rÔ   r¢   r¡   r¨  Úresult_dictrª  r«  s                          @@r9   Úforward_intermediatesz&Gemma4VitEncoder.forward_intermediates‡  sØ  ù€ ð8 ˜_Ñ,Ð,Ð,Ø Ñ&ˆÜ"6´s¸4¿;¹;Ó7GÈÓ"QÑˆ�iä! !¤TÔ*‰a°°)±ˆØŸ™ˆØ×'Ñ'¨Ô,Ø-1×-=Ñ-=¸aÀÈkÓ-ZÑ*ˆˆ<Ð*à,.ˆð	(”3ð 	(œ5Ÿ<™<ð 	(¨Dö 	(ð ˆÙœeŸi™i×4Ñ4Ô6Ø'ˆOà�L‰LØØØØØ+ð ó 
ˆñ Ø Ò"Ü Ð!]Ó^Ð^à×"Ñ" 1Ñ%ˆAÜ�\ &Ñ)×-Ñ-Ó/×4Ñ4Ó6Ó7¸!Ñ;ˆBÜ�\ &Ñ)×-Ñ-Ó/×4Ñ4Ó6Ó7¸!Ñ;ˆBØ`mÖnÐ[\˜QŸY™Y q¨"¨b°"Ó5×=Ñ=¸aÀÀAÀqÓI×TÑTÕVÒnˆMáØ+@À-Ð*PˆKÙ%Ø01�Ð,Ñ-Ø*;Ð);ˆK˜Ñ&ØÐáØ Ð à�-ÐÐùò os   Å;F0Ú
prune_normÚ
prune_headc                 óx   — t        t        | j                  «      |«      \  }}| j                  d|dz    | _        |S )a  Prune layers not required for specified intermediates.

        ``prune_head`` is accepted for API compatibility; the encoder has no
        classifier head so it's a no-op here. (The wrapping ``Gemma4VitClassifier``
        handles its own head pruning.)
        Nr   )r   r¯  ri  )r6   r¡  r¶  r·  r«  r±  s         r9   Úprune_intermediate_layersz*Gemma4VitEncoder.prune_intermediate_layersÓ  s:   € ô #7´s¸4¿;¹;Ó7GÈÓ"QÑˆ�iØ—k‘k . 9¨q¡=Ð1ˆŒØÐr:   )rÝ   rÜ   r·   rP  rÝ   rÜ   r  r  Né   r  r�   rÞ   r·   FFr¸   r¸   r¸   NrS  NN©rS  T©F©Trß   )NNNFFr§  FF©r   FT)#rG   rH   rI   rJ   r   rK   r
   rà   r   r>   rL   r   r.   r3   r	  Úignorerm  r	   rx  r{  r   r   r‚  r†  r‹  rM   r�  r˜  rš  rž  rE   r   rµ  r¹  rN   rO   s   @r9   r   r   j  sI  ø„ ñð& 58Ø ØØ%Ø ØØØØ*.Ø%)Ø"Ø %Ø+0Ø'(Ø %Ø(-Ø$'Ø$'Ø$'Ø,0Ø!ØØñ1m1à˜C  s¨C x¡Ð0Ñ1ðm1ð ðm1ð ð	m1ð
 ðm1ð ðm1ð ðm1ð ðm1ð ðm1ð # 3™-ðm1ð  #ðm1ð ðm1ð ðm1ð &)ðm1ð "%ðm1ð  ð!m1ð" "&ð#m1ð$ "ð%m1ð& "ð'm1ð( "ð)m1ð*   Ñ)ð+m1ð, ð-m1ð2 
õ3m1ð^ ‡Y�Y×ÑñV ð V¸ð VÈò Vó ðVð, ‡Y�Y×Ñð8  S¡ò 8ó ð8ð ‡Y�Y×Ñð  c¨3 h¡ò ó ðð ‡Y�Y×Ññ
 Dð 
°T¸#¸s¸(±^ò 
ó ð
ð ‡Y�Y×Ññ)¨Tð )¸Tò )ó ð)ð ‡Y�Y×Ññ*¨ð *¸ò *ó ð*ð¨E¯L©Lð ¸Tó ð. MQØ-1ñà�|‰|ðð  Ÿ,™,ðð  %Ÿ|™|ð	ð
 % X¨s°E·L±LÐ.AÀ4Ð.GÑ%HÑIðð & c™]ðð 
�‰óðH 37Ø26ñ		@à�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ð	@ð " %§,¡,Ñ/ð	@ð " %§,¡,Ñ/ð		@ð
 
�‰ó	@ña˜eŸl™lð a¸ð aÈÏÉó að 37Ø26ñ	 à�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ð ð " %§,¡,Ñ/ð ð " %§,¡,Ñ/ð	 ð
 
�‰ó ðJ 37Ø26Ø7;ØØ$Ø$Ø',Ø %ñJ à�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ðJ ð " %§,¡,Ñ/ðJ ð " %§,¡,Ñ/ð	J ð
 ˜e C¨¨c© NÑ3Ñ4ðJ ð ðJ ð ðJ ð ðJ ð !%ðJ ð ðJ ð 
ˆt�E—L‘LÑ! 5¨¯©°t¸E¿L¹LÑ7IÐ)IÑ#JÈDÐQTÐVYÐQYÉNÐZÑ	[óJ ð\ ./Ø$Ø#ñ	à˜3  S¡	˜>Ñ*ðð ðð ð	ð
 
ˆc‰÷r:   c            5       óô  ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d;deeeeef   f   dededededed	ed
edededee   dede	de	dedede
de
de
de	de	de	de	dee   deddf4ˆ fd„Zej                  j                  d<dede
ddfd „«       Zej                  j                  dee   fd!„«       Zej                  j                  d=d"e
deeef   fd#„«       Zej                  j                  d>d$e
ddfd%„«       Zej                  j                  d>d&e
ddfd'„«       Zej                  j                  deeef   fd(„«       Zej                  j                  dej4                  fd)„«       Zd?dedee   ddfd*„Z	 	 d@d+eej:                  eeej:                  f   f   d,eej:                     d-eej:                     dej:                  fd.„Z	 	 dAd+ej:                  d-eej:                     d/e
dej:                  fd0„Z	 	 d@d+eej:                  eeej:                  f   f   d,eej:                     d-eej:                     dej:                  fd1„Z 	 	 	 	 	 	 	 dBd+eej:                  eeej:                  f   f   d,eej:                     d-eej:                     d2eeee!e   f      d3e
d4e
d5ed6e
dee!ej:                     eej:                  e!ej:                     f   f   fd7„Z"	 	 	 dCd2eee!e   f   d8e
d9e
de!e   fd:„Z#ˆ xZ$S )Dr   uú  Classification wrapper around ``Gemma4VitEncoder``.

    Holds:
        - ``encoder``: a ``Gemma4VitEncoder``. By default constructed with
          ``global_pool=''`` so the classifier does its own masked-mean pool
          over raw patch tokens in ``forward_head``. Pass
          ``encoder_pool='soft'`` to turn on the native VLM spatial ``kÃ—k``
          soft-token pool inside the encoder; ``forward_features`` then
          returns ``(B, num_soft_tokens, D)`` already pooled (plus the ``âˆšD``
          scale and, for the 31B variant, ``std_bias/std_scale``).
        - ``norm``: optional ``RmsNorm`` after pooling.
        - ``head``: linear classifier.

    Input/output contract matches timm convention: ``forward_features`` returns
    pre-head features (pre-pool ``(B, N, D)`` patch tokens by default, or
    ``(B, num_soft_tokens, D)`` post-soft-pool when ``encoder_pool='soft'``);
    ``forward_head`` does classifier pool + norm + head; ``forward`` =
    ``forward_features`` + ``forward_head``.
    NrG  r’   r“   r¶   rH  Úencoder_poolr”   rI  rä   ro   rå   r  rè   rp   r•   r,  rJ  ré   Ú
final_normÚ	drop_raterK  rL  rM  r  rN  r"   c                 ó(  •— ||dœ}t         ‰| �  «        |dv sJ d|›d�«       ‚|dv sJ d|›d�«       ‚|| _        || _        || _        t        d!i d|“d	|“d
|“d|“d|“d|“d|	“d|
“d|“d|“d|“d|“d|“d|“d|“d|“d|“d|“d|“d|“d|“|¤Ž| _        |rt        |f|ddœ|¤Žnt        j                  «       | _
        t        j                  |«      | _        |dkD  rt        j                  ||fi |¤Žnt        j                  «       | _        | j                  j                  x| _        | _        | j                  j"                  | _        | j                  j$                  | _        | j                  j&                  | _        | j                  j(                  | _        |d k7  rpt+        | j                  t        j                  «      rK| j                  j,                  �4t        j.                  j1                  | j                  j,                  «       y y y y )"Nr$   ©rQ  rR  rS  úBGemma4VitClassifier global_pool must be 'avg', 'none', or '' (got z>); use Gemma4VitEncoder directly for 'soft' VLM-style pooling.)rS  rR  rP  zDGemma4VitClassifier encoder_pool must be '', 'none', or 'soft' (got z).rG  r’   r“   rH  r”   rI  rä   ro   rå   r  rè   rp   r•   r,  rJ  ré   rK  rL  rM  r  rN  Frë   r   r[  r,   )r-   r.   r¶   rH  rÁ  r   Úencoderr   r/   r%  r¢  rö   Ú	head_dropr0   Úheadr_  r`  r”   r’   rk  rl  rÊ   r'   rr  rs  )r6   rG  r’   r“   r¶   rH  rÁ  r”   rI  rä   ro   rå   r  rè   rp   r•   r,  rJ  ré   rÂ  rÃ  rK  rL  rM  r  rN  r%   r&   r7   r8   s                                €r9   r.   zGemma4VitClassifier.__init__ù  sz  ø€ ð< ¨Ñ/ˆÜ‰ÑÔØÐ1Ñ1ð 	KØPÐQ\ÐP_ð `Jð Kó	KÐ1ð Ð3Ñ3ð 	fØRÐS_ÐRbÐbdÐeó	fÐ3à&ˆÔØ&ˆÔØ(ˆÔô (ò 
Ùð
á!ð
ñ ð
ñ %ð	
ñ
  ð
ñ ð
ñ  ð
ñ ð
ñ &ð
ñ 0ð
ñ ð
ñ "ð
ñ %<ð
ñ !4ð
ñ $ð
ñ  !4ð!
ñ" *ð#
ñ$ *ð%
ñ& *ð'
ñ(  ð)
ñ* $Øñ-
ˆŒñ0 MW”G˜IÐH¨8¸EÑHÀRÒHÔ\^×\gÑ\gÓ\iˆŒ	ÜŸ™ IÓ.ˆŒØ?JÈQº”B—I‘I˜i¨Ñ;¸Ò;ÔTV×T_ÑT_ÓTaˆŒ	ð 59·L±L×4MÑ4MÐMˆÔ˜DÔ1ØŸ™×/Ñ/ˆŒØŸ,™,×1Ñ1ˆŒØ ŸL™L×5Ñ5ˆÔà $§¡× =Ñ =ˆÔØ˜&Ò ä˜$Ÿ)™)¤R§Y¡YÔ/°D·I±I·N±NÐ4NÜ—‘—‘˜tŸy™yŸ~™~Õ.ð 5OÐ/ð !r:   rp  r^  c                 ó  — | j                   j                  ||¬«       t        | j                  t        j
                  «      rK| j                  j                  �4t        j                  j                  | j                  j                  «       yyy)z>Init encoder + classifier-specific pieces (head bias to zero).©rp  r^  N)	rÇ  rm  rÊ   rÉ  r/   r0   r'   rr  rs  rv  s      r9   rm  z Gemma4VitClassifier.init_weightsL  s[   € ð 	�‰×!Ñ! t¸Ð!ÔEÜ�d—i‘i¤§¡Ô+°·	±	·±Ð0JÜ�G‰G�N‰N˜4Ÿ9™9Ÿ>™>Õ*ð 1KÐ+r:   c                 ób   — | j                   j                  «       D �ch c]  }d|› �’Œ	 c}S c c}w )Núencoder.)rÇ  rx  )r6   rj   s     r9   rx  z#Gemma4VitClassifier.no_weight_decayS  s)   € à(,¯©×(DÑ(DÓ(FÖG 1�(˜1˜#’ÒGÐGùÒGs   �,r|  c                 ó   — t        ddg¬«      S )Nz*^encoder\.patch_embed|^encoder\.rotary_emb)z^encoder\.blocks\.(\d+)Nr~  r€  r�  s     r9   r‚  z!Gemma4VitClassifier.group_matcherW  s   € ô Ø>Ø6Ð7ô
ð 	
r:   rƒ  c                 ó:   — | j                   j                  |«       y rB   )rÇ  r†  r…  s     r9   r†  z*Gemma4VitClassifier.set_grad_checkpointing_  s   € à�‰×+Ñ+¨FÕ3r:   r‡  c                 ó:   — | j                   j                  |«       y rB   )rÇ  r‹  )r6   r‡  s     r9   r‹  z%Gemma4VitClassifier.set_clamp_enabledc  s   € à�‰×&Ñ& wÕ/r:   c                 ó6   — | j                   j                  «       S rz  )rÇ  r{  r?   s    r9   r{  z"Gemma4VitClassifier.get_patch_sizeg  s   € ð �|‰|×*Ñ*Ó,Ð,r:   c                 ó   — | j                   S rB   )rÉ  r?   s    r9   Úget_classifierz"Gemma4VitClassifier.get_classifierl  s   € à�y‰yÐr:   c                 óœ  — || _         |�|dv sJ d|›d�«       ‚|| _        |dkD  r t        j                  | j                  |«      nt        j
                  «       | _        t        | j                  t        j                  «      rK| j                  j                  �4t        j                  j                  | j                  j                  «       y y y )NrÅ  rÆ  ú)r   )r¶   rH  r/   r0   r”   r%  rÉ  rÊ   r'   rr  rs  )r6   r¶   rH  s      r9   Úreset_classifierz$Gemma4VitClassifier.reset_classifierp  s§   € Ø&ˆÔØÐ"ØÐ"5Ñ5ð fØTÐU`ÐTcÐcdÐeófÐ5à*ˆDÔØ>IÈAºo”B—I‘I˜dŸn™n¨kÔ:ÔSU×S^ÑS^ÓS`ˆŒ	Ü�d—i‘i¤§¡Ô+°·	±	·±Ð0JÜ�G‰G�N‰N˜4Ÿ9™9Ÿ>™>Õ*ð 1KÐ+r:   r@   r®   r¯   c                 ó„   — | j                   dk(  r| j                  |||¬«      S | j                  j                  |||¬«      S )u]  Pre-head features.

        Shape depends on ``encoder_pool``:
          ``''`` / ``'none'``: raw patch tokens ``(B, N, embed_dim)``.
          ``'soft'``: spatial ``kÃ—k`` soft-token pool output
              ``(B, num_soft_tokens, embed_dim)`` (with ``âˆšD`` scale + optional
              ``std_bias/std_scale`` baked in by the encoder).
        rP  ©r®   r¯   )rÁ  rÇ  rš  )r6   r@   r®   r¯   s       r9   rš  z$Gemma4VitClassifier.forward_featuresz  sD   € ð ×Ñ Ò&Ø—<‘< ¨{È�<ÓTÐTØ�|‰|×,Ñ,¨Q¸KÐU`Ð,ÓaÐar:   r›  c                 ó†  — | j                   dk(  r|| j                  dk(  s|€|j                  d¬«      }nX|j                  | j	                  d«      d«      }|j                  d¬«      |j                  dd¬«      j                  d¬	«      z  }| j                  |«      }| j                  |«      }|r|S | j                  |«      S )
uì  Pool (if configured) â†’ norm â†’ head_drop â†’ head.

        Args:
            x: pre-head features from ``forward_features``.
            patch_valid: ``(B, N)`` valid mask for masked mean over raw patch
                tokens. Ignored when ``encoder_pool='soft'`` (the soft pooler
                has already collapsed padding tokens, and the new token count
                no longer aligns with ``patch_valid``).
            pre_logits: If True, return pre-classifier features.
        rQ  rP  r   rS   rQ   r¸   Tr2  r³   )
rH  rÁ  r   rD  r^   r¼   rC   r¢  rÈ  rÉ  )r6   r@   r¯   r›  s       r9   rž  z Gemma4VitClassifier.forward_headŒ  s±   € ð  ×Ñ˜uÒ$Ø× Ñ  FÒ*¨kÐ.AØ—F‘F˜q�F“M‘à—M‘M K <×":Ñ":¸2Ó">ÀÓD�Ø—E‘E˜a�E“L ;§?¡?°qÀ$ ?Ó#G×#MÑ#MÐRSÐ#MÓ#TÑT�à�I‰I�a‹LˆØ�N‰N˜1ÓˆÙˆqÐ0 D§I¡I¨a£LÐ0r:   c                 ó  — t        |t        «      r)|j                  d|«      }|j                  d|«      }|d   }|€*|�(|dk(  j                  d¬«      }|j	                  «       r| }| j                  |||¬«      }| j                  ||¬«      S )Nr®   r¯   rÂ   rQ   rS   rØ  )r¯   )rÊ   rË   rÌ   rÐ   rÑ   rš  rž  )r6   r@   r®   r¯   rÛ   Úfeatss         r9   rE   zGemma4VitClassifier.forward§  s—   € ô �aœÔØŸ%™% ¨{Ó;ˆKØŸ%™% ¨{Ó;ˆKØ�)‘ˆAØÐ ;Ð#:Ø# rÑ)×.Ñ.°2Ð.Ó6ˆHØ�|‰|Œ~Ø'˜i�à×%Ñ% a°[ÈkÐ%ÓZˆØ× Ñ  °KÐ Ó@Ð@r:   r¡  r¢  r£  ra  r¤  c	           
      óH   — | j                   j                  ||||||||¬«      S )N)r®   r¯   r¡  r¢  r£  ra  r¤  )rÇ  rµ  )	r6   r@   r®   r¯   r¡  r¢  r£  ra  r¤  s	            r9   rµ  z)Gemma4VitClassifier.forward_intermediatesÀ  s8   € ð �|‰|×1Ñ1ØØ#Ø#ØØØ!Ø!Ø1ð 2ó 	
ð 		
r:   r¶  r·  c                 óh   — | j                   j                  ||d¬«      }|r| j                  d«       |S )NF)r¶  r·  r   )rÇ  r¹  rÖ  )r6   r¡  r¶  r·  r«  s        r9   r¹  z-Gemma4VitClassifier.prune_intermediate_layersÖ  s8   € ð —|‘|×=Ñ=¸gÐR\ÐinÐ=ÓoˆÙØ×!Ñ! !Ô$ØÐr:   )rÝ   rÜ   r·   iè  rQ  rS  rÝ   rÜ   r  r  Nrº  r  r�   rÞ   r·   FFTr¸   r¸   r¸   r¸   NrS  NNr»  r¼  r½  rB   rß   )NF)NNNFFr§  Fr¾  )%rG   rH   rI   rJ   r   rK   r
   rà   r   r>   rL   r   r.   r3   r	  r¿  rm  r	   rx  r   r   r‚  r†  r‹  r{  r/   ÚModulerÓ  rÖ  rM   rš  rž  rE   r   rµ  r¹  rN   rO   s   @r9   r   r   ä  s6  ø„ ñð, 58Ø ØØ#Ø$Ø "Ø ØØØØ*.Ø%)Ø"Ø %Ø+0Ø'(Ø %Ø(-Ø#Ø"Ø$'Ø$'Ø$'Ø,0Ø!ØØñ9Q/à˜C  s¨C x¡Ð0Ñ1ðQ/ð ðQ/ð ð	Q/ð
 ðQ/ð ðQ/ð ðQ/ð ðQ/ð ðQ/ð ðQ/ð ðQ/ð # 3™-ðQ/ð  #ðQ/ð ðQ/ð ðQ/ð  &)ð!Q/ð" "%ð#Q/ð$ ð%Q/ð& "&ð'Q/ð( ð)Q/ð* ð+Q/ð, "ð-Q/ð. "ð/Q/ð0 "ð1Q/ð2   Ñ)ð3Q/ð4 ð5Q/ð: 
õ;Q/ðf ‡Y�Y×Ññ+ ð +¸ð +Èò +ó ð+ð ‡Y�Y×ÑðH  S¡ò Hó ðHð ‡Y�Y×Ññ
 Dð 
°T¸#¸s¸(±^ò 
ó ð
ð ‡Y�Y×Ññ4¨Tð 4¸Tò 4ó ð4ð ‡Y�Y×Ññ0¨ð 0¸ò 0ó ð0ð ‡Y�Y×Ñð-  c¨3 h¡ò -ó ð-ð ‡Y�Y×Ñð §	¡	ò ó ðñ+¨Cð +¸hÀs¹mð +ÐW[ó +ð 37Ø26ñ	bà�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ðbð " %§,¡,Ñ/ðbð " %§,¡,Ñ/ð	bð
 
�‰óbð* 37Ø$ñ	1à�|‰|ð1ð " %§,¡,Ñ/ð1ð ð	1ð
 
�‰ó1ð< 37Ø26ñ	Aà�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ðAð " %§,¡,Ñ/ðAð " %§,¡,Ñ/ð	Að
 
�‰óAð8 37Ø26Ø7;ØØ$Ø$Ø',ñ
à�U—\‘\ 4¨¨U¯\©\Ð(9Ñ#:Ð:Ñ;ð
ð " %§,¡,Ñ/ð
ð " %§,¡,Ñ/ð	
ð
 ˜e C¨¨c© NÑ3Ñ4ð
ð ð
ð ð
ð ð
ð !%ð
ð 
ˆt�E—L‘LÑ! 5¨¯©°t¸E¿L¹LÑ7IÐ)IÑ#JÐJÑ	Kó
ð0 ./Ø$Ø#ñ		à˜3  S¡	˜>Ñ*ð	ð ð	ð ð		ð
 
ˆc‰÷	r:   TrZ  Únamer^  c                 óN  — t        | t        j                  «      rNt        | j                  d¬«       | j
                  �*t        j                  j                  | j
                  «       yyt        | d«      r| j                  «        y|rt        | d«      r| j                  «        yyy)a  Per-module init for Gemma4Vit (trunc-normal-TF for Linear weights).

    Args:
        module: Module to initialize.
        name: Dotted module name (from ``named_apply``).
        needs_reset: If True, call ``reset_parameters`` on modules that define one.
    r�   rž   Nrm  r5   )rÊ   r/   r0   r   rÒ   r'   rr  rs  Úhasattrrm  r5   )rZ  rß  r^  s      r9   Úinit_weights_gemma4_vitrâ  â  sy   € ô �&œ"Ÿ)™)Ô$Ü˜Ÿ™¨DÕ1Ø�;‰;Ð"Ü�G‰G�N‰N˜6Ÿ;™;Õ'ð #ä	�˜Ô	(Ø×ÑÕÙ	œ Ð);Ô<Ø×ÑÕ!ð =ˆr:   rp  c                 ó$   — t        t        |¬«      S )Nr]  )r   râ  rË  s     r9   ru  ru  ô  s   € äÔ*¸ÔDÐDr:   Ú
state_dictÚmodelc                 óØ  — i }d}| j                  «       D ]Ò  \  }}d}|D ]  }|j                  |«      sŒ|} n |€|j                  d«      r|||<   Œ=|t        |«      d }d|v rŒP|j                  dd«      }|j                  dd«      }|j                  d	d
«      }|j                  dd«      }|j                  dd«      }|j                  dd«      }|j                  dd«      }|||<   ŒÔ |S )u¿  Convert HuggingFace Gemma4 vision encoder weights â†’ ``Gemma4VitEncoder`` keys.

    Pure key remapping â€” no value transforms. The encoder consumes patches in
    HF's native C-P-P flat layout (via ``batch_patchify(channels_last=False)``
    in ``Gemma4PatchEmbed``), so ``input_proj.weight`` passes through unchanged.
    ``Gemma4ClippableLinear`` preserves HF's ``.linear.weight`` + clamp-buffer
    structure, so those pass through too.
    )zmodel.vision_tower.zmodel.vision_model.zvision_model.zvision_tower.N)úpatch_embed.rW  Ústd_zpooler.zrotary_emb.re  zpatch_embedder.rç  zencoder.layers.rW  z.input_layernorm.z.norm1.z.post_attention_layernorm.z.norm2.z.pre_feedforward_layernorm.z.norm3.z.post_feedforward_layernorm.z.norm4.z.self_attn.z.attn.)ÚitemsÚ
startswithr¯  Úreplace)	rä  rå  Úout_dictÚhf_prefixesrj   r  Úmatched_prefixÚprefixÚnew_ks	            r9   Úcheckpoint_filter_fn_encoderrñ  ù  s  € ð €HØb€Kà× Ñ Ó"ò ‰ˆˆ1ØˆØ!ò 	ˆFØ�|‰|˜FÕ#Ø!'�Ùð	ð
 Ð!à�|‰|ÐYÔZØ�˜‘Øà”#�nÓ%Ð&Ð'ˆð ˜5Ñ Øà—‘Ð/°Ó@ˆØ—‘Ð/°Ó;ˆØ—‘Ð1°9Ó=ˆØ—‘Ð:¸IÓFˆØ—‘Ð;¸YÓGˆØ—‘Ð<¸iÓHˆØ—‘˜m¨XÓ6ˆàˆ�Šð7ð: €Or:   c                 ó¢  — d}| j                  «       D ��ci c]*  \  }}|j                  |«      s|j                  d«      r||“Œ, }}}| j                  «       D ��ci c]  \  }}||vsŒ||“Œ }}}t        ||j                  «      }|j                  «       D ��ci c]  \  }}d|› �|“Œ }}}|j	                  |«       |S c c}}w c c}}w c c}}w )uZ  Convert HF or timm-encoder state dict â†’ ``Gemma4VitClassifier`` keys.

    Runs the encoder filter, then prefixes every encoder-owned key with
    ``encoder.``. Top-level keys that belong to the classifier (``norm.*``,
    ``head.*``) pass through unchanged â€” they're absent from HF checkpoints, so
    the model's own init values stand.
    )znorm.zhead.rÍ  )ré  rê  rñ  rÇ  Úupdate)	rä  rå  Úclassifier_local_prefixesrj   r  Úclassifier_localÚ	to_filterÚencoder_dictÚprefixeds	            r9   Úcheckpoint_filter_fn_classifierrù  (  sÜ   € ð !3ÐØ)3×)9Ñ)9Ó);÷ `¡  AØŸ<™<Ð(AÔBÀaÇlÁlÐS]ÔF^ð ˜1™ð `Ðñ `à",×"2Ñ"2Ó"4×R™$˜!˜Q¸ÐAQÒ8Q��A‘ÐR€IÑRä/°	¸5¿=¹=ÓI€LØ.:×.@Ñ.@Ó.B×C¡d a¨�(˜1˜#� Ñ!ÐC€HÑCØ‡O�OÐ$Ô%Ø€Oùó`ùãRùó Ds   –/B?ÁCÁ(CÂCFÚvariantÚ
pretrainedc                 óp   — |j                  dd«      }t        t        | |ft        t	        |d¬«      ddœ|¤ŽS )NÚout_indicesr·   Úgetter©rý  Úfeature_clsrµ   )Úpretrained_filter_fnÚfeature_cfgÚkwargs_filter)Úpopr   r   rñ  rË   ©rú  rû  Úkwargsrý  s       r9   Ú_create_gemma4_vit_encoderr  @  sI   € Ø—*‘*˜]¨AÓ.€KÜÜØØðô :Ü [¸hÔGØ&ñð ñð r:   c                 ón   — |j                  dd«      }t        t        | |ft        t	        |d¬«      dœ|¤ŽS )Nrý  r·   rþ  rÿ  )r  r  )r  r   r   rù  rË   r  s       r9   Ú_create_gemma4_vit_classifierr	  M  sF   € Ø—*‘*˜]¨AÓ.€KäÜØØðô =Ü [¸hÔGñð ñð r:   Úurlc                 ó$   — | dddd dddddd	d
dœ|¥S )Nr   )r·   rÝ   rÝ   )r·   é`   r  rw   ÚbicubicF)r¸   r¸   r¸   )rw   rw   rw   zpatch_embed.input_projrÉ  )r
  r¶   Ú
input_sizeÚmin_input_sizeÚ	pool_sizeÚcrop_pctÚinterpolationÚfixed_input_sizer   rŸ   Ú
first_convÚ
classifierr,   )r
  r  s     r9   Ú_cfgr  Z  s>   € àØØ#ð &ØØØ"Ø!ð
  ØØ.Øñ'ð( ð)ð r:   z"timm/gemma4_vit_167m.gemma4_e4b_itzencoder.patch_embed.input_projz
apache-2.0)Ú	hf_hub_idr  Úlicensez"timm/gemma4_vit_570m.gemma4_31b_itz&timm/gemma4_vit_167m_enc.gemma4_e4b_it)r  r  z&timm/gemma4_vit_570m_enc.gemma4_31b_it)zgemma4_vit_167m.gemma4_e4b_itzgemma4_vit_570m.gemma4_31b_itz!gemma4_vit_167m_enc.gemma4_e4b_itz!gemma4_vit_570m_enc.gemma4_31b_itrÝ   rÜ   r  r  rº  )r”   rI  rä   ro   r  rJ  ré   i€  é   éH   iÐ  )r”   rI  rä   ro   r  rJ  c           	      óR   — t        t        d¬«      }t        dd| it        |fi |¤Ž¤ŽS )zöGemma4 ~167M (E2B/E4B  vision tower) classifier.

    Masked mean pool over patch tokens + norm + linear classifier. Output:
    ``(B, num_classes)``. For the native VLM encoder interface (soft-token
    output), use ``gemma4_vit_167m_enc``.
    T©rÂ  rû  )Úgemma4_vit_167m)rË   Ú
_167M_ARCHr	  ©rû  r  Ú
model_argss      r9   r  r  Ÿ  s0   € ô ”j¨TÔ2€JÜ(ÑpÀzÐpÔUYÐZdÑUoÐhnÑUoÑpÐpr:   c           	      óR   — t        t        d¬«      }t        dd| it        |fi |¤Ž¤ŽS )u  Gemma4 ~167M (E2B/E4B vision tower) â€” native VLM encoder.

    ``global_pool='soft'`` applies the spatial ``kÃ—k`` soft-token pool + âˆšD
    scale; output: ``(B, num_soft_tokens, embed_dim)``. Bit-perfect with HF
    ``Gemma4VisionModel`` on matching weights.
    rP  ©rH  rû  )Úgemma4_vit_167m_enc)rË   r  r  r  s      r9   r#  r#  «  ó0   € ô ”j¨fÔ5€JÜ%ÑqÈ
ÐqÔVZÐ[eÑVpÐioÑVpÑqÐqr:   c           	      óR   — t        t        d¬«      }t        dd| it        |fi |¤Ž¤ŽS )ag  Gemma4 ~570M (26B/31B vision tower) classifier.

    Masked mean pool over patch tokens + norm + linear classifier. Output:
    ``(B, num_classes)``. The classifier uses ``encoder.forward_features`` and
    does its own pool + norm; the encoder's ``std_bias/std_scale`` (which only
    applies in ``'soft'`` pool mode) is not used on the classifier path.
    Tr  rû  )Úgemma4_vit_570m)rË   Ú
_570M_ARCHr	  r  s      r9   r&  r&  ·  s0   € ô ”j¨TÔ2€JÜ(ÑpÀzÐpÔUYÐZdÑUoÐhnÑUoÑpÐpr:   c           	      óR   — t        t        d¬«      }t        dd| it        |fi |¤Ž¤ŽS )u  Gemma4 ~570M (26B/31B vision tower) â€” native VLM encoder.

    ``global_pool='soft'`` output ``(B, num_soft_tokens, embed_dim)`` with
    ``std_bias/std_scale`` standardization applied post-pool (HF-native
    ordering â€” bit-perfect with ``Gemma4VisionModel``).
    rP  r"  rû  )Úgemma4_vit_570m_enc)rË   r'  r  r  s      r9   r)  r)  Ä  r$  r:   )rR   )rR   rR   r»  r¼  )rS  )IrJ   ÚmathÚ	functoolsr   Útypingr   r   r   r   r   r	   r
   r   r3   Útorch.nnr/   Útorch.nn.functionalÚ
functionalr¹   Ú	timm.datar   r   Útimm.layersr   r   r   r   r   Ú_builderr   Ú	_featuresr   Ú_manipulater   r   Ú	_registryr   r   Ú	naflexvitr   Ú__all__rÞ  r   rM   rY   rK   r_   rl   rn   r‘   râ   r  r  r*  r   r   rà   rL   râ  ru  rñ  rù  r  r	  r  Údefault_cfgsrË   r  r'  r  r#  r&  r)  r,   r:   r9   ú<module>r9     sæ  ðñ	ó Ý ß I× IÓ Iã Ý ß Ð ç Aß VÕ Vå *Ý +ß 0ß <Ý %àÐ4Ð
5€ô*˜BŸI™Iô *ðZ(�5—<‘<ð ( E§L¡Ló (ð ñ		.Ø�<‰<ð	.à�\‰\ð	.ð �\‰\ð	.ð ð		.ð
 ‡\�\ó	.ð  Øñ&Ø�<‰<ð&à�\‰\ð&ð �\‰\ð&ð ð	&ð
 ð&ð ‡\�\ó&ô4M˜bŸi™iô Mô`O2�r—y‘yô O2ôdc�b—i‘iô côLX�R—Y‘Yô Xô8F�"—)‘)ô FôR@*˜Ÿ™ô @*ôFw�r—y‘yô wôt{˜"Ÿ)™)ô {ñ|" B§I¡Ið "°Sð "ÈDð "Ð\`ó "ñ$E cð E¸Tð EÈXó Eð
,Ø˜˜eŸl™lÐ*Ñ+ð,àð,ð 
ˆ#ˆu�|‰|Ð
Ñó,ð^Ø˜˜eŸl™lÐ*Ñ+ðà$ðð 
ˆ#ˆu�|‰|Ð
Ñóñ0
¨ð 
¸ð 
ÐTdó 
ñ
¨3ð 
¸Dð 
ÐWjó 
ñˆcð  T¨#¨s¨(¡^ó ñ2 %á%)Ø6Ø3Øô&ñ
 &*Ø6Ø3Øô&ñ *.Ø:Øô*ñ *.Ø:Øô*ñ#&ó €ñ0 ØØ
ØØØØØô€
ñ ØØ
ØØØØô€
ð ñq ð qÐ;Nò qó ðqð ñr Dð rÐ?Oò ró ðrð ñ	q ð 	qÐ;Nò 	qó ð	qð ñr Dð rÐ?Oò ró ñrr:   