Views
No views yet
import mlx.core as mx
import mlx.nn as nn
from mlx_vlm.utils import load
import json
import os
import gc
model_path = "/Model/Path/Here/Qwen3.5-122B-A10B"
output_path = "/Save/Directory/Here/Qwen-122B-Mixed-4bit"
print("1. Loading Qwen 3.5 lazily...")
model, processor = load(model_path, lazy=True)
# ---------------------------------------------------------
# THE PERFECT FILTER (From Script 2)
# ---------------------------------------------------------
def qwen_surgical_filter(path, module):
# 1. Protect the Router traffic cops
if path.endswith(".gate") or "shared_expert_gate" in path:
return False
# 2. THE CRUSH ZONE
# We only want the actual matrices, NOT the SwiGLU wrappers holding them!
if "switch_mlp" in path or "shared_expert" in path:
if path.endswith("gate_proj") or path.endswith("up_proj") or path.endswith("down_proj"):
return True
# 3. Protect everything else (Vision, Attention, IO, and Wrappers)
return False
print("2. Applying the MoE crush (4-bit)...")
nn.quantize(model, group_size=64, bits=4, class_predicate=qwen_surgical_filter)
os.makedirs(output_path, exist_ok=True)
print("3. Saving config and processor metadata...")
if hasattr(processor, "save_pretrained"):
processor.save_pretrained(output_path)
with open(os.path.join(model_path, "config.json"), "r") as f:
raw_config = json.load(f)
raw_config["quantization"] = {"group_size": 64, "bits": 4}
with open(os.path.join(output_path, "config.json"), "w") as f:
json.dump(raw_config, f, indent=4)
def flatten_parameters(obj, parent_key='', sep='.'):
items = []
if isinstance(obj, dict):
for k, v in obj.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else str(k)
items.extend(flatten_parameters(v, new_key, sep=sep).items())
elif isinstance(obj, list):
for i, v in enumerate(obj):
new_key = f"{parent_key}{sep}{i}" if parent_key else str(i)
items.extend(flatten_parameters(v, new_key, sep=sep).items())
else:
items.append((parent_key, obj))
return dict(items)
print("4. Flattening architecture map...")
flat_weights = flatten_parameters(model.parameters())
# ---------------------------------------------------------
# THE MEMORY-SAFE ENGINE
# ---------------------------------------------------------
print("5. Burning the ships (Destroying model tree)...")
del model
del processor
gc.collect()
print("6. Sequentially evaluating and sharding to SSD...")
current_shard = {}
current_shard_size = 0
shard_index = 1
MAX_SHARD_SIZE = 5 * 1024 * 1024 * 1024
flat_weights_keys = list(flat_weights.keys())
total_tensors = len(flat_weights_keys)
for i, name in enumerate(flat_weights_keys):
tensor = flat_weights.pop(name)
if not isinstance(tensor, mx.array):
continue
mx.eval(tensor)
current_shard[name] = tensor
current_shard_size += tensor.nbytes
if current_shard_size >= MAX_SHARD_SIZE:
shard_name = f"model-{shard_index:05d}.safetensors"
print(f" -> Saving {shard_name} ({current_shard_size / (1024**3):.2f} GB) ... [{i+1}/{total_tensors}]")
mx.save_safetensors(os.path.join(output_path, shard_name), current_shard)
current_shard.clear()
current_shard_size = 0
gc.collect()
# Use the updated non-deprecated cache clear
if hasattr(mx, "clear_cache"):
mx.clear_cache()
else:
mx.metal.clear_cache()
shard_index += 1
if current_shard:
shard_name = f"model-{shard_index:05d}.safetensors"
print(f" -> Saving {shard_name} ({current_shard_size / (1024**3):.2f} GB) ... [{total_tensors}/{total_tensors}]")
mx.save_safetensors(os.path.join(output_path, shard_name), current_shard)
current_shard.clear()
gc.collect()
if hasattr(mx, "clear_cache"):
mx.clear_cache()
else:
mx.metal.clear_cache()
print(f"\nSUCCESS! Custom MoE successfully sharded and saved to {output_path}")return weights to the top of the sanitize_weights function to bypass the check entirely.Model: Qwen3.5-122B-A10B-MLX-6.5bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
HUMANEVAL 85.4% 140 164 358.4
MBPP 79.2% 396 500 775.9
LIVECODEBENCH 50.7% 534 1054 11658.4
Model: Qwen-122B-Mixed-5bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
HUMANEVAL 86.6% 142 164 436.1
MBPP 78.8% 394 500 866.4
LIVECODEBENCH 50.9% 537 1054 14491.9
Model: Qwen-122B-Mixed-4bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
HUMANEVAL 86.0% 141 164 376.5
MBPP 79.8% 399 500 796
LIVECODEBENCH 50.6% 533 1054 13160.8
Model: Qwen-122B-Mixed-3bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
HUMANEVAL 87.8% 144 164 311.5
MBPP 80.4% 402 500 837.4
LIVECODEBENCH 50.0% 527 1054 13961
Model: Qwen-122B-Mixed-2bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
HUMANEVAL 86.0% 141 164 422.8
MBPP 75.8% 379 500 1660
Other benchmarks:
Model: Qwen3.5-122B-A10B-MLX-6.5bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
MMLU 90.0% 180 200 233.9
HELLASWAG 93.5% 187 200 159.3
TRUTHFULQA 91.0% 273 300 198.1
ARC_CHALLENGE 97.3% 292 300 178.4
WINOGRANDE 82.0% 246 300 155.9
GSM8K 94.0% 47 50 209.7
Model: Qwen-122B-Mixed-5bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
MMLU 90.0% 180 200 214.2
HELLASWAG 93.5% 187 200 140
TRUTHFULQA 91.7% 275 300 173.7
ARC_CHALLENGE 97.0% 291 300 156.4
WINOGRANDE 82.0% 246 300 139.2
GSM8K 94.0% 47 50 214.5
Model: Qwen-122B-Mixed-4bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
MMLU 90.0% 180 200 194.6
HELLASWAG 93.5% 187 200 128.4
TRUTHFULQA 92.7% 278 300 155.9
ARC_CHALLENGE 97.7% 293 300 140.6
WINOGRANDE 81.0% 243 300 125.6
GSM8K 96.0% 48 50 195.1
Model: Qwen-122B-Mixed-3bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
MMLU 89.5% 179 200 194.2
HELLASWAG 94.0% 188 200 129.8
TRUTHFULQA 91.3% 274 300 157.8
ARC_CHALLENGE 96.7% 290 300 142.5
WINOGRANDE 79.3% 238 300 127
GSM8K 94.0% 47 50 181.9
Model: Qwen-122B-Mixed-2bit
Benchmark Accuracy Correct Total Time(s)
------------------------------------------------------
MMLU 89.0% 178 200 185.8
HELLASWAG 92.5% 185 200 122.9
TRUTHFULQA 90.7% 272 300 153.1
ARC_CHALLENGE 97.0% 291 300 134.4
WINOGRANDE 79.0% 237 300 120.6
GSM8K 92.0% 46 50 192.2