
    rhB              
       J   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Zd dlmZ ej$                  j'                         ZndZdd	lmZ  ej.                  e      Zd
 Z ej6                  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jF                  fdZ$d Z% ej6                  d      Z&d Z'd Z(d Z)	 	 	 d"de
e   de
e    de fdZ* ed      e	 	 	 d#de
e   de
e    de
e    fd               Z+y)$    N)contextmanagerredirect_stdout)StringIO)Optional   )is_torch_availablerequires)	save_fileF)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     u/var/www/html/ai-insurance-compliance-backend/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   4   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?   C   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   rG   rG   t   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 rX   F   c              3   N   K   | ]  }d  d |j                  dd      v   yw).r`   ra   NrZ   ).0r^   numbers     r   	<genexpr>z!is_layer_block.<locals>.<genexpr>   s)     [6(!}		- <<[s   "%)LAYER_SUFFIX_REmatchrZ   groupany)r]   rj   rg   s     @r   is_layer_blockrm      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.
    rX   Nrb   r   )rZ   rF   rm   lenprune_intermediate_layers)r]   rL   r^   layer_blocksrA   	to_removes         r   rq   rq      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=rd   zWriting model trace at z.jsonz_FULL_TENSORS.jsonz_SUMMARY.jsonwrb   )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)   )rC   rH   r[   valuesrD   )valrM   itemcleans      r   r   z:log_model_debug_trace.<locals>.strip_values.<locals>.clean   s\    #t$& A!HC&  D$K  'r   inputsrY   rX   re   )r]   r^   r   strip_valuess     @r   r   z+log_model_debug_trace.<locals>.strip_values   sR    	  	dhhx$%dhhy"%&XXj"- 	 E	 r   )r1   makedirsr2   r3   _debugger_module_dump_name	Exceptionr7   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 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.
    Nr`   r   rY   rX   Tru   rx   rd   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   _inputsrB   r   c              3       K   | ]  }d   yw)r   Nr   )rf   rA   s     r   rh   zX_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward.<locals>.<genexpr>D  s     :Qq:s   rY   _outputsrX   ro   )
r   rp   rG   _debugger_model_call_stackappendr   no_gradsumnamed_childrenr[   )inpskwsdict_inputsrN   r]   r>   finishedr!   r   r   moduleorig_forwardr"   s          r   wrapped_forwardzE_attach_debugger_logic.<locals>.wrap_forward.<locals>.wrapped_forward/  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   ra   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   rB   r   r   rY   r   rX   )r!   r   )
r   rG   r   r   r[   r   rD   keysrq   r   )r   r   top_noder>   r   rN   
class_namer!   r   r   real_top_forwardr"   s         r   top_wrapped_forwardz3_attach_debugger_logic.<locals>.top_wrapped_forwardb  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   r1   r   r   r7   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 spearate 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   rI   )	r   r!   r   r"   rA   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)rd   TT)NTT),r   r   r1   re
contextlibr   r   ior   typingr   utils.import_utilsr   r	   r   torch.distributed.tensorsafetensors.torchr
   r   is_availabler   utilsr   
get_loggerr   r   r   compiler   strr   r    boolr?   rG   rK   r/   r\   ri   rm   rq   r   r   r   r   r   r   <module>r      s      	 	 6   < #+ $)#4#4#A#A#C #(   
		H	%- "rzz"=> C3 C3 C  dh.}.7;.S[\_S`.b(0Xc] (0T (0aijman (0V5 5"- "**_-\")((*Z !$&*	|(|( d^|( 	|(~ 
: !%&*#	8585 d^85 tn	85  85r   