|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from ..utils import is_accelerate_available, is_eetq_available, logging |
|
|
|
|
|
if is_eetq_available(): |
|
import eetq |
|
import torch.nn as nn |
|
|
|
if is_accelerate_available(): |
|
from accelerate import init_empty_weights |
|
|
|
logger = logging.get_logger(__name__) |
|
|
|
|
|
def _replace_with_eetq_linear( |
|
model, |
|
modules_to_not_convert=None, |
|
current_key_name=None, |
|
quantization_config=None, |
|
has_been_replaced=False, |
|
pre_quantized=False, |
|
): |
|
""" |
|
Private method that wraps the recursion for module replacement. |
|
|
|
Returns the converted model and a boolean that indicates if the conversion has been successfull or not. |
|
""" |
|
if current_key_name is None: |
|
current_key_name = [] |
|
|
|
for name, module in model.named_children(): |
|
current_key_name.append(name) |
|
|
|
if (isinstance(module, nn.Linear)) and name not in modules_to_not_convert: |
|
|
|
current_key_name_str = ".".join(current_key_name) |
|
if not any( |
|
(key + "." in current_key_name_str) or (key == current_key_name_str) for key in modules_to_not_convert |
|
): |
|
with init_empty_weights(): |
|
in_features = module.in_features |
|
out_features = module.out_features |
|
model._modules[name] = eetq.EetqLinear( |
|
in_features, out_features, module.bias is not None, module.weight.device |
|
) |
|
if pre_quantized: |
|
model._modules[name].register_scale(module.weight.device) |
|
has_been_replaced = True |
|
|
|
|
|
model._modules[name].requires_grad_(False) |
|
if len(list(module.children())) > 0: |
|
_, has_been_replaced = _replace_with_eetq_linear( |
|
module, |
|
modules_to_not_convert, |
|
current_key_name, |
|
quantization_config, |
|
has_been_replaced=has_been_replaced, |
|
pre_quantized=pre_quantized, |
|
) |
|
|
|
current_key_name.pop(-1) |
|
return model, has_been_replaced |
|
|
|
|
|
def replace_with_eetq_linear( |
|
model, modules_to_not_convert=None, current_key_name=None, quantization_config=None, pre_quantized=False |
|
): |
|
""" |
|
A helper function to replace all `torch.nn.Linear` modules by `eetq.EetqLinear` modules from the `eetq` |
|
library. This will enable running your models using high performance int8 weight-only gemm kerner from |
|
FasterTransformer and TensorRT-LLM. Make sure `eetq` compiled with the correct CUDA |
|
version of your hardware is installed before running this function. EETQ shall be installed via the source |
|
'https://github.com/NetEase-FuXi/EETQ' |
|
|
|
The function will be run recursively and replace all `torch.nn.Linear` modules except for the `lm_head` that should |
|
be kept as a `torch.nn.Linear` module. The replacement is done under `init_empty_weights` context manager so no |
|
CPU/GPU memory is required to run this function. Each weight will be quantized along the channel. |
|
|
|
Parameters: |
|
model (`torch.nn.Module`): |
|
Input model or `torch.nn.Module` as the function is run recursively. |
|
modules_to_not_convert (`List[`str`]`, *optional*, defaults to `["lm_head"]`): |
|
Names of the modules to not convert in `EetqLinear`. In practice we keep the `lm_head` in full precision |
|
for numerical stability reasons. |
|
current_key_name (`List[`str`]`, *optional*): |
|
An array to track the current key of the recursion. This is used to check whether the current key (part of |
|
it) is not in the list of modules to not convert (for instances modules that are offloaded to `cpu` or |
|
`disk`). |
|
""" |
|
|
|
modules_to_not_convert = ["lm_head"] if modules_to_not_convert is None else modules_to_not_convert |
|
|
|
if quantization_config.modules_to_not_convert is not None: |
|
modules_to_not_convert.extend(quantization_config.modules_to_not_convert) |
|
modules_to_not_convert = list(set(modules_to_not_convert)) |
|
model, has_been_replaced = _replace_with_eetq_linear( |
|
model, modules_to_not_convert, current_key_name, quantization_config, pre_quantized=pre_quantized |
|
) |
|
|
|
if not has_been_replaced: |
|
logger.warning( |
|
"You are loading your model using eetq but no linear modules were found in your model." |
|
" Please double check your model architecture, or submit an issue on github if you think this is" |
|
" a bug." |
|
) |
|
|
|
return model |
|
|