|
15 | 15 |
|
16 | 16 | from __future__ import annotations |
17 | 17 |
|
18 | | -from typing import Tuple |
| 18 | +from typing import Optional, Tuple |
| 19 | + |
| 20 | +import torch |
19 | 21 |
|
20 | 22 | from executorch.backends.mlx.builder.op_helpers import to_mlx_qparams |
21 | 23 | from executorch.backends.mlx.builder.program_builder import MLXProgramBuilder |
|
25 | 27 | _BITS = 4 |
26 | 28 |
|
27 | 29 |
|
28 | | -def repack_mlx(P: MLXProgramBuilder, weight_node: Node) -> Tuple[Slot, Slot, Slot, int]: |
| 30 | +def repack_mlx( |
| 31 | + P: MLXProgramBuilder, |
| 32 | + weight_node: Node, |
| 33 | + scale_dtype: Optional[torch.dtype] = None, |
| 34 | +) -> Tuple[Slot, Slot, Slot, int]: |
29 | 35 | """Unpack a raw Q4_K blob and repack into MLX qparam constants. |
30 | 36 |
|
31 | 37 | Adjacent sub-blocks with identical scale/min are merged into a larger group |
32 | 38 | size (up to 128) when lossless, so ``group_size`` may be 32, 64, or 128. |
33 | 39 | Returns ``(packed_slot, scales_slot, biases_slot, group_size)``. |
| 40 | +
|
| 41 | + ``scale_dtype`` sets the dtype of the emitted scales/biases constants; pass |
| 42 | + the activation dtype so MLX ``quantized_matmul`` does not promote (a bf16 |
| 43 | + activation with f16 scales, or vice versa, promotes to float32). |
34 | 44 | """ |
35 | 45 | from executorch.extension.llm.export.gguf import ExportableGGUFTensor |
36 | 46 |
|
37 | 47 | weight_target, raw = P.get_placeholder_target_and_tensor(weight_node) |
38 | 48 | intx = ExportableGGUFTensor.from_raw(raw, "q4_k").to_intx_unpacked_to_int8_tensor( |
39 | | - max_group_size=128 |
| 49 | + max_group_size=128, scale_dtype=scale_dtype |
40 | 50 | ) |
41 | 51 | group_size = int(intx.block_size[-1]) |
42 | 52 | qdata, scale, zero_point = intx.qdata, intx.scale, intx.zero_point |
|
0 commit comments