spb/zyquo-mlx Public MIT
The local MLX foundry for your Mac — run, fine-tune, quantize, and ship models. Nothing leaves your machine.
Swift 93.4%
Python 3.8%
Makefile 2.2%
Shell 0.5%
1#2# zyquo_convert.py3# Zyquo MLX4#5# Author: Simon-Pierre Boucher6# Mail: contact@spboucher.ai7#8# Conversion/quantization driver: HF model → MLX format, optionally9# quantized (mlx_lm.convert semantics — docs/MLX-RESEARCH.md §5.2).10# JSON-lines protocol on stdout.11#12# Usage: zyquo_convert.py --hf-path <repo-or-dir> --mlx-path <dir>13# [--quantize --q-bits 4 --q-group-size 64 --q-mode affine]14# [--dtype float16|bfloat16|float32] [--dequantize]1516import argparse17import json18import sys19import time202122def emit(obj):23 sys.stdout.write(json.dumps(obj) + "\n")24 sys.stdout.flush()252627def main():28 parser = argparse.ArgumentParser()29 parser.add_argument("--hf-path", required=True)30 parser.add_argument("--mlx-path", required=True)31 parser.add_argument("--quantize", action="store_true")32 parser.add_argument("--q-bits", type=int, default=None)33 parser.add_argument("--q-group-size", type=int, default=None)34 parser.add_argument("--q-mode", default="affine",35 choices=["affine", "mxfp4", "nvfp4", "mxfp8"])36 parser.add_argument("--dtype", default=None,37 choices=["float16", "bfloat16", "float32"])38 parser.add_argument("--dequantize", action="store_true")39 args = parser.parse_args()4041 try:42 emit({"event": "start", "stage": "convert", "hf_path": args.hf_path, "ts": time.time()})4344 from mlx_lm import convert4546 # mlx-lm 0.31.3 first downloads weights with allow_patterns, then its47 # copy step demands the FULL snapshot with local_files_only=True and48 # trips IncompleteSnapshotError on aux files (.gitattributes, LICENSE…).49 # Pre-fetch the complete snapshot for remote repos to sidestep it.50 import os51 if not os.path.isdir(args.hf_path):52 from huggingface_hub import snapshot_download53 emit({"event": "stage", "stage": "downloading"})54 snapshot_download(repo_id=args.hf_path)5556 kwargs = {57 "hf_path": args.hf_path,58 "mlx_path": args.mlx_path,59 "quantize": args.quantize,60 "dequantize": args.dequantize,61 }62 if args.q_bits is not None:63 kwargs["q_bits"] = args.q_bits64 if args.q_group_size is not None:65 kwargs["q_group_size"] = args.q_group_size66 if args.quantize:67 kwargs["q_mode"] = args.q_mode68 if args.dtype:69 kwargs["dtype"] = args.dtype7071 convert(**kwargs)72 emit({"event": "done", "mlx_path": args.mlx_path})73 except Exception as exc: # noqa: BLE00174 emit({"event": "error", "message": str(exc), "type": type(exc).__name__})75 sys.exit(1)767778if __name__ == "__main__":79 main()80