在 MacBook Pro M5 Max 128GB 上,从 lordx64 的 Claude 4.7 Opus reasoning 蒸馏版出发,用 oMLX 生成 6 档(VLM × 3 + Text × 3)混合精度量化模型,并发布到 HuggingFace。

🎯 目标产物

产物模态量化级别大小HF 链接
VLM-MLX-oQ4图文oQ4 (~4.8 bpw)19.6 GBhf.co/wangkezun/…VLM-MLX-oQ4
VLM-MLX-oQ6图文oQ6 (~6.5 bpw)27 GBhf.co/wangkezun/…VLM-MLX-oQ6
VLM-MLX-oQ8图文oQ8 (~8.7 bpw)35 GBhf.co/wangkezun/…VLM-MLX-oQ8
Text-MLX-oQ4纯文本oQ419 GBhf.co/wangkezun/…Text-MLX-oQ4
Text-MLX-oQ6纯文本oQ627 GBhf.co/wangkezun/…Text-MLX-oQ6
Text-MLX-oQ8纯文本oQ834 GBhf.co/wangkezun/…Text-MLX-oQ8

总数据量 162 GB(量化产物) + 102 GB(中间产物)= 264 GB


📚 关键概念

oMLX 的 oQ 量化

oMLX 是 jundot 开发的 MLX 推理服务,提供独家的 oQ 系列混合精度量化

  • oQ4 / oQ6 / oQ8:表示平均比特数(4.8 / 6.5 / 8.7 bpw),不是固定值
  • 混合精度策略:根据 sensitivity model 打分,对每个权重分配不同 bit 数
    • 高分权重(推理路径关键) → 保留 8bit
    • 低分权重 → 激进压缩到 2-4bit
  • vs mxfp8:mxfp8 是 OCP FP8 标准,固定 8bit + scale;oQ8 是平均 8.7bpw 的变长 INT 量化

Sensitivity Model 的作用

oQ 量化需要一个 sensitivity model 来指导量化策略,本质是”权重重要性参考”:

  • 不用 sens → 退化为均匀量化,oQ4 等于普通 4bit AWQ
  • 用 sens → 量化器知道哪些权重对推理路径重要,混合精度按重要性分配

oMLX 限制:sensitivity model 下拉只识别 MLX 量化版(不是 BF16 full-precision)。所以即使想用 BF16 模型作 sens,也必须先量化成 8bit。

VLM vs Text-Only

Qwen3.6-35B-A3B 本身是 VLM(image-text-to-text),但 oMLX 量化时可以选择 Text Only 模式:

  • 关 Text Only → 保留 vision tower → VLM 量化产物
  • 开 Text Only → 剥离 vision tower → 纯文本量化产物

两者文件大小差距很小(< 1 GB),因为 vision tower 参数占整个模型不到 2%。但纯文本版推理速度快约 10%(少了 vision 计算路径)。


🎯 本次量化的配置选择

选定配置

角色选择用途
源模型lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled被量化的对象(产物来自它)
Sensitivity同蒸馏版的 8bit MLX 量化量化决策的权重重要性参考
dtypebfloat16M5 Max 在 BF16 上更稳定
量化档位oQ4 / oQ6 / oQ8覆盖低中高 3 档
模态VLM + Text-Only 各做一份两种使用场景

为什么源选蒸馏版

蒸馏版(lordx64)已经是从 Claude 4.7 Opus reasoning 数据 LoRA 微调过的模型,回答时会带 <think> 思考标签,符合 Claude Code、AstrBot 等场景的预期使用习惯。

如果想要保留 Qwen3.6 原始通用能力(比如最纯净的中文创作),可以另外做一份基于官方原版 Qwen/Qwen3.6-35B-A3B 的量化——本次没做,但流程一致,未来可以补。

为什么 sens 用同模型 8bit

oMLX 要求 sens 是 MLX 量化版,所以不能直接用 BF16 蒸馏版作 sens。把蒸馏版量化到 8bit 作 sens 有几个考虑:

  • 架构 100% 对齐源模型,分布偏移最小
  • 同时做 reasoning 蒸馏的偏向(高 sens 分数集中在 reasoning 路径)
  • 不需要找其他兼容模型

如果未来 lordx64 出新版本但官方 Qwen3.6 不变,可以复用同样的 sens 流程。

为什么做 6 档(VLM × 3 + Text × 3)

用途推荐版本
Claude Code 主力Text-oQ4 / Text-oQ6
AstrBot 后端(图文兼容)VLM-oQ4 / VLM-oQ6
高质量参考基线VLM-oQ8 / Text-oQ8
内存紧张场景oQ4 系列
性价比首选oQ6 系列

不同场景灵活切换。每档量化只需 30 分钟,总磁盘 ~162 GB,成本可接受。


🛠️ 环境准备

工具栈

# Python 工具用 uv tool 隔离
uv tool install mlx-lm
uv tool install mlx-vlm --with torch --with torchvision
uv tool install --with hf_transfer --reinstall huggingface-hub
 
# oMLX 通过 Homebrew
brew tap jundot/omlx
brew install omlx

关键环境变量

# HF 加速下载(国内可选)
export HF_ENDPOINT=https://hf-mirror.com
 
# HF 上传加速(必装,能跑到 50+ MB/s)
export HF_HUB_ENABLE_HF_TRANSFER=1

📋 完整步骤

阶段 0:清理 + 工具升级

# 升级 mlx-vlm 到最新版(v0.4.4+)
uv tool upgrade mlx-vlm
 
# 清理之前用 mlx_lm.convert 转的产物(丢了 vision tower,无用)
rm -rf ~/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Distilled-MLX-BF16
rm -rf ~/.cache/huggingface/models/wangkezun/MLX-Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-8bit

阶段 1:转换源模型(BF16 VLM)

mlx_vlm.convert \
  --hf-path /Users/wangkezun/.cache/huggingface/models/lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled \
  --mlx-path /Users/wangkezun/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-BF16 \
  --dtype bfloat16

耗时:~10 分钟 产物:~67 GB 峰值内存:~80 GB

阶段 2:转换 Sensitivity Model(8bit VLM)

mlx_vlm.convert \
  --hf-path /Users/wangkezun/.cache/huggingface/models/lordx64/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled \
  --mlx-path /Users/wangkezun/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-VLM-8bit \
  --quantize \
  --q-bits 8 \
  --dtype bfloat16

耗时:~15 分钟 产物:~35 GB

阶段 3:验证转换

python3 -c "
import json
path = '/path/to/model'
with open(path + '/model.safetensors.index.json') as f:
    keys = list(json.load(f)['weight_map'].keys())
vision = [k for k in keys if 'vision' in k.lower() or 'visual' in k.lower()]
print(f'Total: {len(keys)}, Vision: {len(vision)}')
"

预期:Vision keys ~333(Qwen3.6 ViT 块数)

阶段 4:oMLX 量化(6 次)

打开 oMLX → 模型管理器 → 重新加载(确保识别新转的两个模型)。

进 oQ 量化页面,6 次任务的通用配置:

源模型Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-BF16
SensitivityQwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-VLM-8bit
Non-quant dtypebfloat16

每次只改两个开关:

#oQ 级别Text Only单次耗时产物大小
1oQ4~30 min19.6 GB
2oQ6~30 min27 GB
3oQ8~30 min35 GB
4oQ4~30 min19 GB
5oQ6~30 min27 GB
6oQ8~30 min34 GB

每次产物名相同...-MLX-oQ4/oQ6/oQ8),跑完立刻改名加 -VLM--Text- 区分:

# VLM 版改名
mv ~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-oQ4 \
   ~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4
 
# Text 版改名
mv ~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-oQ4 \
   ~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-Text-MLX-oQ4

阶段 5:补全 VLM processor 配置

每次量化后必须补 VLM processor 文件(参见 坑 3:lordx64 蒸馏版本身缺 VLM processor 配置):

SRC=~/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-BF16
DST=~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4
 
cp -Lvn $SRC/processor_config.json $DST/
cp -Lvn $SRC/video_preprocessor_config.json $DST/

阶段 6:上传到 HuggingFace

# 登录(一次性)
hf auth login
 
# 加速
export HF_HUB_ENABLE_HF_TRANSFER=1
 
# 单个上传
hf upload \
  wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4 \
  ~/.omlx/models/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4 \
  --commit-message "Initial upload: VLM oQ4 quantization"

阶段 7:备份到 NAS

NAS_ROOT=/Volumes/nas/omlx-models
 
mkdir -p $NAS_ROOT/{quants,intermediate}
 
# 备份 6 个量化产物
rsync -avh --progress --size-only \
  ~/.omlx/models/ \
  $NAS_ROOT/quants/
 
# 备份 BF16 源 + 8bit sens
rsync -avh --progress --size-only \
  ~/.cache/huggingface/models/wangkezun/ \
  $NAS_ROOT/intermediate/

阶段 8:清理本地中间产物

rm -rf ~/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-BF16
rm -rf ~/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-VLM-8bit

释放约 102 GB


🐛 踩过的坑

坑 1:mlx_lm.convert 不能转 VLM

最初尝试用 mlx_lm.convert 转 lordx64 蒸馏版,转换”成功”但视觉塔丢失:

Total: 733, Vision: 0  ❌

原因mlx-lm 是纯 LM 工具,看到 vision tower 直接丢弃。

解决:必须用 mlx-vlm 包,它专门处理 VLM 架构。mlx_vlm.convert 转完后 Vision: 333

坑 2:mlx-vlm 缺 torch/torchvision 依赖

第一次跑 mlx_vlm.convert 报错:

ImportError: Qwen3VLVideoProcessor requires the Torchvision library

原因:Qwen3.6 的 processor 需要 torchvision 处理视频帧。mlx-vlm 包默认没声明这个依赖。

解决

uv tool install --with torch --with torchvision --reinstall mlx-vlm

坑 3:lordx64 蒸馏版本身缺 VLM processor 配置

oMLX 量化产物运行 mlx_vlm.generate 时报错:

OSError: Can't load image processor ... preprocessor_config.json

根本原因链

  1. lordx64 上传蒸馏版时漏了 preprocessor_config.json(可能是 unsloth 训练后保存疏漏)
  2. mlx_vlm.convert 不会主动从基座补这个文件
  3. oMLX 量化产物只复制 BF16 源里有的文件
  4. → 一路传染,量化产物缺关键 VLM 配置

解决:从官方 Qwen/Qwen3.6-35B-A3B 借这几个文件,并先补到 BF16 源里(让后续量化能继承):

OFFICIAL=~/.cache/huggingface/models/Qwen/Qwen3.6-35B-A3B
DST=~/.cache/huggingface/models/wangkezun/Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-MLX-BF16
 
# 注意 -L 跟随软链接,否则 hfd 下载是 symlink
cp -Lv $OFFICIAL/preprocessor_config.json $DST/
cp -Lv $OFFICIAL/video_preprocessor_config.json $DST/
cp -Lv $OFFICIAL/generation_config.json $DST/

oMLX 仍只会自动复制部分文件(白名单机制)。具体行为:

文件oMLX 自动复制?
chat_template.jinja
tokenizer.json / tokenizer_config.json
config.json
preprocessor_config.json✅(如果源里有)
generation_config.json
processor_config.json
video_preprocessor_config.json

每次量化后都要手动补这两个文件:

cp -Lvn $SRC/processor_config.json $DST/
cp -Lvn $SRC/video_preprocessor_config.json $DST/

坑 4:oMLX 命名冲突

oMLX 量化产物默认命名 {源名}-oQ4VLM 和 Text Only 两次量化会输出同名,第二次会覆盖第一次。

解决:每次量化跑完立刻 mv 改名-VLM--Text- 标识,避免下次量化覆盖。

坑 5:sens model 必须是 MLX 量化版

oMLX 的 sensitivity model 下拉只识别已量化的 MLX 格式,BF16 full-precision 模型选不上。

解决:必须先做一份 8bit 量化版作 sens(阶段 2),不能直接用 BF16 源。

坑 6:fp16 vs bf16 选择

oMLX 提供两个选项:

  • float16:M1/M2 prefill 快 ~20%(原生 FP16 加速)
  • bfloat16:M3+ 更稳定,数值动态范围大

M5 Max 选 bfloat16 是对的(M3+ 的 fp16 红利消失,bf16 在量化场景更安全)。

坑 7:HF cache 软链接陷阱

hfdhf download --local-dir 默认下载是软链接到 ~/.cache/huggingface/hub/... 的实际文件。直接 cp 会复制软链接本身,必须用 cp -L 才能复制实际内容。

# 错误:复制了软链接(目标移动后会失效)
cp $OFFICIAL/preprocessor_config.json $DST/
 
# 正确:跟随软链接复制实际文件
cp -L $OFFICIAL/preprocessor_config.json $DST/

📊 实测性能对比

测试硬件:MacBook Pro M5 Max 128GB 测试图片:网络梗图(“核善的笑容”,Antony Starr 演 Homelander)

VLM 系列

档位大小内存Prompt t/sGen t/s知识识别
oQ419.6 GB22 GB157117”金发男子”(泛泛)
oQ627 GB30 GB617103认出演员+剧+角色
oQ835 GB39 GB63796同 oQ6(边际收益小)

关键发现:oQ4 → oQ6 是质的飞跃(世界知识保留),oQ6 → oQ8 是量变。oQ6 是性价比最高档位

Text 系列

档位大小内存Gen t/s
oQ419 GB20 GB127
oQ627 GB28 GB112
oQ834 GB37 GB103

Text 比 VLM 快 ~10%(少了 vision 计算路径)。

Vision keys 验证

VLM 系列:Total 2010, Vision 333
Text 系列:Total 1677, Vision 0  ✅ 视觉塔成功剥离

333 个 vision keys 是 Qwen3.6 ViT 的标准结构。


🗂️ 最终目录结构

本地:
~/.cache/huggingface/models/
├── Qwen/
│   └── Qwen3.6-35B-A3B/                              # 官方原版(保留,可作未来量化源)
└── lordx64/
    └── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled/  # 蒸馏源(保留)

~/.omlx/models/
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ6
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ8
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-Text-MLX-oQ4
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-Text-MLX-oQ6
└── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-Text-MLX-oQ8

NAS:
/Volumes/nas/
├── hf-models/                  # hfd 管理的 HF 原版下载
└── omlx-models/                # 自转 + 量化产物
    ├── quants/                 # 6 个最终量化产物(162 GB)
    └── intermediate/           # BF16 源 + 8bit sens(102 GB)

HuggingFace:
huggingface.co/wangkezun/
├── Qwen3.6-35B-A3B-Claude-4.7-Opus-Reasoning-Distilled-VLM-MLX-oQ4
├── ...VLM-MLX-oQ6
├── ...VLM-MLX-oQ8
├── ...Text-MLX-oQ4
├── ...Text-MLX-oQ6
└── ...Text-MLX-oQ8

🔄 后续工作流(重做量化时)

如果将来 lordx64 出新版本(比如 v2 或 4.8 蒸馏),重做量化只需:

# 1. 更新蒸馏源
hf download lordx64/Qwen3.6-35B-A3B-Claude-X.X-Opus-Reasoning-Distilled \
  --local-dir ~/.cache/huggingface/models/lordx64/...
 
# 2. 从 NAS 恢复 BF16 + 8bit sens(如果之前同源没变)
rsync -avh --progress /Volumes/nas/omlx-models/intermediate/ \
  ~/.cache/huggingface/models/wangkezun/
 
# 否则重新运行阶段 1 + 2 重新转换
 
# 3. 直接进 oMLX 跑量化(阶段 4)
# 4. 修复 processor 配置(阶段 5)
# 5. 上传 HF(阶段 6)

💡 经验总结

  1. VLM 量化必须用 mlx-vlm,不要用 mlx-lm
  2. uv tool install 时记得 --with torch --with torchvision
  3. 量化产物总要手动补 processor_config.json + video_preprocessor_config.json
  4. oMLX 命名会撞,量化跑完立刻 mv 加标识
  5. cp -L 才能复制软链接的实际内容
  6. dry-run rsync 是好习惯-n 标志)
  7. HF 上传必装 hf_transfer,速度提升 3-5 倍
  8. oQ6 是性价比拐点,质量逼近 oQ8,体积小 8GB

📎 相关链接


🏷️ 标签

mlx apple-silicon quantization omlx vlm qwen claude-distilled workflow completed