三次架构演进

从翻车到稳定,每次更简洁


v1: GLM-5 + mlx_lm.server

日期: 2026-02-12 (Day 0) 状态: Abandoned

code
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

code
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

code
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已启用,零性能损失

演进总结

code
v1  GLM-5 + mlx_lm           三层(含模型本身)  → 翻车
v2  M2.5 + mlx_lm + CCR      四层              → 能用但复杂
v3  M2.5 + oMLX              两层              → 简洁稳定

每一步都在做减法。从 417GB 的 GLM-5 到 237GB 的 M2.5,从三层代理到原生 API。

为道日损。损之又损,以至于无为。无为而无不为。


架构的最终形态不是最复杂的那个,而是减到不能再减的那个。