
    謜iB              	       :   d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ ddl	m
Z
 ddlmZmZ  e       r-d dlZd dlmZ dZej$                  j'                         r	d dlZd	ZndZ e
j*                  e      Zd
 Z ej2                  d      ZdedefdZd Z	 d!dedz  dededz  fdZd!dedz  dededz  fdZ dejB                  fdZ"d Z# ej2                  d      Z$d Z%d Z&dedz  fdZ'	 	 	 d"dededefdZ( ed      e	 	 	 d#dedz  dedefd               Z)y)$    N)contextmanagerredirect_stdout)StringIO   )logging)is_torch_availablerequires)	save_fileFTc                      t         rt        j                  j                         syt        j                  j	                         dk(  S )z7Return True if rank=0 or we aren't running distributed.Tr   )_torch_distributed_availabletorchdistributedis_initializedget_rank     ^/mnt/e/genesis-system/.venv/lib/python3.12/site-packages/transformers/model_debugging_utils.py_is_rank_zeror   ,   s3    (U->->-M-M-O%%'1,,r   zobject at 0x[0-9A-Fa-f]+x_strreturnc                 .    t         j                  d|       S )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   6   s    
  ##$:EBBr   c                 H    t               rdt        | j                         S y)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                 `   t        j                  d       |rt        |       }n|rx|j                  d      s|dz  }|r t        j
                  j                  ||      n|}t        d| j                         j                         j                         i|       d| }nt        d|d|d      t        | j                        t        | j                        |d	}| j                  t         j                  t         j                   t         j"                  hv r|j%                  t'        t        | j)                                     t'        t        | j+                                     t'        t        | j-                                     t'        t        | j/                                     d
       |S )a  
    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>   E   sN   $ 
D)!%(		%%n5^+M>H277<<
M: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                    t        | t        t        f      r0t        |       D cg c]  \  }}t	        |||| d|        c}}S t        | t
              r6| j                         D ci c]  \  }}|t	        |||| d|        c}}S t        | d      rt        | j                  |||      S t        | t        j                        rt        | |||      S t        t        |             S c c}}w c c}}w )a  
    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   rF   rF   v   s   ( %$' "%(
1 !
XXeWffghigjUkl
 	

 % 
1 }Q:[hZiijkljmXnoo
 	

 uo&(JYf
 	
 %&(:PXhuvv"4;//'

s   C/*C5r(   c                    t        j                  dd       t               5 }t        |      5  t	        |        |j                         }ddd       ddd       t              j                         S # 1 sw Y   *xY w# 1 sw Y   .xY w)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.      st     
DC8	 sOC0 elln  #3'2244   s"   A?A3
A?3A<	8A??Bc                 v    | j                  d      r(| j                  dd        | d   D ]  }t        |        y y )Nchildrenoutputs)getpopprune_outputs_if_children)nodechilds     r   r[   r[      s?     xx
D!*% 	-E%e,	- r   z(.*)\.(\d+)$c                     t         j                  | j                  dd            }|r| j                  d      sy|j                  d      t	        fd| d   D              S )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 rW   F   c              3   N   K   | ]  }d  d |j                  dd      v   yw).r_   r`   NrY   ).0r]   numbers     r   	<genexpr>z!is_layer_block.<locals>.<genexpr>   s)     [6(!}		- <<[s   "%)LAYER_SUFFIX_REmatchrY   groupany)r\   ri   rf   s     @r   is_layer_blockrl      sT     !!$((=""=>E,[[^F[$zJZ[[[r   c                 n   | j                  d      syt        | d         D cg c]  \  }}t        |      s||f }}}t        |      dkD  r@|dd D cg c]  \  }}|	 }}}t        | d         D cg c]  \  }}||vs| c}}| d<   | d   D ]  }t	        |        yc c}}w c c}}w c c}}w )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.
    rW   Nra   r   )rY   rE   rl   lenprune_intermediate_layers)r\   rK   r]   layer_blocksr@   	to_removes         r   rp   rp      s     88J/8j9I/Jd81en]bNcQJdLd
<1#/"#5641aQ6	62;D<L2MdhaQRZcQcEdZj! )!%() e 7ds   B%B%B+7B1B1c                    | rF	 t        j                  | d       t         j                  j                  | |j                  dz         }n|j                  dz   }t        j                  d| d       |dz   }|d	z   }t        |j                         t        |d
      5 }t        j                  |j                  |d       d d d        fdt        j                  t        j                  |j                              } |       t        |d
      5 }t        j                  ||d       d d d        y # t
        $ r}t        d|  d      |d }~ww xY w# 1 sw Y   xY w# 1 sw Y   y xY w)NTexist_ok_debug_tree"Unexpected or existing debug_path=rc   zWriting model trace at z.jsonz_FULL_TENSORS.jsonz_SUMMARY.jsonwra   )indentc                     fd | j                  di               | j                  di              | j                  dg       D ]
  } |        y )Nc                     t        | t              r0| j                  dd        | j                         D ]
  } |        y t        | t              r| D ]
  } |        y y )Nr(   )rB   rG   rZ   valuesrC   )valrL   itemcleans      r   r   z:log_model_debug_trace.<locals>.strip_values.<locals>.clean   s\    #t$& A!HC&  D$K  'r   inputsrX   rW   rd   )r\   r]   r   strip_valuess     @r   r   z+log_model_debug_trace.<locals>.strip_values   sR    	  	dhhx$%dhhy"%&XXj"- 	 E	 r   )r0   makedirsr1   r2   _debugger_module_dump_name	Exceptionr6   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      sJ   	XKK
T277<<
E,L,L},\]D //-?
KK)$u56++I/)Le../	i	 1		%""Aa01   

4::e&6&678I	lC	  *A		)Qq)* *E  	XA*QOPVWW	X1 1.* *s0   AD5 #EE"5	E>EEE"E+do_prune_layersc                    	
  j                   j                  		ddg d _        g  _        	 _        r	 t        j                  d        fd} j                         D ]  \  }}|dk(  r ||	 d|          j                  
t        j                  
      	 
fd	       }| _
        y# t        $ r}t        d d      |d}~ww xY w)
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 associated 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   rX   rW   Trt   rw   rc   c                 v      j                   t        j                         fd       }| _         y )Nc                     t               r\| |d}|D ci c]  }t        ||         dkD  s|||    }}t        | d      d g d}	j                  j	                  |       t        j                         5   | i |}d d d        t               rt        d 
j                         D              dkD  rd d<   nt         d      d<   	j                  j                         }|d	   s|j                  d	       	j                  r!	j                  d
   d	   j	                  |       S c c}w # 1 sw Y   xY w)Nargskwargsr   _inputsrA   r   c              3       K   | ]  }d   yw)r   Nr   )re   r@   s     r   rg   zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>F  s     :Qq:s   rX   _outputsrW   rn   )
r   ro   rF   _debugger_model_call_stackappendr   no_gradsumnamed_childrenrZ   )inpskwsdict_inputsrM   r\   r=   finishedr    r   r   moduleorig_forwardr!   s          r   wrapped_forwardzE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward1  sZ   '+s;:EaQ[YZ^I\_`I`q+a.0aa#,+##-!))27&;	  $ "
 0077= 1"D0C01 :&"7"7"9::Q>&*DO&3#-!))28&<	'DO !;;??A
+LL,3344R8DKKHUJE b1 1s   D4D4<	D99E)forward	functoolswraps)r   r   r   r   r    r   r!   s   `` @r   wrap_forwardz,_attach_debugger_logic.<locals>.wrap_forward.  s6    ~~		&%	 %	 
'%	N )r   r`   c                     t               r8 dt        | |d d      d g d}	j                  j                  |        
| i |}t               r	j                  rt        | d      d<   	j                  j	                         }|d   	j
                  d<   |d   	j
                  d<   |d	   	j
                  d	<   t        	j
                  j                               D cg c].  }	j
                  |   r	j
                  j	                  |d       0 c} rt        	j
                         t        	
       |S c c}w )Nz (top-level)r   r   rA   r   r   rX   r   rW   )r    r   )
r   rF   r   r   rZ   r   rC   keysrp   r   )r   r   top_noder=   r   rM   
class_namer    r   r   real_top_forwardr!   s         r   top_wrapped_forwardz3_attach_debugger_logic.<locals>.top_wrapped_forwardd  sV   ?",\:'!S1)%%/L"8	  
H ,,33H=,,?u??"/%!!+H5	#HY 77;;=H)1();EX&*29*=EY'+3J+?EZ(489I9I9N9N9P4QmqY^YiYijkYlU!!!T*m )%*:*:;!ZuE
 ns   ,EE)	__class____name__r   r   r   r0   r   r   r6   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 8i2:Y:,av 678 }}__%&# # '#J (EM  	XA*QOPVWW	Xs   B: :	CCC)r   )backendsc              #   <  K   | j                         D ci c]  \  }}||j                   }}}| j                  || <   t        | |||       	 |  |j                         D ]  \  }}||_         yc c}}w # |j                         D ]  \  }}||_         w xY ww)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 separate 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   rH   )	r   r    r   r!   r@   morig_forwardsmodule_instanceforward_methods	            r   model_addition_debugger_contextr     s     f /4.A.A.CDdaQ		\DMD ==M%5*oxH5/</B/B/D 	5+O^&4O#	5 E 0=/B/B/D 	5+O^&4O#	5s'   BA2 BA8 &B8!BB)NTN)rc   TT)NTT)*r   r   r0   re
contextlibr   r   ior   utilsr   utils.import_utilsr   r	   r   safetensors.torchr
   r   r   is_availabletorch.distributed.tensor
get_loggerr   r   r   compiler   strr   r   boolr>   rF   rJ   r.   r[   rh   rl   rp   r   r   r   r   r   r   <module>r      s      	 	 6   < +#( %%'''+$#(  
		H	%- "rzz"=> C3 C3 C  ^b.Tz.48.PSVZPZ.b(0S4Z (0$ (0^adh^h (0V5 5"- "**_-\")((*cDj (*Z  	|(|( |( 	|(~ 
: " 	85d
85 85 	85  85r   