Skip to content

在 Mac 上运行本地 LLM

hermes agent 在 Mac 上运行本地 LLM

本指南将带你在 macOS 上运行一个带有 OpenAI 兼容 API 的本地 LLM 服务器。你可以获得完整隐私、零 API 成本,以及在 Apple Silicon 上出人意料的良好性能。

我们将介绍两个后端:

后端安装最擅长格式
llama.cppbrew install llama.cpp最快的首 token 延迟,用于低内存的量化 KV cacheGGUF
omlxomlx.ai最快的 token 生成,原生 Metal 优化MLX(safetensors)

两者都会暴露一个兼容 OpenAI 的 /v1/chat/completions 端点。Hermes 可以与任意一个配合使用 —— 只需要将其指向 http://localhost:8080http://localhost:8000

对于入门,我们推荐 Qwen3.5-9B —— 它是一个强大的推理模型,在量化后可以轻松适配 8GB+ 统一内存。

变体磁盘大小所需 RAM(128K 上下文)后端
Qwen3.5-9B-Q4_K_M(GGUF)5.3 GB使用量化 KV cache 时约 10 GBllama.cpp
Qwen3.5-9B-mlx-lm-mxfp4(MLX)约 5 GB约 12 GBomlx

内存经验法则:模型大小 + KV cache。一个 9B Q4 模型约为 5 GB。使用 Q4 量化时,128K 上下文的 KV cache 会额外增加约 4–5 GB。使用默认的 f16 KV cache 时,它会膨胀到约 16 GB。llama.cpp 中的量化 KV cache flags 是内存受限系统中的关键技巧。

对于更大的模型(27B、35B),你需要 32 GB+ 的统一内存。9B 是 8–16 GB 机器的最佳平衡点。

llama.cpp 是最便携的本地 LLM 运行时。在 macOS 上,它开箱即用 Metal 进行 GPU 加速。

Terminal window
brew install llama.cpp

这会让你在全局获得 llama-server 命令。

你需要一个 GGUF 格式的模型。最简单的来源是通过 huggingface-cli 从 Hugging Face 下载:

Terminal window
brew install huggingface-cli

然后下载:

Terminal window
huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models
Terminal window
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

下面是每个 flag 的作用:

Flag作用
-ngl 99将所有层卸载到 GPU(Metal)。使用较大的数字以确保没有层留在 CPU 上。
-c 131072上下文窗口大小(128K tokens)。如果内存不足,请降低这个值。
-np 1并行 slots 数量。单用户使用时保持为 1 —— 更多 slots 会拆分你的内存预算。
-fa onFlash attention。降低内存使用,并加速长上下文推理。
--cache-type-k q4_0将 key cache 量化为 4-bit。这是主要的内存节省手段。
--cache-type-v q4_0将 value cache 量化为 4-bit。与上面的参数一起使用,相比 f16 可将 KV cache 内存减少约 75%。
--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 cache 类型KV cache 内存(128K ctx,9B 模型)
f16(默认)约 16 GB
q8_0约 8 GB
q4_0约 4 GB

在 8 GB Mac 上,使用 q4_0 KV cache,并将上下文降低到 -c 32768(32K)。在 16 GB 上,可以比较轻松地使用 128K 上下文。在 32 GB+ 上,可以运行更大的模型或多个并行 slots。

如果仍然内存不足,请先降低上下文大小(-c),然后尝试更小的量化版本(例如使用 Q3_K_M 而不是 Q4_K_M)。

Terminal window
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 端点:

Terminal window
curl -s http://localhost:8080/v1/models | jq '.data[].id'

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。

Terminal window
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 可以同时服务多个模型:

Terminal window
curl -s http://127.0.0.1:8000/v1/models | jq '.data[].id'

两个后端都在同一台机器上测试(Apple M5 Max,128 GB 统一内存),运行相同模型(Qwen3.5-9B),并使用可比较的量化级别(GGUF 使用 Q4_K_M,MLX 使用 mxfp4)。测试包含五个不同提示词,每个提示词运行三次,后端按顺序测试,以避免资源争用。

指标llama.cpp(Q4_K_M)MLX(mxfp4)胜出者
TTFT(平均)67 ms289 msllama.cpp(快 4.3 倍)
TTFT(p50)66 ms286 msllama.cpp(快 4.3 倍)
生成速度(平均)70 tok/s96 tok/sMLX(快 37%)
生成速度(p50)70 tok/s96 tok/sMLX(快 37%)
总耗时(512 tokens)7.3s5.5sMLX(快 25%)
  • llama.cpp 擅长提示词处理 —— 它的 flash attention + 量化 KV cache 流水线可以让你在约 66ms 内获得第一个 token。如果你正在构建交互式应用,并且感知响应速度很重要(聊天机器人、自动补全),这是一个有意义的优势。
  • MLX 一旦开始生成,token 生成速度约快 37%。对于批处理工作负载、长文本生成,或任何总完成时间比初始延迟更重要的任务,MLX 会更快完成。
  • 两个后端都非常稳定 —— 多次运行之间的方差可以忽略不计。你可以信赖这些数字。
使用场景推荐
交互式聊天、低延迟工具llama.cpp
长文本生成、批量处理MLX(omlx)
内存受限(8–16 GB)llama.cpp(量化 KV cache 无可匹敌)
同时服务多个模型omlx(内置多模型支持)
最大兼容性(也支持 Linux)llama.cpp

本地服务器运行后:

Terminal window
hermes model

选择 Custom endpoint,并按照提示操作。它会要求输入 base URL 和模型名称 —— 使用你上面设置的对应后端的值。

Hermes 会自动检测本地端点(localhost、LAN IP),并放宽其流式输出超时时间。大多数设置无需配置。

如果你仍然遇到超时错误(例如在较慢硬件上使用非常大的上下文),可以覆盖流式读取超时时间:

Terminal window
# 在你的 .env 中 —— 从默认 120s 提高到 30 分钟
HERMES_STREAM_READ_TIMEOUT=1800
超时默认值本地自动调整环境变量覆盖
流式读取(socket 级别)120s提高到 1800sHERMES_STREAM_READ_TIMEOUT
停滞流检测180s完全禁用HERMES_STREAM_STALE_TIMEOUT
API 调用(非流式)1800s无需更改HERMES_API_TIMEOUT

流式读取超时是最可能导致问题的那个 —— 它是接收下一块数据的 socket 级截止时间。在大上下文预填充期间,本地模型可能会在处理提示词时连续数分钟不产生输出。自动检测会透明地处理这种情况。

-
0:000:00