使用 Apple MLX 框架在 M4 芯片上部署 GLM-4 模型(附三种方案对比)
在前两篇教程中,我们分别介绍了使用 Ollama 和 llama.cpp 在 MacBook Air M4 上部署 GLM-4 模型的方法。本文将介绍第三种方案——使用 Apple 官方的 MLX 框架。MLX 是专为 Apple Silicon 芯片设计的机器学习数组框架,能够充分利用 M4 芯片的统一内存架构和 Metal GPU,为 GLM-4 模型提供最原生的运行体验。
MLX 框架简介
MLX 是 Apple 官方开源的机器学习框架,于 2023 年底发布。与 PyTorch 类似,MLX 提供了张量计算、自动微分等功能,但专门针对 Apple Silicon 进行了深度优化:
- 统一内存架构:MLX 原生支持 Apple Silicon 的统一内存,CPU 和 GPU 共享同一块内存,无需数据拷贝
- 惰性计算:采用惰性求值策略,只在需要结果时才执行计算,自动优化计算图
- 动态图:支持动态计算图,方便调试和灵活建模
- 多设备支持:无缝在 CPU 和 GPU 之间切换
- Python 友好:API 设计与 NumPy/PyTorch 高度相似,学习成本低
MLX-LM 是基于 MLX 构建的大语言模型推理库,原生支持 GLM-4、Llama、Qwen 等主流模型,无需额外适配即可直接运行。
第一步:环境搭建
确认系统要求
# 确认 macOS 版本(建议 macOS 14.0+)
sw_vers
# 确认 Python 版本(需要 3.9+)
python3 --version
# 确认芯片型号
sysctl -n machdep.cpu.brand_string
安装 Homebrew 和 Python
# 安装 Homebrew(如果尚未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安装 Python 3.12
brew install python@3.12
# 验证安装
python3.12 --version
创建虚拟环境
# 创建项目目录
mkdir -p ~/mlx-glm && cd ~/mlx-glm
# 创建 Python 虚拟环境
python3.12 -m venv venv
# 激活虚拟环境
source venv/bin/activate
# 升级 pip
pip install --upgrade pip
第二步:安装 MLX-LM
# 安装 MLX 和 MLX-LM
pip install mlx-lm
# 验证安装
python -c "import mlx; print(f'MLX version: {mlx.__version__}')"
python -c "import mlx_lm; print('MLX-LM installed successfully')"
MLX-LM 已内置 GLM-4 模型架构支持(包括 glm.py、glm4.py、glm4_moe.py 等模型文件),无需安装任何额外依赖。
第三步:使用预转换的 GLM-4 MLX 模型
命令行快速运行
mlx-community 组织在 HuggingFace 上提供了大量已经转换为 MLX 格式的模型,可以直接下载使用:
# 使用预转换的 GLM-4-9B-Chat 4bit 模型
# 首次运行会自动从 HuggingFace 下载模型(约 5-6GB)
mlx_lm.generate \
--model mlx-community/GLM-4-9B-Chat-4bit \
--prompt "你好,请用中文介绍一下你自己" \
--max-tokens 512
# 进入交互式聊天模式
mlx_lm.chat --model mlx-community/GLM-4-9B-Chat-4bit
指定生成参数
# 自定义生成参数
mlx_lm.generate \
--model mlx-community/GLM-4-9B-Chat-4bit \
--prompt "写一个 Python 冒泡排序算法" \
--max-tokens 1024 \
--temp 0.7 \
--top-p 0.9
第四步:自行转换 GLM-4 模型
如果预转换模型不满足需求,你可以从 HuggingFace 上的原始 GLM-4 模型自行转换为 MLX 格式,并选择自定义的量化位数。
# 从原始模型转换为 4bit 量化 MLX 格式
mlx_lm.convert \
--model THUDM/glm-4-9b-chat \
--quantize \
--q-bits 4 \
--upload-repo mlx-community/my-glm4-4bit
# 参数说明:
# --model HuggingFace 上的原始模型名称或本地路径
# --quantize 启用量化
# --q-bits 4 4bit 量化(也可选 2, 3, 6, 8)
# --upload-repo 上传到 HuggingFace(可选,不加则保存到本地)
# 转换并保存到本地目录
mlx_lm.convert \
--model THUDM/glm-4-9b-chat \
--quantize \
--q-bits 4 \
--mlx-path ./my-glm4-4bit
不同量化位数的效果对比:
| 量化位数 | 模型大小 | 质量损失 | 适合内存 |
|---|---|---|---|
| 2-bit | ~2.5 GB | 较大 | 8GB |
| 3-bit | ~3.8 GB | 中等 | 8GB |
| 4-bit | ~5.2 GB | 较小 | 8GB/16GB |
| 6-bit | ~7.5 GB | 极小 | 16GB |
| 8-bit | ~9.8 GB | 几乎无 | 16GB/24GB |
第五步:Python API 开发
基础调用
from mlx_lm import load, generate
# 加载模型(首次会自动下载)
model, tokenizer = load("mlx-community/GLM-4-9B-Chat-4bit")
# 应用聊天模板
prompt = tokenizer.apply_chat_template(
[{"role": "user", "content": "解释一下什么是闭包,并给出 Python 示例"}],
add_generation_prompt=True
)
# 生成回复
response = generate(
model,
tokenizer,
prompt=prompt,
max_tokens=1024,
verbose=True # 打印生成速度等信息
)
print(response)
多轮对话
from mlx_lm import load, generate
model, tokenizer = load("mlx-community/GLM-4-9B-Chat-4bit")
# 维护对话历史
messages = [
{"role": "system", "content": "你是一个专业的Python编程助手"}
]
def chat(user_input):
messages.append({"role": "user", "content": user_input})
prompt = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True
)
response = generate(
model,
tokenizer,
prompt=prompt,
max_tokens=512,
verbose=True
)
messages.append({"role": "assistant", "content": response})
return response
# 多轮对话
print(chat("什么是装饰器?"))
print(chat("给我一个实际的使用例子"))
print(chat("装饰器和闭包有什么关系?"))
流式输出
from mlx_lm import load, stream_generate
model, tokenizer = load("mlx-community/GLM-4-9B-Chat-4bit")
prompt = tokenizer.apply_chat_template(
[{"role": "user", "content": "写一首关于秋天的诗"}],
add_generation_prompt=True
)
# 流式生成,逐 token 输出
for response in stream_generate(
model,
tokenizer,
prompt=prompt,
max_tokens=512
):
print(response.text, end="", flush=True)
print() # 换行
第六步:启动 OpenAI 兼容 API 服务
启动服务
# 启动兼容 OpenAI API 的本地服务
mlx_lm.server \
--model mlx-community/GLM-4-9B-Chat-4bit \
--host 0.0.0.0 \
--port 8080
# 服务启动后,可通过 http://localhost:8080/v1 访问
使用 OpenAI SDK 调用
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed"
)
# 普通对话
response = client.chat.completions.create(
model="mlx-community/GLM-4-9B-Chat-4bit",
messages=[
{"role": "user", "content": "什么是 Apple MLX 框架?"}
]
)
print(response.choices[0].message.content)
# 流式输出
stream = client.chat.completions.create(
model="mlx-community/GLM-4-9B-Chat-4bit",
messages=[
{"role": "user", "content": "写一个 Python 异步爬虫示例"}
],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
第七步:高级优化
调整 Wired Memory 限制
对于大模型推理,macOS 默认的 Wired Memory 限制可能不够。可以通过以下命令临时调整(重启后失效):
# 查看当前 wired memory 限制
sysctl iogpu.wired_limit_mb
# 对于 16GB Mac,设置为 12GB(留 4GB 给系统)
sudo sysctl iogpu.wired_limit_mb=12288
# 对于 24GB Mac,设置为 18GB
sudo sysctl iogpu.wired_limit_mb=18432
# 恢复默认值
sudo sysctl iogpu.wired_limit_mb=0
使用 KV Cache 量化
from mlx_lm import load, generate
# 加载模型时启用 KV Cache 量化,减少内存占用
model, tokenizer = load(
"mlx-community/GLM-4-9B-Chat-4bit",
# MLX-LM 会自动管理 KV Cache
)
# 减小上下文窗口以节省内存
prompt = tokenizer.apply_chat_template(
[{"role": "user", "content": "你好"}],
add_generation_prompt=True
)
response = generate(
model,
tokenizer,
prompt=prompt,
max_tokens=256,
verbose=True
)
指定使用 GPU 或 CPU
import mlx.core as mx
from mlx_lm import load, generate
# 默认使用 GPU
# 可以手动切换到 CPU(不推荐,性能会大幅下降)
# mx.set_default_device(mx.Device(mx.DeviceType.CPU))
# 加载模型并生成
model, tokenizer = load("mlx-community/GLM-4-9B-Chat-4bit")
# 检查当前使用的设备
print(f"Default device: {mx.default_device()}")
prompt = tokenizer.apply_chat_template(
[{"role": "user", "content": "1+1等于几?"}],
add_generation_prompt=True
)
response = generate(model, tokenizer, prompt=prompt, max_tokens=64, verbose=True)
print(response)
三种部署方案全面对比
| 对比项 | Ollama | llama.cpp | MLX-LM |
|---|---|---|---|
| 安装难度 | ⭐ 极简 | ⭐⭐⭐ 需编译 | ⭐⭐ pip 安装 |
| 性能表现 | 优秀 | 极致 | 优秀 |
| GPU 加速 | Metal | Metal | Metal(原生) |
| 内存效率 | 好 | 好 | 最佳(统一内存) |
| Python API | 通过 HTTP | 通过 HTTP | 原生 Python |
| 模型量化 | 预定义 | 灵活(Q2~Q8) | 灵活(2~8bit) |
| 自定义训练 | 不支持 | 不支持 | 支持(LoRA 微调) |
| 社区生态 | 庞大 | 庞大 | 快速增长 |
| 适合人群 | 普通用户 | 开发者/极客 | Python 开发者 |
| OpenAI 兼容 | ✅ | ✅ | ✅ |
性能基准对比
以下是在 MacBook Air M4(16GB)上运行 GLM-4-9B-Chat Q4 量化版本的参考性能数据:
| 方案 | 加载时间 | Prompt 处理 (t/s) | 生成速度 (t/s) | 内存占用 |
|---|---|---|---|---|
| Ollama | ~3s | ~110 | ~40 | ~7GB |
| llama.cpp | ~2s | ~120 | ~43 | ~6.5GB |
| MLX-LM | ~4s | ~100 | ~45 | ~6GB |
注:以上数据为参考值,实际性能受 macOS 版本、后台进程、环境温度等因素影响。
方案选择建议
- 新手用户:选择 Ollama,两条命令搞定,开箱即用
- 追求极致性能:选择 llama.cpp,可精细调优每个参数
- Python 开发者:选择 MLX-LM,原生 Python API,方便集成到项目中
- 需要模型微调:选择 MLX-LM,支持 LoRA 等微调技术
- 需要 API 服务:三种方案都支持 OpenAI 兼容 API,按需选择
系列总结
本系列三篇文章完整介绍了在 MacBook Air M4 上部署 GLM-4 模型的三种方案:
- Ollama 方案(入门篇):最简单的一键部署方案,适合新手
- llama.cpp 方案(进阶篇):手动编译 Metal 加速,追求极致性能
- MLX 方案(高级篇):Apple 官方框架,原生 Python 开发体验
MacBook Air M4 凭借其强大的 M4 芯片、Metal GPU 加速和统一内存架构,已经完全具备在本地流畅运行 9B 参数大语言模型的能力。无论你是想保护隐私数据、节省 API 费用,还是进行 AI 应用开发,MacBook Air M4 都是一个出色的本地 AI 推理平台。
希望这个系列教程能帮助你顺利在 MacBook Air M4 上部署 GLM-4 模型。如果你在操作过程中遇到任何问题,欢迎在评论区留言交流!







