
    ^j5                        d Z ddlmZ ddlZddlmc mZ d
ddZ	 	 d	 	 	 	 	 	 	 	 	 ddZ		 d
	 	 	 	 	 	 	 	 	 	 	 ddZ
	 d
	 	 	 	 	 	 	 	 	 ddZ	 d
	 	 	 	 	 	 	 ddZ	 d
	 	 	 	 	 	 	 dd	Zy)u  Vision utility functions for pre-computing very dynamic and
data-dependent tensors that can break model graph capturing.

All functions are standalone (no model weights) and compute tensors from
`grid_thw` + config scalars. They are used by vision encoders and can be
precomputed before `torch.compile` / `torch.export` tracing since they
use untraceable ops (`repeat_interleave`, `.tolist()`, `nonzero()`, loops).

Each `get_*` accepts an optional `kwargs` dict; if it contains the
precomputed tensor under the natural key (`"cu_seqlens"`, `"position_ids"`,
…), the function pops and returns it instead of computing. Vision encoders
write `x = get_vision_x(..., kwargs=kwargs)` and the matching key is
removed from the caller's kwargs as a side-effect of the pop.
    )annotationsNc                P   ||j                  dd      x}|S t        j                  | dddf   | dddf   z  | dddf         j                  dt        j                  j                         r| j                  nt        j                        }t        j                  |dd      S )	u  Get cumulative sequence lengths from vision grid info, or pop from `kwargs` if precomputed.

    Args:
        grid_thw: `(num_images_or_videos, 3)` — temporal, height, width per entry.
        kwargs: optional caller kwargs — if it contains `"cu_seqlens"` it is popped and returned.

    Returns:
        `cu_seqlens`: `(total_patches + 1,)` int32 cumulative sequence boundaries.
    N
cu_seqlens      r   )dimdtype)r   r   )value)
poptorchrepeat_interleavecumsumjit
is_tracingr	   int32Fpad)grid_thwkwargsr   s      d/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/transformers/vision_utils.pyget_vision_cu_seqlensr   #   s     VZZd-KKzX((!Q$(1a4.)H(STVWSW.Y``uyy';';'=X^^5;; a J 55V1--    c           
        ||j                  dd      x}|S | j                  }t        |t              r0t	        j
                  |g|      j                  t        |             }g }t        | j                         |j                               D ]e  \  \  }}}}	t	        j                  t	        j                  ||      t	        j                  ||      d      \  }
}||	z  |	||	z  |	f}|
j                  |      j                  dd      j                         }
|j                  |      j                  dd      j                         }|rrt	        j                  ||      j                  ||z        }|j!                  t	        j"                  ||
j%                  |      |j%                  |      gd	             .|j!                  t	        j"                  |
|gd	      j%                  |d             h t	        j&                  |d
	      S )u  Get position IDs for vision rotary embeddings, or pop from `kwargs` if precomputed.

    Args:
        grid_thw: `(num_images_or_videos, 3)`
        spatial_merge_size: merge block size — either a single `int` (same for all images)
            or a `(num_images_or_videos,)` tensor (per-image).
        kwargs: optional caller kwargs — if it contains `"position_ids"` it is popped and returned.
        include_temporal: when ``True``, prepend a temporal-index column and return
            `(total_tokens, 3)` — for encoders whose rotary embedding rotates T/H/W axes
            (minimax_m3_vl). When ``False`` (default), return `(total_tokens, 2)` for the
            2-axis (h, w) case (qwen2_5_vl / qwen3_vl / glm4v / paddleocr_vl); the h/w
            indices are still repeated ``t`` times for video inputs.

    Returns:
        `position_ids`: `(total_tokens, 3)` long if ``include_temporal`` else `(total_tokens, 2)`,
        with the spatial indices laid out block-major over ``m×m`` spatial-merge blocks.
    Nposition_idsdeviceij)indexingr   r   r   r   )r   r   
isinstanceintr   tensorexpandlenziptolistmeshgridarangereshape	transposeflattenr   appendstackrepeatcat)r   spatial_merge_sizeinclude_temporalr   r   r   thw
merge_sizehpos_idswpos_idsblock_shapetpos_idss                 r   get_vision_position_idsr;   5   s   . vzz.$/OO|\__F$c*"\\+=*>vNUUVYZbVcdL!$X__%68J8Q8Q8S!T X	Aq:"^^LL6*LL6*
(
 J
AOZP##K0::1a@HHJ##K0::1a@HHJ||Af5GGANHXxq7I8??[\K],^df ghXx,@b I P PQRTU VWX 99\q))r   c                L   |,|j                  dd      }|j                  dd      }||||fS g }dg}d}||z  |z  }|dz  }	| j                         D ]o  \  }
}}t        |
      t        |      t        |      }}}
||z  }||z  }t        j                  |
|z  |z        j                  |
||      }|||z  z
  }|||z  z
  }||z   |z  }||z   |z  }t        j                  |d|d|fdd      }|j                  |
||||      }|j                  ddd	dd
      j                  |
||z  ||      }|dk7  j                  dd	g      j                  d      }|j                  d      }||dk7     }|j                  ||z          |j                  d      |	z  |d   z   }|j                  |j                                ||
|z  |z  z  }r t        j                  |d      }t        j                  || j                  t        j                         }t        j"                  |      }||fS )u  Get window attention indices, or pop `"window_index"`/`"cu_window_seqlens"` from `kwargs` if both precomputed.

    Args:
        grid_thw: `(num_images_or_videos, 3)`
        spatial_merge_size: merge block size from vision config.
        window_size: window size from vision config.
        patch_size: patch size from vision config.
        kwargs: optional caller kwargs — if it contains both `"window_index"` and `"cu_window_seqlens"` they are popped and returned.

    Returns:
        `window_index`: `(total_tokens,)` long — reorder indices for windowed attention.
        `cu_window_seqlens`: `(num_windows + 1,)` int32 — cumulative window boundaries.
    Nwindow_indexcu_window_seqlensr   r   constantir         r   r    )r   r	   )r   r'   r"   r   r)   r*   r   r   permutesumr-   r   extendr0   r#   r   r   unique_consecutive)r   r1   window_size
patch_sizer   r=   r>   window_index_idvit_merger_window_sizespatial_merge_unitgrid_tgrid_hgrid_w
llm_grid_h
llm_grid_windexpad_hpad_wnum_windows_hnum_windows_windex_paddedseqlens	index_newcu_seqlens_tmps                           r   get_vision_window_indexrY   f   s   ( zz.$7"JJ':DA#(9(E!222L cO(,>>*L+Q."*//"3 <!$Vc&k3v;11
11
Vj0:=>FFvz[ef&6L)LL&6L)LL#e+0FF#e+0FFuuUQq%$8*dK#++M#9=J`
 $++Aq!Q:BBMM13IKa
  4',,aV4<<R@#++B/ !56	I78 *-??BSTVBWW  !6!6!896J.;;-<0 99\q1L%6xV[VaVab001BC***r   c           	     |   |,|j                  dd      }|j                  dd      }||||fS |}|}| j                  }t        d      D 	cg c]  }	g  }
}	t        d      D 	cg c]  }	g  }}	| j                         D ]  \  }}}t	        |      t	        |      t	        |      }}}t        j                  d|dz
  ||      }t        j                  d|dz
  ||      }|j	                         }|j	                         }|dz   j                  |dz
        }|dz   j                  |dz
        }||z
  }||z
  }||z  }||z  }|dddf   |dddf   z   j                         |dddf   |dddf   z   j                         |dddf   |dddf   z   j                         |dddf   |dddf   z   j                         g}d|z
  dddf   d|z
  dddf   z  j                         d|z
  dddf   |dddf   z  j                         |dddf   d|z
  dddf   z  j                         |dddf   |dddf   z  j                         g}t        j                  ||      j                  ||z  |      }t        j                  ||      j                  ||z  |      }|ddddddf   |z  |ddddddf   z   j                  dd	      j                         j                  |      }t        d      D ]6  }|
|   j                  ||   |          ||   j                  ||   |          8  t        j                  |
D cg c]  }t        j                  |       c}      }t        j                  |D cg c]  }t        j                  |       c}      }||fS c c}	w c c}	w c c}w c c}w )
u  Get bilinear interpolation indices/weights, or pop `"bilinear_indices"`/`"bilinear_weights"` from `kwargs` if both precomputed.

    Args:
        grid_thw: `(num_images_or_videos, 3)`
        num_grid_per_side: `int(num_position_embeddings ** 0.5)` from vision config.
        spatial_merge_size: merge block size from vision config.
        kwargs: optional caller kwargs — if it contains both `"bilinear_indices"` and `"bilinear_weights"` they are popped and returned.

    Returns:
        `bilinear_indices`: `(4, total_thw)` long — bilinear corner indices into pos_embed table.
        `bilinear_weights`: `(4, total_thw)` float — interpolation weights.
    Nbilinear_indicesbilinear_weightsrA   r   r   r   )maxr   )r   r   ranger'   r"   r   linspaceclampr,   r)   viewr+   r/   r-   r.   r0   ) r   num_grid_per_sider1   r   r[   r\   sider6   r   _	idx_partsweight_partsr3   r4   r5   h_gridw_gridh_floorw_floorh_ceilw_ceilh_fracw_frach_floor_offseth_ceil_offsetcorner_indicescorner_weightsh_idxw_idxreorderips                                    r   'get_vision_bilinear_indices_and_weightsrx      s   $ !::&8$?!::&8$?',<,H#%555D#J__F7<Qx*@!2*@I*@:?(-CQb-CL-C??$ $?1aa&#a&#a&a14!8Qv>4!8Qv>**,**,A+$$$2A+$$$2'!'! 4 AtG$wtQw'77@@BAtG$vdAg6??A1d7#gdAg&66??A1d7#fT1Wo5>>@	
 &j!T'"a&j$'%::CCE&j!T'"VD!G_4==?AtG_F
D!G44==?AtG_vdAg.779	
 Qv.33AOZPQv.33AOZPAtT)*Q.tT1a7G1HHSSTUWXYaacjjklmq 	?AaLq 1' :;O"">!#4W#=>	?E$?L {{)#DQEIIaL#DE{{,#GQEIIaL#GH---W +A-CP $E#Gs   	N*$	N/N4N9c                2   ||j                  dd      x}|S | j                  }t        j                  d|z  dd|z  |      }g }| j	                         D ]  \  }}t        |      t        |      }}t        j                  ||      |z  }	t        j                  ||      |z  }
t        j                  |	|d      }t        j                  |
|d      }|j                  |dddf   |z  |z   j                                 t        j                  |      S )u  Get nearest-neighbor position IDs into a `num_patches_per_side**2` 2-D table, or pop
    from `kwargs` if precomputed.

    For each image of size `(h, w)`, maps fractional grid coordinates `i/h` to the nearest
    bucket on a `num_patches_per_side` grid (via `bucketize`) and flattens to 1-D embedding
    indices, concatenated across all images. Used by NaViT-style packers (e.g. MiniCPM-V).

    Args:
        target_sizes: `(num_images, 2)` int — `(h, w)` per image.
        num_patches_per_side: side length of the learned 2-D position-embedding grid.
        kwargs: optional caller kwargs — if it contains `"position_ids"` it is popped and returned.

    Returns:
        `position_ids`: `(sum(h_i * w_i),)` long — flat indices into a `num_patches_per_side**2` table.
    Nr   r   g      ?r   T)right)
r   r   r   r)   r'   r"   	bucketizer-   r,   r0   )target_sizesnum_patches_per_sider   pos_idsr   
boundariespos_ids_listheightwidthh_coordsw_coordsbucket_hbucket_ws                r   get_vision_nearest_position_idsr      s   $ &**^T*JJwW  Fa"66QAU=U^deJL%,,. ]FSZ<<v6?<<f5=??8ZtD??8ZtDXag.1EEPYY[\] 99\""r   c                    ||j                  dd      x}|S |\  }}t        | d   j                               |z  t        | d   j                               |z  fS )u  Get post-window-merge `(merged_h, merged_w)` Python ints, or pop from `kwargs` if precomputed.

    `.view()` needs Python ints, but `target_sizes[0].item()` is non-traceable. Callers must pop
    the precomputed value from `kwargs` when running under `torch.export`. Assumes uniform
    `target_sizes` across the batch (standard NaViT preprocessing output).

    Args:
        target_sizes: `(num_images, 2)` int — `(h, w)` per image.
        window_kernel_size: `(window_h, window_w)` window-attention kernel.
        kwargs: optional caller kwargs — if it contains `"merged_shape"` it is popped and returned.

    Returns:
        `(merged_h, merged_w)`: per-image grid size after window merging, as Python ints.
    Nmerged_shape)r   r   )r   r   )r   r"   item)r|   window_kernel_sizer   mergedwindow_hwindow_ws         r   get_vision_merged_shaper     sj    " ND)IIvV+Hh|D!&&()X5s<;M;R;R;T7UYa7aaar   )N)r   torch.Tensorr   dict | Nonereturnr   )FN)
r   r   r1   zint | torch.Tensorr2   boolr   r   r   r   )r   r   r1   r"   rF   r"   rG   r"   r   r   r   !tuple[torch.Tensor, torch.Tensor])
r   r   rb   r"   r1   r"   r   r   r   r   )r|   r   r}   r"   r   r   r   r   )r|   r   r   tuple[int, int]r   r   r   r   )__doc__
__future__r   r   torch.nn.functionalnn
functionalr   r   r;   rY   rx   r   r    r   r   <module>r      s9   #   .* #	.*.**.* .* 	.*
 .*l :+:+:+ :+ 	:+
 :+ ':+B 	F.F.F. F. 	F.
 'F.T RV##69#CN##D \`bb4CbMXbbr   