SPB Git

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%
2.7 KB · 80 lines python
Raw Blame History
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