
    Uh4                        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  e       rd dlZd dlZddlmZ  ej$                  e      Zej*                  j-                         Zd	 Z ej2                  d
      ZdedefdZd Zd Zdej>                  fdZ d Z! ej2                  d      Z"d Z#d Z$d Z%	 	 dde
e   de
e&   fdZ' ed      edde
e   de
e&   fd              Z(y)    N)contextmanagerredirect_stdout)StringIO)Optional)requires   )is_torch_available)loggingc                      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     t/var/www/catia.catastroantioquia-mas.com/valormas/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   5   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   c                 X   t        | t        t        f      r| D cg c]  }t        |       c}S t        | t              r-| j                         D ci c]  \  }}|t        |       c}}S t        | d      rXt        j                  d       t        |       }t        | j                  j                        t        | j                  j                        |d}| j                  j                  t        j                  t        j                  t        j                   hv r| j                  j#                         } |j%                  t'        t        | j)                                     t'        t        | j+                                     t'        t        | j-                                     t'        t        | j/                                     d       |S t        | t        j0                        r t        j                  d       t        |       }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 t'        t        |             S c c}w c c}}w )a  
    Recursively build a JSON-serializable Python structure from `value`.
    Tensors and DTensors become sanitized repr strings.
    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.

    Returns:
        A nested Python structure (list, dict, or sanitized string) that is safe to json.dump.
    r   T)sci_mode)shapedtypevalue)meanstdminmax)
isinstancelisttuple_serialize_iodictitemshasattrr   set_printoptions_repr_to_listr   r   r"   r#   float16float32bfloat16cloneupdater   r%   r&   r'   r(   Tensor)r$   vkval_reprouts        r   r,   r,   D   s3    %$'*/0Qa 00%05>1=##>>uo&- '%--334%--334

 $$u~~(VV''--/EJJ3D4FG24		3DE24		3DE24		3DE	 
%&- '%++&%++&

 ;;5==%--HHJJ3D4FG24		3DE24		3DE24		3DE	 
"4;//[ 1 ?s   L!L&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   r0   r   r   printgetvaluer   
splitlines)r$   bufraws      r   r1   r1      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   rI   rI      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 rE   F   c              3   N   K   | ]  }d  d |j                  dd      v   yw).rM   rN   NrG   ).0rK   numbers     r   	<genexpr>z!is_layer_block.<locals>.<genexpr>   s)     [6(!}		- <<[s   "%)LAYER_SUFFIX_REmatchrG   groupany)rJ   rW   rT   s     @r   is_layer_blockrZ      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.
    rE   NrO   r   )rG   	enumeraterZ   lenprune_intermediate_layers)rJ   irK   layer_blocks_	to_removes         r   r_   r_      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_treez"Unexpected or existing debug_path=z. zWriting model trace at z.jsonz_FULL_TENSORS.jsonz_SUMMARY.jsonwrO   )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$   )r)   r-   rH   valuesr*   )valr8   itemcleans      r   rn   z:log_model_debug_trace.<locals>.strip_values.<locals>.clean   s\    #t$& A!HC&  D$K  'r   inputsrF   rE   rR   )rJ   rK   rn   strip_valuess     @r   rp   z+log_model_debug_trace.<locals>.strip_values   sR    	  	dhhx$%dhhy"%&XXj"- 	 E	 r   )osmakedirspathjoin_debugger_module_dump_name	Exception
ValueErrorloggerinforI   
_call_treeopenjsondumploadsdumps)	
debug_pathmodelbasee	full_pathsummary_pathf	tree_copyrp   s	           @r   log_model_debug_tracer      sL   	U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  	UA*RPQsSTT	U1 1.* *s0   AD5 #EE#5	E>EEE #E,r   do_prune_layersc                 8     j                   j                  ddg d _        g  _         _         fd} j                         D ]  \  }}|dk(  r || d|          j                  t        j                         fd       }| _        y)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.
    NrM   ro   rF   rE   c                 r      j                   t        j                         fd       }| _         y )Nc                  n   t               rU| |d}|D ci c]  }t        ||         dkD  s|||    }}t        |      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<   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   r   c              3       K   | ]  }d   yw)r   Nr   )rS   rb   s     r   rU   zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>  s     :Qq:s   rF   rE   r\   )
r   r^   r,   _debugger_model_call_stackappendr   no_gradsumnamed_childrenrH   )inpskwsdict_inputsr9   rJ   r;   finishedr   r   moduleorig_forwards          r   wrapped_forwardzE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward  s/   '+s;:EaQ[YZ^I\_`I`q+a.0aa#,+K8# "	 0077= 1"D0C01 :&"7"7"9::Q>&*DO&3C&8DO ;;??A
+LL,3344R8DKKHUJ1 b1 1s   D&D&5	D++D4)forward	functoolswraps)r   r   r   r   r   s   `` @r   wrap_forwardz,_attach_debugger_logic.<locals>.wrap_forward  s0    ~~		&	 
'	: )r   rN   rQ   c                  ~   t               r1 dt        | |d      d g d}	j                  j                  |        
| i |}t               r	j                  rt        |      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   rF   ro   rE   )r   r   )
r   r,   r   r   rH   rz   r*   keysr_   r   )r   r   top_noder;   r   r9   
class_namer   r   r   real_top_forwards         r   top_wrapped_forwardz3_attach_debugger_logic.<locals>.top_wrapped_forward1  s,   ?",\:'(EF	H ,,33H=,,?u??"/"4HY77;;=H)1();EX&*29*=EY'+3J+?EZ(489I9I9N9N9P4QmqY^YiYijkYlU!!!T*m )%*:*:;!ZuE
 ns   D:3D:)		__class____name__rz   r   ru   named_modulesr   r   r   )	r   r   r   r   name	submoduler   r   r   s	   ```    @@r   _attach_debugger_logicr      s     ))J (2Td`bcE')E$'1E$!)H !..0 8i2:Y:,av 678 }}__%& '6 (EMr   )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.
    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
    import requests
    from transformers import LlavaProcessor, LlavaForConditionalGeneration
    from transformers.model_debugging_utils import 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, low_cpu_mem_usage=True)

    # 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   r.   )r   r   r   rb   morig_forwardsmodule_instanceforward_methods           r   model_addition_debugger_contextr   P  s     R /4.A.A.CDdaQ		\DMD ==M%5*o>5/</B/B/D 	5+O^&4O#	5 E 0=/B/B/D 	5+O^&4O#	5s'   BA1BA7 &B7!BB)rQ   T)NT))r   r|   rq   re
contextlibr   r   ior   typingr   transformers.utils.import_utilsr   utilsr	   r   torch.distributed.tensorr
   
get_loggerr   rx   r   is_availabler   r   compiler   strr   r   r,   r7   r1   rI   rV   rZ   r_   r   boolr   r   r   r   r   <module>r      s7      	 	 6   4 % #  
		H	%  %00==? - "rzz"=> C3 C3 C ;0|5 5"- "**_-\")((*Z !$&*^(^( d^^(B 
:.5x} .5^fgk^l .5  .5r   