在 Mac 上运行本地 LLM
本指南带你完成使用 OpenAI 兼容 API 在 macOS 上运行本地 LLM 服务器。你获得完全隐私、零 API 成本和在 Apple Silicon 上令人惊讶的良好性能。
我们涵盖两个后端:
| 后端 | 安装 | 擅长 | 格式 | |
|---------|---------|---------|--------| |
| llama.cpp | brew install llama.cpp | 首次 token 最快时间、量化 KV 缓存低内存 | GGUF |
| omlx | omlx.ai | token 生成最快、原生 Metal 优化 | MLX (safetensors) |
两者都暴露 OpenAI 兼容的 /v1/chat/completions 端点。Hermes 与任一后端配合工作 — 只需将其指向 http://localhost:8080 或 http://localhost:8000。
本指南面向配备 Apple Silicon(M1 及更新版本)的 Mac。Intel Mac 可以使用 llama.cpp 但没有 GPU 加速 — 预期会明显更慢。
选择模型
对于入门,我们推荐 Qwen3.5-9B — 这是一个强大的推理模型,量化后可在 8GB+ 统一内存中舒适运行。
| 变体 | 磁盘大小 | 需要的 RAM(128K 上下文) | 后端 | | |---------|-------------|---------------------------|---------| | | Qwen3.5-9B-Q4_K_M (GGUF) | 5.3 GB | ~10 GB(量化 KV 缓存) | llama.cpp | | | Qwen3.5-9B-mlx-lm-mxfp4 (MLX) | ~5 GB | ~12 GB | omlx | |
内存经验法则: 模型大小 + KV 缓存。Q4 的 9B 模型约 5 GB。Q4 量化的 128K 上下文 KV 缓存增加约 4-5 GB。使用默认(f16)KV 缓存,这会膨胀到约 16 GB。llama.cpp 中的量化 KV 缓存标志是内存受限系统的关键技巧。
对于更大模型(27B、35B),你需要 32 GB+ 统一内存。9B 是 8-16 GB 机器的最佳选择。
选项 A:llama.cpp
llama.cpp 是最可移植的本地 LLM 运行时。在 macOS 上它开箱即用地使用 Metal 进行 GPU 加速。
安装
brew install llama.cpp
这为你提供全局的 llama-server 命令。
下载模型
你需要 GGUF 格式的模型。最简单的来源是通过 huggingface-cli 从 Hugging Face 下载:
brew install huggingface-cli
然后下载:
huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models
Hugging Face 上某些模型需要身份验证。如果遇到 401 或 404 错误,先运行 huggingface-cli login。
启动服务器
llama-server -m ~/models/Qwen3.5-9B-Q4_K_M.gguf \
-ngl 99 \
-c 131072 \
-np 1 \
-fa on \
--cache-type-k q4_0 \
--cache-type-v q4_0 \
--host 0.0.0.0
每个标志的作用:
| 标志 | 用途 | |
|------|---------| |
| -ngl 99 | 将所有层卸载到 GPU(Metal)。使用高数字以确保没有任何停留在 CPU 上。 | |
| -c 131072 | 上下文窗口大小(128K tokens)。如果内存不足,请减少。 | |
| -np 1 | 并行槽数量。对于单用户使用保持在 1 — 更多槽会分割你的内存预算。 | |
| -fa on | Flash attention。减少内存使用并加速长上下文推理。 | |
| --cache-type-k q4_0 | 将 key 缓存量化为 4 位。这是大内存节省器。 | |
| --cache-type-v q4_0 | 将 value 缓存量化为 4 位。与上面一起,这比 f16 减少约 75% 的 KV 缓存内存。 | |
| --host 0.0.0.0 | 监听所有接口。如果不需要网络访问,使用 127.0.0.1。 | |
当你看到以下内容时服务器就绪:
main: server is listening on http://0.0.0.0:8080
srv update_slots: all slots are idle
内存受限系统的内存优化
--cache-type-k q4_0 --cache-type-v q4_0 标志是内存受限系统最重要的优化。以下是 128K 上下文的影响:
| KV 缓存类型 | KV 缓存内存(128K 上下文,9B 模型) | | |---------------|--------------------------------------| | | f16(默认) | ~16 GB | | | q8_0 | ~8 GB | | | q4_0 | ~4 GB | |
在 8 GB Mac 上,使用 q4_0 KV 缓存并将上下文减少到 -c 32768(32K)。在 16 GB 上,你可以舒适地使用 128K 上下文。在 32 GB+,你可以运行更大模型或多个并行槽。
如果仍然内存不足,首先减少上下文大小(-c),然后尝试更小的量化(Q3_K_M 而不是 Q4_K_M)。
测试
curl -s http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5-9B-Q4_K_M.gguf",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 50
}' | jq .choices[0].message.content
获取模型名称
如果你忘记模型名称,查询 models 端点:
curl -s http://localhost:8080/v1/models | jq '.data[].id'
选项 B:通过 omlx 的 MLX
omlx 是一个 macOS 原生应用,管理和提供 MLX 模型。MLX 是 Apple 自己的机器学习框架,针对 Apple Silicon 的统一内存架构进行了优化。
安装
从 omlx.ai 下载并安装。它提供模型管理的 GUI 和内置服务器。
下载模型
使用 omlx 应用浏览和下载模型。搜索 Qwen3.5-9B-mlx-lm-mxfp4 并下载。模型本地存储(通常在 ~/.omlx/models/)。
启动服务器
omlx 默认在 http://127.0.0.1:8000 上提供模型。从应用 UI 启动服务,或使用 CLI(如果有)。
测试
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen3.5-9B-mlx-lm-mxfp4",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 50
}' | jq .choices[0].message.content
列出可用模型
omlx 可以同时提供多个模型:
curl -s http://127.0.0.1:8000/v1/models | jq '.data[].id'
基准测试:llama.cpp vs MLX
两个后端在同一台机器上测试(Apple M5 Max,128 GB 统一内存),运行相同模型(Qwen3.5-9B)at comparable quantization levels (Q4_K_M for GGUF, mxfp4 for MLX)。五个不同提示,各三次运行,后端顺序测试以避免资源竞争。
结果
| 指标 | llama.cpp (Q4_K_M) | MLX (mxfp4) | 胜者 | | |--------|-------------------|-------------|--------| | | TTFT(平均) | 67 ms | 289 ms | llama.cpp(快 4.3 倍) | | | TTFT(p50) | 66 ms | 286 ms | llama.cpp(快 4.3 倍) | | | 生成(平均) | 70 tok/s | 96 tok/s | MLX(快 37%) | | | 生成(p50) | 70 tok/s | 96 tok/s | MLX(快 37%) | | | 总时间(512 tokens) | 7.3s | 5.5s | MLX(快 25%) | |
含义
-
llama.cpp 擅长提示处理 — 其 flash attention + 量化 KV 缓存管道让你在约 66ms 内获得第一个 token。如果你在构建交互式应用程序,其中感知响应能力很重要(聊天机器人、自动补全),这是一个有意义的优势。
-
MLX 一旦启动,token 生成速度快约 37%。对于批处理工作负载、长篇生成或任何总完成时间比初始延迟更重要的任务,MLX 更快完成。
-
两个后端都非常一致 — 运行之间的差异可以忽略不计。你可以依赖这些数字。
你应该选择哪个?
| 用例 | 推荐 | | |----------|---------------| | | 交互式聊天、低延迟工具 | llama.cpp | | | 长篇生成、批量处理 | MLX (omlx) | | | 内存受限(8-16 GB) | llama.cpp(量化 KV 缓存无与伦比) | | | 同时提供多个模型 | omlx(内置多模型支持) | | | 最大兼容性(也支持 Linux) | llama.cpp | |
连接到 Hermes
本地服务器运行后:
hermes model
选择 Custom endpoint 并按照提示操作。它会询问 base URL 和模型名称 — 使用你上面设置的任一后端的值。
超时
Hermes 自动检测本地端点(localhost、LAN IP)并放宽其流式传输超时。大多数设置无需配置。
如果你仍然遇到超时错误(例如非常慢的硬件上大上下文),可以覆盖流式读取超时:
# 在你的 .env 中 — 从默认的 120s 提高到 30 分钟
HERMES_STREAM_READ_TIMEOUT=1800
| 超时 | 默认 | 本地自动调整 | 环境变量覆盖 | |
|---------|---------|----------------------|------------------| |
| 流读取(socket 级别) | 120s | 提高到 1800s | HERMES_STREAM_READ_TIMEOUT | |
| 静止流检测 | 180s | 完全禁用 | HERMES_STREAM_STALE_TIMEOUT | |
| API 调用(非流式) | 1800s | 不需要更改 | HERMES_API_TIMEOUT | |
流读取超时是最可能产生问题的 — 这是接收下一块数据的 socket 级别截止日期。在大上下文上预填充期间,本地模型可能几分钟不产生输出,同时处理提示。自动检测透明处理这个问题。