
    PiE                        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
 d dlZd dlm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mZmZ ddlmZ ddlmZ  G d dee          Ze G d de                      Z  ee           dej!        j"        de dej!        j"        fd            Z#e G d de                      Z$ G d de$          Z% ee$          dej!        j"        de$dej!        j"        fd            Z&e G d de                      Z' G d de'          Z( ee'          dej!        j"        de'dej!        j"        fd            Z) G d  d!e          Z*d"ej!        j"        d#e
ed$f         ddfd%Z+dS )&    N)	dataclass)Enum)AnyListOptionalTuple)AOBaseConfig)_QUANTIZE_CONFIG_HANDLER register_quantize_module_handler)TwoStepQuantizer   )FakeQuantizedEmbedding)FakeQuantizeConfigFakeQuantizeConfigBaseIntxFakeQuantizeConfig_infer_fake_quantize_configs)FakeQuantizedLinear_log_deprecation_warningc                       e Zd ZdZdZdZdS )QATStepzZ
    Enum value for the `step` field in :class:`~torchao.quantization.qat.QATConfig`.
    prepareconvertN)__name__
__module____qualname____doc__PREPARECONVERT     p/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/torchao/quantization/qat/api.pyr   r   !   s$          GGGGr!   r   c            
           e Zd ZU dZee         ed<   ee         ed<   ee         ed<   eed<   	 	 	 ddddee         dee         dee         defd	Z	d
 Z
dS )	QATConfigaV  
    Config for applying quantization-aware training (QAT) to a `torch.nn.Module`,
    to be used with :func:`~torchao.quantization.quant_api.quantize_`.

    This config has two steps, "prepare" and "convert". The prepare step applies
    "fake" quantization to the model and should be applied before training, while
    the convert step converts the model into an actual quantized model. Fake
    quantization here refers to simulating the quantization numerics (e.g. int4)
    using high precision arithmetic (e.g. bf16), with the goal of reducing
    eventual degradation from quantization.

    There are two ways to use this config. The first involves passing a base
    post-training quantization (PTQ) config, which we will use to automatically
    infer the corresponding fake quantization schemes to use in the prepare phase.
    In the convert phase, we will then apply the base PTQ config to the model.
    This will be the most common use case.

    Example usage::

        from torchao.quantization import (
            quantize_,
            Int8DynamicActivationInt4WeightConfig,
        )
        from torchao.quantization.qat import QATConfig

        base_config = Int8DynamicActivationInt4WeightConfig(group_size=32)
        quantize_(model, QATConfig(base_config, step="prepare"))
        train_loop(model)
        quantize_(model, QATConfig(base_config, step="convert"))

    Currently only the following are supported as base configs:

        - :class:`~torchao.quantization.Int8DynamicActivationInt4WeightConfig`
        - :class:`~torchao.quantization.Int4WeightOnlyConfig`

    The second way to use this config involves specifying the fake quantization
    schemes directly. Users will pass in :class:`~torchao.quantization.qat.FakeQuantizeConfigBase`
    for weights and/or activations instead of the base PTQ config. This use case
    is mostly for experimentation, e.g. when the corresponding PTQ config does
    not exist yet.

    Example usage::

        from torchao.quantization import quantize_
        from torchao.quantization.qat import IntxFakeQuantizeConfig

        activation_config = IntxFakeQuantizeConfig(
            torch.int8, "per_token", is_symmetric=False,
        )
        weight_config = IntxFakeQuantizeConfig(
            torch.int4, group_size=32, is_symmetric=True,
        )
        qat_config = QATConfig(
            # must specify one of `base_config` or `weight_config`
            activation_config=act_config,
            weight_config=weight_config,
            step="prepare",
        )
        quantize_(model, qat_config)

    Args:
        base_config (Optional[AOBaseConfig]): Base PTQ config to infer the fake
            quantization configs during the prepare phase, and to apply directly
            during the convert phase.
        activation_config (Optional[FakeQuantizeConfigBase]): Custom fake
            quantization config for input activations, always optional.
            Must be None if `base_config` is used.
        weight_config (Optional[FakeQuantizeConfigBase]): Custom fake quantization
            config for weights. Must be None if `base_config` is used.

    Keyword args:
        step (str): One of "prepare" or "convert", determines the QAT phase

    Raises:
        ValueError: If `base_config` and `activation_config` are both specified
        ValueError: If `base_config` and `weight_config` are both specified
        ValueError: If none of `base_config`, `activation_config`, or
            `weight_config` are specified
        ValueError: If either `activation_config` or `weight_config` is specified
             and `step` is "convert"
        ValueError: If `step` is not one of "prepare" or "convert"
        ValueError: If the config is applied on a module that is not a
            `torch.nn.Linear` or `torch.nn.Embedding`, or it is applied on
            `torch.nn.Embedding` with an activation config
    base_configactivation_configweight_configstepNr   )r(   c                f    || _         || _        || _        || _        |                                  d S N)r%   r&   r'   r(   __post_init__)selfr%   r&   r'   r(   s        r"   __init__zQATConfig.__init__   s;     '!2*	r!   c                    t           j                            d           | j                                        | _        d t
          D             }| j        |vrt          d|           | j        | j        t          d          | j        | j	        t          d          | j        t
          j
        k    r0t          | j        | j        | j	        f          st          d          | j        t
          j        k    r| j        | j	        t          d          t          | j        t                    r)| j        j        j        }t          | d| d	| d
          d S )Nz"torchao.quantization.qat.QATConfigc                     g | ]	}|j         
S r    )value).0ss     r"   
<listcomp>z+QATConfig.__post_init__.<locals>.<listcomp>   s    444q17444r!   z`step` must be one of z9Cannot specify both `base_config` and `activation_config`z5Cannot specify both `base_config` and `weight_config`zWMust specify `base_config`, `activation_config`, or `weight_config` in the prepare stepzICannot specify `weight_config` or `activation_config` in the convert stepz~ was passed as `base_config`. Did you mean to do the following instead?
    qat_config = QATConfig(
        activation_config=z(...),
        weight_config=z$(...),
        step="prepare",
    ))torch_C_log_api_usage_oncer(   lowerr   
ValueErrorr%   r&   r'   r   anyr   
isinstancer   	__class__r   )r,   all_step_valuesconfig_types      r"   r+   zQATConfig.__post_init__   s   $$%IJJJIOO%%	44G4449O++GoGGHHH'D,B,NK   'D,>,JTUUU9''t5t7IJ1
 1
' i   9''".$2D2P[   d&(>?? 		*4=K  -8  *5    		 		r!   )NNN)r   r   r   r   r   r	   __annotations__r   r   r-   r+   r    r!   r"   r$   r$   *   s         T Tl ,'''' 6777723333
MMM /3>B:>	 "  l+ $$:;   67	    " " " " "r!   r$   moduleconfigreturnc                 ^   ddl m}m} |j        }|j        }|t
          j        k    r|t          |          \  }}n|j        }|j	        }t          | t          j        j                  rQt          ||          r+|t          ||          sJ |                    | ||          S t          j        | ||          S t          | t          j        j                  r&|t#          d          t%          j        | |          S t#          dt)          |           z            |t
          j        k    sJ d|z              |j        
J d            |j	        
J d            t          | t          t$          |f          s| S i }d	}	t-          | d
          rPt          | j        j        t2                    r1| j        j        j        r | j        j        |d<   | j        j        |d<   d}	t          | t          |f          r|                                 } n=t          | t$                    r|                                 } nt#          d|  d          |b|	r?t-          |d          r/t?          j         d           tC          j"        |          }d|_#        tI          t)          |                   | |fi |S | S )a|  
    During the prepare step, perform module swap to apply fake quantization.
    If the base PTQ config is specified, derive the fake quantization configs from it.

    During the convert step, first perform module swap to revert all fake quantized
    modules to the corresponding built-in `torch.nn.Module`s, then apply the
    base config directly to quantize the module.
    r   )NVFP4FakeQuantizeConfigNVFP4FakeQuantizedLinearN;Activation fake quantization is not supported for embedding-Module of type '%s' does not have QAT supportz!unexpected step '%s' in QATConfigzunexpected `activation_config`zunexpected `weight_config`Fweight_fake_quantizercustom_scalecustom_zero_pointTzEncountered unexpected module z, should never happenintx_choose_qparams_algorithmz'Disabling intx_choose_qparams_algorithm)%torchao.prototype.qatrC   rD   r%   r(   r   r   r   r&   r'   r:   r4   nnLinearfrom_linearr   	Embeddingr8   r   from_embeddingtyper   hasattrrG   r@   r   range_learningscale
zero_point	to_linearto_embeddingloggingdebugcopydeepcopyrJ   r
   )
r?   r@   rC   rD   r%   r(   
act_configr'   kwargshas_custom_scale_and_zero_points
             r"   _qat_config_transformr_      sW           $K;Dw"*F{*S*S'Z1J"0Mfeho.. 	-)@AA 
!)Z 7. .))  0;;J   +6J    233 		% Q   *8OOO?$v,,N  
 w&&&(Kd(R&&&'//1Q///#++-I+++  "8:RS
 
 	 M */'F344	367>@VWW	3 ,3B	3
 &,%A%GF>"*0*F*QF&'.2+ f24LMNN 	%%''FF 677 	((**FFNNNN   ". A7<4 4 A GHHH"mK88<@9+D,=,=> '-   Mr!   c                   N    e Zd ZU dZdZee         ed<   dZee         ed<   d Z	dS )#IntXQuantizationAwareTrainingConfiga  
    (Deprecated) Please use :class:`~torchao.quantization.qat.QATConfig` instead.

    Config for applying fake quantization to a `torch.nn.Module`.
    to be used with :func:`~torchao.quantization.quant_api.quantize_`.

    Example usage::

        from torchao.quantization import quantize_
        from torchao.quantization.qat import IntxFakeQuantizeConfig
        activation_config = IntxFakeQuantizeConfig(
            torch.int8, "per_token", is_symmetric=False,
        )
        weight_config = IntxFakeQuantizeConfig(
            torch.int4, group_size=32, is_symmetric=True,
        )
        quantize_(
            model,
            IntXQuantizationAwareTrainingConfig(activation_config, weight_config),
        )

    Note: If the config is applied on a module that is not
    `torch.nn.Linear` or `torch.nn.Embedding`, or it is applied on
    `torch.nn.Embedding` with an activation config, then we will raise
    ValueError as these are not supported.
    Nr&   r'   c                 $    t          |            d S r*   r   r,   s    r"   r+   z1IntXQuantizationAwareTrainingConfig.__post_init__F       &&&&&r!   )
r   r   r   r   r&   r   r   r>   r'   r+   r    r!   r"   ra   ra   &  s^          6 ;?x 67>>>6:M823:::' ' ' ' 'r!   ra   c                       e Zd ZdS ) intx_quantization_aware_trainingNr   r   r   r    r!   r"   rf   rf   K          Dr!   rf   c                 T   | }|j         }|j        }t          |t          j        j                  rt          j        |||          S t          |t          j        j                  r&|t          d          t          j        ||          S t          dt          |          z            )NrE   rF   )r&   r'   r:   r4   rL   rM   r   rN   rO   r8   r   rP   rQ   )r?   r@   modr&   r'   s        r"   +_intx_quantization_aware_training_transformrk   O  s    
 C0(M#ux'' V".
 
 	

 
C+	,	, V(M   &4S-HHHH4PS99TUUUr!   c                       e Zd ZdZd ZdS )'FromIntXQuantizationAwareTrainingConfiga  
    (Deprecated) Please use :class:`~torchao.quantization.qat.QATConfig` instead.

    Config for converting a model with fake quantized modules,
    such as :func:`~torchao.quantization.qat.linear.FakeQuantizedLinear`
    and :func:`~torchao.quantization.qat.linear.FakeQuantizedEmbedding`,
    back to model with the original, corresponding modules without
    fake quantization. This should be used with
    :func:`~torchao.quantization.quant_api.quantize_`.

    Example usage::

        from torchao.quantization import quantize_
        quantize_(
            model_with_fake_quantized_linears,
            FromIntXQuantizationAwareTrainingConfig(),
        )
    c                 $    t          |            d S r*   r   rc   s    r"   r+   z5FromIntXQuantizationAwareTrainingConfig.__post_init__}  rd   r!   N)r   r   r   r   r+   r    r!   r"   rm   rm   h  s-         &' ' ' ' 'r!   rm   c                       e Zd ZdS )%from_intx_quantization_aware_trainingNrg   r    r!   r"   rp   rp     rh   r!   rp   rj   c                     t          | t                    r|                                 S t          | t                    r|                                 S | S )z
    If the given module is a fake quantized module, return the original
    corresponding version of the module without fake quantization.
    )r:   r   rV   r   rW   )rj   r@   s     r"   0_from_intx_quantization_aware_training_transformrr     sO     #*++ }}	C/	0	0 !!!
r!   c                       e Zd ZdZdee         fdZdej        j	        de
de
dej        j	        fdZdej        j	        de
de
dej        j	        fd	Zd
S )ComposableQATQuantizerab  
    Composable quantizer that users can use to apply multiple QAT quantizers easily.
    Quantizers will be applied in the order they are specified in the constructor.

    Note: the quantizers provided must apply to different modules in the model,
    e.g. nn.Linear and nn.Embedding, otherwise the behavior will be undefined.

    Example usage::

        my_quantizer = ComposableQATQuantizer([
            QATQuantizer1(),
            QATQuantizer2(),
            QATQuantizer3(),
        ])
        model = my_quantizer.prepare(model)
        train(model)
        model = my_quantizer.convert(model)
    
quantizersc                 R    t           j                            d           || _        d S )Nz/torchao.quantization.qat.ComposableQATQuantizer)r4   r5   r6   ru   )r,   ru   s     r"   r-   zComposableQATQuantizer.__init__  s$    $$%VWWW$r!   modelargsr]   rA   c                 D    | j         D ]}|                    |          }|S r*   )ru   r   r,   rw   rx   r]   	quantizers        r"   r   zComposableQATQuantizer.prepare  /      	- 	-I%%e,,EEr!   c                 D    | j         D ]}|                    |          }|S r*   )ru   r   rz   s        r"   r   zComposableQATQuantizer.convert  r|   r!   N)r   r   r   r   r   r   r-   r4   rL   Moduler   r   r   r    r!   r"   rt   rt     s         &%4(8#9 % % % %X_-0<?	   X_-0<?	     r!   rt   rw   example_inputs.c                     t           j                            d           ddlm dt           j        j        ffd}|                     |            | |  dS )z
    (Prototype) Initialize the scales and zero points on all
    :class:`~torchao.quantization.qat.fake_quantizer.IntxFakeQuantizerBase`
    in the model based on the provided example inputs.
    z3torchao.quantization.qat.initialize_fake_quantizersr   )IntxFakeQuantizermc                 :    t          |           r	d| _        d S d S )NT)r:   _initialized)r   r   s    r"   _set_initializedz4initialize_fake_quantizers.<locals>._set_initialized  s+    a*++ 	"!ANNN	" 	"r!   N)r4   r5   r6   'torchao.quantization.qat.fake_quantizerr   rL   r~   apply)rw   r   r   r   s      @r"   initialize_fake_quantizersr     s     
H  !VWWW JIIIII"EHO " " " " " " 
KK !!!	E>r!   ),rZ   rX   dataclassesr   enumr   typingr   r   r   r   r4   torchao.core.configr	   %torchao.quantization.transform_moduler
   r   torchao.quantization.unifiedr   	embeddingr   fake_quantize_configr   r   r   r   linearr   utilsr   strr   r$   rL   r~   r_   ra   rf   rk   rm   rp   rr   rt   r   r    r!   r"   <module>r      s     ! ! ! ! ! !       - - - - - - - - - - - -  , , , , , ,        : 9 9 9 9 9 - - - - - -            ( ' ' ' ' ' + + + + + +    c4    N N N N N N N Nb "!),,fHOff X_f f f -,fR  '  '  '  '  ',  '  '  'H	 	 	 	 	'J 	 	 	 "!"EFFVHOV/V X_V V V GFV0 ' ' ' ' 'l ' ' '2	 	 	 	 	,S 	 	 	 "!"IJJ	3 X_   KJ $ $ $ $ $- $ $ $N8?#s(O 
     r!   