o
    Ti!#                     @   s   d dl Z d dlmZ d dlmZ d dlZed Zed ZdZdd Z	d	d
 Z
dd ZG dd deZG dd dedZG dd dZdefddZdS )    N)abstractmethod)TypeInferenceModelLayerContainerPARAM_MAPPINGc                        fdd}|S )z6
    Normal getter implementation for a property.
    c                    s   t | d  d S N__)getattrselfclsnameparam o/home/ubuntu/.local/lib/python3.10/site-packages/deepspeed/inference/v2/model_implementations/parameter_base.pyparam_getter   s   z'make_param_getter.<locals>.param_getterr   )r   r   r   r   r   r   make_param_getter   s   r   c                    r   )zl
    Setter implementation that will call complete component to potentially
    finalize the parameter.
    c                    s$   t | d  d | |   d S r   )setattrcomplete_componentr   valuer   r   r   param_setter$   s   z'make_param_setter.<locals>.param_setterr   )r   r   r   r   r   r   make_param_setter   s   r   c                  C   s   dd } | S )zC
    Setter implementation that will raise an error if called.
    c                 S   s   t d)Nz'Cannot set a ParametrizedList directly.)
ValueErrorr   r   r   r   paramlist_setter0   s   z.make_readonly_setter.<locals>.paramlist_setterr   )r   r   r   r   make_readonly_setter+   s   r   c                       s,   e Zd ZdZ fddZ fddZ  ZS )ParameterMetaclassa$  
    MetaClass for the ParameterBase base class. This class will parse the `src_params`
    attribute and create properties for each of the dependencies. A dependency can either
    be represented as a string, which is interpreted as a named Tensor, or a `ParametrizedList`
    subclass.
    c           
         s   | di }dd | D }t|}| D ]+\}}t|tr5t|ds)J dtt||t ||< qtt||t	||||< qt
 | |||}	||	_|	S )N__annotations__c                 S   s&   i | ]\}}t |tjtfr||qS r   )
issubclasstorchTensorParametrizedList).0name
annotationr   r   r   
<dictcomp>A   s
    z.ParameterMetaclass.__new__.<locals>.<dictcomp>
count_attrzTParametrizedList must have a count_attr attribute to access on the inference module.)getitemslenr   r"   hasattrpropertyr   r   r   super__new__n_dependencies)
clsr   basesattrsannotationsdependenciesr/   d_named_typenew_cls	__class__r   r   r.   >   s"   
zParameterMetaclass.__new__c                    s   t  j|i |}|j|i | t|dd  |j D ]G\}}t|trUt|j	|j
s<J d|jj d| d|j
 ||t|j	|j
}t|d|jj d| | qt|d|jj d| d  q|S )N
dest_paramznew_obj=z, name=z, annotation.count_attr=r	   )r-   __call____init__r   r   r)   r   r"   r+   inference_modelr'   r9   __name__r
   )r0   argskwargsnew_objr$   r%   
param_listr8   r   r   r;   V   s   
zParameterMetaclass.__call__)r>   
__module____qualname____doc__r.   r;   __classcell__r   r   r8   r   r   6   s    r   c                   @   sH   e Zd ZdZ	 	 dededdfddZedej	fdd	Z
dd
dZdS )ParameterBasea%  
    A ParameterBase allows us to consolidate tracking the dependencies of loading a parameter from
    a checkpoint into a single object. This class should not be used directly, but rather subclassed
    and the `src_params` attribute set to a list of strings and/or `ParametrizedList`s.
    modelparent_containerreturnNc                 C   s   || _ d| _t|| _dS )a  
        Direct constructor. This should not be called from client code.

        Args:
            model (InferenceModel): Inference model that will be used to shard and transform the
                parameter in `finalize`.
            parent_container (LayerContainer): The parent container that this parameter is a member
                of. We will build a weakref to this container to call the finalization callback.
        r   N)r=   completed_componentsweakrefrefrI   )r   rH   rI   r   r   r   r<   ~   s   
zParameterBase.__init__c                 C   s   dS )z
        Finalize the parameter after all of its source parameters have been set. This method
        will be automatically called when all inputs have been set. It should return the Tensor
        with all transformations performed on it.
        Nr   r   r   r   r   finalize   s   zParameterBase.finalizec                 C   s:   |  j d7  _ | j | jkrdS |  }|  | | dS )a  
        Mark a component as completed. This should be called by the relevant setter of a direct
        property or a ParametrizedList. This method will automatically call `finalize` when all
        dependencies have been met and then call the finalization callback on the parent container.

        Once the finalization callback has been called, the parameter will be replaced with the
        `dst_param` attribute on the parent container, and this instance will be destroyed.
           N)rK   r/   rN   rI   finalization_callback)r   finalized_paramr   r   r   r      s
   	z ParameterBase.complete_component)rJ   N)r>   rC   rD   rE   r   r   r<   r   r    r!   rN   r   r   r   r   r   rG   k   s    rG   )	metaclassc                   @   sT   e Zd ZU dZeed< 	 eed< 	 dededdfddZdd	 Zd
d Z	dd Z
dS )r"   a  
    A ParametrizedList is a list of parameters that are dependencies
    of a `ParameterBase` but may vary in length depending on the model
    configuration (rather than architecture). For example, a MoE layer
    may have different number of experts depending on the size of the model.

    This class is used to manage these lists and provide integer indexing
    of a single component rather than accessing names directly. For example,
    it tends to be more natural to access the 8th expert with `experts[8]`
    rather than a name like `expert_8`, especially as an attribute.

    To inherit from this class, set static variables `name` and `count_attr`.

    ```python
    class MyParametrizedList(ParametrizedList):
        count_attr: str = "my_list_count"
    ```

    In the above example, `my_list_count` should be an accessible attribute
    of the inference model (i.e. via `self.inference_model.my_list_count`).

    NOTE: There are some APIs in which this type cannot be used as if it is
    just a list of Tensors. For example, `torch.cat(param_list)` will not work.
    However, you can make it compatible with a tuple wrapper:
        `torch.cat(tuple(param_list))`
    n_paramsr   rJ   Nc                 C   s(   || _ d| _t|| _dg| | _dS )z
        Constructor. Should not be called from client code.

        Args:
            param (ParameterBase): The owning parameter.
            n_params (int): The number of parameters this list contains. This should be
        r   N)rS   
set_paramsrL   rM   r   _params)r   r   rS   r   r   r   r<      s   zParametrizedList.__init__c                 C   s
   | j | S N)rU   )r   indexr   r   r   __getitem__      
zParametrizedList.__getitem__c                 C   sN   | j | d urtd|| j |< |  jd7  _| j| jkrd S |    d S )NzCannot set a parameter twice.rO   )rU   r   rT   rS   r   r   )r   rW   r   r   r   r   __setitem__   s   
zParametrizedList.__setitem__c                 C   s
   t | jS rV   )iterrU   r   r   r   r   __iter__   rY   zParametrizedList.__iter__)r>   rC   rD   rE   intr   rG   r<   rX   rZ   r\   r   r   r   r   r"      s   
 r"   attrc                    s   G  fdddt }|S )a  
    Helper to create a subclass of ParametrizedList with the desired `count_attr`.

    In this manner, we can annotate the type of a Parameter dependency with the
    following:

    ```python
    class CustomParameter(ParameterBase):
        dependency_list: ParamList("dependencies_count_name")
    ```

    where "dependencies_count_name" is the name of the attribute on the inference model.
    c                       s   e Zd ZU  Zeed< dS )z+ParamList.<locals>.ParametrizedListInstancer'   N)r>   rC   rD   r'   strr   r   r^   r   r   ParametrizedListInstance   s   
 ra   )r"   )r^   ra   r   r`   r   	ParamList   s   rb   )rL   abcr   typingr   r    r   r   MAPPING_KEYr   r   r   typer   rG   r"   r_   rb   r   r   r   r   <module>   s   5<F