Download conversion/quantize_weights.py from FluidInference/decision-1.0-lex-coreml: direct link, hf CLI and curl.
- Browser
- Download file 4.21 kB
-
https://huggingface.co/FluidInference/decision-1.0-lex-coreml/resolve/main/conversion/quantize_weights.py
- Command line
-
hf download hf://FluidInference/decision-1.0-lex-coreml/conversion/quantize_weights.py
-
curl -L -o quantize_weights.py https://huggingface.co/FluidInference/decision-1.0-lex-coreml/resolve/main/conversion/quantize_weights.py
4.21 kB
| """Create an experimental per-channel W8 variant of one validated typed package. | |
| This is weight-only compression. The caller must separately verify native | |
| decisions, Core ML placement, and full-request latency before publishing it. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| from pathlib import Path | |
| from typed_coreml import package_sha256 | |
| def package_bytes(package: Path) -> int: | |
| return sum(path.stat().st_size for path in package.rglob("*") if path.is_file()) | |
| def quantize(source: Path, destination: Path, scope: str = "all", linear_mode: str = "linear_symmetric") -> dict: | |
| import coremltools as ct | |
| from coremltools.optimize.coreml import ( | |
| OpLinearQuantizerConfig, | |
| OptimizationConfig, | |
| get_weights_metadata, | |
| linear_quantize_weights, | |
| ) | |
| source = source.resolve() | |
| destination = destination.resolve() | |
| if source == destination or destination.exists(): | |
| raise ValueError("Destination must be a distinct, nonexistent package") | |
| if source.suffix != ".mlpackage" or destination.suffix != ".mlpackage": | |
| raise ValueError("Source and destination must be .mlpackage directories") | |
| if not source.is_dir(): | |
| raise FileNotFoundError(source) | |
| source_report = source.with_suffix(".json") | |
| if not source_report.is_file(): | |
| raise FileNotFoundError(source_report) | |
| metadata = json.loads(source_report.read_text()) | |
| if metadata.get("coreml_choice_agreement") is not True: | |
| raise ValueError( | |
| "The source package must have successful conversion validation" | |
| ) | |
| original = ct.models.MLModel(str(source), skip_model_load=True) | |
| quantizer = OpLinearQuantizerConfig( | |
| mode=linear_mode, dtype="int8", granularity="per_channel", weight_threshold=2048, | |
| ) | |
| selected_weights = None | |
| if scope == "embedding": | |
| weights = get_weights_metadata(original, weight_threshold=2048) | |
| selected_weights = [ | |
| name for name, weight in weights.items() | |
| if len(weight.val.shape) == 2 | |
| and any(op.op_type == "gather" for op in weight.child_ops) | |
| and "embeddings_tok_embeddings" in name | |
| ] | |
| if len(selected_weights) != 1: | |
| raise ValueError(f"expected one token embedding, found {selected_weights}") | |
| config = OptimizationConfig(op_name_configs={selected_weights[0]: quantizer}) | |
| elif scope == "all": | |
| config = OptimizationConfig(global_config=quantizer) | |
| else: | |
| raise ValueError(f"unsupported compression scope: {scope}") | |
| compressed = linear_quantize_weights(original, config=config) | |
| destination.parent.mkdir(parents=True, exist_ok=True) | |
| compressed.save(str(destination)) | |
| result = { | |
| "kind": metadata["kind"], | |
| "shape": metadata["shape"], | |
| "source_repo": metadata["source_repo"], | |
| "source_revision": metadata["source_revision"], | |
| "package_sha256": package_sha256(destination), | |
| "package_bytes": package_bytes(destination), | |
| "compressed_from": { | |
| "package": source.name, | |
| "sha256": package_sha256(source), | |
| "bytes": package_bytes(source), | |
| }, | |
| "compression": { | |
| "type": "weight-only linear quantization", | |
| "mode": linear_mode, | |
| "dtype": "int8", | |
| "granularity": "per_channel", | |
| "weight_threshold": 2048, | |
| "scope": scope, | |
| "selected_weights": selected_weights, | |
| }, | |
| "validated": False, | |
| } | |
| destination.with_suffix(".json").write_text(json.dumps(result, indent=2) + "\n") | |
| return result | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.add_argument("--source", required=True, type=Path) | |
| parser.add_argument("--output", required=True, type=Path) | |
| parser.add_argument("--scope", choices=("all", "embedding"), default="all") | |
| parser.add_argument("--linear-mode", choices=("linear_symmetric", "linear"), default="linear_symmetric") | |
| args = parser.parse_args() | |
| print(json.dumps(quantize(args.source, args.output, args.scope, args.linear_mode), indent=2)) | |
| if __name__ == "__main__": | |
| main() | |