U
    di!                     @   s   d dl Z d dlmZmZmZmZmZmZ d dlm	Z	 ddl
mZ ddlmZ er\ddlmZ dd	lmZmZmZmZmZ dd
lmZ e rd dlZeeZG dd deZdS )    N)TYPE_CHECKINGAnyDictListOptionalUnion)version   )HfQuantizer)get_module_from_name   )PreTrainedModel)is_accelerate_availableis_optimum_quanto_availableis_quanto_availableis_torch_availablelogging)QuantoConfigc                       s,  e Zd ZdZddgZdZdZed fddZd	d
 Z	dd Z
dd ZdddddZee eee dddZddeeeef edddZeeeeef f eeeeef f dddZddeddd d!Zddd"d#d$Zg fdee d%d&d'Zd(d) Zed0ed d+d,d-Zd1d.d/Z  ZS )2QuantoHfQuantizerz*
    Quantizer for the quanto library
    quanto
accelerateTF)quantization_configc                    s   t  j|f| |   d S N)super__init__	post_init)selfr   kwargs	__class__ L/tmp/pip-unpacked-wheel-bm_b0l5e/transformers/quantizers/quantizer_quanto.pyr   3   s    zQuantoHfQuantizer.__init__c                 C   s   | j jdk	r| jstddS )z 
        Safety checker
        NzWe don't support quantizing the activations with transformers library.Use quanto library for more complex use cases such as activations quantization, calibration and quantization aware training.)r   ZactivationsZpre_quantized
ValueError)r   r    r    r!   r   7   s    zQuantoHfQuantizer.post_initc                 O   s&   t  st stdt s"tdd S )NzhLoading an optimum-quanto quantized model requires optimum-quanto library (`pip install optimum-quanto`)z`Loading an optimum-quanto quantized model requires accelerate library (`pip install accelerate`))r   r   ImportErrorr   )r   argsr   r    r    r!   validate_environmentA   s    z&QuantoHfQuantizer.validate_environmentc                 C   s   |d krddi}t d |S )N cpuzThe device_map was not initialized. Setting device_map to {'':'cpu'}. If you want to use the model for inference, please set device_map ='auto')loggerinfo)r   
device_mapr    r    r!   update_device_mapK   s    z#QuantoHfQuantizer.update_device_mapztorch.dtype)torch_dtypereturnc                 C   s   |d krt d tj}|S )NzVYou did not specify `torch_dtype` in `from_pretrained`. Setting it to `torch.float32`.)r(   r)   torchZfloat32)r   r,   r    r    r!   update_torch_dtypeU   s    
z$QuantoHfQuantizer.update_torch_dtype)missing_keysprefixr-   c                    s   t  rddlm} nt r0td ddlm} g  | D ]T\}}t||r<|D ]<}||ksp|| d| krR|	dsR|	dsR 
| qRq< fdd|D S )	Nr   QModuleMixinuImporting from quanto will be deprecated in v4.47. Please install optimum-quanto instrad `pip install optimum-quanto`.z.weightz.biasc                    s   g | ]}| kr|qS r    r    ).0kZnot_missing_keysr    r!   
<listcomp>n   s      z9QuantoHfQuantizer.update_missing_keys.<locals>.<listcomp>)r   optimum.quantor3   r   r(   warning_oncer   Znamed_modules
isinstanceendswithappend)r   modelr0   r1   r3   namemodulemissingr    r8   r!   update_missing_keys[   s*    
z%QuantoHfQuantizer.update_missing_keysr   ztorch.Tensor)r?   param_value
param_name
state_dictr-   c                 K   s   t  rddlm} nt r0td ddlm} |dd}|dd}|dk	r|dk	rt|	 }	|dkrt
|	dkr|	dhks|	dd	hksd
S t||\}
}t|
|rd|kr|
j S d
S dS )z=
        Check if a parameter needs to be quantized.
        r   r2   r4   r*   Nparam_devicer'   r	   ZdiskFweight)r   r:   r3   r   r(   r;   r   getsetvalueslenr   r<   frozen)r   r?   rD   rE   rF   r   r3   r*   rG   Zdevice_map_valuesrA   Ztensor_namer    r    r!   check_quantized_paramp   s$    z'QuantoHfQuantizer.check_quantized_param)
max_memoryr-   c                 C   s   dd |  D }|S )Nc                 S   s   i | ]\}}||d  qS )g?r    )r6   keyvalr    r    r!   
<dictcomp>   s      z7QuantoHfQuantizer.adjust_max_memory.<locals>.<dictcomp>)items)r   rO   r    r    r!   adjust_max_memory   s    z#QuantoHfQuantizer.adjust_max_memoryztorch.device)r?   rD   rE   target_devicec           
      O   s<   ddl m} ||||| t||\}}	|  d|j_dS )ze
        Create the quantized parameter by calling .freeze() after setting it to the module.
        r   )set_module_tensor_to_deviceFN)accelerate.utilsrV   r   freezerH   Zrequires_grad)
r   r?   rD   rE   rU   r$   r   rV   rA   _r    r    r!   create_quantized_param   s
    z(QuantoHfQuantizer.create_quantized_param)target_dtyper-   c                 C   sZ   t tj dt dkrNddlm} tj|j|j	|j
d}|| jj }|S tdd S )Nr   z0.27.0r   )CustomDtype)int8Zfloat8Zint4Zint2zYou are using `device_map='auto'` on an optimum-quanto quantized model. To automatically compute the appropriate device map, you should upgrade your `accelerate` library,`pip install --upgrade accelerate` or install it from source.)r   parse	importlibmetadatarW   r\   r.   r]   ZFP8ZINT4ZINT2r   weightsr"   )r   r[   r\   mappingr    r    r!   adjust_target_dtype   s    z%QuantoHfQuantizer.adjust_target_dtype)r?   keep_in_fp32_modulesc                 K   sx   ddl m}m} | jjd kr(||| _n
| jj| _t| jtsH| jg| _| j| ||| j| jd\}}| j|j_d S )Nr   )get_keys_to_not_convertreplace_with_quanto_layers)modules_to_not_convertr   )	Zintegrationsre   rf   r   rg   r<   listextendconfig)r   r?   rd   r   re   rf   rY   r    r    r!   $_process_model_before_weight_loading   s    

  
z6QuantoHfQuantizer._process_model_before_weight_loadingc                 C   s   |S r   r    r   r?   r    r    r!   #_process_model_after_weight_loading   s    z5QuantoHfQuantizer._process_model_after_weight_loadingN)r?   c                 C   s   dS )NTr    rl   r    r    r!   is_trainable   s    zQuantoHfQuantizer.is_trainablec                 C   s   dS )NFr    )r   Zsafe_serializationr    r    r!   is_serializable   s    z!QuantoHfQuantizer.is_serializable)N)N) __name__
__module____qualname____doc__Zrequired_packagesZ requires_parameters_quantizationZrequires_calibrationr   r   r   r%   r+   r/   r   strrC   r   r   boolrN   r   intrT   rZ   rc   rk   rm   propertyr   rn   ro   __classcell__r    r    r   r!   r   *   s@   



$0 r   )r_   typingr   r   r   r   r   r   	packagingr   baser
   Zquantizers_utilsr   Zmodeling_utilsr   utilsr   r   r   r   r   Zutils.quantization_configr   r.   Z
get_loggerrp   r(   r   r    r    r    r!   <module>   s    
