
    ##h-                        d dl Z d dlZd dlZd dl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 ddlm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 Zd Z defdZ! e	d      d        Z" e	d      eddee   fd              Z#y)    N)contextmanager)Optional)export   )is_torch_available)nn)PreTrainedModel)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     _/var/www/html/sandstorm/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   c                    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      rRt        | j                  j                        t        | j                  j                        t        t        |             dS t        | t        j                        r>t        | j                        t        | j                        t        t        |             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   )shapedtypevalue)
isinstancelisttuple_serialize_iodictitemshasattrr   r   r!   r"   r   r   Tensor)r#   vks      r   r'   r'   E   s     %$'*/0Qa 00%05>1=##>>uo& %--334%--334,T%[9
 	
 %& ekk*T%++5FQhimnsitQuvv #4;//' 1 ?s   D7D<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   r3   r3   i   s?     xx
D!*% 	-E%e,	- r   c                    | rF	 t        j                  | d       t         j                  j                  | |j                  dz         }n|j                  dz   }t        j                  d|        t        |d      5 }t        |j                         t        j                  |j                  |d	       d d d        y # t
        $ r}t        d|  d|       d }~ww xY w# 1 sw Y   y xY w)
NF)exist_okz_debug_tree.jsonz"Unexpected or existing debug_path=z. zWriting model trace at w   )indent)osmakedirspathjoin_debugger_module_dump_name	Exception
ValueErrorloggerinfoopenr3   
_call_treejsondump)
debug_pathmodeloutput_patheoutfiles        r   log_model_debug_tracerM   r   s    	UKK
U3'',,z53S3SVh3hiK 669KK
KK)+78	k3	 77!%"2"23		%""GA67 7  	UA*RPQsSTT	U
7 7s$   AB= <8C=	CCCC(rH   c                     d d g d _         g  _         _         fd} j                         D ]  \  }}|dk(  r || d|          j                  t        j                         fd       }| _         fd} j                  |       ddg}|D ]E  }	t         |	d       }
|
st        |
t        j                  t        f      s4|
j                  |        y  y )	Nmodule_pathinputsr0   r/   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   rO   c              3       K   | ]  }d   yw)r   Nr   ).0_s     r   	<genexpr>zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>   s     :Qq:s   r0   r/   )
r   lenr'   _debugger_model_call_stackappendr   inference_modesumnamed_childrenr2   )inpskwsdict_inputsr-   r4   outfinished	full_pathrI   moduleorig_forwards          r   wrapped_forwardzE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward   s2   '+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)rh   rg   rj   ri   rI   s   `` @r   wrap_forwardz,_attach_debugger_logic.<locals>.wrap_forward   s0    ~~		&	 
'	: )r    .c                  6   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} |S c c}w )Nz (top-level)rT   rO   r0   rQ   r/   )r   r'   r]   r^   r2   rE   r%   keys)	rb   rc   top_nodere   rf   r-   
class_namerI   real_top_forwards	         r   top_wrapped_forwardz3_attach_debugger_logic.<locals>.top_wrapped_forward   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
 ns   D3Dc                    t               r\j                  rPj                  j                         }|d   j                  d<   |d   j                  d<   |d   j                  d<   t               rt	               y y )NrQ   r0   r/   )rH   rI   )r   r]   r2   rE   rM   )rY   rQ   r0   rf   rH   rI   s       r   
final_hookz*_attach_debugger_logic.<locals>.final_hook   sw    ?u??77;;=H)1();EX&*29*=EY'+3J+?EZ(?!ZuE r   language_modelrI   )rE   r]   r?   named_modulesrk   rl   rm   register_forward_hookgetattrr$   r   Moduler	   )rI   rt   rH   rn   name	submodulerv   rx   possible_model_calls
model_callthis_model_callru   s   ```        @r   _attach_debugger_logicr      s    '1Td`bcE')E$'1E$!)H !..0 8i2:Y:,av 678 }}__%& '. (EMF 

+ -g6* 
!%T:z/BII;WX11*=	r   )r   )backendsc                       j                   t        j                   j                          fd       }| _          S )a  
    # Model addition debugger - a model adder tracer
    This decorator 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 decorator enforces `torch.inference_mode()`.
    ## Usage

    add decorator to your model class
    ```python
    from ...modeling_utils import model_addition_debugger

    @model_addition_debugger
    class MyModel(nn.Module) # Can inherit from PreTrainedModel too
        # ... nothing else changes
    ```
    Then, in a separate script (example is for Llava)

    ```python
    import torch
    from PIL import Image
    import requests
    from transformers import LlavaProcessor, LlavaForConditionalGeneration
    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 torch.no_grad():
        output = model.forward(**inputs)
    ```

    c                 J     | g|i | t        | j                         y N)r   __name__)selfrU   rV   cls	orig_inits      r   wrapped_initz-model_addition_debugger.<locals>.wrapped_init  s#    $(((tS\\2r   )__init__rl   rm   )r   r   r   s   ` @r   model_addition_debuggerr      s<    \ I__S\\"3 #3  CLJr   c              #   b   K   t        | | j                  j                  |       	 |  y# 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.inference_mode()`.

    ## Usage

    add the context manager to a model to debug

    ```python
    import torch
    from PIL import Image
    import requests
    from transformers import LlavaProcessor, LlavaForConditionalGeneration
    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):
        output = model.forward(**inputs)
    ```

    N)r   	__class__r   )rI   rH   s     r   model_addition_debugger_contextr     s/     P 5%//":":JGs   "/* /,/r   )$rl   rF   r;   re
contextlibr   typingr   transformers.utils.import_utilsr   utilsr   r   torch.distributed.tensorr   modeling_utilsr	   r
   
get_loggerr   rB   r   is_availabler   r   compiler   strr   r   r'   r3   rM   r   r   r   r   r   r   <module>r      s       	 	 %  2 % #/  
		H	%  %00==? - "rzz"=> C3 C3 C !0H-7`# `F 5 5p *x} *  *r   