CoolFace
Modelpublic

WisdomShell/CodeShell-7B

sourceHugging Faceupdated 3y agoView on Hugging Face
81likes1.5kdownloads
quantizer.py156 linesDownload Raw Back to root
1# coding=utf-82# Copyright 2023 WisdomShell Inc. All Rights Reserved.3 4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8#     http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15 16try:17    import bitsandbytes as bnb18    from bitsandbytes.nn.modules import Params4bit, Int8Params19except ImportError:20    pass21import torch22 23def Params4bitCuda(self, device):24    self.data = self.data.cuda(device)25    self.quant_state[0] = self.quant_state[0].cuda(device)26    self.quant_state[4][0] = self.quant_state[4][0].cuda(device)27    self.quant_state[4][1][0] = self.quant_state[4][1][0].cuda(device)28    self.quant_state[4][1][1] = self.quant_state[4][1][1].cuda(device)29 30    self.quant_state[6] = self.quant_state[6].cuda(device)31    return self32 33class Linear4bitOnline(torch.nn.Module):34    def __init__(self, weight, bias, quant_type):35        super().__init__()36        self.weight = Params4bit(37            weight.data, requires_grad=False, compress_statistics=True, quant_type=quant_type38        )39        self.compute_dtype = None40        #self.weight.cuda(weight.device)41        self.bias = bias42 43    def forward(self, x: torch.Tensor):44        # weights are cast automatically as Int8Params, but the bias has to be cast manually45        if self.bias is not None and self.bias.dtype != x.dtype:46            self.bias.data = self.bias.data.to(x.dtype)47 48        if getattr(self.weight, "quant_state", None) is None:49            print(50                "FP4 quantization state not initialized. Please call .cuda() or .to(device) on the LinearFP4 layer first."51            )52        inp_dtype = x.dtype53        if self.compute_dtype is not None:54            x = x.to(self.compute_dtype)55 56        bias = None if self.bias is None else self.bias.to(self.compute_dtype)57        out = bnb.matmul_4bit(58            x, self.weight.t(), bias=bias, quant_state=self.weight.quant_state59        )60 61        out = out.to(inp_dtype)62 63        return out64 65class Linear8bitLtOnline(torch.nn.Module):66    def __init__(67        self,68        weight,69        bias,70        has_fp16_weights=True,71        memory_efficient_backward=False,72        threshold=0.0,73        index=None,74    ):75        super().__init__()76        assert (77            not memory_efficient_backward78        ), "memory_efficient_backward is no longer required and the argument is deprecated in 0.37.0 and will be removed in 0.39.0"79        self.state = bnb.MatmulLtState()80        self.index = index81 82        # Necessary for stacked layers83        self.state.threshold = threshold84        self.state.has_fp16_weights = has_fp16_weights85        self.state.memory_efficient_backward = memory_efficient_backward86        if threshold > 0.0 and not has_fp16_weights:87            self.state.use_pool = True88 89        self.weight = Int8Params(90            weight.data,91            has_fp16_weights=has_fp16_weights,92            requires_grad=has_fp16_weights,93        )94        self.bias = bias95 96    def init_8bit_state(self):97        self.state.CB = self.weight.CB98        self.state.SCB = self.weight.SCB99        self.weight.CB = None100        self.weight.SCB = None101 102    def forward(self, x: torch.Tensor):103        self.state.is_training = self.training104        if self.weight.CB is not None:105            self.init_8bit_state()106 107        # weights are cast automatically as Int8Params, but the bias has to be cast manually108        if self.bias is not None and self.bias.dtype != x.dtype:109            self.bias.data = self.bias.data.to(x.dtype)110 111        out = bnb.matmul(x, self.weight, bias=self.bias, state=self.state)112 113        if not self.state.has_fp16_weights:114            if self.state.CB is not None and self.state.CxB is not None:115                # we converted 8-bit row major to turing/ampere format in the first inference pass116                # we no longer need the row-major weight117                del self.state.CB118                self.weight.data = self.state.CxB119        return out120 121def quantize_online(model, bits: int):122    def quant(weight, bias=None):123        if bits == 8:124            linear = Linear8bitLtOnline(125                weight,126                bias,127                has_fp16_weights=False,128                threshold=6.0,129            )130            if bias is not None:131                linear.bias = torch.nn.Parameter(bias)132        elif bits == 4:133            linear = Linear4bitOnline(134                weight,135                bias,136                quant_type="nf4", #fp4/nf4137            )138        else:139            raise ValueError("quantize only support 4/8 bit")140        return linear141 142    def auto_quant(layer):143        if hasattr(layer,"bias"):144            linear = quant(layer.weight,bias=layer.bias)145        else:146            linear = quant(layer.weight)147        return linear148 149    for i,layer in enumerate(model.transformer.h):150        layer.mlp.c_fc = auto_quant(layer.mlp.c_fc)151        layer.mlp.c_proj = auto_quant(layer.mlp.c_proj)152 153        layer.attn.c_attn=auto_quant(layer.attn.c_attn)154        layer.attn.c_proj=auto_quant(layer.attn.c_proj)155 156    return model