77"""Quantize weights to torchao tensor subclasses.
88
99``quantize_weight`` quantizes a single tensor given a ``QuantConfig``,
10- returning an ``Int4Tensor`` (4-bit) or ``IntxUnpackedToInt8Tensor`` (8-bit).
10+ returning an ``Int4Tensor`` (4-bit) or ``IntxUnpackedToInt8Tensor`` (6- or
11+ 8-bit).
1112
1213``quantize_model`` walks a model's parameters, applies a ``QuantRecipe``,
1314and returns a single state dict containing both quantized subclass tensors
@@ -152,11 +153,14 @@ def _to_intx_tensor(
152153 weight : torch .Tensor ,
153154 config : QuantConfig ,
154155) -> torch .Tensor :
155- """Quantize 8-bit and wrap in IntxUnpackedToInt8Tensor.
156+ """Quantize to 6- or 8-bit and wrap in IntxUnpackedToInt8Tensor.
156157
157158 Quantizes in float32 for numerical precision, then constructs the
158159 subclass directly. We avoid ``from_hp`` because it quantizes in the
159160 input dtype (bf16), which loses precision for small-magnitude weights.
161+
162+ Sub-byte data (e.g. 6-bit) is still stored unpacked in an int8 container;
163+ ``target_dtype`` records the true bit width for the export/runtime path.
160164 """
161165 from torchao .quantization import IntxUnpackedToInt8Tensor
162166 from torchao .quantization .quant_primitives import (
@@ -165,19 +169,23 @@ def _to_intx_tensor(
165169 quantize_affine ,
166170 )
167171
172+ qmin = - (1 << (config .bits - 1 ))
173+ qmax = (1 << (config .bits - 1 )) - 1
174+ target_dtype = getattr (torch , f"int{ config .bits } " )
175+
168176 if config .method == "hqq" :
169177 if not config .symmetric :
170178 raise ValueError (
171- "8-bit HQQ only supports symmetric quantization "
172- "(HQQ_SCALE_ONLY). Use method='min_max' for asymmetric 8-bit ."
179+ "intx HQQ only supports symmetric quantization "
180+ "(HQQ_SCALE_ONLY). Use method='min_max' for asymmetric intx ."
173181 )
174182 from torchao .quantization .quant_primitives import (
175183 _choose_qparams_and_quantize_scale_only_hqq ,
176184 )
177185
178186 w2d = weight .float ().reshape (- 1 , weight .shape [- 1 ])
179187 qdata , scale = _choose_qparams_and_quantize_scale_only_hqq (
180- w2d , [1 , config .group_size ], - 128 , 127
188+ w2d , [1 , config .group_size ], qmin , qmax
181189 )
182190 qdata = qdata .to (torch .int8 ).reshape (weight .shape )
183191 scale = scale .to (torch .bfloat16 ).reshape (weight .shape [0 ], - 1 )
@@ -190,8 +198,8 @@ def _to_intx_tensor(
190198 mapping ,
191199 block_size ,
192200 target_dtype = torch .int8 ,
193- quant_min = - 128 ,
194- quant_max = 127 ,
201+ quant_min = qmin ,
202+ quant_max = qmax ,
195203 scale_dtype = torch .bfloat16 ,
196204 zero_point_dtype = torch .int8 ,
197205 )
@@ -201,8 +209,8 @@ def _to_intx_tensor(
201209 scale ,
202210 zero_point ,
203211 output_dtype = torch .int8 ,
204- quant_min = - 128 ,
205- quant_max = 127 ,
212+ quant_min = qmin ,
213+ quant_max = qmax ,
206214 )
207215 N , n_groups = weight .shape [0 ], weight .shape [- 1 ] // config .group_size
208216 scale = scale .reshape (N , n_groups )
@@ -212,7 +220,7 @@ def _to_intx_tensor(
212220 qdata = qdata ,
213221 scale = scale ,
214222 zero_point = zero_point ,
215- target_dtype = torch . int8 ,
223+ target_dtype = target_dtype ,
216224 block_size = (1 , config .group_size ),
217225 dtype = torch .bfloat16 ,
218226 activation_quantization = None ,
@@ -222,9 +230,10 @@ def _to_intx_tensor(
222230def quantize_weight (weight : torch .Tensor , config : QuantConfig ) -> torch .Tensor :
223231 """Quantize ``weight`` to a torchao tensor subclass.
224232
225- Returns ``Int4Tensor`` for 4-bit or ``IntxUnpackedToInt8Tensor`` for 8-bit.
233+ Returns ``Int4Tensor`` for 4-bit or ``IntxUnpackedToInt8Tensor`` for 6-
234+ and 8-bit.
226235 """
227- if config .bits == 8 :
236+ if config .bits in ( 6 , 8 ) :
228237 return _to_intx_tensor (weight , config )
229238
230239 if config .bits != 4 :
0 commit comments