ó
    Eñiü  ã            	       ór  • S r SSKJr  SSKJrJrJr  SSKrSSKJ	r	J
r
  \(       a  \	" 5       (       a  SSKJr  S\R                  R                  4S	 jrS
\S\\   S\4S jrS
\S\4S jr\
S\R                  R                  4S j5       r\
S\4S\R                  R                  S\S   S\\   4S jj5       rg)z,
Needed utilities for torchao FP8 training.
é    )Úpartial)ÚTYPE_CHECKINGÚCallableÚOptionalNé   )Úis_torchao_availableÚtorchao_required)ÚFloat8LinearConfigÚmodelc                 ó¦   • Su  pU R                  5        H7  u  p4[        U[        R                  R                  5      (       d  M0  Uc  UnUnM9     X4$ )zà
Finds the first and last linear layer names in a model.

This is needed during FP8 to avoid issues with instability by keeping the first and last layers unquantized.

Ref: https://x.com/xariusrke/status/1826669142604141052
)NN)Únamed_modulesÚ
isinstanceÚtorchÚnnÚLinear)r   Úfirst_linearÚlast_linearÚnameÚmodules        ÚP/home/mande/repo/quber/.venv/lib/python3.13/site-packages/accelerate/utils/ao.pyÚfind_first_last_linear_layersr       sQ   € ð !+Ñ€LØ×+Ñ+Ö-‰ˆÜ�fœeŸh™hŸo™o×.Ó.ØÑ#Ø#�ØŠKñ	 .ð
 Ð$Ð$ó    ÚfqnÚlayers_to_filterÚreturnc                 ó°   • [        U [        R                  R                  5      (       a'  U R                  S-  S:w  d  U R
                  S-  S:w  a  gX;   a  gg)an  
A function which will check if `module` is:
- a `torch.nn.Linear` layer
- has in_features and out_features divisible by 16
- is not part of `layers_to_filter`

Args:
    module (`torch.nn.Module`):
        The module to check.
    fqn (`str`):
        The fully qualified name of the layer.
    layers_to_filter (`List[str]`):
        The list of layers to filter.
é   r   FT)r   r   r   r   Úin_featuresÚout_features)r   r   r   s      r   Úfilter_linear_layersr    1   sM   € ô �&œ%Ÿ(™(Ÿ/™/×*Ñ*Ø×Ñ Ñ" aÓ'¨6×+>Ñ+>ÀÑ+CÀqÓ+HØØ
ÓØØr   c                 ó2   • [        U 5      u  p#[        XX#/S9$ )av  
A filter function which will filter out all linear layers except the first and last.

<Tip>

    For stability reasons, we skip the first and last linear layers Otherwise can lead to the model not training or
    converging properly

</Tip>

Args:
    module (`torch.nn.Module`):
        The module to check.
    fqn (`str`):
        The fully qualified name of the layer.
©r   )r   r    )r   r   r   r   s       r   Ú#filter_first_and_last_linear_layersr#   H   s!   € ô" !>¸fÓ EÑ€LÜ ¸|Ð>YÑZÐZr   c                 óf   • SSK Jn  U R                  5        H  u  p#[        X15      (       d  M    g   g)Nr   )ÚFloat8LinearTF)Útorchao.float8.float8_linearr%   r   r   )r   r%   r   r   s       r   Úhas_ao_layersr'   ]   s-   € å9à×+Ñ+Ö-‰ˆÜ�f×+Ó+Ùñ .ð r   Úconfigr
   Úmodule_filter_funcc                 ó\   • SSK Jn  [        U 5      u  pEUc  [        [        XE/S9nU" XUS9  g)a  
Converts all `nn.Linear` layers in the model (except the first and last) to torchao's `Float8Linear` layer inplace.

Args:
    model (`torch.nn.Module`):
        The model to convert.
    config (`torchao.float8.Float8LinearConfig`, *optional*):
        The configuration for the FP8 training. Recommended to utilize
        `torchao.float8.recipe_name_to_linear_config` to generate this. In general, the default config should be
        sufficient (what is passed when set to `None`).
    module_filter_func (`Callable`, *optional*, defaults to `filter_linear_layers`):
        Optional function that must take in a module and layer name, and returns a boolean indicating whether the
        module should be converted to FP8. Defaults to `filter_linear_layers`. See it for an example.

Example:

```python
from accelerate.utils.ao import convert_model_to_fp8_ao
from accelerate import Accelerator

accelerator = Accelerator(

model = MyModel()
model.to(accelerator.device)
convert_to_float8_training(model)

model.train()
```
r   )Úconvert_to_float8_trainingNr"   )Úmodule_filter_fnr(   )Útorchao.float8r+   r   r   r    )r   r(   r)   r+   r   r   s         r   Úconvert_model_to_fp8_aor.   g   s7   € õF :ä =¸eÓ DÑ€LØÑ!Ü$Ô%9È\ÐLgÑhÐÙ˜uÐRXÓYr   )Ú__doc__Ú	functoolsr   Útypingr   r   r   r   Úimportsr   r	   r&   r
   r   ÚModuler   ÚstrÚlistÚboolr    r#   r'   r.   © r   r   Ú<module>r8      så   ðñõ ß 4Ñ 4ã ç ;ö Ù×ÑÝCð%¨¯©¯©ô %ð" cð ¸TÀ#¹Yð È4ô ð.[°Sð [¸Tô [ð* ð˜Ÿ™Ÿ™ó ó ðð ð .2Ø-Pñ'ZØ�8‰8�?‰?ð'ZàÐ)Ñ*ð'Zð ! Ñ*ô'Zó ñ'Zr   