三次架构演进
从翻车到稳定,每次更简洁
v1: GLM-5 + mlx_lm.server
日期: 2026-02-12 (Day 0) 状态: Abandoned
Claude Code → mlx_lm.server → GLM-5-MLX (417GB)
故事
Mac Studio M3 Ultra 512GB 到手当晚,GLM-5 刚发布不到 48 小时。417GB 模型以 11GB/min 下载,结果 HuggingFace 仓库还在上传中——下载完成后缺了 3 个 safetensors 文件。
写了蹲点脚本每 3 分钟检查远端,终于补齐文件。GLM-5 跑起来了:17.9 tok/s,峰值 449GB。
但 GLM-5 太慢了(对比 M2.5),第二天决定放弃。
教训
- 开源模型首发窗口期 = 混乱期
- HuggingFace CLI 不校验模型完整性
- 先验证再投入,417GB 的下载成本不小
v2: M2.5 + mlx_lm + CCR
日期: 2026-02-13 ~ 2026-02-14 (Day 1-2) 状态: Superseded
Claude Code → CCR (:3456) → mlx_lm.server (:8080) → M2.5
↑
Anthropic → OpenAI 格式转换
故事
MiniMax M2.5 开源了但没有 MLX 版本。用 mlx_lm.convert 自行转换,27 分钟下完原始权重,同时产出 4-bit (120GB, 51 tok/s) 和 8-bit (237GB, ~25 tok/s)。
要让 Claude Code 接入本地模型,需要 Anthropic API → OpenAI API 的格式转换。尝试 LiteLLM 失败,发现开源的 claude-code-mlx-proxy,重写为纯格式转换层 CCR (Claude Code Router)。
CCR 深度优化:完整支持 tool_use 转换、streaming、partial JSON……但这是三层架构,复杂度高。
代价
- OOM 内核 Panic (Day 2) — 模型切换时双进程 435GB 压爆 512GB
- 手动 patch mlx_lm 的 server.py 加
--max-kv-size - CCR 需要维护 Anthropic ↔ OpenAI 协议的每一个细节
教训
- 先搜索开源方案再造轮子
- 三层架构 = 三倍维护成本
- mlx_lm server 的 KV cache 不限制会膨胀到 OOM
v3: M2.5 + oMLX (当前)
日期: 2026-02-15 ~ 至今 (Day 3+) 状态: ✅ Active
Claude Code → oMLX (:8000) → M2.5
↑
原生 Anthropic + OpenAI 双 API
故事
发现 oMLX —— 一个原生支持 Anthropic API 和 OpenAI API 的 MLX 推理服务器。不再需要 CCR 中间层,架构从三层变两层。
一小时完成迁移:禁用旧 plist、配置 oMLX、更新 LaunchAgent。
但在使用过程中发现 SSD Paged Cache 存在死锁问题:推理 2-15 分钟后静默卡死。Fork oMLX,花了两天修复:
- PR #12:
<think>标签过滤 - PR #16: SSD cache 死锁 v3→v4,彻底解决
技术亮点
- 连续批处理 — 多请求并发
- SSD Paged Cache — KV cache 持久化,prefix 复用
- 多模型发现 — 自动扫描 ~/models/ 目录
- LRU 驱逐 — 内存不够时自动卸载不活跃模型
当前性能
| 指标 | 数值 |
|---|---|
| 推理速度 | ~25 tok/s (8-bit) |
| Wired 内存 | ~234GB |
| Free 内存 | ~240GB |
| SSD Cache | 已启用,零性能损失 |
演进总结
v1 GLM-5 + mlx_lm 三层(含模型本身) → 翻车
v2 M2.5 + mlx_lm + CCR 四层 → 能用但复杂
v3 M2.5 + oMLX 两层 → 简洁稳定
每一步都在做减法。从 417GB 的 GLM-5 到 237GB 的 M2.5,从三层代理到原生 API。
为道日损。损之又损,以至于无为。无为而无不为。
架构的最终形态不是最复杂的那个,而是减到不能再减的那个。