我的本地推理配置
我决定写篇短文分享下目前在用的本地 LLM 推理配置。我的机器是一台古老的 MacBook Pro,Apple M1 Max + 32GB 统一内存,一般情况下有 20+GB 内存可用于 GPU。这里描述的配置方案适合类似配置的 Mac,显存大小相当的 NVIDIA 卡(比如 24GB 显存的 3090 系列)用户也可以参考部分内容。
为什么是现在来写呢?因为:
- 上个月发布的 Qwen3.5(尤其是 35B-A3B 和 27B 两个版本)是当下最适合本地部署的先进大语言模型,估计在未来至少半年都会是。
- 对 Mac 用户来说,终于有了个真正可用、有前途的 MLX 架构本地推理引擎 oMLX,我从它最早的版本就开始试用,还提了不少 bug,作者更新非常积极,很快就补齐了该用的所有东西(显然也是重度 AI 辅助开发的)。
- 我自己开发的阅读工具 Mercury 已渐完善,其中提供了自动摘要、翻译、自动标签等 agent 功能,这些任务对模型能力要求不高,但日常消耗量很大,非常适合使用本地模型。
配置选型
模型
- Qwen3.5-35B-A3B:总参数量 35B、同时激活参数仅 3B 的 MoE 模型,在中低配置的机器上速度惊人,我这机器都能跑到每秒 50+ tokens,能力中规中矩,完成一些简单任务,尤其是传统 NLP 任务(如摘要和标签)都挺好;不要指望它能完成复杂编程任务。
- Qwen3.5-27B:参数量 27B 的稠密(dense)模型,100B 以下无对手,也是中低配硬件能驱动 coding agent 的唯一选择,可惜在我的机器上速度只有 10-15tps,在 3090 以上显卡上应该是可堪一用的。
- HY-MT1.5-1.8B:混元的翻译专用模型,只用于较大量文本的翻译任务,我自己试下来效果和同一个模型的 7B 版本效果差不多但快得多,最重要的是实在太小巧了,在我这系统上都能和 Qwen3.5-35B-A3B 同时跑。
引擎与工具
- llama.cpp:用于 GGUF 格式量化模型的推理引擎,历史悠久,积累丰富,从各种优化兼容到 API 的完备性都无可挑剔,有针对 Apple 芯片优化的 Metal 专用后端,虽然速度比不上 MLX,但量化选择多、质量更好,我将其作为终极保底方案。顺便恭喜团队加入 HF,未来可期。
- llama-swap:提供模型 on-demand 加载和切换等功能,配置能力强大但并不算复杂,是
llama.cpp的绝配;理论上也支持 MLX 推理引擎,但我试下来并没有像llama.cpp那样完善又纯粹的选项,我差点想自己搓一个,但下面这个选项及时出现了。 - oMLX:刚诞生一个月的 MLX 本地推理套件,整合了 MLX Python 运行时、模型管理、on-demand 加载等功能和一个 web 管理界面,作者还改进了原版的 KV cache,增加了内存和 SSD 两层 cache 机制,(AI 加持下)修问题和加功能都极其迅速。
- LM Studio:我最早用的一体化解决方案,啥都有,界面和交互越做越好了,内置的
llama.cpp和 MLX 双引擎也很好用,如果懒得折腾其实就用这一个就行了,但我现在只拿它当模型搜索和下载器用了,原因后叙。
具体量化版本
Qwen3.5-35B-A3B
GGUF 格式的推荐社区非常受欢迎的 unsloth 版本,对我的硬件来说最合适的是 Q4(4-bit 量化)版本,参考 Reddit 上网友的测评:35B-A3B Q4 和 27B Q4,可以看出量化损失的差距并不大,Q4_K_M / UD-Q4_K_M / UD-Q4_K_L 几个版本都是不错的,我自己用的最后一个。另外我也很喜欢 unsloth 团队每次给新模型写的 guide。
MLX 格式的我最后选择了 RepublicOfKorokke/Qwen3.5-35B-A3B-mlx-lm-mxfp4,这是移除了视觉模型只保留文本生成模型的版本,更小也更快。
Qwen3.5-27B
这个模型我最后没使用 GGUF 版本,因为本来就慢,MLX 的速度优势就更重要了。MLX 格式选择了 nightmedia/Qwen3.5-27B-Text-mxfp4-mlx,同样也是仅文本的模型。
HY-MT1.5-1.8B
这个模型的 FP8 版本才不到 2GB,GGUF 版本可以用大一点的量化,我最后选的是 Q8_0 版本。
选型说明
为什么要保留 GGUF 和 MLX 两种格式支持?
两点:
- MLX 生态还是年轻,难说什么时候就会遇到一些棘手的问题或者不便,GGUF 格式的方案总是要的。
- 但 MLX 又是 Apple 芯片的 Mac 用户一定要用的,因为太快了,以我现在的主力模型 Qwen3.5-35B-A3B 来说,MLX 版本比 GGUF 版本要快 50% 以上,50+tps 和 30+ 的感受是完全不同的。
为什么不用 LM Studio 了?
也是两点:
- LM Studio 毕竟不是完全开源,而且已经有明显的一些迹象,不确定啥时候就出幺蛾子,不可太过依赖。
- 一些基本能力缺陷,比如它实现的 API server 实在是一言难尽,至今在 structured output 和 tool calling 上还是问题一堆;还有模型参数配置也远不如 llama.cpp 完善。
不过它搜索下载 HF 模型真方便,甚至还提供了一个巨快的代理,所以现在主要被我拿来做下载器,以及下载之后的初步测试用。
如果是配置 NVIDIA 显卡的 Linux 系统呢?
如果是 3090 以上显卡,有 24GB 或者更多显存,那么可以把 Qwen3.5 的 35B 和 27B 两个模型都用起来,引擎选 llama.cpp 或者 vLLM 均可,再加上 llama-swap 就齐活,具体量化版本选择参考我上面给的 Reddit 上的两个帖子即可。
安装与配置
系统要求
- Apple M 系芯片的 Mac,不少于 32GB 统一内存
- Homebrew
llama.cpp
brew install llama.cpp --HEAD
没有需要配置的。之所以装 HEAD 版本是因为有时候新模型出来只有 HEAD 版本能支持,如果不急着尝鲜,等1-2周 stable 版本自然跟上,那就可以去掉上面命令里最后的 `–HEAD`。
llama-swap
brew tap mostlygeek/llama-swap
brew install llama-swap
装好之后必须准备一个配置文件(YAML 格式),官方的文档以及示例都写的很好,刚开始看着会有点复杂,但其实还好,以我的配置文件为例说明我比较喜欢的几个特性:
healthCheckTimeout: 300
logLevel: info
logTimeFormat: "rfc3339"
logToStdout: "proxy"
metricsMaxInMemory: 1000
captureBuffer: 15
startPort: 9001
sendLoadingState: true
includeAliasesInList: false
一开始是一组全局配置,最需要了解的是 startPort 参数,因为 llama-swap 支持同时运行多个模型推理实例,每个实例使用独立的端口与 llama-swap 通信而 llama-swap 将用户的请求分发给正确的实例,这里的 startPort 就是这些独立端口的初始值,然后 llama-swap 可以自动给不同模型分配不同的端口(比如 9001,9002,9003... 等)。
然后可以配置一些宏 macros ,后面可以复用,比如 llama-server 的命令模板,你存放下载模型的位置,统一指定的参数值等:
macros:
"latest-llama": |
/opt/homebrew/bin/llama-server
--port ${PORT}
"default_ctx": 16384
"default_args": "--ctx-size ${default_ctx}"
"models_dir": "${env.HOME}/.lmstudio/models"
注意在 llama-server 命令模板里的 --port ${PORT} 的后半部分是 llama-swap 的内置宏,会根据上面设定的 startPort 自增设定。设定宏 models_dir 里还展示了如何直接使用你的环境变量比如 HOME 的值。
然后就可以配置你的模型实例了。下面是我目前本地跑的五个模型实例:
models:
"qwen3.5-35b-a3b":
cmd: |
${latest-llama}
--model ${models_dir}/unsloth/Qwen3.5-35B-A3B-GGUF/Qwen3.5-35B-A3B-UD-Q4_K_L.gguf
--ctx-size ${default_ctx}
--temp 0.6
--top-p 0.95
--top-k 20
--min-p 0.00
--cache-type-k q8_0
--cache-type-v q8_0
-np 1
-ngl 99
name: "Qwen3.5 35B"
description: "Qwen's newest multimodel MoE model for local use"
checkEndpoint: /health
ttl: 3600
aliases:
- "qwen3.5"
"qwen3.5-35b-a3b-non-thinking":
cmd: |
${latest-llama}
--model ${models_dir}/unsloth/Qwen3.5-35B-A3B-GGUF/Qwen3.5-35B-A3B-UD-Q4_K_L.gguf
--ctx-size ${default_ctx}
--temp 0.7
--top-p 0.8
--top-k 20
--min-p 0.00
--chat-template-kwargs "{\"enable_thinking\": false}"
--cache-type-k q8_0
--cache-type-v q8_0
-np 1
-ngl 99
name: "Qwen3.5 35B Non-thinking"
description: "Qwen's newest multimodel MoE model for local use"
checkEndpoint: /health
ttl: 3600
aliases:
- "qwen3.5-nt"
"hy-mt1.5-1.8b":
cmd: |
${latest-llama}
--model ${models_dir}/tencent/HY-MT1.5-1.8B-GGUF/HY-MT1.5-1.8B-Q8_0.gguf
--ctx-size ${default_ctx}
--temp 0.7
--top-p 0.6
--top-k 20
name: "Hunyuan Translation Model v1.5"
checkEndpoint: /health
ttl: 3600
aliases:
- "hy-mt"
"nomic-embed-text-v1.5":
cmd: |
${latest-llama}
--model ${models_dir}/nomic-ai/nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.Q8_0.gguf
--ctx-size 8192
--batch-size 8192
--ubatch-size 4096
--rope-scaling yarn
--rope-freq-scale 0.75
-ngl 99
--embeddings
aliases:
- "nomic"
"snowflake-arctic-embed-l-v2.0":
cmd: |
${latest-llama}
--model ${models_dir}/Casual-Autopsy/snowflake-arctic-embed-l-v2.0-gguf/snowflake-arctic-embed-l-v2.0-q8_0.gguf
--ctx-size 8192
--batch-size 8192
--ubatch-size 4096
--rope-scaling yarn
--rope-freq-scale 0.75
-ngl 99
--embeddings
aliases:
- "snowflake"
使用 llama-swap 有个很方便的功能,就是对 Qwen 3.x 这类可以切换 thinking / non-thinking 模式的模型,可以配置开关思考能力各一个模型实例,上面前两个模型都指向同一个模型 GGUF 文件,但不同参数配置实现一个是带 thinking 的另一个则不带( --chat-template-kwargs "{\"enable_thinking\": false}" 参数)。
另外一些值得注意的点:
- 使用
macros简化统一的配置值,比如你存放模型的目录models_dir。 - 使用
cmd: |语法实现多行的配置。 - 使用
aliases给模型实例一些简短方便的名字,可以让客户端调用时更方便。 - 我这里还配了俩 embedding 模型,注意使用
llama-server的--embeddings参数。
实际上 llama-swap 还支持更高级的一些配置,我没用,需要的可以去啃它的官方文档和例子。
整好自己的配置文件之后,将其保存为 ~/.config/llama-swap/llama-swap.yaml 文件,然后用如下命令来启动 llama-swap :
llama-swap -config /Users/username/.config/llama-swap/llama-swap.yaml -listen 0.0.0.0:9000
命令中配置文件地址改为你系统里实际文件位置,最后的监听地址(IP 及端口)可按需要配置。
这时配置好的模型就可以通过兼容 OpenAI API 的方式访问了,设置 base_url="http://0.0.0.0:9000/v1" 以及任意 api_key 即可。还可以通过 http://0.0.0.0:9000/ui/ 访问 llama-swap 的 web 控制台。
当然,更好的办法是把 llama-swap 配置成自动启动的服务。在 ~/Library/LaunchAgents 目录下创建文件 llama-swap.plist 并写入如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com">
<plist version="1.0">
<dict>
<key>Label</key>
<string>llama-swap</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/bin/llama-swap</string>
<string>--config</string>
<string>/Users/username/.config/llama-swap/llama-swap.yaml</string>
<string>-listen</string>
<string>0.0.0.0:9000</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>WorkingDirectory</key>
<string>/opt/homebrew/bin/</string>
<key>StandardErrorPath</key>
<string>/tmp/com.llamaswap.server.err</string>
<key>StandardOutPath</key>
<string>/tmp/com.llamaswap.server.out</string>
</dict>
</plist>
其中配置文件地址改为你系统里实际文件位置,最后的监听地址可按需要配置。
oMLX
去项目的 Releases 页面下载最新版本安装运行,会在系统菜单条里出现一个小鸟图标。第一次启动的时候会引导你设置一些参数,全默认即可,但 API Key 需要设一下,这个密码既用于登录 oMLX 的 web 控制台,也用于 API 调用时的 api_key 参数。
实际上 oMLX 也支持通过 Homebrew 安装,但我早期尝试时发现会和 Python 环境有些冲突,所以我就没走那条路,如果喜欢该方案的话不妨一试,没准现在已经解决好了。
另外就是模型放哪里的问题,oMLX 默认模型放在 ~/.omlx/models 而不像 llama-swap 那样可以通过配置文件随意指定模型位置,如果想使用比如 LM Studio 下载好的模型,有两个方法(任一):
- 把默认的模型目录改为 LM Studio 的模型目录(默认在
~/.lmstudio/models下); - 在默认目录
~/.omlx/models下建立符号链接,把你随便放在哪里的模型目录链过来。
显然后一个方式更灵活,所以我现在就这么干的。
LM Studio
去项目的下载页面下载最新版本安装,实际上 LM Studio 的 Beta 版本也是比较稳定的,所以也可以去下载 Beta Release。
然后你可以和我一样把它当 HF 高级下载器用(绝对比 HF 自己的好得多),或者也可以用它的各种其他功能,如果你要偷懒,甚至可以跳过前面所有的安装步骤,用 LM Studio 搞定一切,前提是你能容忍我前面说的那些问题。
应用举例
我自己目前主要把本地模型用于我的阅读器 Mercury。有兴趣的朋友可以去项目的 Releases 页面下载最新版本安装运行,然后打开应用设置 → Agents 设置:
- Providers 设置:你可以给
llama-swap和 oMLX 各配置一个 provider; - Models 设置:可以把你在
llama-swap和 oMLX 里的模型都配置好; - Agents 设置:我目前给三个智能体任务配置的模型分别是:
- Summary:主模型用 oMLX 下的 Qwen3.5-35B(在 oMLX 控制台关闭 thinking 模式,下同),备份模型用 DeepSeek;
- Translation:主模型用
llama-swap下的 HY-MT1.5,备份模型用 oMLX 下的 Qwen3.5-35B; - Tagging:同 Summary。