kev-0.6b-coreml / source /quantize.py
alexwengg's picture
Publish verified Kev 0.6B FP16 Core ML conversion
d4eb935 verified
Raw
History Blame Contribute Delete
3.3 kB
"""Compress the Kev Core ML package and leave the FP16 source untouched."""
from __future__ import annotations
import argparse
import time
from pathlib import Path
import coremltools as ct
import coremltools.optimize.coreml as cto
from assets import ROOT
def package_bytes(path: Path) -> int:
return sum(item.stat().st_size for item in path.rglob("*") if item.is_file())
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--length", type=int, default=128)
parser.add_argument("--max-options", type=int, default=32)
parser.add_argument("--precision", choices=("e8", "w8", "w8mlp", "w8mlp12", "w4"), required=True)
parser.add_argument("--build-dir", type=Path, default=ROOT / "build")
args = parser.parse_args()
stem = f"kev_0_6b_fp16_L{args.length}_options{args.max_options}"
source = args.build_dir / f"{stem}.mlpackage"
target = args.build_dir / f"{stem.replace('fp16', args.precision)}.mlpackage"
model = ct.models.MLModel(str(source), compute_units=ct.ComputeUnit.CPU_ONLY)
metadata = cto.get_weights_metadata(model, weight_threshold=2048)
embeddings = [
name for name, weight in metadata.items() if weight.child_ops and weight.child_ops[0].op_type == "gather"
]
linear = [
name
for name, weight in metadata.items()
if len(weight.val.shape) == 2 and weight.child_ops and weight.child_ops[0].op_type == "linear"
]
if args.precision == "e8":
names = embeddings
config = cto.OpLinearQuantizerConfig(mode="linear_symmetric", dtype="int8", granularity="per_channel")
compressed = cto.linear_quantize_weights(
model, cto.OptimizationConfig(op_name_configs={name: config for name in names})
)
elif args.precision in ("w8", "w8mlp", "w8mlp12"):
names = embeddings + linear
if args.precision == "w8mlp":
names = embeddings + [name for name in linear if "_mlp_" in name]
elif args.precision == "w8mlp12":
names = embeddings + [
name
for name in linear
if "_mlp_" in name and int(name.split("_", 2)[1]) % 2 == 0
]
config = cto.OpLinearQuantizerConfig(mode="linear_symmetric", dtype="int8", granularity="per_channel")
compressed = cto.linear_quantize_weights(
model, cto.OptimizationConfig(op_name_configs={name: config for name in names})
)
else:
names = embeddings + linear
config = cto.OpPalettizerConfig(mode="kmeans", nbits=4, granularity="per_tensor", num_kmeans_workers=8)
compressed = cto.palettize_weights(
model, cto.OptimizationConfig(op_name_configs={name: config for name in names})
)
compressed.user_defined_metadata["precision"] = args.precision
compressed.short_description = (model.short_description or "") + f" [{args.precision}]"
started = time.perf_counter()
compressed.save(str(target))
print(
f"Saved {target.name}: {package_bytes(target) / 1e6:.0f} MB from "
f"{package_bytes(source) / 1e6:.0f} MB; {len(names)} compressed constants; "
f"save {time.perf_counter() - started:.1f} s",
flush=True,
)
if __name__ == "__main__":
main()