
    h<E                     &   S SK r S SKrS SKJr  S SKJr  S SKJrJrJ	r	J
r
  S SKrS SKJr  S SKJrJr  S SKJr  SS	KJr  SS
KJrJrJrJr  SSKJr  SSKJr   " S S\\5      r\ " S S\5      5       r \" \ 5      S\RB                  RD                  S\ S\RB                  RD                  4S j5       r#\ " S S\5      5       r$ " S S\$5      r%\" \$5      S\RB                  RD                  S\$S\RB                  RD                  4S j5       r&\ " S S\5      5       r' " S S\'5      r(\" \'5      S\RB                  RD                  S\'S\RB                  RD                  4S j5       r) " S  S!\5      r*S"\RB                  RD                  S#\
\S$4   SS4S% jr+g)&    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                        \ rS rSrSrSrSrSrg)QATStep!   zR
Enum value for the `step` field in :class:`~torchao.quantization.qat.QATConfig`.
prepareconvert N)__name__
__module____qualname____firstlineno____doc__PREPARECONVERT__static_attributes__r       V/home/james-whalen/.local/lib/python3.13/site-packages/torchao/quantization/qat/api.pyr   r   !   s     GGr$   r   c            
           \ rS rSr% Sr\\   \S'   \\   \S'   \\   \S'   \	\S'      SSS	.S\\   S\\   S\\   S\	4S
 jjjr
S rSrg)	QATConfig*   a>  
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                T    Xl         X l        X0l        X@l        U R	                  5         g N)r)   r*   r+   r,   __post_init__)selfr)   r*   r+   r,   s        r%   __init__QATConfig.__init__   s'     '!2*	r$   c                 x   [         R                  R                  S5        U R                  R	                  5       U l        [
         Vs/ s H  oR                  PM     nnU R                  U;  a  [        SU 35      eU R                  b  U R                  b  [        S5      eU R                  b  U R                  b  [        S5      eU R                  [
        R                  :X  a<  [        U R                  U R                  U R                  45      (       d  [        S5      eU R                  [
        R                  :X  a%  U R                  c  U R                  b  [        S5      e[        U R                  [        5      (       a4  U R                  R                   R"                  n[        U SU SU S	35      eg s  snf )
Nz"torchao.quantization.qat.QATConfigz`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   value
ValueErrorr)   r*   r+   r!   anyr"   
isinstancer   	__class__r   )r0   sall_step_valuesconfig_types       r%   r/   QATConfig.__post_init__   s   $$%IJIIOO%	,34Gq77G499O+5o5FGHH'D,B,B,NK  'D,>,>,JTUU99't55t7I7IJ1
 1
 i  99'"".$2D2D2P[  d&&(>??**44==K-  --8M :))4 6  @- 5s   F7)r*   r)   r,   r+   )NNN)r   r   r   r   r    r   r	   __annotations__r   r   r1   r/   r#   r   r$   r%   r'   r'   *   s    Tl ,'' 677233
M /3>B:>	 "l+ $$:;   67	 "r$   r'   moduleconfigreturnc                    UR                   nUR                  nU[        R                  :X  Ga  Ub  [	        U5      u  pEOUR
                  nUR                  n[        U [        R                  R                  5      (       aV  SSKJnJn  [        XV5      (       a'  Ub  [        XF5      (       d   eUR                  XU5      $ [        R                  " XU5      $ [        U [        R                  R                   5      (       a$  Ub  [#        S5      e[$        R&                  " X5      $ [#        S[)        U 5      -  5      eU[        R*                  :X  d
   SU-  5       eUR
                  b   S5       eUR                  b   S5       e[        U [        [$        45      (       d  U $ 0 nS	n	U R,                  R.                  n[        U[0        5      (       aE  UR2                  (       a4  U R,                  R4                  US
'   U R,                  R6                  US'   Sn	[        U [        5      (       a  U R9                  5       n O5[        U [$        5      (       a  U R;                  5       n O[#        SU  S35      eUbd  U	(       aD  [=        US5      (       a3  [>        R@                  " S5        [B        RD                  " U5      nSUl#        [H        [)        U5         " X40 UD6$ U $ )ad  
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.
Nr   )NVFP4FakeQuantizeConfigNVFP4FakeQuantizedLinear;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custom_scalecustom_zero_pointTzEncountered unexpected module z, should never happenintx_choose_qparams_algorithmz'Disabling intx_choose_qparams_algorithm)%r)   r,   r   r!   r   r*   r+   r;   r4   nnLineartorchao.prototype.qatrF   rG   from_linearr   	Embeddingr9   r   from_embeddingtyper"   weight_fake_quantizerrC   r   range_learningscale
zero_point	to_linearto_embeddinghasattrloggingdebugcopydeepcopyrL   r
   )
rB   rC   r)   r,   
act_configr+   rF   rG   kwargshas_custom_scale_and_zero_points
             r%   _qat_config_transformrb      s     $$K;;Dw"*F{*S'Z11J"00Mfehhoo..
 -AA!)Z. .   0;;  +66   2 233% Q  *88OO?$v,N 
 w&R(Kd(RR&''/Q1QQ/##+I-II+ &#68N"OPPM */'44;;}&<==,,%+%A%A%G%GF>"*0*F*F*Q*QF&'.2+ f122%%'F 677((*F08MN  ".7<4 4 GH"mmK8<@9+D,=>'-  Mr$   c                   H    \ rS rSr% SrSr\\   \S'   Sr	\\   \S'   S r
Srg)#IntXQuantizationAwareTrainingConfigi#  ay  
(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                     [        U 5        g r.   r   r0   s    r%   r/   1IntXQuantizationAwareTrainingConfig.__post_init__C  
     &r$   r   )r   r   r   r   r    r*   r   r   rA   r+   r/   r#   r   r$   r%   rd   rd   #  s/    6 ;?x 67>6:M823:'r$   rd   c                       \ rS rSrSrg) intx_quantization_aware_trainingiH  r   Nr   r   r   r   r#   r   r$   r%   rj   rj   H      r$   rj   c                    U nUR                   nUR                  n[        U[        R                  R
                  5      (       a  [        R                  " UUU5      $ [        U[        R                  R                  5      (       a$  Ub  [        S5      e[        R                  " X$5      $ [        S[        U5      -  5      e)NrH   rI   )r*   r+   r;   r4   rM   rN   r   rP   rQ   r9   r   rR   rS   )rB   rC   modr*   r+   s        r%   +_intx_quantization_aware_training_transformro   L  s    
 C00((M#uxx''"..
 	

 
C++	,	,(M  &44SHHH4PS9TUUr$   c                       \ rS rSrSrS rSrg)'FromIntXQuantizationAwareTrainingConfigie  ag  
(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                     [        U 5        g r.   r   rf   s    r%   r/   5FromIntXQuantizationAwareTrainingConfig.__post_init__z  rh   r$   r   N)r   r   r   r   r    r/   r#   r   r$   r%   rq   rq   e  s    &'r$   rq   c                       \ rS rSrSrg)%from_intx_quantization_aware_trainingi  r   Nrk   r   r$   r%   ru   ru     rl   r$   ru   rn   c                     [        U [        5      (       a  U R                  5       $ [        U [        5      (       a  U R	                  5       $ U $ )z
If the given module is a fake quantized module, return the original
corresponding version of the module without fake quantization.
)r;   r   rX   r   rY   )rn   rC   s     r%   0_from_intx_quantization_aware_training_transformrw     s@     #*++}}	C/	0	0!!
r$   c                       \ rS rSrSrS\\   4S jrS\R                  R                  S\S\S\R                  R                  4S	 jrS\R                  R                  S\S\S\R                  R                  4S
 jrSrg)ComposableQATQuantizeri  a*  
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                 N    [         R                  R                  S5        Xl        g )Nz/torchao.quantization.qat.ComposableQATQuantizer)r4   r5   r6   rz   )r0   rz   s     r%   r1   ComposableQATQuantizer.__init__  s    $$%VW$r$   modelargsr`   rD   c                 N    U R                    H  nUR                  U5      nM     U$ r.   )rz   r   r0   r}   r~   r`   	quantizers        r%   r   ComposableQATQuantizer.prepare  '     I%%e,E )r$   c                 N    U R                    H  nUR                  U5      nM     U$ r.   )rz   r   r   s        r%   r   ComposableQATQuantizer.convert  r   r$   )rz   N)r   r   r   r   r    r   r   r1   r4   rM   Moduler   r   r   r#   r   r$   r%   ry   ry     s    &%4(8#9 %XX__-0<?	XX__-0<?	r$   ry   r}   example_inputs.c                    ^ [         R                  R                  S5        SSKJm  S[         R
                  R                  4U4S jjnU R                  U5        U " U6   g)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                 8   > [        U T5      (       a  SU l        g g )NT)r;   _initialized)r   r   s    r%   _set_initialized4initialize_fake_quantizers.<locals>._set_initialized  s    a*++!AN ,r$   N)r4   r5   r6   'torchao.quantization.qat.fake_quantizerr   rM   r   apply)r}   r   r   r   s      @r%   initialize_fake_quantizersr     sI     
HH  !VW J"EHHOO " 
KK !	>r$   ),r]   r[   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'   rM   r   rb   rd   rj   ro   rq   ru   rw   ry   r   r   r$   r%   <module>r      s     !  - -  , : -  ( +c4  N N Nb "),cHHOOcc XX__c -cL  ',  '  'H	'J 	 ""EFVHHOOV/V XX__V GV0 'l ' '2	,S 	 ""IJ	3 XX__ K $- $N88??#s(O 
r$   