+
    œ°³jf±  ã                  ó4  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t	^ RI
Ht ^ RIHt ^RIHt ^RIHt ^RIHt ]P(                  ! ]4      t]! 4       '       d   ^ RIt^RIHt ^R	IHtHtHtHtHtH t  / t!R
]"R&   / t#R]"R&   / t$R]"R&   ]PJ                  R R l4       t&]PJ                  R R l4       t']PJ                  R R l4       t(R R lt)R R lt*R R lt+R R lt,R R lt-R R  lt.]/3t0R!]"R"&   ]! 4       '       d6   ]0]Pb                  ]Pd                  ]Pf                  ]Ph                  3,          t0R# R$ lt5RXR% R& llt6R' R( lt7R) R* lt8R+ R, lt9R- R. lt:R/ R0 lt;RYt<R1 R2 lt=R3 R4 lt>/ t?R5]"R6&   R7 R8 lt@]@! R94      R: R; l4       tA]@! R<4      R= R> l4       tB]@! R?R@4      RA RB l4       tC]@! R?RC4      RD RE l4       tDRF RG ltE]PJ                  RH RI l4       tFRJ RK ltGRL RM ltHRZRN RO lltIR[tJR\tKRP RQ ltLRR RS ltMRT RU ltNRZRV RW lltOR# )]ué  Shared export utilities used by all exporter backends.

Organised into five sections (search for the `# â”€â”€ Name â”€â”€` banners):

- **Patch and fix registries** â€” backend-keyed `_PATCHES` / `_FX_NODE_FIXES` /
  `_FX_PROGRAM_FIXES` populated via `@register_patch(backend, *paths)` /
  `@register_fx_node_fix` / `@register_fx_program_fix`, applied via
  `apply_patches` / `apply_fx_node_fixes` / `apply_fx_program_fixes`.
- **Recursive structure traversal** â€” internal helpers (`_map_leaf_tensors`,
  `_iter_leaf_tensors`) that drive every other tensor utility.
- **Public tensor utilities** â€” `get_leaf_tensors`, `duplicate_leaf_tensors`,
  `cast_leaf_tensors`, and `prepare_for_export` (sets attention/experts impl,
  patches non-exportable patterns, strips output flags).
- **Export input preparers** â€” `@register_export_input_preparer(marker)`
  registry that precomputes the per-encoder kwargs (`cu_seqlens`, `position_ids`,
  audio chunks, â€¦) the model would otherwise need data-dependent ops for.
- **Decomposition** â€” `decompose_prefill_decode` (split a generative forward
  into prefill + decode) and `decompose_multimodal` + `is_multimodal` (split a
  multimodal forward into one entry per submodule), backed by `_capture_forward`.
)ÚannotationsN)ÚMutableMapping)ÚAny)Úlogging)Úget_max_seqlen)Úis_torch_available)ÚPreTrainedModel)Úget_vision_attention_seqlensÚ,get_vision_interpolation_indices_and_weightsÚget_vision_merged_shapeÚget_vision_nearest_position_idsÚget_vision_position_idsÚget_vision_window_indexz*dict[str, list[tuple[Any, str, callable]]]Ú_PATCHESzdict[str, list[callable]]Ú_FX_NODE_FIXESÚ_FX_PROGRAM_FIXESc               ó$   € V ^8„  d   QhRRRRRR/# )é   Úobjr   Ú	attributeÚstrÚfactory© )Úformats   "Ú]/home/luca/screen-checking/.venv/lib/python3.14/site-packages/transformers/exporters/utils.pyÚ__annotate__r   S   s!   € ÷ *ñ *˜ð *¨ð *°sñ *ó    c              #  óŒ   "  € \        W4      p\        WV! V4      4        Rx € \        WV4       R#   \        YT4       i ; i5i)zNSwap `obj.<attribute>` with `factory(original)` for the duration of the block.N)ÚgetattrÚsetattr)r   r   r   Úoriginals   &&& r   Úpatch_attributer!   R   s<   é € ô �sÓ&€HÜˆC™G HÓ-Ô.ð*Ûä� Ö)øŒ� Õ)üs   ‚A¡3 ¥A³AÁAc               ó   € V ^8„  d   QhRR/# )r   Úpatcheszlist[tuple[Any, str, callable]]r   )r   s   "r   r   r   ^   s   € ÷ 	ñ 	Ð=ñ 	r   c           
   #  óØ   "  € \         P                  ! 4       ;_uu_ 4       pV  F!  w  r#pVP                  \        W#V4      4       K#  	  Rx € RRR4       R#   + '       g   i     R# ; i5i)uå   Install `(obj, attribute, factory)` patches for the duration of the block.

Plural form of `patch_attribute` â€” each `factory(original)` returns the replacement
callable. Originals are restored on exit, even if the body raises.
N)Ú
contextlibÚ	ExitStackÚenter_contextr!   )r#   Ústackr   r   r   s   &    r   Úpatch_attributesr)   ]   sM   é € ô 
×	Ò	×	Ô	 5Û'.Ñ#ˆC˜GØ×Ñ¤°ÀÓ HÖIñ (/ã÷ 
 ×	×	Ò	üs   ‚A* ,AÁ
A*ÁA'	Á!	A*c               ó   € V ^8„  d   QhRR/# ©r   Úbackendr   r   )r   s   "r   r   r   k   s   € ÷ ñ ˜3ñ r   c              #  óž   "  € \        \        P                  V . 4      4      ;_uu_ 4        Rx € RRR4       R#   + '       g   i     R# ; i5i)z:Install `_PATCHES[backend]` for the duration of the block.N)r)   r   Úget)r,   s   &r   Úapply_patchesr/   j   s.   é € ô 
œ(Ÿ,™, w°Ó3×	4Õ	4Û÷ 
5×	4×	4Ò	4üs   ‚(Aª9¯
A¹A
	Á	Ac               ó   € V ^8„  d   QhRR/# r+   r   )r   s   "r   r   r   q   s   € ÷ ñ  #ñ r   c                ó   a € V 3R lpV# )zKAppend the decorated `(gm, node) -> bool` fix to `_FX_NODE_FIXES[backend]`.c                óR   <€ \         P                  S. 4      P                  V 4       V # ©N)r   Ú
setdefaultÚappend©Úfnr,   s   &€r   Ú	decoratorÚ'register_fx_node_fix.<locals>.decoratort   s#   ø€ Ü×!Ñ! '¨2Ó.×5Ñ5°bÔ9Øˆ	r   r   ©r,   r8   s   f r   Úregister_fx_node_fixr;   q   s   ø€ õð Ðr   c               ó   € V ^8„  d   QhRR/# r+   r   )r   s   "r   r   r   {   s   € ÷ ñ  Sñ r   c                ó   a € V 3R lpV# )u  Append the decorated `(exported_program) -> None` fix to `_FX_PROGRAM_FIXES[backend]`.

Use this for fixes that need program-level context (range_constraints, graph_signature,
state_dict) â€” the per-node `_FX_NODE_FIXES` shape only sees one node at a time.
c                óR   <€ \         P                  S. 4      P                  V 4       V # r3   )r   r4   r5   r6   s   &€r   r8   Ú*register_fx_program_fix.<locals>.decorator‚   s#   ø€ Ü×$Ñ$ W¨bÓ1×8Ñ8¸Ô<Øˆ	r   r   r:   s   f r   Úregister_fx_program_fixr@   {   s   ø€ õð Ðr   c               ó    € V ^8„  d   QhRRRR/# ©r   r,   r   ÚreturnÚNoner   )r   s   "r   r   r   ‰   s   € ÷ ñ  Cð ¸dñ r   c                óP   € \         P                  V . 4       F  pV! V4       K  	  R# )zDApply `_FX_PROGRAM_FIXES[backend]` to `exported_program` (in place).N)r   r.   )r,   Úexported_programÚfixs   && r   Úapply_fx_program_fixesrH   ‰   s"   € ä ×$Ñ$ W¨bÖ1ˆÙÐÖó 2r   c               ó    € V ^8„  d   QhRRRR/# )r   r,   r   Úpathsr   )r   s   "r   r   r   �   s   € ÷ ñ ˜Cð ¨ñ r   c                ó   a a€ V V3R lpV# )uE  Append the decorated `factory(original)` to `_PATCHES[backend]`, once per `path`.

Each `path` is a dotted Python path like `"torch.where"`, `"torch.Tensor.unsqueeze"`,
or `"transformers.models.nllb_moe.modeling_nllb_moe.NllbMoeTop2Router._cast_classifier"`.
The rightmost segment is the attribute to swap; the rest is the object that owns it.
Paths are resolved at decoration time â€” submodules are imported as needed, falling
back to `getattr` for class attributes. A path that fails to resolve (e.g. the backend
isn't installed) is silently skipped so the module still imports.

Passing multiple paths registers the SAME factory against each â€” useful for swapping
the same method or torch op across several call sites (e.g. ``torch.unsqueeze`` +
``torch.Tensor.unsqueeze``, or one vision-attention forward across N model classes).
c                ó²   <€ S FO  pVP                  R 4      w  r#p\        V4      pVf   K(  \        P                  S. 4      P	                  WTV 34       KQ  	  V # )Ú.)Ú
rpartitionÚ_resolve_dotted_pathr   r4   r5   )r7   ÚpathÚobj_pathÚ_r   r   r,   rJ   s   &     €€r   r8   Ú!register_patch.<locals>.decoratorž   sY   ø€ ÛˆDØ%)§_¡_°SÓ%9Ñ"ˆH˜Ü& xÓ0ˆCØŠ{ÙÜ×Ñ ¨Ó,×3Ñ3°SÀRÐ4HÖIñ ð ˆ	r   r   )r,   rJ   r8   s   fj r   Úregister_patchrT   �   s   ù€ öð Ðr   c               ó   € V ^8„  d   QhRR/# )r   rP   r   r   )r   s   "r   r   r   ª   s   € ÷ ñ ˜sñ r   c                ó:  € ^ RI pV P                  R4      p VP                  V^ ,          4      pVR,           F$  p VP                  VP                   RV 24      pK&  	  V#   \        \
        3 d    \        Y44      p KI  i ; i  \        \
        3 d     R# i ; i)uñ   Resolve a dotted Python path to the actual object â€” importing submodules where
possible, falling back to `getattr` for class attributes (e.g. `torch.Tensor`).
Returns `None` if the path can't be resolved (e.g. the backend isn't installed).NrM   :é   NN)Ú	importlibÚsplitÚimport_moduleÚ__name__ÚImportErrorÚAttributeErrorr   )rP   rX   Úpartsr   Úparts   &    r   rO   rO   ª   s    € ó à�J‰J�s‹O€Eð	Ø×%Ñ% e¨A¥hÓ/ˆØ˜"—I�IˆDð)Ø×-Ñ-°·±°¸aÀ¸vÐ.FÓG’ñ ð
 ˆ
øô  ¤Ð0ô )Ü˜cÓ(“ð)ûô œÐ(ô Úðús4   —$B ¼ A"ÁB Á"BÁ>B ÂBÂB ÂBÂBc               ó    € V ^8„  d   QhRRRR/# rB   r   )r   s   "r   r   r   ½   s   € ÷ ñ  ð °tñ r   c                óä  € \         P                  V . 4      pVP                  4        F­  p\        V\        P
                  P                  4      '       g   K/  \        VP                  P                  4       F0  pVP                  R8w  d   K  V F  pV! W44      '       g   K   K.  	  K2  	   VP                  P                  4        VP                  4        K¯  	  R#   \        \        3 d     KÇ  i ; i)uŽ  Walk every call_function node and apply the first matching `_FX_NODE_FIXES[backend]`
fix, then DCE.

Each fix has signature `(gm, node) -> bool`. Returning `True` means the fix consumed
the node â€” no further fixes run against it. Fixes are expected to be disjoint by
`node.target`; if multiple could apply, list order decides.

After the walk, `Graph.eliminate_dead_code` runs on every sub-GraphModule and
`gm.recompile()` is called once. PyTorch DCE occasionally raises `SystemError` /
`KeyError` from `erase_node._update_args_kwargs` on orphaned symbolic-size nodes â€”
we swallow both; any survivors are handled by the downstream backend optimizer.
Úcall_functionN)r   r.   ÚmodulesÚ
isinstanceÚtorchÚfxÚGraphModuleÚlistÚgraphÚnodesÚopÚeliminate_dead_codeÚ	recompileÚSystemErrorÚKeyError)r,   Úgraph_moduleÚfixesÚgmÚnoderG   s   &&    r   Úapply_fx_node_fixesrt   ½   s¶   € ô ×Ñ˜w¨Ó+€EØ×"Ñ"Ö$ˆÜ˜"œeŸh™h×2Ñ2×3Ò3ÙÜ˜Ÿ™Ÿ™Ö(ˆDØ�w‰w˜/Ô)ÙÛ�Ù�r—=”=Úó ñ )ð	Ø�H‰H×(Ñ(Ô*Ø�L‰LŽNó %øô œXÐ&ô 	Úð	ús   Â**CÃC/Ã.C/ztuple[type, ...]Ú_LEAF_SKIP_TYPESc               ó$   € V ^8„  d   QhRRRRRR/# )r   r   r   r7   ÚcallablerC   r   )r   s   "r   r   r   ç   s!   € ÷ ñ ˜3ð  Hð °ñ r   c           	     ó  a€ \        V \        4      '       d   V # \        V \        P                  4      '       d	   S! V 4      # \        V \        \
        \        34      '       d   \        V 4      ! V3R lV  4       4      # \        V \        4      '       d)   \	        V 4       F  p\        W,          S4      W&   K  	  V # \        V R4      '       d9   \        V 4      P                  4        F  w  r4\        W\        VS4      4       K  	  V # )u�  Apply `fn` to every tensor in a nested structure, preserving container types.

Mutates dicts and `__dict__`-bearing objects in place (preserving identity â€” callers
rely on this so downstream pops/mutations propagate back to the original mapping);
rebuilds lists/tuples/sets/frozensets (immutable or order-sensitive containers).
Skips non-traversable leaf types (enum, SymInt, etc.).
c              3  ó<   <"  € T F  p\        VS4      x € K  	  R # 5ir3   ©Ú_map_leaf_tensors)Ú.0Úitemr7   s   & €r   Ú	<genexpr>Ú$_map_leaf_tensors.<locals>.<genexpr>ô   s   øé € ÐEÁ¸Ô*¨4°×4Ð4Ãùs   ƒÚ__dict__)rd   ru   re   ÚTensorrh   ÚtupleÚsetÚtypeÚdictr{   ÚhasattrÚvarsÚitemsr   )r   r7   ÚkÚattrÚattr_vals   &f   r   r{   r{   ç   sÆ   ø€ ô �#Ô'×(Ò(Øˆ
Ü�#”u—|‘|×$Ò$Ù�#‹wˆÜ�#œœe¤SÐ)×*Ò*Ü�CŒyÔEÁÓEÓEÐEÜ�#”t×ÒÜ�c–ˆAÜ& s¥v¨rÓ2ˆC‹Fñ àˆ
Üˆs�J×ÒÜ" 3›iŸo™oÖ/‰NˆDÜ�CÔ0°¸2Ó>Ö?ñ 0à€Jr   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   Úprefixr   r   )r   s   "r   r   r   ÿ   s   € ÷ 9ñ 9˜Cð 9¨ñ 9r   c              #  ó‚  "  € \        V \        4      '       d   R# \        V \        P                  4      '       d   T;'       g    RV 3x € R# \        V \        \
        \        34      '       dD   \        V 4       F2  w  r#V'       d   V RV 2M
\        V4      p\        W44       Rj  x€L
  K4  	  R# \        V \        4      '       d@   V P                  4        F)  w  rVV'       d   V RV 2MTp\        Wd4       Rj  x€L
  K+  	  R# \        V R4      '       d    \        \        V 4      V4       Rj  x€L
  R# R#  L’ L? L5i)zEYield `(dotted_path, tensor)` for every tensor in a nested structure.NÚoutputrM   r€   )rd   ru   re   r�   rh   r‚   rƒ   Ú	enumerater   Ú_iter_leaf_tensorsr…   rˆ   r†   r‡   )r   r�   Úindexr}   rP   ÚkeyÚvalues   &&     r   r‘   r‘   ÿ   sü   é € ä�#Ô'×(Ò(ÙÜ�#”u—|‘|×$Ò$Ø× Ð ˜ #Ð%Ô%Ü	�Cœ$¤¤sÐ+×	,Ò	,Ü$ Sž>‰KˆEß*0�f�X˜Q˜u˜gÑ&´c¸%³jˆDÜ)¨$Ó5×5Ò5ó *ô 
�Cœ×	Ò	ØŸ)™)ž+‰JˆCß(.�f�X˜Q˜s˜eÑ$°CˆDÜ)¨%Ó6×6Ò6ó &ô 
��j×	!Ò	!Ü%¤d¨3£i°Ó8×8Ò8ñ 
"ñ 6ñ 7á8ùs>   ‚AD?ÁA"D?Â&D9Â'AD?Ã;D;Ã<4D?Ä0D=Ä1	D?Ä;D?Ä=D?c               ó    € V ^8„  d   QhRRRR/# )r   r   r   rC   zdict[str, torch.Tensor]r   )r   s   "r   r   r     s   € ÷ 
)ñ 
)˜#ð 
)Ð"9ñ 
)r   c                ó*   € \        \        V 4      4      # )a  Recursively retrieve all leaf tensors from a potentially nested structure.

Args:
    obj (`Any`):
        A tensor, dataclass, dict, list, tuple, or any nesting thereof.

Returns:
    `dict[str, torch.Tensor]`: Flat mapping from dotted path strings to tensors.
)r…   r‘   )r   s   &r   Úget_leaf_tensorsr—     s   € ô Ô" 3Ó'Ó(Ð(r   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   rC   r   )r   s   "r   r   r   "  s   € ÷ *ñ * ð *¨ñ *r   c                ó@   a€ \        4       oR V3R llp\        W4      # )a€  Clone tensors that appear more than once in an output structure.

When a model returns the same tensor under two output names (e.g. `last_hidden_state`
and `hidden_states[0]`), the ONNX optimizer deduplicates the two output nodes and
renames one, breaking the expected name mapping. Cloning duplicates gives each output
leaf a distinct identity so the optimizer has nothing to merge.
c               ó    € V ^8„  d   QhRRRR/# ©r   Útensorztorch.TensorrC   r   )r   s   "r   r   Ú,duplicate_leaf_tensors.<locals>.__annotate__,  s   € ÷ ñ �|ð ¨ñ r   c                ó|   <€ \        V 4      S9   d   V P                  4       # SP                  \        V 4      4       V # r3   )ÚidÚcloneÚadd)rœ   Úseens   &€r   Ú_dedupÚ&duplicate_leaf_tensors.<locals>._dedup,  s0   ø€ Üˆf‹:˜ÔØ—<‘<“>Ð!Ø�‰”�F“ÔØˆr   )rƒ   r{   )r   r£   r¢   s   & @r   Úduplicate_leaf_tensorsr¥   "  s#   ø€ ô ‹5€D÷ð ô ˜SÓ)Ð)r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   r   Údtypeztorch.dtypeÚdeviceztorch.devicerC   r   )r   s   "r   r   r   5  s(   € ÷ )ñ )˜3ð ) {ð )¸Lð )ÈSñ )r   c                ó0   aa€ R VV3R llp\        W4      # )zJRecursively cast all floating-point tensors to the given dtype and device.c               ó    € V ^8„  d   QhRRRR/# r›   r   )r   s   "r   r   Ú'cast_leaf_tensors.<locals>.__annotate__8  s   € ÷ qñ q�lð q |ñ qr   c                óz   <€ V P                  4       '       d   V P                  SSR 7      # V P                  SR7      # )©r§   r¨   )r¨   )Úis_floating_pointÚto)rœ   r¨   r§   s   &€€r   Ú_castÚ cast_leaf_tensors.<locals>._cast8  s9   ø€ Ø8>×8PÑ8P×8RÒ8Rˆv�y‰y˜u¨VˆyÓ4ÐpÐX^×XaÑXaÐioÐXaÓXpÐpr   rz   )r   r§   r¨   r°   s   &ff r   Úcast_leaf_tensorsr²   5  s   ù€ ÷qñ qô ˜SÓ(Ð(r   c               ó    € V ^8„  d   QhRRRR/# )r   Úmodelú!PreTrainedModel | torch.nn.ModulerC   ztorch.device | Noner   )r   s   "r   r   r   >  s   € ÷ 	ñ 	Ð:ð 	Ð?Rñ 	r   c                óª   € \        V R4      '       d   V P                  #  \        V P                  4       4      P                  #   \         d     R# i ; i)a  `.device` for any `nn.Module`. `PreTrainedModel` exposes it directly via `ModuleUtilsMixin`;
for plain submodules (e.g. a `Linear` or `MultiModalProjector` from a decomposed multimodal model)
we fall back to the first parameter. Returns `None` if the module has no parameters at all.r¨   N)r†   r¨   ÚnextÚ
parametersÚStopIteration©r´   s   &r   Úmodule_devicer»   >  sL   € ô ˆu�h×ÒØ�|‰|ÐðÜ�E×$Ñ$Ó&Ó'×.Ñ.Ð.øÜô Úðúó    "A ÁAÁAc               ó    € V ^8„  d   QhRRRR/# )r   r´   rµ   rC   ztorch.dtype | Noner   )r   s   "r   r   r   J  s   € ÷ ñ Ð9ð Ð>Pñ r   c                óª   € \        V R4      '       d   V P                  #  \        V P                  4       4      P                  #   \         d     R# i ; i)zE`.dtype` for any `nn.Module`. Same fallback story as `module_device`.r§   N)r†   r§   r·   r¸   r¹   rº   s   &r   Úmodule_dtyper¿   J  sJ   € äˆu�g×ÒØ�{‰{ÐðÜ�E×$Ñ$Ó&Ó'×-Ñ-Ð-øÜô Úðúr¼   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r´   rµ   ÚinputszMutableMapping[str, Any]rC   zRtuple[PreTrainedModel | torch.nn.Module, MutableMapping[str, Any], dict[str, Any]]r   )r   s   "r   r   r   X  s$   € ÷ 4'ñ 4'Ø,ð4'Ø6Nð4'àWñ4'r   c                óf  € R F+  pVP                  VR4      pVf   K  \        RV RV R24      h	  \        V R4      '       d)   \        V P                  RR4      '       d   \        R4      hVP                  RR4      '       d   \        R	4      h\         Uu/ uF  qDV9   g   K  WAP                  V4      bK  	  pp\        P                  ! 4       ;_uu_ 4        \        W4       RRR4       \        V 4      p\        V 4      pVf   Ve   \        WVR
7      pWV3# u upi   + '       g   i     LD; i)u
  Configure model and inputs for export. Mutates both `model` and `inputs` in place,
returning `(model, inputs, output_flags)` where `output_flags` holds the values popped
from `inputs` for `use_cache`, `return_dict`, etc. (to be applied reversibly onto
`model.config` by `patch_model_config` during the trace).

- Strips label inputs (`labels`, `future_values`) â€” loss computation is unsupported.
- Pops output flags (`use_cache`, `return_dict`, â€¦) from `inputs` so they don't appear
  as traced kwargs; the values are returned for the trace block to apply onto
  `model.config`.
- Pre-computes data-dependent vision/audio kwargs registered via
  `@register_export_input_preparer` and writes them into `inputs`.
- Casts input tensors to match the model's `dtype` / `device`.
NzFound 'zM' in inputs. Loss computation is not supported during export. Please remove 'z+' from your inputs before calling export().ÚconfigÚreturn_lossFzœFound 'model.config.return_loss=True'. Loss computation is not supported during export. Please set 'model.config.return_loss=False' before calling export().z•Found 'return_loss=True' in inputs. Loss computation is not supported during export. Please remove 'return_loss' from your inputs or set it to False.r­   )ÚlabelsÚfuture_values)ÚpopÚ
ValueErrorr†   r   rÃ   r.   Ú_OUTPUT_FLAGSre   Úno_gradÚprecompute_export_inputsr¿   r»   r²   )r´   rÁ   Ú	label_keyr”   ÚflagÚoutput_flagsr§   r¨   s   &&      r   Úprepare_for_exportrÏ   X  s0  € ó" 1ˆ	Ø—
‘
˜9 dÓ+ˆØÔÜØ˜)˜ð %"Ø"+ Ð,WðYóð ñ 1ô ˆu�h×Ò¤G¨E¯L©L¸-È×$OÒ$OÜðSó
ð 	
ð ‡z�z�- ×'Ò'ÜðOó
ð 	
õ 8EÓW±}¨tÐPVÉÔ*�DŸ*™* TÓ*Ò*±}€LÐWô
 
�Š��Ü  Ô/÷ 
ô
 ˜Ó€EÜ˜5Ó!€FØÒ˜FÒ.Ü" 6¸vÔFˆà˜,Ð&Ð&ùò X÷
 
�ús   ÂDÂ$DÃD Ä D0	c               ó$   € V ^8„  d   QhRRRRRR/# )r   r´   útorch.nn.ModuleÚnamer   rC   z
Any | Noner   )r   s   "r   r   r   –  s!   € ÷ ñ  ð °sð ¸zñ r   c                ó\   € V P                  4        F  p\        W!R4      ;pf   K  Vu # 	  R# )zTReturn the first non-None value of `name` found on `model` or any of its submodules.N)rc   r   )r´   rÒ   Úmoduler”   s   &&  r   Ú_find_submodule_attrrÕ   –  s.   € à—-‘-–/ˆÜ˜V¨4Ó0Ð0ˆEÔ=ØŠLñ "ñ r   zdict[tuple[str, ...], callable]Ú_EXPORT_INPUT_PREPARERSc               ó   € V ^8„  d   QhRR/# )r   Úmarkersr   r   )r   s   "r   r   r   ¡  s   € ÷ 
ñ 
¨Sñ 
r   c                 ó   a € V 3R lpV# )u(  Register `fn(model, inputs) -> None`. Dispatched when every `marker` is a key in
`inputs` with a non-`None` value â€” no model_type list to maintain. Use multiple
markers to narrow the match when a single kwarg is too ambiguous (e.g.
`("input_features", "feature_lens")` for omni audio encoders).c                ó   <€ V \         S&   V # r3   )rÖ   )r7   rØ   s   &€r   r8   Ú1register_export_input_preparer.<locals>.decorator§  s   ø€ Ø+-Ô Ñ(Øˆ	r   r   )rØ   r8   s   j r   Úregister_export_input_preparerrÜ   ¡  s   ø€ õð Ðr   Úgrid_thwc               ó$   € V ^8„  d   QhRRRRRR/# ©r   r´   rÑ   rÁ   údict[str, Any]rC   rD   r   )r   s   "r   r   r   ¯  s,   € ÷ Idñ Id¨?ð IdÀNð IdÐW[ñ Idr   c           	     óþ  € VR,          p\        V R4      pVf   VP                  R^4      p\        P                  \	        V 4      P
                  ,          p\        VR4      p\        W P                  WQR7      w  VR&   VR&   \        V R	4      RJp\        W#VR
7      VR&   \        V R4      p\        V R4      pVe=   Ve9   \        W#Wx4      w  VR&   VR&   \        VR,          V P                  VRR7      VR&   \        V R4      p	V	eU   \        V R4      ;'       g    Rp
\        V R4      ;'       g    Rp\        V R4      RJ p\        VV	V
VVVR7      w  VR&   VR&   V'       d   VP                  V4      VR&   \        VR4      '       d?   \        V R4      p\        V\        4      '       g   TMWÝ3w  rïVP!                  W.V4      VR&   \        VR 4      '       d$   \        V R!4      pVP#                  VV4      VR"&   R# R# )#uk  Precompute helpers driven by `grid_thw`: `cu_seqlens`, `max_seqlen`, `position_ids`, plus optional
`window_index`/`cu_window_seqlens`/`max_window_seqlen` (XNet-style window attn) and
`bilinear_indices`/`bilinear_weights` (interpolation-based merging).

Optional helpers are gated by a submodule attribute (`window_size`+`patch_size` for window
attention, `num_grid_per_side` for bilinear) or, for model-specific ones, by the encoder's
modeling module defining the helper (`get_vision_frame_index` / `get_vision_temporal_merge_index`
for kimi_k25) â€” so a model that doesn't use a feature won't get its kwarg injected.
rÝ   Úspatial_merge_sizeNÚmerge_sizesÚget_vision_frame_index)Úmerge_temporalÚkwargsÚ
cu_seqlensÚ
max_seqlenÚaxis_dim)Úinclude_temporalÚposition_idsÚwindow_sizeÚ
patch_sizeÚwindow_indexÚcu_window_seqlensÚmax_window_seqlen)ræ   Ú
kwarg_nameÚnum_grid_per_sideÚinterpolation_modeÚbilinearÚinterpolation_paddingÚborderÚinterpolation_align_cornersT)ÚmodeÚalign_cornersrâ   ÚpaddingÚinterp_indicesÚinterp_weightsÚframe_indexÚget_vision_temporal_merge_indexÚmerge_kernel_sizeÚtemporal_merge_indexÚget_vision_pixel_shuffle_indexÚ
merge_sizeÚpixel_shuffle_index)rÕ   r.   Úsysrc   r„   Ú
__module__r†   r	   rÃ   r   r   r   r
   rä   rd   Úintrþ   r  )r´   rÁ   rÝ   râ   rÔ   Útemporal_encoderrê   rì   rí   rò   rø   rú   rù   rÿ   Úkernel_heightÚkernel_widthr  s   &&               r   Ú_prepare_grid_thw_vision_inputsr
  ®  s<  € ð �jÕ!€HÜ-¨eÐ5IÓJÐØÒ!ð $ŸZ™Z¨°qÓ9Ðô
 �[‰[œ˜e›×/Ñ/Õ0€FÜ˜vÐ'?Ó@ÐÜ1MØ—,‘,Ð/?ô2Ñ.€Fˆ<Ñ˜& Ñ.ô
 ,¨E°:Ó>ÀdÐJÐÜ4°XÐdtÔu€Fˆ>Ñä& u¨mÓ<€KÜ% e¨\Ó:€JØÒ :Ò#9Ü>UØ¨+ó?
Ñ;ˆˆ~Ñ Ð':Ñ ;ô '5ØÐ&Õ'¨¯©¸fÐQdô'
ˆÐ"Ñ#ô -¨UÐ4GÓHÐØÒ$ô
 $ EÐ+?Ó@×NÐNÀJˆÜ& uÐ.EÓF×RÐRÈ(ˆÜ,¨UÐ4QÓRÐVZÐZˆÜ=iØØØØ'Ø1Øô>
Ñ:ˆÐÑ  &Ð)9Ñ":÷ Ø &× =Ñ =¸hÓ Gˆˆ}Ñô ˆvÐ8×9Ò9Ü0°Ð8KÓLÐä%/Ð0AÄ3×%GÒ%GÑÐN_ÐMsñ 	$ˆð *0×)OÑ)OÐPXÐiuÓ)vˆÐ%Ñ&ô ˆvÐ7×8Ò8Ü)¨%°Ó>ˆ
Ø(.×(MÑ(MÈhÐXbÓ(cˆÐ$Ó%ñ 9r   Útarget_sizesc               ó$   € V ^8„  d   QhRRRRRR/# rß   r   )r   s   "r   r   r   ü  s'   € ÷ Wñ W¨ð WÀð WÐTXñ Wr   c                ó&  € VR,          p\        V R4      pVe   \        W#4      VR&   \        V R4      pVeÚ   \        P                  P                  P                  VR^R7      p\        V^V^ ,          ^R7      w  VR&   VR	&   \        W$4      VR
&   \        P                  P                  P                  \        P                  ! VR,          VR,          ,          ^ \        P                  R7      R4      p\        W`P                  VR7      VR&   R# R# )zùNaViT-style packed encoders carry per-image `(h, w)` as `target_sizes` instead of `grid_thw`.
Synthesise `grid_thw = [1, h, w]` and run the nearest-position-id / window-index /
merged-shape / maximum-sequence-length helpers outside the traced graph.r  Únum_patches_per_sideNrë   Úwindow_kernel_size)r”   )râ   rì   rí   rî   rï   Úmerged_shape)Údimr§   ©ræ   rè   )rW   é    )ºNNNr  )r  rW   )rÕ   r   re   ÚnnÚ
functionalÚpadr   r   ÚcumsumÚint32r   rÃ   )r´   rÁ   r  r  r  rÝ   rç   s   &&     r   Ú_prepare_navit_vision_inputsr  û  sý   € ð
 ˜.Õ)€LÜ/°Ð7MÓNÐØÒ'Ü!@ÀÓ!dˆˆ~Ñä-¨eÐ5IÓJÐØÒ%Ü—8‘8×&Ñ&×*Ñ*¨<¸ÀqÐ*ÓIˆÜ>UØ¨Ð8JÈ1Õ8MÐZ[ô?
Ñ;ˆˆ~Ñ Ð':Ñ ;ô "9¸Ó!Zˆˆ~ÑÜ—X‘X×(Ñ(×,Ñ,Ü�LŠL˜ dÕ+¨l¸4Õ.@Õ@ÀaÌuÏ{É{Ô[Ð]có
ˆ
ô  .¨j¿,¹,ÈvÔVˆˆ|Óñ &r   Úinput_featuresÚfeature_lensc               ó$   € V ^8„  d   QhRRRRRR/# rß   r   )r   s   "r   r   r     s'   € ÷ ]ñ ] oð ]¸~ð ]ÐRVñ ]r   c                ó,  € VR,          pVR,          p\         P                  \        V 4      P                  ,          p\	        VR4      p\	        VR4      p\	        VR4      pV! W2V P
                  4      w  r‰W�R&   W‘R&   \        V R4      '       d8   V! W’V P                  V P
                  4      VR	&   V! W�P
                  4      VR
&   M+V! V	4      VR	&   V! V	4      VR
&   \	        VR4      ! V4      VR&   \        VR	,          V P                  VR7      VR&   R# )u|  Replace `input_features`/`feature_lens` with precomputed `padded_feature`, `chunk_lengths`,
`cu_seqlens`, `max_seqlen`, `valid_indices` (+ `pool_indices` on Qwen2.5-Omni-style encoders) so the
encoder's `.split(.tolist(), dim=0)` and related data-dependent ops happen outside the
traced graph.

The helpers (`chunk_and_pad_features`, `get_audio_cu_seqlens`, â€¦) all live in the model's
own ``modeling_*.py`` module, so we resolve them via ``type(model).__module__`` rather than
hard-coding one Omni variant. ``n_window_infer`` selects the Qwen3-Omni-style four-arg
``get_audio_cu_seqlens`` over the Qwen2.5-Omni-style single-arg form.
r  r  Úchunk_and_pad_featuresÚget_audio_cu_seqlensÚget_valid_indicesÚpadded_featureÚchunk_lengthsÚn_window_inferrç   Úvalid_indicesÚget_pool_indicesÚpool_indicesr  rè   N)
r  rc   r„   r  r   Ún_windowr†   r$  r   rÃ   )
r´   rÁ   r  r  rÔ   r  r   r!  r"  r#  s
   &&        r   Ú_prepare_omni_audio_inputsr)    s  € ð ˜.Õ)€LØÐ,Õ-€NÜ�[‰[œ˜e›×/Ñ/Õ0€Fä$ VÐ-EÓFÐÜ" 6Ð+AÓBÐÜ Ð(;Ó<Ðá$:¸>ÐY^×YgÑYgÓ$hÑ!€NØ-ÐÑØ+ˆ?ÑÜˆuÐ&×'Ò'Ù3°MÐQV×QeÑQeÐgl×guÑguÓvˆˆ|ÑÙ"3°MÇ>Á>Ó"RˆˆÒá3°MÓBˆˆ|ÑÙ"3°MÓ"BˆˆÑÜ!(¨Ð1CÔ!DÀ\Ó!Rˆˆ~ÑÜ)¨&°Õ*>ÀÇÁÐU[Ô\€Fˆ<Ór   Úinput_features_maskc               ó$   € V ^8„  d   QhRRRRRR/# rß   r   )r   s   "r   r   r   4  s'   € ÷ ]ñ ]¨?ð ]ÀNð ]ÐW[ñ ]r   c                óö  € ^RI Hp \        V R4      p\        V R4      pVe   Vf   R# VR,          pVP                  w  rgWs^,          ,          pVP	                  R
4      P                  \        P                  4      p	VP                  WhR
4      P	                  R
R7      P                  R
4      P                  \        P                  4      p
V! W©WC4      VR&   \        VR,          V P                  VR7      VR	&   R# )zÅPrecompute `cu_seqlens` and `max_seqlen` for Qwen3-ASR so the encoder pops them from
``kwargs``. Mirrors the few lines that build ``feature_lens``/``chunk_lengths`` in
``Qwen3ASREncoder.forward``.
)r   r(  r$  Nr*  ©r  rç   r  rè   éÿÿÿÿ)Ú#models.qwen3_asr.modeling_qwen3_asrr   rÕ   ÚshapeÚsumr¯   re   ÚlongÚviewÚreshaper   rÃ   )r´   rÁ   r   r(  r$  r*  Ú
batch_sizeÚpadded_feature_lengthÚ
num_chunksr  r#  s   &&         r   Ú_prepare_qwen3_asr_audio_inputsr8  3  sá   € õ Kä# E¨:Ó6€HÜ)¨%Ð1AÓB€NØÒ˜>Ò1Ùà Ð!6Õ7ÐØ(;×(AÑ(AÑ%€JØ&°a­<Õ8€JØ&×*Ñ*¨2Ó.×1Ñ1´%·*±*Ó=€LØ'×,Ñ,¨ZÀRÓH×LÑLÐQSÐLÓT×\Ñ\Ð]_Ó`×cÑcÔdi×dnÑdnÓo€MÙ/°È^Óf€Fˆ<ÑÜ)¨&°Õ*>ÀÇÁÐU[Ô\€Fˆ<Ór   c               ó$   € V ^8„  d   QhRRRRRR/# rß   r   )r   s   "r   r   r   I  s"   € ÷ $ñ $ Oð $¸^ð $ÐPTñ $r   c                óØ  a€ SP                  R4      fé   \        V R4      '       d×   SP                  R4      pSP                  R4      pVRJ ;'       g4    VRJ ;'       g(    VP                  ^,          VP                  ^,          8H  pV'       dn   \        \        P
                  ! V P                  4      P                  4      pV Uu/ uF  qfS9   g   K  VSV,          bK  	  ppV P                  ! R	/ VB w  r‰VSR&   \        P                  4        FP  w  r«\        ;QJ d    V3R lV
 4       F  '       d   K   RM	  RM! V3R lV
 4       4      '       g   KG  V! V S4       KR  	  R# u upi )
uÖ  Inject precomputed tensors for data-dependent ops the model would otherwise hit during tracing.

Two layers:
- Outer LLM rope index (`get_rope_index`) â€” generic `hasattr` probe; covers Qwen-VL / GLM-4V etc.
- Per-encoder preparer dispatched by marker kwargs present in `inputs` (e.g. `grid_thw`,
  `target_sizes`, `(input_features, feature_lens)`) â€” see `register_export_input_preparer`.
  A preparer fires only when every one of its markers is present in `inputs`.
rë   NÚget_rope_indexÚ	input_idsÚattention_maskc              3  óJ   <"  € T F  pSP                  V4      R Jx € K  	  R # 5ir3   )r.   )r|   ÚmrÁ   s   & €r   r~   Ú+precompute_export_inputs.<locals>.<genexpr>a  s   øé € Ð:±'¨Qˆv�z‰z˜!‹} DÕ(³'ùs   ƒ #FTr   )r.   r†   r0  rƒ   ÚinspectÚ	signaturer;  r¸   rÖ   rˆ   Úall)r´   rÁ   r<  Ú	attn_maskÚ
is_prefillÚrope_paramsr‰   Úrope_inputsrë   rR   rØ   Úpreparers   &f          r   rË   rË   I  s&  ø€ ð ‡z�z�.Ó!Ò)¬g°eÐ=M×.NÒ.NØ—J‘J˜{Ó+ˆ	Ø—J‘JÐ/Ó0ˆ	Ø $Ð&×gÐg¨)°tÐ*;×gÐg¸y¿¹ÈqÕ?QÐU^×UdÑUdÐefÕUgÑ?gˆ
ßÜœg×/Ò/°×0DÑ0DÓE×PÑPÓQˆKÙ1<ÓL±¨AÀVÁœ<˜1˜f Q�iš<±ˆKÐLØ#×2Ò2ÑA°[ÑA‰OˆLØ%1ˆF�>Ñ"ô 5×:Ñ:Ö<Ñˆß‹3Ô:±'Ó:�3�3Š3Ô:±'Ó:×:Ô:Ù�U˜FÖ#ó =ùò Ms   ÃE'ÃE'c               ó   € V ^8„  d   QhRR/# )r   rÔ   rÑ   r   )r   s   "r   r   r   n  s   € ÷ "ñ "˜_ñ "r   c              #  óÚ   aaa"  € . oV P                   o\        P                  ! S4      o\        P                  ! S4      VVV3R l4       pWn          Sx € SV n         R#   ST n         i ; i5i)zÒCapture forward call kwargs into a list (one dict per call).

Positional args are normalised to kwargs via `inspect.signature` so the
captured dicts can be passed directly as `kwargs=inputs` to `torch.export`.
c                 óð  <€ / pS	P                   ! V / VB pVP                  P                  4        F«  w  rES	P                  V,          pVP                  \
        P                  P                  8X  d(   VP                  \        P                  ! V4      4       Kh  VP                  \
        P                  P                  8w  g   K“  \        P                  ! V4      W$&   K­  	  SP                  V4       S! V / VB # r3   )ÚbindÚ	argumentsrˆ   r¸   ÚkindrA  Ú	ParameterÚVAR_KEYWORDÚupdateÚcopyÚdeepcopyÚVAR_POSITIONALr5   )
Úargsræ   ÚcapturedÚboundrÒ   r”   ÚparamÚcallsr    Úsigs
   *,     €€€r   ÚwrapperÚ!_capture_forward.<locals>.wrappery  sµ   ø€ àˆØ—’˜$Ð) &Ñ)ˆØ Ÿ?™?×0Ñ0Ö2‰KˆDØ—N‘N 4Õ(ˆEØ�z‰zœW×.Ñ.×:Ñ:Ô:Ø—‘¤§¢¨eÓ 4Ö5Ø—‘œw×0Ñ0×?Ñ?Ö?Ü!%§¢¨uÓ!5�“ñ 3ð 	�‰�XÔÙ˜Ð( Ñ(Ð(r   N)ÚforwardrA  rB  Ú	functoolsÚwraps)rÔ   r[  rY  r    rZ  s   & @@@r   Ú_capture_forwardr`  m  s`   úé € ð €EØ�~‰~€HÜ
×
Ò
˜HÓ
%€Cä‡_‚_�XÓö
)ó ð
)ð „Nð"ØŠà!ˆŽø˜ˆ�üs   …AA+ÁA Á	A+Á	A(Á(A+c               ó    € V ^8„  d   QhRRRR/# )r   Údecode_callsz
list[dict]rC   r…   r   )r   s   "r   r   r   �  s   € ÷ 5ñ 5 jð 5°Tñ 5r   c                óD  a aa€ S ^ ,          p\         P                   ! V4      oR R lo\        ;QJ d    V3R lS  4       F  '       g   K   RM	  RM! V3R lS  4       4      '       d   \         P                   ! S R,          4      # R V V3R llpV! R^4       V! R	^4       V! R
^ 4       V! RR4       S  Uu. uF  q3P                  R4      NK  	  pp\        ;QJ d    R V 4       F  '       d   K   RM	  RM! R V 4       4      '       d   \	        V4      SR&   S# u upi )uª  Merge consecutive single-token decode captures into one multi-token decode input.

Each `model.generate` decode step feeds a single new token, so `torch.export` (with `Dim.AUTO`)
sees a query-sequence axis of length 1 and specializes it to a constant â€” the exported decode can
then only ever run one token. Concatenating `N` consecutive decode steps along that axis yields a
genuine `N`-token decode input: the traced graph is identical (a KV-cache forward), but the sequence
axis now has hint `N > 1` so it stays dynamic. The exported decode then handles both a single token
(ordinary decoding) and many (continuation-from-past for multi-turn, or a plain prefill when the cache is empty).

The cache (`past_key_values`) is taken from the FIRST step (the state right after prefill, before
the chunk). The per-token tensors are concatenated along their sequence axis; `attention_mask` is
handled below (its layout depends on the cache).
c               ó    € V ^8„  d   QhRRRR/# )r   Úcallr…   rC   z
int | Noner   )r   s   "r   r   Ú)_merge_decode_calls.<locals>.__annotate__   s   € ÷ ñ ˜4ð  Jñ r   c                ól   € R F-  pV P                  V4      pVf   K  VP                  ^,          u # 	  R# )r<  N)r<  Úinputs_embeds)r.   r0  )re  r“   r”   s   &  r   Úquery_lengthÚ)_merge_decode_calls.<locals>.query_length   s2   € Û1ˆCØ—H‘H˜S“MˆEØÔ Ø—{‘{ 1•~Ò%ñ 2ñ r   c              3  ó:   <"  € T F  pS! V4      ^8g  x € K  	  R# 5i)rW   Nr   )r|   re  ri  s   & €r   r~   Ú&_merge_decode_calls.<locals>.<genexpr>§  s   øé € Ð
<©| t‰<˜Ó Ö"«|ùs   ƒTFc               ó$   € V ^8„  d   QhRRRRRR/# )r   r“   r   r  r  rC   rD   r   )r   s   "r   r   rf  ª  s!   € ÷ 5ñ 5˜#ð 5 Cð 5¨Dñ 5r   c                óÒ   <€ S Uu. uF  q"P                  V 4      f   K  W ,          NK!  	  pp\        V4      \        S4      8X  d   \        P                  ! W1R7      SV &   R # R # u upi )Nr-  )r.   Úlenre   Úcat)r“   r  re  Úvaluesrb  Úmergeds   &&  €€r   Úconcat_alongÚ)_merge_decode_calls.<locals>.concat_alongª  sS   ø€ Ù(4ÓR© ¿¹À»”)�$—)�)©ˆÐRÜˆv‹;œ#˜lÓ+Ô+ÜŸ)š) FÔ4ˆF�3‹Kñ ,ùò Ss
   †A$ŸA$r<  rh  Úcache_positionrë   r=  c              3  ó(   "  € T F  qR Jx € K
  	  R # 5ir3   r   )r|   Úmasks   & r   r~   rl  ¿  s   é € Ð
.© �tÕ«ùs   ‚r.  )rR  Úanyr.   rC  Ú_merge_step_masks)rb  Úfirstrs  re  Úmasksrr  ri  s   f    @@r   Ú_merge_decode_callsr|  �  sê   ú€ ð ˜�O€EÜ�YŠY�uÓ€Fõ÷ ƒsÔ
<©|Ó
<‡s‡s‚sÔ
<©|Ó
<×<Ò<Ü�yŠy˜ bÕ)Ó*Ð*÷5ñ 5ñ
 �˜aÔ Ù� !Ô$ÙÐ! 1Ô%ñ � Ô$ñ 5AÓA±L¨D�X‰XÐ&Ö'±L€EÐAß
ƒsÑ
.©Ó
.‡s‡s‚sÑ
.©Ó
.×.Ò.Ü#4°UÓ#;ˆÐÑ à€Mùò	 Bs   Â8Dc               ó    € V ^8„  d   QhRRRR/# )r   r{  z	list[Any]rC   r   r   )r   s   "r   r   r   Å  s   € ÷ ñ ˜Yð ¨3ñ r   c                ó¨  a€ V R,          oSf   R# \        S\        4      '       d4   S UUu/ uF$  q\        V  Uu. uF  q"V,          NK  	  up4      bK&  	  upp# SP                  4       ^8X  dY   \        ;QJ d    V3R lV  4       F  '       d   K   RM	  RM! V3R lV  4       4      '       d   \
        P                  ! V ^R7      # S# u upi u uppi )aÌ  Merge one attention mask per decode step into a single multi-token mask.

A 4D causal mask `[batch, heads, query, kv]` is concatenated along the query axis (each step is one
causal row against the fixed cache); a 2D padding mask keeps the last step (it already spans the most
positions). A dict `{attention_type: mask}` (hybrid-attention models) is merged entry by entry, and a
`None` mask (an attention type the model leaves unmasked) is preserved as `None`.
Nc              3  óp   <"  € T F+  qP                   ^,          SP                   ^,          8H  x € K-  	  R# 5i)é   N)r0  )r|   rw  Ú	last_masks   & €r   r~   Ú$_merge_step_masks.<locals>.<genexpr>Ò  s'   øé € Ð#ZÑTYÈD§J¡J¨q¥M°Y·_±_ÀQÕ5GÖ$GÓTYùs   ƒ36FTr-  r.  )rd   r…   ry  r  rC  re   rp  )r{  r“   rw  r�  s   &  @r   ry  ry  Å  s§   ø€ ð �b•	€IØÒÙÜ�)œT×"Ò"ÙQZÔ[ÑQZÈ#Ô&¹eÓ'D¹e°d¨S¯	¨	¹eÑ'DÓEÒEÑQZÒ[Ð[Ø‡}�}ƒ˜!Ô§£Ô#ZÑTYÓ#Z§§¢Ô#ZÑTYÓ#Z× ZÒ ZÜ�yŠy˜ AÔ&Ð&ØÐùò (EùÓ[s   ¬CºC	ÁCÃ	Cc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# ©r   r´   r   rÁ   rà   Úgeneration_configr   Úmulti_token_decodeÚboolrC   ú'dict[str, tuple[torch.nn.Module, dict]]r   )r   s   "r   r   r   ×  sA   € ÷ Dñ DØðDàðDð ðDð ð	Dð
 -ñDr   c                óD  € V'       d   ^M^p\         P                  ! Ve   TMV P                  4      pWEn        WEn         \        V 4      ;_uu_ 4       pV P                  ! R/ \         P                  ! V4      BRV/B  RRR4       \        X4      T8  d5   \        RT R\        T 4      P                   RT R	\        T4       R
2	4      hT F  pTP                  RR4       K  	  T^ ,          p	T'       d   \        T^T 4      MT^,          p
R\         P                   ! T 4      T	3R\         P                   ! T 4      T
3/#   + '       g   i     LÉ; i  \         dC   p\        R\        T 4      P                   R\        TP                  4       4       R24      ThRp?ii ; i)uý  Run `model.generate()` and capture prefill and decode inputs.

Reuses the full generation machinery so every architecture (decoder-only, SSM,
encoder-decoder, multi-modal, â€¦) gets correct inputs without reimplementing the loop.

`generation_config` is forwarded to `generate()` (defaulting to the model's own), so the captured
inputs use whatever cache `generate()` would build. Pass one with `cache_implementation="static"`
and `max_cache_len=N` to capture a **statically sized** cache in the decode inputs â€” the basis for
a static-cache export. `max_cache_len` sizes the cache independently of the capture, so the
exported decode takes a fixed `[..., N, ...]` cache rather than a growing one.

When `multi_token_decode`, the `decode` component is captured as a **multi-token** decode â€” two
consecutive decode steps merged (see `_merge_decode_calls`) so its query-sequence axis stays
symbolic (a single-token decode would specialize that axis to 1). It then handles both one token
(ordinary decoding) and many (continuation-from-past, or a plain prefill when the cache is empty). Otherwise `decode` is the
classic single-token decode.

Returns:
    `dict[str, tuple[torch.nn.Module, dict]]`:
    `{"prefill": (model, prefill_inputs), "decode": (model, decode_inputs)}`.
Nr…  z$decompose_prefill_decode failed for ú. Inputs passed: z<. Make sure the inputs are compatible with model.generate().z+decompose_prefill_decode expected at least z
 calls to z*.forward() during generate(max_new_tokens=z), but captured z«. This likely means generate() bypasses the top-level forward() (e.g. delegates to an inner model), so prefill/decode decomposition is not supported for this architecture.Úlogits_to_keepÚprefillÚdecoder   )rR  rS  r…  Úmax_new_tokensÚmin_new_tokensr`  ÚgenerateÚ	ExceptionÚRuntimeErrorr„   r[   rh   Úkeysro  rÇ   r|  )r´   rÁ   r…  r†  Únum_new_tokensÚcapture_configrY  Úere  Úprefill_inputsÚdecode_inputss   &&&&       r   Údecompose_prefill_decoder™  ×  s”  € ÷@ -‘Q°!€NÜ—]’]Ð8IÒ8UÑ#4Ð[`×[rÑ[rÓs€NØ$2Ô!Ø$2Ô!ðÜ˜e×$Ô$¨Ø�NŠNÑUœTŸ]š]¨6Ó2ÑUÀnÓU÷ %ô ˆ5ƒz�NÔ"ÜØ9¸.Ð9IÈÜ�E‹{×#Ñ#Ð$Ð$NÈ~ÐN^ð _Ü˜E›
�|ð $%ð%ó
ð 	
ó ˆØ�‰Ð! 4Ö(ñ ð ˜1•X€NßDVÔ'¨¨a°Ð(?Ô@Ð\aÐbcÕ\d€Mà”D—I’I˜eÓ$ nÐ5Ø”4—9’9˜UÓ# ]Ð3ðð ÷9 %×$ûäô ÜØ2´4¸³;×3GÑ3GÐ2Hð IÜ" 6§;¡;£=Ó1Ð2ð 3IðJó
ð ð		ûðús6   Á E Á+D?Á>E Ä?E	Å
E ÅE ÅFÅ=FÆFc               ó    € V ^8„  d   QhRRRR/# )r   r´   r   rC   zdict[str, torch.nn.Module]r   )r   s   "r   r   r   $  s   € ÷ "ñ " ð "Ð;Uñ "r   c                ón  € / pRpR F+  pV P                  VR7      pVf   K  W@Jg   K"  WAV R2&   RpK-  	  V P                  4       pVe
   WPJd   WQR&   W P                  0 F@  p\        \        ,            F(  pWq9  g   K  \        WgR4      f   K  \        Wg4      W&   K*  	  KB  	  V'       d   RV9  d   / # V# )u  Return `{attr_name: module}` for multi-modal submodules found on `model`.

Uses the canonical `PreTrainedModel.get_encoder("image"/"audio")` and `get_decoder()`
accessors for encoders and the language model. Projectors and `lm_head` are looked
up by name on `model` and its `base_model` (e.g. `LlavaModel` under `LlavaForConditionalGeneration`).

Only returns results when at least one modal encoder AND a language model are found â€”
otherwise the model is not multi-modal and should be exported as a single unit.
F)ÚmodalityNÚ_encoderTÚlanguage_model)ÚimageÚaudio)Úget_encoderÚget_decoderÚ
base_modelÚ_MULTIMODAL_PROJECTOR_NAMESÚ_MULTIMODAL_LM_HEAD_NAMESr   )r´   ÚfoundÚhas_encoderrœ  ÚencoderÚdecoderÚrootrÒ   s   &       r   Ú_find_multimodal_submodulesr«  $  sÌ   € ð )+€Eà€KÛ&ˆØ×#Ñ#¨XÐ#Ó6ˆð Ô 7Õ#7Ø+2�X�J˜hÐ'Ñ(ØŠKñ 'ð ×ÑÓ!€GØÒ˜wÓ3Ø")ÐÑà×(Ñ(Ó)ˆÜ/Ô2K×KÐKˆDØÖ ¤W¨T¸Ó%>Ô%JÜ% dÓ1�“ó Lñ *÷
 Ð*°%Ô7Øˆ	à€Lr   c               ó    € V ^8„  d   QhRRRR/# )r   r´   rµ   rC   r‡  r   )r   s   "r   r   r   I  s   € ÷ [ñ [Ð:ð [¸tñ [r   c                óZ   € \        V \        4      ;'       d    \        \        V 4      4      # )a  Returns `True` if the model is multi-modal with modal encoders and a language model.

A non-`PreTrainedModel` (e.g. a bare `nn.Module`) has no canonical `get_encoder`/`get_decoder`
accessors and is trivially not multi-modal, so it short-circuits to `False`.
)rd   r   r‡  r«  rº   s   &r   Úis_multimodalr®  I  s%   € ô �eœ_Ó-×ZÐZ´$Ô7RÐSXÓ7YÓ2ZÐZr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   r´   r   rÁ   rà   rC   rˆ  r   )r   s   "r   r   r   R  s"   € ÷ )ñ ) ð )¸ð )ÐLsñ )r   c                ó@  € \        V 4      pV'       g#   \        R\        V 4      P                   R24      h \        P
                  ! 4       ;_uu_ 4       p\        P                  ! 4       ;_uu_ 4        VP                  4        UUu/ uF  w  rEWCP                  \        V4      4      bK!  	  pppV ! R/ \        P                  ! V4      B  RRR4       RRR4       TP                  4        UUu/ uF'  w  rEXT,          '       g   K  YEYd,          R,          3bK)  	  upp# u uppi   + '       g   i     Lb; i  + '       g   i     Lm; i  \         dC   p\        R\        T 4      P                   R\        TP!                  4       4       R24      ThRp?ii ; iu uppi )	uW  Capture inputs to each multi-modal submodule via a single forward pass.

Detects all known multi-modal submodules by attribute name (vision tower, projector,
language model, lm_head, â€¦) and captures their forward kwargs during one
`model(**inputs)` call.

Each submodule is returned as a separate `name: (module, inputs)` entry for
independent export. The token-merge step (e.g. `masked_scatter` for multi-modal models)
is intentionally left outside the exported graphs â€” it is the caller's responsibility
to assemble `inputs_embeds` from the encoder outputs before running the decoder.

Returns:
    `dict[str, tuple[torch.nn.Module, dict]]`: One `name: (module, inputs)`
    entry per detected submodule (image/audio encoder, projector, language model, lm_head).

Raises:
    `ValueError`: if no known multi-modal submodules are found on the model.
z8decompose_multimodal found no multi-modal submodules on zB. Expected an image/audio encoder + language model, found neither.Nz decompose_multimodal failed for rŠ  rM   r   r.  )r«  rÈ   r„   r[   r%   r&   re   rÊ   rˆ   r'   r`  rR  rS  r‘  r’  rh   r“  )r´   rÁ   Ú
submodulesr(   rÒ   rÔ   Úsubmodule_inputsr–  s   &&      r   Údecompose_multimodalr³  R  sk  € ô& -¨UÓ3€JßÜØFÄtÈEÃ{×G[ÑG[ÐF\ð ]Oð Pó
ð 	
ð
	Ü×!Ò!×#Ô# u¬e¯mªm¯o­oàXb×XhÑXhÔXjô ÙXjÉÈ�×)Ñ)Ô*:¸6Ó*BÓCÒCÑXjð ñ  ñ Ñ*”D—M’M &Ó)Ò*÷	 />×#ð '×,Ñ,Ô.ôá.‰LˆDØ˜D×!Ñ!ô 	3ˆÐ'Õ-¨bÕ1Ð2Ò2Ù.òð ùó ÷ />¯oú×#×#ûô
 ô ÜØ.¬t°E«{×/CÑ/CÐ.DÐDUÔVZÐ[a×[fÑ[fÓ[hÓViÐUjÐjkÐló
àð	ûðüó
sk   ·E
 ÁD7Á2D$	Â%DÂ+D$	Ã
D7ÃE
 Ã-FÄFÄD$	Ä$D4Ä/D7Ä7E	ÅE
 ÅE
 Å
FÅ=FÆFc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# r„  r   )r   s   "r   r   r   ~  s4   € ÷ #ñ #Øð#Ø$2ð#ØGJð#Øgkð#à,ñ#r   c                óŠ   € \        WW#R7      pVR,          w  rV\        V4      '       g   V# \        WV4      pVR,          VR&   V# )u�  Decompose a generative model into independently exportable `(model, forward_inputs)` pairs.

Runs `decompose_prefill_decode` to capture prefill and decode forward kwargs from a real
`model.generate(**inputs, max_new_tokens=2)`. If the prefill is multi-modal (per `is_multimodal`),
further splits it into one entry per submodule (vision/audio encoder, projector, language model,
`lm_head`) via `decompose_multimodal`.

Args:
    model: Generative model. Must support `model.generate(**inputs)`.
    inputs: **Generate** kwargs â€” what you'd pass to `model.generate(**inputs)`.
    generation_config: Optional `GenerationConfig` forwarded to `generate()` during capture. Pass
        one with `cache_implementation="static"` + `max_cache_len=N` to export against a statically
        sized cache (see `decompose_prefill_decode`).
    multi_token_decode: When `True`, capture the `decode` component as a multi-token decode (dynamic
        query sequence axis: multiple tokens at once â€” continuation-from-past, or a plain prefill when the cache is empty); a
        single-token decode can't stay dynamic (see `decompose_prefill_decode`).

Returns:
    `{component_name: (submodel, forward_inputs)}`. Keys are `"prefill"` / `"decode"` for
    plain generative models and `"<modality>_encoder"` / `"multi_modal_projector"` /
    `"language_model"` / `"lm_head"` / `"decode"` for multi-modal generative models.
)r…  r†  rŒ  r�  )r™  r®  r³  )r´   rÁ   r…  r†  ÚstagesÚprefill_modelr—  Ú
componentss   &&&&    r   Údecompose_for_generationr¹  ~  sR   € ô2 &ØÐ):ô€Fð %+¨9Õ$5Ñ!€Mä˜×'Ò'Øˆä% mÓD€JØ! (Õ+€JˆxÑØÐr   )Ú )Ú	use_cacheÚoutput_attentionsÚoutput_hidden_statesÚreturn_dictrÄ   )NF)Úmulti_modal_projectorÚ	connectorÚembed_visionÚembed_audio)Úlm_head)PÚ__conditional_annotations__Ú__doc__Ú
__future__r   r%   rR  Úenumr^  rA  r  Úcollections.abcr   Útypingr   Úutilsr   Úutils.genericr   Úutils.import_utilsr   Ú
get_loggerr[   Úloggerre   Úmodeling_utilsr   Úvision_utilsr	   r
   r   r   r   r   r   Ú__annotations__r   r   Úcontextmanagerr!   r)   r/   r;   r@   rH   rT   rO   rt   r„   ru   ÚEnumÚSymIntÚSymFloatÚSymBoolr{   r‘   r—   r¥   r²   r»   r¿   rÉ   rÏ   rÕ   rÖ   rÜ   r
  r  r)  r8  rË   r`  r|  ry  r™  r¤  r¥  r«  r®  r³  r¹  )rÄ  s   @r   Ú<module>r×     sK  øðô õ* #ã Û Û Û Û Û 
Ý *Ý å Ý *Ý 3ð 
×	Ò	˜HÓ	%€ñ ×ÒÛå0÷÷ ð" 8:€Ð
4Ó 9Ø,.€Ð)Ó .Ø/1Ð Ð,Ó 1ð ×Ñô*ó ð*ð ×Ñô	ó ð	ð ×Ñôó ðõõõõõ6õ&ðJ '+ WÐ Ð"Ó ,Ù×ÒØ˜Ÿ™ E§L¡L°%·.±.À%Ç-Á-ÐPÕPÐõ÷09õ,
)õ*õ&)õ	õð i€õ4'õ|ð <>Ð Ð8Ó =õ
ñ   
Ó+ôIdó ,ðIdñX   Ó/ôWó 0ðWñ,  Ð 0°.ÓAô]ó Bð]ñ@  Ð 0Ð2GÓHô]ó Ið]õ*$ðH ×Ñô"ó ð"õ>5õp÷$DðR dÐ Ø(Ð õ"õJ[õ)÷X#ñ #r   