MLX-VLM:在 Apple Silicon 上运行与微调视觉语言模型
posts posts 2026-04-06T17:30:00+08:00MLX-VLM 是 Blaizzy 维护的 MLX 套件,用于在 Apple Silicon 上推理与微调视觉语言模型和全能模型。本文覆盖架构、支持模型、视觉特征缓存、KV Cache 量化、LoRA 微调与 FastAPI 服务器部署。技术笔记MLX, Apple Silicon, VLM, 本地AIMLX-VLM:在 Apple Silicon 上运行与微调视觉语言模型
想要在 Mac 上本地跑视觉语言模型(VLM),最顺手的入口是 MLX-VLM。它把推理和微调都封装好了:读图、听音频、看视频、开一个 OpenAI 兼容的接口,或者用 LoRA 调一个自己的模型,都可以在这一个包里完成。它的价值来自底层 MLX 与 Apple Silicon 统一内存的配合——模型权重直接放在 GPU 可访问的内存里,省掉了 CPU 与 GPU 之间的搬运,让消费级 Mac 也能跑多模态模型。
下面按“是什么 → 架构 → 能跑哪些模型 → 怎么用 → 进阶调优 → 部署”展开。
学习目标
读完本文后,你应该能够:
- 说清 MLX-VLM 在 Apple Silicon 上的推理原理和优势
- 安装 MLX-VLM,并会用命令行和 Python API 做图像、音频、视频理解
- 根据内存选择模型,并理解视觉特征缓存与 KV Cache 量化的取舍
- 用 LoRA/QLoRA 微调自己的模型
- 启动 FastAPI 服务器并调用 OpenAI 兼容接口
目录
- 1. MLX-VLM 是什么
- 2. 技术架构
- 3. 支持模型
- 4. 基本用法
- 5. 视觉特征缓存
- 6. KV Cache 量化:Uniform 与 TurboQuant
- 7. LoRA / QLoRA 微调
- 8. 服务器部署
- 9. 安装与配置
- 10. 实践建议
- 11. 常见问题与排查
- 12. 总结
- 自测题
- 练习
- 进阶路径
1. MLX-VLM 是什么
1.1 定位
MLX-VLM 是一个 Python 包,由 Blaizzy Prince Canuma 维护,专注做两件事:在 Apple Silicon Mac 上推理和微调两类模型:
- 视觉语言模型(VLM):看图说话、视觉问答、图文对照
- 全能模型(Omni Model):VLM 的扩展,额外支持音频、视频输入
模型权重通常来自 Hugging Face 上的 mlx-community 组织,那里提供了大量预量化权重,首次使用自动下载,无需手动转换格式。
1.2 关键信息
| 项目 | 说明 |
|---|---|
| 开发者 | Blaizzy Prince Canuma |
| 许可证 | MIT |
| 支持模型 | 50+ 种架构 |
| 微调方式 | LoRA、QLoRA |
| 服务器 | FastAPI,兼容 OpenAI Chat Completions / Responses API |
| 安装 | pip install -U mlx-vlm |
本地推理意味着数据不离开设备。图片、音频、提示词都只在你的 Mac 上处理,涉及隐私或合规的场景这一点很关键;代价是算力和内存都花在本地。
1.3 技术标签
mlx · vision-language-model · apple-silicon · omni-model · local-ai1.4 主要特点
- Apple Silicon 优先:基于 MLX,利用统一内存与 Metal GPU 加速
- 多模态输入:图像、视频、音频,取决于所加载的模型架构
- 量化友好:直接加载 mlx-community 的 4-bit 等量化权重
- 本地可微调:LoRA/QLoRA,用小批量数据在本地训出垂直模型
- 服务化:FastAPI 服务器,OpenAI 兼容,便于接进现有应用
2. 技术架构
2.1 MLX 框架为什么适合做这件事
MLX 是 Apple 的开源机器学习框架,几个特性直接决定 VLM 能在 Mac 上跑起来:
- 统一内存:CPU 与 GPU 共享同一块物理内存,模型权重省去在两者之间搬移。VRAM 受限的显卡生态里,超大模型的显存放不下,而 Mac 可以整块模型驻留在统一内存里。
- Metal GPU 加速:张量计算走 Apple GPU 的并行内核。
- Python 优先:API 风格接近 NumPy,写起来直接。
2.2 MLX-VLM 的分层结构
MLX-VLM 提供三层入口,上层是 CLI 和服务器,中层是各种模型实现,底层是 MLX 的算子:
用户接口层 CLI(mlx_vlm.generate / chat / chat_ui)
Python API(load / generate / stream_generate / apply_chat_template)
服务器(FastAPI,/v1/chat/completions、/responses、/health)
───────────────────────────────────────────────
模型层 Vision Encoder · LLM Backbone · Audio Encoder(按模型架构组合)
───────────────────────────────────────────────
MLX 核心层 mlx.core · mlx.nn · mlx.optim
───────────────────────────────────────────────
硬件层 Apple GPU(统一内存架构,Metal)注意一点:并非所有模型都同时带这三块。只有 Omni 架构(如 Gemma-3n、Qwen3-Omni、MiniCPM-o、Phi-4 Multimodal)才有音频编码器。
2.3 核心模块
mlx_vlm.load:加载模型与处理器(processor),支持 Hugging Face 仓库 ID 或本地路径。mlx_vlm.generate:一次性生成。mlx_vlm.stream_generate:逐 token 流式返回,适合交互式界面。mlx_vlm.prompt_utils.apply_chat_template:把提示词、图片占位符、对话历史格式化成模型预期的输入。
加载和生成的例子:
from mlx_vlm import load, generate
model, processor = load("mlx-community/Qwen2-VL-2B-Instruct-4bit")
output = generate(
model, processor, "描述这张图片", image=["image.jpg"]
)
print(output)3. 支持模型
按用途分组,列一部分常用架构。标注“多图/视频/音频”的,指的是该架构在 MLX-VLM 中支持对应输入。
3.1 图像理解
| 架构 | 代表示例 | 备注 |
|---|---|---|
| Qwen2-VL / Qwen2.5-VL | mlx-community/Qwen2-VL-2B-Instruct-4bit | 支持多图与视频 |
| Qwen3-VL / Qwen3-VL-MoE | 同上系列 | 新一代视觉模型 |
| Qwen3.5 / Qwen3.5-MoE | 同系列 | 支持思考预算 |
| LLaVA 系列 | llava 等 | 多图 |
| Gemma-4 | google/gemma-4-26b-a4b-it | 26B MoE,约 4B 激活 |
| Pixtral | pixtral | Mistral 的多模态模型 |
| Molmo / MolmoPoint | molmo、molmo_point | Point 支持像素级指认 |
| Moondream3 | moondream3 | 9.27B MoE,约 2B 激活,轻量 |
| SmolVLM | smolvlm | 小型,适合内存紧张 |
| Llama-3.2-Vision | mllama | 单图 |
| InternVL / Kimi-VL | internvl_chat、kimi_vl | 国内模型 |
| Florence-2 / ARIA | florence2 | 提示词驱动的视觉任务 |
3.2 OCR 专用模型
处理文档、表格、公式、版面:
| 架构 | 用途 |
|---|---|
| DeepSeek-OCR / OCR-2 | 通用文档识别 |
| DOTS-OCR / DOTS-MOCR | 版面 JSON、表格、公式提取 |
| GLM-OCR | GLM 系 OCR |
| PaddleOCR-VL | PaddleOCR 视觉语言版 |
3.3 音频理解(全能模型)
| 架构 | 能力 |
|---|---|
| Gemma-3n | 图像 + 音频 |
| Qwen3-Omni | 图像 + 音频 |
| MiniCPM-o | 图像 + 音频 |
| Phi-4 Multimodal | 图像 + 音频 + 文本 |
3.4 视频理解
Qwen2-VL、Qwen2.5-VL、Idefics3、LLaVA 支持视频输入,可做字幕生成、片段摘要。
4. 基本用法
4.1 命令行
图像理解:
python -m mlx_vlm.generate \
--model mlx-community/Qwen2-VL-2B-Instruct-4bit \
--prompt "描述这张图片" \
--image path/to/image.jpg音频理解(加载 Omni 模型):
python -m mlx_vlm.generate \
--model mlx-community/gemma-3n-E2B-it-4bit \
--prompt "描述你听到的声音" \
--audio path/to/audio.wav4.2 Python API:图像理解
from mlx_vlm import load, generate
model, processor = load("mlx-community/Qwen2-VL-2B-Instruct-4bit")
output = generate(model, processor, "描述这张图片", image=["image.jpg"])
print(output)4.3 多图像
多图模型需要按图片数量格式化提示词:
from mlx_vlm import load, generate
from mlx_vlm.prompt_utils import apply_chat_template
model, processor = load("mlx-community/Qwen2-VL-2B-Instruct-4bit")
images = ["path/to/image1.jpg", "path/to/image2.jpg"]
prompt = apply_chat_template(
processor, model.config,
"比较这两张图片的异同",
num_images=len(images),
)
output = generate(model, processor, prompt, images)
print(output)4.4 音频理解
from mlx_vlm import load, generate
from mlx_vlm.prompt_utils import apply_chat_template
model, processor = load("mlx-community/gemma-3n-E2B-it-4bit")
audio = ["/path/to/audio1.wav"]
prompt = apply_chat_template(
processor, model.config,
"描述你听到的内容",
num_audios=len(audio),
)
output = generate(model, processor, prompt, audio=audio)
print(output)5. 视觉特征缓存
5.1 解决什么问题
多轮对话里,同一张图如果每轮都重新过一遍视觉编码器,前面的对话越多,浪费越大。比如先问“图里有什么”,再问“穿什么颜色”,图片本身没变,却没完没了地重复编码。
5.2 怎么做
视觉特征缓存按输入图像的特征做缓存:命中就直接复用已编码的特征,跳过编码这一步。它在服务器(FastAPI)里默认启用,容量用 --vision-cache-size 控制,默认 20 条。多图聊天里复用同一批图效果最明显。
官方介绍称多轮场景能带来数量级的提速;具体数字依赖模型、图片尺寸和 Mac 型号,建议在自己的机器上跑两轮对比实测。
5.3 用法
启动服务器时指定缓存容量即可:
python -m mlx_vlm.server \
--model mlx-community/Qwen2-VL-2B-Instruct-4bit \
--vision-cache-size 20本质是拿内存换时间:缓存占一点统一内存,换来多轮对话少做视觉编码。上到长视频、大图这类本身就重的输入,收益会更明显。
6. KV Cache 量化:Uniform 与 TurboQuant
6.1 为什么需要
长上下文推理的显存大头往往不是权重,而是 KV Cache——注意力层要记住前面每个 token 的 key 和 value。上下文到几十万 token 时这块内存非常可观。把它量化,是压低长上下文内存占用最直接的手段。
6.2 两种方案
MLX-VLM 服务器在连续批处理(Continuous Batching)下支持两种 KV Cache 量化:
| 选项 | 位宽 | 机制 |
|---|---|---|
| Uniform | 通常 8-bit | 均匀量化,速度影响小 |
| TurboQuant | 3.5-bit | 3-bit keys + 4-bit values,压缩更狠 |
对应参数:
--kv-bits:位宽,Uniform 写8,TurboQuant 写3.5--kv-quant-scheme:后端,uniform或turboquant--kv-group-size:均匀量化的组大小,默认 64
6.3 机理
量化不是无脑做。实测说明里提到几点取舍:
- 全注意力层使用量化的批缓存;滑动窗口层保留固定大小的旋转缓存。
- 最后一个全注意力层默认保持不量化——深度靠后的层对数值更敏感。
6.4 官方实测数据
官方在 gemma-4-26b-a4b-it、20K 上下文上测过(来源:仓库 PR #1030):
| 配置 | 生成速度 | KV Cache 占用 | 压缩倍数 |
|---|---|---|---|
| 不量化 | 50.3 tok/s | 0.624 GB | 1x |
| Uniform 8-bit | 52.6 tok/s | 0.469 GB | 1.33x |
| TurboQuant 3.5-bit | 25.6 tok/s | 0.365 GB | 1.71x |
值得注意:这篇实测是 MoE 模型,滑动窗口多,压缩倍数不算高。纯全注意力模型(Qwen、LLaMA 这类)压缩空间大得多,官方说明称 8-bit 可达约 3.6x、4-bit 可达约 6.4x。同时 TurboQuant 明显降速(25.6 vs 50.3),换来的内存上限要按场景权衡。
README 对长上下文场景给出的总体结论是约 76% 的内存削减。这些数字来自仓库维护者,不同模型和上下文长度会变化,应以实测为准。
6.5 用法
python -m mlx_vlm.server \
--model google/gemma-4-26b-a4b-it \
--kv-bits 3.5 \
--kv-quant-scheme turboquant选量化前先问自己缺的是内存还是速度:内存紧张、要超长上下文,TurboQuant;要吞吐,Uniform 或干脆不量化,配大内存。
7. LoRA / QLoRA 微调
7.1 为什么用 LoRA
VLM 权重动辄几十亿参数,全量微调在本地不现实。LoRA 只给权重加少量低秩适配器,可训练参数占比小,配合量化(即 QLoRA)能进一步压低内存,是本地微调的主要路径。
7.2 数据格式
用 Hugging Face 的 datasets,每行包含两个关键字段:
- 图像/音频列:放媒体路径或 URL
messages列:对话格式,含 role 与 content
需要多轮、带媒体的样本时,把角色和媒体按模型模板组织好。
7.3 训练
仓库提供一个 lora.py 脚本(或 mlx_vlm.train 模块)。典型调用:
python -m mlx_vlm.train \
--model mlx-community/Qwen3-VL-2B-Instruct-bf16 \
--dataset your-custom-dataset \
--batch-size 2 \
--epochs 2 \
--learning-rate 2e-5 \
--lora-rank 8 \
--output-path ./my-lora-adapter.safetensors要动视觉塔,加 --train-vision;要省显存,可配合梯度检查点。数据集规模和批次按内存调整。
7.4 使用微调后的适配器
推理时把适配器传进 load:
from mlx_vlm import load, generate
model, processor = load(
"mlx-community/Qwen3-VL-2B-Instruct-bf16",
adapter_path="./my-lora-adapter.safetensors",
)
output = generate(model, processor, "描述这张图片", image=["image.jpg"])
print(output)8. 服务器部署
8.1 启动
python -m mlx_vlm.server \
--model mlx-community/Qwen2-VL-2B-Instruct-4bit \
--port 8080不给 --model 也行,在第一个请求到达时再加载。
8.2 接口
服务器提供 /v1/chat/completions 和 /responses(兼容 OpenAI),另有 /health 做健康检查。特性包括:
- 连续批处理(Continuous Batching):并发请求共享批
- 自动前缀缓存(APC):复用相同提示词前缀
- KV Cache 量化(见第 6 节)
- 视觉特征缓存(见第 5 节)
- logprob 输出:
/chat/completions支持logprobs参数
8.3 调用示例
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "mlx-community/Qwen2-VL-2B-Instruct-4bit",
"messages": [
{"role": "user", "content": "描述这张图片"}
]
}'Python 侧直接接 OpenAI SDK 即可,把 base_url 指到本地。
9. 安装与配置
9.1 系统要求
- Apple Silicon 芯片(M1 及以上)
- macOS 13 或更新版本
- Python 3.9 或更新版本
- 统一内存足够容纳所选模型与上下文
9.2 安装
pip install -U mlx-vlm或从源码安装最新功能:
git clone https://github.com/Blaizzy/mlx-vlm.git
cd mlx-vlm
pip install -e .9.3 验证
python -m mlx_vlm.generate --help能打印出参数说明即安装成功。跑通一次图像理解,再确认网络能访问 Hugging Face(首次会下载权重)。
10. 实践建议
10.1 选模型:按内存
- 16 GB 起步:
Qwen2-VL-2B-Instruct-4bit、Moondream、SmolVLM 这类 4-bit 小模型 - 24 GB 以上:
Qwen2.5-VL-7B-Instruct-4bit、Pixtral-12B - 64 GB 以上:能跑更大的 Qwen、Gemma-4 或 MoE 模型,配合量化
具体上限要看量化位宽和上下文长度,落地前在自己机器上实测一次内存峰值。
10.2 内存紧张时
- 优先用 mlx-community 的量化权重
- 长上下文用 KV Cache 量化(第 6 节)
- 多轮多图开视觉特征缓存(第 5 节)
10.3 吞吐优先时
- 服务器接 OpenAI SDK,启用连续批处理和前缀缓存
- 上下文不大就少用 TurboQuant,它省内存但降速
11. 常见问题与排查
模型加载失败
多半是网络或模型 ID 问题。检查能否访问 Hugging Face;把模型显式下到本地,再从本地路径加载;核对 ID 写在 mlx-community/ 下。
内存不足(OOM)
先用更小的量化模型,缩短上下文,再考虑 KV Cache 量化;多轮会话清理未用的视觉缓存。
多轮对话很慢
确认走了视觉特征缓存,并复用了同一批图像。图片尺寸越大,复用的收益越大。
生成速度慢
检查是否启用了量化、是否有其他进程占用 GPU;长上下文下 TurboQuant 也会明显降速。
12. 总结
MLX-VLM 把 Apple Silicon 上跑 VLM 和 Omni 模型这件事做成了“装上就能用”:50+ 架构、预量化权重、LoRA/QLoRA 微调、OpenAI 兼容服务器。三个调优点对应三种瓶颈:视觉特征缓存治多轮重复编码,KV Cache 量化治长上下文内存,量化权重治模型过大。它们的取舍都指向同一件事——你的统一内存和期望的响应速度落在哪里。
相关资源:
- 仓库:https://github.com/Blaizzy/mlx-vlm
- 预量化权重:https://huggingface.co/mlx-community
- 问题反馈:https://github.com/Blaizzy/mlx-vlm/issues
自测题
回答下面 5 个问题,检验你的理解:
- MLX 的“统一内存”为什么能降低运行 VLM 的门槛?它在 CPU/GPU 分工上解决的是什么问题?
- 视觉特征缓存解决哪种场景的浪费?它用
--vision-cache-size控制什么? - Uniform 与 TurboQuant 的 KV Cache 量化各有什么取舍?TurboQuant 的位宽构成是什么?
- 一台 16 GB 内存的 Mac,你倾向先试哪个模型?为什么?
- MLX-VLM 的服务器提供哪些 OpenAI 兼容端点?continuous batching 和自动前缀缓存各自有什么用?
参考答案
题 1:统一内存让 CPU 和 GPU 共享同一块物理内存,模型权重不必在两者之间搬运。这样显卡显存堆不下的多模态模型,可以整块驻留在 Mac 的统一内存里运行,也省去了跨 PCIe 传输的时间。
题 2:它针对“同一批图像在多轮或多图对话里被重复做视觉编码”的浪费。命中缓存的图像直接复用已编码特征,跳过视觉塔。--vision-cache-size 控制缓存条数,默认 20。
题 3:Uniform(通常 8-bit)量化均匀,速度影响小;TurboQuant(3.5-bit,3-bit keys + 4-bit values)压缩更狠、省更多内存,但会明显降速(官方实测 20K 上下文中约匀速的一半)。内存紧张选 TurboQuant,吞吐优先选 Uniform。
题 4:先试小规模 4-bit 模型,如 Qwen2-VL-2B-Instruct-4bit。权重小、容易跑通,可作为后续选型的基线。
题 5:/v1/chat/completions、/responses 和 /health。continuous batching 让并发请求共享一个批,提高吞吐;自动前缀缓存(APC)复用相同提示词前缀的计算,减少重复处理。
练习
- 环境搭建:按第 9 节完成安装,跑通一次
generate --help和一次图像理解。 - 多模态对比:用同样的图片分别测 Qwen2-VL-2B 和 Moondream 的生成质量与速度。
- 多轮对话:不带和带视觉特征缓存各跑两轮,对比第二轮耗时。
- KV Cache 量化:在
gemma-4-26b-a4b-it上分别用不量化、Uniform 8-bit、TurboQuant 3.5-bit 跑长上下文,对比内存峰值与 tok/s。 - 部署:启动服务器,用 Python 的
requests或 OpenAI SDK 调用一次/v1/chat/completions。
进阶路径
阶段 1:跑通基础(1-2 天)
- 安装并跑通图像、音频示例
- 记录自己的 Mac 内存峰值,建立选型基线
阶段 2:调优(3-5 天)
- 给多轮对话加视觉特征缓存,量化验证加速
- 对比 KV Cache 三种配置在长上下文下的显存与速度
- 读
mlx_vlm/源码,理解 load 与 generate 的加载流程
阶段 3:部署与微调(1-2 周)
- 服务器 + OpenAI SDK 接入现有应用
- 用 LoRA 调一个自己的垂直模型,并用
adapter_path加载
阶段 4:深入原理(2-4 周)
- 对照 mlx 源码理解 KV Cache 量化与 Metal 内核实现
- 读 MLX 的算子与内存管理,理解统一内存的边界
- 尝试给仓库提 PR 或补新模型适配
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。