
    <hB              
       b   S SK r S SKrS SKrS SKrS SKJrJr  S SKJr  S SK	J
r
  SSKJrJr  \" 5       (       a)  S SKrS SKrS SKJr  \R$                  R'                  5       rOSrSS	KJr  \R.                  " \5      rS
 r\R6                  " S5      rS\S\4S jrS r S!S\
\   S\ S\
\   4S jjr!S!S\
\   S\ S\
\   4S jjr"S\RF                  4S jr$S r%\R6                  " S5      r&S r'S r(S r)   S"S\
\   S\
\    S\ 4S jjr*\" SS9\   S#S\
\   S\
\    S\
\    4S  jj5       5       r+g)$    N)contextmanagerredirect_stdout)StringIO)Optional   )is_torch_availablerequires)	save_fileF)loggingc                      [         (       a#  [        R                  R                  5       (       d  g[        R                  R	                  5       S:H  $ )z7Return True if rank=0 or we aren't running distributed.Tr   )_torch_distributed_availabletorchdistributedis_initializedget_rank     Z/var/www/html/shao/venv/lib/python3.13/site-packages/transformers/model_debugging_utils.py_is_rank_zeror   *   s9    ((U->->-M-M-O-O%%'1,,r   zobject at 0x[0-9A-Fa-f]+x_strreturnc                 .    [         R                  SU 5      $ )z
Replace memory addresses in an object's repr with a stable placeholder
so that beautiful JSON diffs won't be ruined by ephemeral addresses.
zobject at 0xXXXXXXXX)MEMORY_ADDRESS_REGEXsub)r   s    r   _sanitize_repr_for_diffr   4   s    
  ##$:EBBr   c                 R    [        5       (       a  S[        U R                  5       3$ g)z@Return a stable string representation for a DTensor-like object.zDTensor (rank0) -> zDTensor(non-rank0))r   repr_local_tensor)xs    r   _dtensor_reprr    <   s#    $T!//%:$;<<r   
debug_pathuse_reprpath_to_valuec                    [         R                  " SS9  U(       a  [        U 5      nOU(       a  UR                  S5      (       d  US-  nU(       a  [        R
                  R                  X5      OUn[        SU R                  5       R                  5       R                  5       0U5        SU 3nO[        SU< SU< S35      e[        U R                  5      [        U R                  5      US	.nU R                  [         R                  [         R                   [         R"                  1;   a  UR%                  ['        [        U R)                  5       5      5      ['        [        U R+                  5       5      5      ['        [        U R-                  5       5      5      ['        [        U R/                  5       5      5      S
.5        U$ )aa  
Converts Tensors and DTensors to a JSON-serializable dictionary representation.

Args:
    value: Any Python object, often including torch Tensors, lists, dicts, etc.
    debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
    use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensor as the
        `value` property in the asscoiated FULL_TENSORS.json file, or to store the full tensors in separate
        SafeTensors file and store the relative path to that file in the `value` property in the dictionary.
    path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
        tensor value if `use_repr=False`.

Returns:
    A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
T)sci_modez.safetensorsdataz./z	use_repr=z and path_to_value=z cannot both be falsy.)shapedtypevalue)meanstdminmax)r   set_printoptions_repr_to_listendswithospathjoinr
   
contiguousdetachcpu
ValueErrorr   r'   r(   float16float32bfloat16updater   r*   r+   r,   r-   )r)   r!   r"   r#   	value_outfilepathouts          r   _serialize_tensor_like_ior?   C   sO   $ 
D)!%(		%%n55^+M>H277<<
:m65++-446::<=xH(	IH;&:M+;;QRSS ekk"ekk"C
 {{u}}emmU^^DD

/UZZ\0BC.tEIIK/@A.tEIIK/@A.tEIIK/@A		
 Jr   c                    [        U [        [        45      (       a,  [        U 5       VVs/ sH  u  pE[	        XQX# SU 3S9PM     snn$ [        U [
        5      (       a2  U R                  5        VVs0 sH  u  peU[	        XQX# SU 3S9_M     snn$ [        U S5      (       a  [        U R                  XUS9$ [        U [        R                  5      (       a
  [        XX#S9$ [        [        U 5      5      $ s  snnf s  snnf )aR  
Recursively build a JSON-serializable Python structure from `value`.
Tensors and DTensors become either sanitized repr strings, or are saved to disk as SafeTensors files and their
relative paths are recorded in the returned Python structure.
Lists/tuples/dicts are recursed into.
All memory addresses are replaced with a stable placeholder.

Args:
    value: Any Python object, often including torch Tensors, lists, dicts, etc.
    debug_path (`str`, *optional*, defaults to `None`): Directory to dump debug JSON and SafeTensors files.
    use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
        `value` property in the asscoiated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
        files and store the relative path to that file in the `value` property.
    path_to_value (`str`, *optional*, defaults to `None`): The file name for the SafeTensors file holding the full
        tensor value if `use_repr=False`.

Returns:
    A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
_r!   r"   r#   r   )
isinstancelisttuple	enumerate_serialize_iodictitemshasattrr?   r   r   Tensorr   r   )r)   r!   r"   r#   ivks          r   rG   rG   t   s   ( %$'' "%(
( !XWffghigjUkl(
 	

 % 
% }QZiijkljmXnoo%
 	

 uo&&(JYf
 	
 %&&(PXvv"4;//'

s   C20C8r)   c                 &   [         R                  " SSS9  [        5        n[        U5         [	        U 5        UR                  5       nSSS5        SSS5        [        W5      R                  5       $ ! , (       d  f       N/= f! , (       d  f       N8= f)z
Converts a tensor into a sanitized multi-line string representation.

Args:
    value (`torch.Tensor`): The tensor to represent.

Returns:
    `list[str]`: List of string lines representing the tensor.
Tx   )r%   	linewidthN)r   r.   r   r   printgetvaluer   
splitlines)r)   bufraws      r   r/   r/      s_     
DC8	sOC0elln 1 #3'2244 10s"   BA1B1
A?	;B
Bc                     U R                  S5      (       a*  U R                  SS 5        U S    H  n[        U5        M     g g )Nchildrenoutputs)getpopprune_outputs_if_children)nodechilds     r   r\   r\      s=     xx
D!*%E%e, & r   z(.*)\.(\d+)$c                    ^ [         R                  U R                  SS5      5      nU(       a  U R                  S5      (       d  gUR                  S5      m[	        U4S jU S    5       5      $ )z
Checks whether a node represents a layer block with submodules.

Args:
    node (`dict`): A node from the call tree.

Returns:
    `bool`: Whether the node is a layer block.
module_path rX   F   c              3   T   >#    U H  nS T S 3UR                  SS5      ;   v   M      g7f).r`   ra   NrZ   ).0r^   numbers     r   	<genexpr>!is_layer_block.<locals>.<genexpr>   s+     [JZ6(!}		- <<JZs   %()LAYER_SUFFIX_REmatchrZ   groupany)r]   rk   rg   s     @r   is_layer_blockrn      sW     !!$((=""=>E,,[[^F[$zJZ[[[r   c                    U R                  S5      (       d  g[        U S   5       VVs/ sH  u  p[        U5      (       d  M  X4PM     nnn[        U5      S:  aD  USS  VVs/ sH  u  pUPM	     nnn[        U S   5       VVs/ sH  u  pX;  d  M  UPM     snnU S'   U S    H  n[	        U5        M     gs  snnf s  snnf s  snnf )z
Recursively removes intermediate layers from the tree to improve readability.
Keeps at least the first and last layers if many consecutive layers are present.

Args:
    node (`dict`): The root or subnode to prune recursively.
rX   Nrb   r   )rZ   rF   rn   lenprune_intermediate_layers)r]   rL   r^   layer_blocksrA   	to_removes         r   rr   rr      s     88J/8j9I/Jd/J81n]bNcJQJ/JLd
<1#/"#56#541Q#5	62;D<L2Md2MhaQRQcE2MdZj!!%( " e 7ds   B7B7#B=
CCc                   ^ U (       aC   [         R                  " U SS9  [         R                  R                  XR                  S-   5      nOUR                  S-   n[        R                  SU S35        US-   nUS	-   n[        UR                  5        [        US
5       n[        R                  " UR                  USS9  S S S 5        U4S jm[        R                  " [        R                  " UR                  5      5      nT" U5        [        US
5       n[        R                  " XvSS9  S S S 5        g ! [
         a  n[        SU  S35      UeS nAff = f! , (       d  f       N= f! , (       d  f       g = f)NTexist_ok_debug_tree"Unexpected or existing debug_path=rd   zWriting model trace at z.jsonz_FULL_TENSORS.jsonz_SUMMARY.jsonwrb   )indentc                    >^ U4S jmT" U R                  S0 5      5        T" U R                  S0 5      5        U R                  S/ 5       H  nT" U5        M     g )Nc                    > [        U [        5      (       a2  U R                  SS 5        U R                  5        H  nT" U5        M     g [        U [        5      (       a  U  H  nT" U5        M     g g )Nr)   )rC   rH   r[   valuesrD   )valrM   itemcleans      r   r   :log_model_debug_trace.<locals>.strip_values.<locals>.clean   sX    #t$$&A!H &C&&D$K   'r   inputsrY   rX   re   )r]   r^   r   strip_valuess     @r   r   +log_model_debug_trace.<locals>.strip_values   sM    	  	dhhx$%dhhy"%&XXj"-E .r   )r1   makedirsr2   r3   _debugger_module_dump_name	Exceptionr7   loggerinfor\   
_call_treeopenjsondumploadsdumps)	r!   modelbasee	full_pathsummary_pathf	tree_copyr   s	           @r   log_model_debug_tracer      s6   	XKK
T277<<
,L,L},\]D //-?
KK)$u56++I/)Le../	i			%""Aa0 
   

4::e&6&678I	lC	 A		)q) 
!	 E  	XA*QOPVWW	X 
	. 
!	 s0   AD5 !EE(5
E?EE
E%(
E6do_prune_layersc                   ^ ^^^^	^
 T R                   R                  m	T	SS/ S.T l        / T l        T	T l        T(       a   [
        R                  " TSS9  UU U4S jnT R                  5        H  u  pgUS:X  a  M  U" UT	 SU 35        M     T R                  m
[        R                  " T
5      U	UUU U
U4S	 j5       nUT l
        g! [         a  n[        ST S35      UeSnAff = f)
a  
Attaches a debugging wrapper to every module in the model.

This records structured inputs and outputs during the forward pass into a call tree.

Args:
    model (`PreTrainedModel`, `nn.Module`): Model to wrap.
    debug_path (`str`): Optional directory to dump debug JSON files.
    do_prune_layers (`bool`, *optional*, defaults to `True`): Whether to prune intermediate layers.
    use_repr (bool, *optional*, defaults to `True`): Whether to save a `repr()`-ized version of the tensors as the
        `value` property in the asscoiated FULL_TENSORS.json file, or to store full tensors in separate SafeTensors
        files and store the relative path to that file in the `value` property.
Nr`   r   rY   rX   Trv   ry   rd   c                 z   >^ ^^ T R                   m[        R                  " T5      UUUU UU4S j5       nUT l         g )Nc                    > [        5       (       aZ  XS.nU Vs0 sH  n[        X#   5      S:  d  M  X2U   _M     nnT[        UTTT S3S9S / S.nT	R                  R	                  U5        [
        R                  " 5          T" U 0 UD6nS S S 5        [        5       (       a  [        S T
R                  5        5       5      S:  a  S WS'   O[        WTTT S3S9WS'   T	R                  R                  5       nUS	   (       d  UR                  S	5        T	R                  (       a!  T	R                  S
   S	   R	                  U5        W$ s  snf ! , (       d  f       N= f)Nargskwargsr   _inputsrB   r   c              3   $   #    U H  nS v   M	     g7f)r   Nr   )rf   rA   s     r   rh   X_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>D  s     :"9Qq"9s   rY   _outputsrX   rp   )
r   rq   rG   _debugger_model_call_stackappendr   no_gradsumnamed_childrenr[   )inpskwsdict_inputsrN   r]   r>   finishedr!   r   r   moduleorig_forwardr"   s          r   wrapped_forwardE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward/  sS   '+;:Ea+Q[^I\_`I`0qa.0+a#,+##-!))27&;	  $ "
 0077="D0C0 ! :&"7"7"9::Q>&*DO&3#-!))28&<	'DO !;;??A
+LL,3344R8DKKHUJE b !s   E	E 	E


E)forward	functoolswraps)r   r   r   r   r!   r   r"   s   `` @r   wrap_forward,_attach_debugger_logic.<locals>.wrap_forward,  s6    ~~		&%	 %	 
'%	N )r   ra   c                    > [        5       (       a4  T S3[        XS.TTT S3S9S / S.nT	R                  R                  U5        T
" U 0 UD6n[        5       (       a  T	R                  (       a  [        UTTT S3S9WS'   T	R                  R	                  5       nUS   T	R
                  S'   US   T	R
                  S'   US	   T	R
                  S	'   [        T	R
                  R                  5       5       Vs/ sH5  nT	R
                  U   (       a  M  T	R
                  R	                  US 5      PM7       nT(       a  [        T	R
                  5        [        TT	S
9  U$ s  snf )Nz (top-level)r   r   rB   r   r   rY   r   rX   )r!   r   )
r   rG   r   r   r[   r   rD   keysrr   r   )r   r   top_noder>   r   rN   
class_namer!   r   r   real_top_forwardr"   s         r   top_wrapped_forward3_attach_debugger_logic.<locals>.top_wrapped_forwardb  sa   ??",\:'!1)%%/L"8	  
H ,,33H=,,??u??"/%!!+H5	#HY 77;;=H)1();EX&*29*=EY'+3J+?EZ(489I9I9N9N9P4Qm4QqY^YiYijkYl*U!!!T*4Qm )%*:*:;!ZuE
 ns   4E E)	__class____name__r   r   r   r1   r   r   r7   named_modulesr   r   r   )r   r!   r   r"   r   r   name	submoduler   r   r   s   ````     @@r   _attach_debugger_logicr     s    & ))J (2Td`bcE')E$'1E$	XKK
T2+)\ !..02:Y:,av 67 1 }}__%&# # '#J (EM  	XA*QOPVWW	Xs   C 
C"CC")r   )backendsc              #   6  #    U R                  5        VVs0 sH  u  pEXUR                  _M     nnnU R                  X`'   [        XX#5         U v   UR                  5        H  u  pxXl        M     gs  snnf ! UR                  5        H  u  pxXl        M     f = f7f)a  
# Model addition debugger - context manager for model adders
This context manager is a power user tool intended for model adders.

It tracks all forward calls within a model forward and logs a slice of each input and output on a nested JSON file.
If `use_repr=True` (the default), the JSON file will record a `repr()`-ized version of the tensors as a list of
strings. If `use_repr=False`, the full tensors will be stored in spearate SafeTensors files and the JSON file will
provide a relative path to that file.

To note, this context manager enforces `torch.no_grad()`.

## Usage

add the context manager to a model to debug

```python
import torch

from PIL import Image
from transformers import LlavaProcessor, LlavaForConditionalGeneration, model_addition_debugger_context

torch.random.manual_seed(673)

# load pretrained model and processor
model_id = "llava-hf/llava-1.5-7b-hf"
processor = LlavaProcessor.from_pretrained(model_id)
model = LlavaForConditionalGeneration.from_pretrained(model_id)

# create random image input
random_image = Image.fromarray(torch.randint(0, 256, (224, 224, 3), dtype=torch.uint8).numpy())

# prompt
prompt = "<image>Describe this image."

# process inputs
inputs = processor(text=prompt, images=random_image, return_tensors="pt")

# call forward method (not .generate!)
with model_addition_debugger_context(model, debug_path="Your_debug_path", do_prune_layers=False):
    output = model.forward(**inputs)
```

N)r   r   r   rI   )	r   r!   r   r"   rA   morig_forwardsmodule_instanceforward_methods	            r   model_addition_debugger_contextr     s     f /4.A.A.CD.CdaQ		\.CMD ==M5oH5/</B/B/D+O&4# 0E E 0=/B/B/D+O&4# 0Es'   BA/BA5 &B5!BB)NTN)rd   TT)NTT),r   r   r1   re
contextlibr   r   ior   typingr   utils.import_utilsr   r	   r   torch.distributed.tensorsafetensors.torchr
   r   is_availabler   utilsr   
get_loggerr   r   r   compiler   strr   r    boolr?   rG   rK   r/   r\   rj   rn   rr   r   r   r   r   r   r   <module>r      s      	 	 6   < #+ $)#4#4#A#A#C #(   
		H	%- zz"=> C3 C3 C  dh.}.7;.S[\_S`.b(0Xc] (0T (0aijman (0V5 5"- **_-\")((*Z !$&*	|(|( d^|( 	|(~ 
: !%&*#	8585 d^85 tn	85  85r   