o
    h-                     @   s(  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eZej Zd
d ZedZdedefddZdd Zdd Zdd Zdd Z defddZ!e	dddd Z"e	dded"dee fd d!Z#dS )#    N)contextmanager)Optional)export   )is_torch_available)nn)PreTrainedModel)loggingc                   C   s    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 r   r   v/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/transformers/model_debugging_utils.py_is_rank_zero,   s   r   zobject at 0x[0-9A-Fa-f]+x_strreturnc                 C   s   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   r   r   r   _sanitize_repr_for_diff6   s   r   c                 C   s   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)xr   r   r   _dtensor_repr>   s   r   c                 C   s   t | ttfrdd | D S t | trdd |  D S t| dr3t| jjt| jj	t
t| dS t | tjrIt| jt| j	t
t| dS t
t| S )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.
    c                 S   s   g | ]}t |qS r   _serialize_io).0vr   r   r   
<listcomp>S   s    z!_serialize_io.<locals>.<listcomp>c                 S   s   i | ]	\}}|t |qS r   r   )r   kr   r   r   r   
<dictcomp>V   s    z!_serialize_io.<locals>.<dictcomp>r   )shapedtypevalue)
isinstancelisttupledictitemshasattrr   r   r"   r#   r   r   Tensor)r$   r   r   r   r   E   s   




 r   c                 C   s4   |  dr| dd  | d D ]}t| qd S d S )Nchildrenoutputs)getpopprune_outputs_if_children)nodechildr   r   r   r0   i   s   

r0   c              
   C   s   | r,zt j| dd t j| |jd }W n ty+ } z
td|  d| d }~ww |jd }td|  t	|d}t
|j tj|j|dd	 W d    d S 1 sXw   Y  d S )
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openr0   
_call_treejsondump)
debug_pathmodeloutput_patheoutfiler   r   r   log_model_debug_tracer   s   

"rI   rD   c                    s    d d g d_ g _ _fdd} D ]\}}|dkr!q||  d|  qjt fdd}|_fdd	}| d
dg}|D ]}	t|	d }
|
rkt	|
t
jtfrk|
|  d S qQd S )Nmodule_pathinputsr-   r,   c                    s,   j t fdd}|_ d S )Nc                     s   t  r | |d  fdd D  t d g d}j| t  | i |}W d    n1 s6w   Y  t  rqtdd  D dkrPd |d< nt||d< j }|d	 sd|d	 jrqjd
 d	 | |S )Nargskwargsc                    s&   i | ]}t  | d kr| | qS )r   )lenr   r    dict_inputsr   r   r!      s   & zY_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<dictcomp>rJ   c                 s   s    | ]}d V  qdS )r   Nr   )r   _r   r   r   	<genexpr>   s    zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>r   r-   r,   )	r   r   _debugger_model_call_stackappendr   inference_modesumnamed_childrenr/   )inpskwsr1   outfinished)	full_pathrE   moduleorig_forwardrR   r   wrapped_forward   s,   




zE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward)forward	functoolswraps)ra   r`   rc   rE   )r`   ra   rb   r   wrap_forward   s   
z,_attach_debugger_logic.<locals>.wrap_forward .c                     s   t  r  dt| |dd g d}j| | i |}t  rSjrSt||d< j }|d jd< |d jd< |d jd< fddtj D  |S )	Nz (top-level)rM   rJ   r-   rL   r,   c                    s$   g | ]} j | s j |d qS N)rA   r/   rQ   rg   r   r   r      s   $ zG_attach_debugger_logic.<locals>.top_wrapped_forward.<locals>.<listcomp>)r   r   rW   rX   r/   rA   r&   keys)r\   r]   top_noder^   r_   )
class_namerE   real_top_forwardr   r   top_wrapped_forward   s    
z3_attach_debugger_logic.<locals>.top_wrapped_forwardc                    sZ   t  r jr j }|d jd< |d jd< |d jd< t  r+t d d S d S )NrL   r-   r,   rD   rE   )r   rW   r/   rA   rI   )rT   rL   r-   r_   rq   r   r   
final_hook   s   
z*_attach_debugger_logic.<locals>.final_hooklanguage_modelrE   )rA   rW   r;   named_modulesrd   re   rf   register_forward_hookgetattrr%   r   Moduler   )rE   rn   rD   rh   name	submodulerp   rr   possible_model_calls
model_callthis_model_callr   )rn   rD   rE   ro   r   _attach_debugger_logic   s,   $


r}   )r   )backendsc                    s*    j t j  fd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                    s&   | g|R i | t |  j d S rk   )r}   __name__)selfrN   rO   cls	orig_initr   r   wrapped_init  s   z-model_addition_debugger.<locals>.wrapped_init)__init__re   rf   )r   r   r   r   r   model_addition_debugger   s
   .
r   c                 c   s"    t | | jj| z| V  W dS 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   )rE   rD   r   r   r   model_addition_debugger_context  s
   (r   rk   )$re   rB   r7   re
contextlibr   typingr   transformers.utils.import_utilsr   utilsr   r   torch.distributed.tensorr   modeling_utilsr   r	   
get_loggerr   r>   r   is_availabler
   r   compiler   strr   r   r   r0   rI   r}   r   r   r   r   r   r   <module>   s:   


$	c
8