o
    *iB                     @   s  U 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m	Z	m
Z
mZmZmZ d dlZd dlmZ e eZe jed< g dZe
eee f Z			d'd	ejjd
eee  deee  dee dedeeeejjf  fddZ			d'd	ejjd
eee  deee  dee dedeeeejjejjf  fddZdedejjd
eee  de	e fddZde edB  defddZ!		d(d	ejjd
eee  deee  dedee	e	ejj   f
ddZ"e# dfdedejjd
eeee f deeee f dee defddZ$	d)d	ejjd
eeee f dedeejj def
d d!Z%d)ded"edee defd#d$Z&dejjd"edefd%d&Z'dS )*    N)defaultdict)	Generator)IterableListMappingOptionalTupleUnion)InternalModule_LOGGER)match_named_modulesmatch_named_parametersmatch_targetsmatch_modules_setget_lowest_common_ancestor_nameis_matchis_narrow_matchFmodeltargetsignorefusedwarn_on_failreturnc           	      c   s    |pg }|pg }t |}|  D ]%\}}|D ]}t||||dr5||h8 }t||||ds3||fV   nqq|rK|D ]}td| d| jj  q;dS dS )a  
    Yields names and modules which match `targets` but do not match `ignore`.
    Values are returned in order of `model.named_modules()`

    :param model: model containing submodules to match against
    :param targets: target strings, potentially containing "re:" prefixes
    :param ignore: targets to ignore, potentially containing "re:" prefixes
    :fused: optional mapping from suffixes of fused modules to the suffixes of their
        corresponding shards. See `compressed_tensors.utils.match.is_match`
    :param warn_on_fail: if True, warns if any targets do not match any modules in model
    :return: generator of module names and modules
    )r   Could not match `` in instance of N)setnamed_modulesr   r   warning	__class____name__)	r   r   r   r   r   unmatched_targetsnamemoduletarget r$   [/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/compressed_tensors/utils/match.pyr   +   s(   

r   c                 #   s    |pg }|pg }t |}|  D ]>\}}t|trq|jddD ]-\}}	| d| |D ]}
t|
 rM||
h8 }t fdd|D sM||	fV  q.q!q|rd|D ]}
td|
 d| j	j
  qTdS dS )	a  
    Yields parameters which match `targets` but do not match `ignore`.
    Values are returned in order of `model.named_modules()`

    :param model: model containing params to match against
    :param targets: target strings, potentially containing "re:" prefixes
    :param ignore: targets to ignore, potentially containing "re:" prefixes
    :fused: optional mapping from suffixes of fused modules to the suffixes of their
        corresponding shards. See `compressed_tensors.utils.match.is_match`
    :param warn_on_fail: if True, warns if any targets do not match any params in model
    :return: generator of fully-qualified param names, parent modules, and params
    F)recurse.c                 3   s    | ]	}t | V  qd S N_match_name.0ignr   	param_fqnr$   r%   	<genexpr>s   s    z)match_named_parameters.<locals>.<genexpr>r   r   N)r   r   
isinstancer
   named_parametersr*   anyr   r   r   r   )r   r   r   r   r   r    module_namer"   
param_nameparamr#   r$   r.   r%   r   R   s0   

	r   r!   r"   c                 C   sr   |pg }t |trg S t|dd d}g }|D ]}t| |r#|| q|D ]}t||r6||vr6|| q&|S )av  
    Returns the targets that match the given name and module.

    :param name: the name of the module
    :param module: the module to match
    :param targets: the target strings, potentially containing "re:" prefixes
    :return: the targets that match the given name and module

    Outputs are ordered by type: exact name match, regex name match, class name match
    c                 S   s   d| v | fS )Nre:r$   )xr$   r$   r%   <lambda>   s    zmatch_targets.<locals>.<lambda>)key)r1   r
   sortedr*   append_match_class)r!   r"   r   matched_targetsr#   r$   r$   r%   r   }   s   
	


r   namesc                 C   s`   dd | D } t | dkrdS dt|  d }dt|  d }tj||g}|d|d S )a  
    Given a list of names, returns the lowest-scope common name ignoring Nones.

    Implementation is a small alteration of os.path.commonprefix
    https://docs.python.org/3/library/os.path.html#os.path.commonprefix

    ([s1, s2]->prefix->result)
    # case 0: multiple modules: [abc.a., abc.b.] -> .abc. -> abc
    # case 1: single module: [abc.] -> .abc. -> abc
    # case 2: substring modules: [abc., ab.] -> .ab -> ""
    # case 3: parent & child: [ab., ab.a.] -> .ab. -> ab
    c                 S   s   g | ]}|d ur|qS r(   r$   )r,   r!   r$   r$   r%   
<listcomp>   s    z3get_lowest_common_ancestor_name.<locals>.<listcomp>r    r'      )lenminmaxospathcommonprefixrfind)r?   s1s2common_prefixr$   r$   r%   r      s   r   Terror_on_module_rematchc                 #   s*   |pg }|pg }t t d}t|}|  D ]Y\}}t }|D ]<}	t|||	|r\t||g}
|sI|
|krI fdd|D V  t t |}
t|} |	 | |
}||	h8 }||	hO }q t|dkrp|rptd| d| dq|t|krydS |s fdd|D V  dS td	t||  d
| )aR  
    Yields modules grouped by parent context.

    We group by parent context so that we can return ALL matches of a
    specific target that can be paired with another target. This is most
    relevant in the case of MoE modules with multiple modules for each
    expert i.e. post_attention_layernorm <-> mlp.expert.N.gate_proj,
    mlp.expert.N.up_proj for all N. The parent context will differ from
    one layer to another while being the same for one expert to another.

    Each returned group is a list (of lists) with the same size
    and order as `targets` while all matches for each target and
    the overall order of the groups are ordered in the same way
    as `model.named_modules`


    E.g. the following targets would yield modules belonging to the following layers:
    ```python3
    match_modules_set(model, ["q_proj", "k_proj", "v_proj"]) == (
        [
            [`layers.0.self_attn.q_proj`],
            [`layers.0.self_attn.k_proj`],
            [`layers.0.self_attn.v_proj`],
        ],
        [
            [`layers.1.self_attn.q_proj`],
            [`layers.1.self_attn.k_proj`],
            [`layers.1.self_attn.v_proj`],
        ],
        ...
    )
    ```

    This can be used to match layers to their corresponding downstream counterparts.
    For example, matching layer norms to their subsequent linear layers
    ```python3
    for norm, q, k, v in match_modules_set(model, (norm_tgt, q_tgt, k_tgt, v_tgt)):
        fuse_norm_linears(*norm, [*q, *k, *v])
    ```

    Alternatively for MoE you would get multiple matches
    per target per group, E.g.

    ```python3

    targets = [
        "post_attention_layernorm",
        "up_proj",
        "down_proj"
    ]
    match_modules_set(model, targets) == (
        [
            [layers.0.post_attention_layernorm],
            [
                `layers.0.mlp.experts.0.up_proj`,
                `layers.0.mlp.experts.1.up_proj`,
                ...
            ],
            [
                `layers.0.mlp.experts.0.down_proj`,
                `layers.0.mlp.experts.1.down_proj`,
                ...

            ]
        ], # <- first yield
        [
            [layers.1.post_attention_layernorm],
            [
                `layers.1.mlp.experts.0.up_proj`,
                `layers.1.mlp.experts.1.up_proj`,
                ...
            ],
            [
                `layers.1.mlp.experts.0.down_proj`,
                `layers.1.mlp.experts.1.down_proj`,
                ...
            ]
        ],
        ...
    )
    ```

    :param model: model containing modules to match against
    :param targets: target strings, potentially containing "re:" prefixes
    :param ignore: targets to ignore, potentially containing "re:" prefixes
    :param error_on_module_rematch: if True, errors when a module gets
      matched to multiple targets, if False, no error. (Defaults to True)
    Nc                       g | ]} | qS r$   r$   r,   r#   matchesr$   r%   r@   @      z%match_modules_set.<locals>.<listcomp>rB   zmodule: z$ was matched with multiple targets: zT which is unexpected disable this check by setting `error_on_module_rematch = False`c                    rN   r$   r$   rO   rP   r$   r%   r@   W  rR   z:Found a final incomplete set with matches found for keys: z  but no matches found for keys: )	r   listr   r   r   r   r<   rC   
ValueError)r   r   r   rM   parent_contextr    r!   r"   matched_targets_for_cur_moduler#   new_parent_contextr$   rP   r%   r      sT   ^


r   c                    sj   t |tr|gn|}t |tr|gn|}t t o4t fdd|D o4t fdd|D  S )a  
    Returns true if either module name or module parent classes match against target
    and the module is not an internal module. The name and module may refer to a fused
    module defined by vLLM. In these cases, a `fused` mapping must be provided.

    For example, in `vllm/model_executor/models/llama.py`:
    ```python
    packed_modules_mapping = {
        "qkv_proj": ["q_proj", "k_proj", "v_proj"],
        "gate_up_proj": ["gate_proj", "up_proj"]
    }
    ```

    :param name: name of module
    :param module: module to match
    :param target: target which matches name or module, potentially contains regex
    :fused: optional mapping from suffixes of fused modules to the suffixes of their
        corresponding shards
    c                 3   &    | ]}t | pt|V  qd S r(   r*   r=   rO   r   r"   r!   r$   r%   r0     s
    
zis_match.<locals>.<genexpr>c                 3   rX   r(   rY   r+   rZ   r$   r%   r0     s    
)r1   strr
   r3   )r!   r"   r   r   r   r$   rZ   r%   r   a  s   r   c                    s`   t |tr|gn|} dur n|  ddd | t fdd|D S )a  
    Checks if any of the targets narrowly match the module. A target narrowly matches
    a module if the target matches the module, but does not match the module's parent

    :param model: model containing both module and its parent
    :param targets: target strings, potentially containing "re:" prefixes
    :param name: name of module to match
    :param module: module to match. If none is provided, then get module from model
    :return: True if any of the targets narrow match the module
    Nr'   rB   r   c                 3   s*    | ]}t  |ot | V  qd S r(   )r   rO   r"   r!   parentparent_namer$   r%   r0     s
    
z"is_narrow_match.<locals>.<genexpr>)r1   r[   get_submodulersplitr3   )r   r   r!   r"   r$   r\   r%   r     s   
r   r#   c                    sn   |dur#|D ]}|  |r"| | t fdd|| D   S qdr3td| duS | kS )a  
    Returns true if target string begins with "re:" and regex matches or if target
    string exactly matches name. If the name refers to a fused module defined by vLLM,
    a `fused` mapping must be provided.

    :param name: name of module
    :param target: target name, potentially contains regex
    :fused: optional mapping from suffixes of fused modules to the suffixes of their
        corresponding shards
    Nc                 3   s    | ]
}t  | V  qd S r(   r)   )r,   shard_suffixname_strippedr#   r$   r%   r0     s
    
z_match_name.<locals>.<genexpr>r7   )endswithremovesuffixr3   
startswithrematchremoveprefix)r!   r#   r   fused_suffixr$   rb   r%   r*     s   


r*   c                    s   t  fdd| jjD S )a  
    Returns true if any torch parent class names match the target string exactly.
    A special exception is made for vllm's `LinearBase` class which matches `Linear`

    :param module: module to match
    :param target: target which matches name or module
    c                 3   s:    | ]}t |tjjo|j kp|jd ko dkV  qdS )
LinearBaseLinearN)
issubclasstorchnnModuler   )r,   clsr#   r$   r%   r0     s    

z_match_class.<locals>.<genexpr>)r3   r   __mro__)r"   r#   r$   rr   r%   r=     s   	r=   )NNF)NTr(   )(loggingrF   rg   collectionsr   collections.abcr   typingr   r   r   r   r   r	   rn   !compressed_tensors.utils.internalr
   	getLoggerr   r   Logger__annotations____all__r[   FusedMapppingro   rp   boolr   	Parameterr   r   rS   r   r   tupler   r   r*   r=   r$   r$   r$   r%   <module>   s   
 


*


+

&


 )
,

 