
     `iB              	       l   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 ddlmZmZ  e            r,d dlZd dlmZ d	Zej                                        rd dlZd
Znd	Z ej        e          Zd Z ej        d          ZdedefdZd Z	 d#de
e         de de
e         fdZ!d#de
e         de de
e         fdZ"dej#        fdZ$d Z% ej        d          Z&d Z'd Z(de
e         fdZ)	 	 	 d$dede de fdZ* ed !          e	 	 	 d%de
e         de de fd"                        Z+dS )&    N)contextmanagerredirect_stdout)StringIO)Optional   )logging)is_torch_availablerequires)	save_fileFTc                      t           rt          j                                        sdS t          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     v/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/transformers/model_debugging_utils.py_is_rank_zeror   -   s?    ( U->-M-M-O-O t%%''1,,r   zobject at 0x[0-9A-Fa-f]+x_strreturnc                 8    t                               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   7   s    
  ##$:EBBBr   c                 P    t                      rdt          | j                   S dS )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|r|                    d          s|dz  }|r t          j                            ||          n|}t          d|                                 	                                
                                i|           d| }nt          d|d|d          t          | j                  t          | j                  |d	}| j        t           j        t           j        t           j        hv r|                    t'          t          |                                                     t'          t          |                                                     t'          t          |                                                     t'          t          |                                                     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?   F   s   $ 
D)))) 
T!%((			 T%%n55 	,^+M>H[27<<
M:::m65++--4466::<<=xHHH(((		RHRRMRRRSSS ek""ek"" C
 {u}emU^DDD

/UZZ\\0B0BCC.tEIIKK/@/@AA.tEIIKK/@/@AA.tEIIKK/@/@AA	 	
 	
 	
 Jr   c                    t          | t          t          f          rfdt          |           D             S t          | t                    r"fd|                                 D             S t          | d          rt          | j                  S t          | t          j
                  rt          |           S t          t          |                     S )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.
    c           
      F    g | ]\  }}t          | d |           S _r!   r"   r#   _serialize_io).0ivr!   r#   r"   s      r   
<listcomp>z!_serialize_io.<locals>.<listcomp>   sN     
 
 
1 !
XXeUkUkhiUkUklll
 
 
r   c                 H    i | ]\  }}|t          | d |           S rB   rE   )rG   krI   r!   r#   r"   s      r   
<dictcomp>z!_serialize_io.<locals>.<dictcomp>   sP     
 
 
1 }Q:[hXnXnklXnXnooo
 
 
r   r   rD   )
isinstancelisttuple	enumeratedictitemshasattrr?   r   r   Tensorr   r   )r)   r!   r"   r#   s    ```r   rF   rF   w   s'   ( %$'' 

 
 
 
 
 
!%((
 
 
 	

 % 

 
 
 
 
 

 
 
 	

 uo&& 
(JYf
 
 
 	
 %&& w(:PXhuvvvv"4;;///r   r)   c                 P   t          j        dd           t                      5 }t          |          5  t	          |            |                                }ddd           n# 1 swxY w Y   ddd           n# 1 swxY w Y   t          |                                          S )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888	 sOC00  ellnn                              #3''22444s4   A<$A%A<%A)	)A<,A)	-A<<B B c                     |                      d          r0|                     dd            | d         D ]}t          |           d S d S )Nchildrenoutputs)getpopprune_outputs_if_children)nodechilds     r   rc   rc      se     xx
 -D!!!*% 	- 	-E%e,,,,- -	- 	-r   z(.*)\.(\d+)$c                     t                               |                     dd                    }|r|                     d          sdS |                    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 r_   F   c              3   P   K   | ] }d  d |                     dd          v V  !dS ).rg   rh   Nra   )rG   re   numbers     r   	<genexpr>z!is_layer_block.<locals>.<genexpr>   s>      [[}6}}}		- < <<[[[[[[r   )LAYER_SUFFIX_REmatchra   groupany)rd   rp   rm   s     @r   is_layer_blockrs      s}     !!$((=""="=>>E ,, u[[^^F[[[[$zJZ[[[[[[r   c                 >   |                      d          sdS d t          | d                   D             }t          |          dk    r8d |dd         D             fdt          | d                   D             | d<   | d         D ]}t          |           dS )	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.
    r_   Nc                 :    g | ]\  }}t          |          ||fS r   )rs   )rG   rH   re   s      r   rJ   z-prune_intermediate_layers.<locals>.<listcomp>   s.    ddd81en]bNcNcdQJdddr   ri   c                     g | ]\  }}|S r   r   )rG   rH   rC   s      r   rJ   z-prune_intermediate_layers.<locals>.<listcomp>   s    66641aQ666r   r   c                 "    g | ]\  }}|v	|S r   r   )rG   rH   re   	to_removes      r   rJ   z-prune_intermediate_layers.<locals>.<listcomp>   s)    dddhaQRZcQcQcEQcQcQcr   )ra   rQ   lenprune_intermediate_layers)rd   layer_blocksre   ry   s      @r   r{   r{      s     88J ddyj9I/J/JdddL
<166<"#5666	dddd)D<L2M2MdddZj! ) )!%(((() )r   c                    | rf	 t          j        | d           t           j                            | |j        dz             }n0# t
          $ r}t          d|  d          |d }~ww xY w|j        dz   }t                              d| d           |dz   }|d	z   }t          |j
                   t          |d
          5 }t          j        |j
        |d           d d d            n# 1 swxY w Y   fdt          j        t          j        |j
                            } |           t          |d
          5 }t          j        ||d           d d d            d S # 1 swxY w Y   d S )NTexist_ok_debug_tree"Unexpected or existing debug_path=rk   zWriting model trace at z.jsonz_FULL_TENSORS.jsonz_SUMMARY.jsonwri   )indentc                     fd |                      di                       |                      di                      |                      dg           D ]} |           d S )Nc                     t          | t                    r:|                     dd            |                                 D ]} |           d S t          | t                    r| D ]} |           d S d S )Nr)   )rN   rR   rb   valuesrO   )valrI   itemcleans      r   r   z:log_model_debug_trace.<locals>.strip_values.<locals>.clean   s    #t$$  &&&  AE!HHHH C&&      DE$KKKK      r   inputsr`   r_   rl   )rd   re   r   strip_valuess     @r   r   z+log_model_debug_trace.<locals>.strip_values   s    	  	  	  	  	  	dhhx$$%%%dhhy"%%&&&XXj"-- 	  	 EL	  	 r   )r1   makedirsr2   r3   _debugger_module_dump_name	Exceptionr7   loggerinforc   
_call_treeopenjsondumploadsdumps)	r!   modelbasee	full_pathsummary_pathf	tree_copyr   s	           @r   log_model_debug_tracer      s$    @	XK
T22227<<
E,L},\]]DD 	X 	X 	XO*OOOPPVWW	X /-?
KK5$555666++I/)Le.///	i		 1	%"Aa00001 1 1 1 1 1 1 1 1 1 1 1 1 1 1           
4:e&67788IL	lC	 	  *A	)Qq))))* * * * * * * * * * * * * * * * * *s;   >A 
A'A""A' C))C-0C-?E$$E(+E(rk   do_prune_layersc                    	
  j         j        		ddg d _        g  _        	 _        r>	 t          j        d           n&# t          $ r}t          d d          |d}~ww xY w fd} 	                                D ]\  }}|dk    r ||	 d|             j
        
t          j        
          	 
fd	            }| _
        dS )
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rg   r   r`   r_   Tr~   r   rk   c                 r      j         t          j                   fd            }| _         d S )Nc                     t                      rH| |dfdD             t           d          d g d}j                            |           t	          j                    5   
| i |}d d d            n# 1 swxY w Y   t                      rt          d 	                                D                       dk    rd |d<   nt          | d	          |d<   j                                        }|d
         s|                    d
           j        r&j        d         d
                             |           |S )Nargskwargsc                 T    i | ]$}t          |                   d k    ||         %S )r   )rz   )rG   rL   dict_inputss     r   rM   zY_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<dictcomp>6  s7    aaaQ[YZ^I\I\_`I`I`q+a.I`I`I`r   _inputsrD   r   c              3      K   | ]}d V  dS )r   Nr   )rG   rC   s     r   rn   zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>G  s"      ::Qq::::::r   r   r`   _outputsr_   rw   )	r   rF   _debugger_model_call_stackappendr   no_gradsumnamed_childrenrb   )inpskwsrd   r>   finishedr   r!   r   r   moduleorig_forwardr"   s        @r   wrapped_forwardzE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward2  s    >'+s;;aaaa+aaa#,+##-!))2&;&;&;	    $ "
 
 077=== 1 1"lD0C001 1 1 1 1 1 1 1 1 1 1 1 1 1 1  V::&"7"7"9"9:::::Q>>&*DOO&3#-!))2&<&<&<	' ' 'DO !;??AA
+ -LL,,,3 V4R8DKKHUUUJs   ,	BBB)forward	functoolswraps)r   r   r   r   r!   r   r"   s   `` @r   wrap_forwardz,_attach_debugger_logic.<locals>.wrap_forward/  sb    ~		&	&%	 %	 %	 %	 %	 %	 %	 %	 %	 
'	&%	N )r   rh   c                  J   t                      r; dt          | |d
 d          d g d}j                            |            	| i |}t                      rj        rt          |
 d          |d<   j                                        }|d         j        d<   |d         j        d<   |d	         j        d	<   fd
t          j                                                  D              rt          j                   t                     |S )Nz (top-level)r   r   rD   r   r   r`   r   r_   c                 `    g | ]*}j         |         j                             |d           +S )N)r   rb   )rG   rL   r   s     r   rJ   zG_attach_debugger_logic.<locals>.top_wrapped_forward.<locals>.<listcomp>  s;    mmmqY^YijkYlmU!!!T**mmmr   )r!   r   )
r   rF   r   r   rb   r   rO   keysr{   r   )r   r   top_noder>   r   
class_namer!   r   r   real_top_forwardr"   s        r   top_wrapped_forwardz3_attach_debugger_logic.<locals>.top_wrapped_forwarde  s   ?? 	>",:::'!S11)%%/"8"8"8	    
 
H ,33H===,,,?? 	Fu? 	F"/%!!+555	# # #HY 7;;==H)1();EX&*29*=EY'+3J+?EZ(mmmmD9I9N9N9P9P4Q4Qmmmm  <)%*:;;;!ZuEEEE
r   )	__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     sv   & )J (2Td`bccE')E$'1E$ X	XK
T22222 	X 	X 	XO*OOOPPVWW	X+) +) +) +) +) +) +)\ !..00 8 8i2::Y: 6 6 6 67777 }_%&&# # # # # # # # # '&#J (EMMMs   A 
A*A%%A*)r   )backendsc              #     K   d |                                  D             }| j        || <   t          | |||           	 | V  |                                D ]\  }}||_        dS # |                                D ]\  }}||_        w xY 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)
    ```

    c                 $    i | ]\  }}||j         S r   )r   )rG   rC   ms      r   rM   z3model_addition_debugger_context.<locals>.<dictcomp>  s     DDDdaQ	DDDr   N)r   r   r   rS   )r   r!   r   r"   orig_forwardsmodule_instanceforward_methods          r   model_addition_debugger_contextr     s      f EDe.A.A.C.CDDDM =M%5*oxHHH5/</B/B/D/D 	5 	5+O^&4O##	5 	5}/B/B/D/D 	5 	5+O^&4O##	5s   A% %#B)NTN)rk   TT)NTT),r   r   r1   re
contextlibr   r   ior   typingr   utilsr   utils.import_utilsr	   r
   r   safetensors.torchr   r   r   is_availabletorch.distributed.tensor
get_loggerr   r   r   compiler   strr   r    boolr?   rF   rU   r/   rc   ro   rs   r{   r   r   r   r   r   r   <module>r      s         				 				 6 6 6 6 6 6 6 6                   < < < < < < < <  )LLL++++++#( %%'' ,'''''+$#(  
	H	%	%- - - "rz"=>> C3 C3 C C C C      dh. .}.7;.S[\_S`. . . .b(0 (0Xc] (0T (0aijman (0 (0 (0 (0V5 5 5 5 5"- - - "*_--\ \ \") ) )((*hsm (* (* (* (*Z  	|( |(|( |( 	|( |( |( |(~ 
: !% 	85 8585 85 	85 85 85  85 85 85r   