oMLX

用外接 SSD 存放 oMLX 模型,并用 Kopia 定时备份

October 6, 2026 · 2 分钟阅读

上一篇 mem0 的文章提到 oMLX 在这台机器上提供对话和嵌入模型,但有一件事没说:这些模型都不在内置硬盘上。整个模型库放在一块外接 SSD 里,另有第二块硬盘每小时对它做一次备份。这篇文章讲这两半是怎么搭的。

为什么用外接 SSD

跑服务的 Mac mini 内置硬盘只有 1 TB,而 MLX 模型的体积增长很快 —— 单个 27B 的 4bit 模型就是 ~15 GB。目前我的模型库已经 36 GB,还在涨:

/Volumes/Mate_Mini/omlx/base/models/
├── Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed
└── mlx-community/
    ├── bge-m3-mlx-8bit
    ├── gemma-4-e2b-it-4bit
    └── Kokoro-82M-bf16

从一块通过雷雳(Thunderbolt)连接的 SSD 加载模型,体验和内置硬盘几乎没有差别 —— 权重只会一次性读入统一内存,之后的推理是计算受限的。内置硬盘省下的空间(以及免去反复下载几个 GB 大文件的磨损),远比那点感知不到的加载时间差距值钱。

让 oMLX 指向 SSD

oMLX 把所有东西 —— 模型、HF 缓存、日志、配置、用量统计 —— 都放在一个 base path 之下。迁移只需要改一个设置,应用会把这个选择持久化到一个 bootstrap 文件里:

$ cat ~/Library/Application\ Support/oMLX/base-path
/Volumes/Mate_Mini/omlx/base

通过 Homebrew 安装的 omlx CLI 其实只是一个 shim:读取这个文件、导出为环境变量,然后把控制权交给 App bundle 里的真正二进制:

BOOTSTRAP="$HOME/Library/Application Support/oMLX/base-path"
if [ -r "$BOOTSTRAP" ]; then
    IFS= read -r OMLX_BASE_PATH < "$BOOTSTRAP" || OMLX_BASE_PATH=""
    if [ -n "$OMLX_BASE_PATH" ]; then
        export OMLX_BASE_PATH
    fi
fi
exec '/Applications/oMLX.app/Contents/MacOS/omlx-cli' "$@"

base path 里最重要的文件是 settings.json,它显式记录了模型目录:

{
  "model": {
    "model_dirs": ["/Volumes/Mate_Mini/omlx/base/models"]
  }
}

重启服务器(omlx restart)之后就从 SSD 对外服务了。我开了 launch_at_login,台式 mini 上硬盘一直挂着 —— 如果你的使用场景不同,看文末的坑。

为什么要备份"可以重新下载"的文件

模型权重是公开资源,丢了总能重新下。但慢速或按流量计费的网络下,36 GB 意味着几个小时的等待;而且这个目录不只有权重:settings.json、每个模型的调优参数 model_settings.json、hf_download_tasks.json,还有存了服务统计的 usage.sqlite3 —— 这些是下载不回来的。备份的目标不是给 Hugging Face 的目录做灾备,而是让"恢复目录、重启服务"变成一个五分钟的操作。

用 Kopia 做备份

Kopia 是一个去重、加密、内容寻址的备份工具 —— 可以理解为调度更友好的 restic。我在 mini 上跑 KopiaUI,仓库放在第二块外接盘(一块 9 TB 的机械盘)上,因为源和备份在同一块盘上不叫备份,叫副本:

源目录:  /Volumes/Mate_Mini/omlx          (3 TB SSD)
仓库:    /Volumes/Getea/VM-backups/mate_mini_backups   (9 TB HDD)

仓库在磁盘上是密码加密的 —— 所有 Kopia 仓库都是如此。这个仓库还存了同一块 SSD 上的另外三个目录(虚拟机、语音模型、容器数据),Kopia 会在它们之间做全局去重。

oMLX 目录的策略,和 UI 里配置的一致:

等价的 CLI 命令(直接用 KopiaUI 内置的二进制):

KOPIA="/Applications/KopiaUI.app/Contents/Resources/server/kopia"

"$KOPIA" policy set /Volumes/Mate_Mini/omlx \
  --snapshot-interval=1h \
  --keep-latest=5 --keep-hourly=24 --keep-daily=12 \
  --keep-weekly=4 --keep-monthly=24 --keep-annual=3 \
  --compression=zstd-fastest

模型库是 Kopia 的最佳场景

对模型目录做快照几乎零成本,因为模型权重是不可变的:bge-m3-mlx-8bit 下载完之后,那几个 GB 就再也不会变。Kopia 对所有内容做分块和内容寻址,所以第一次快照之后,每小时的运行几乎不需要上传任何东西。真实的快照列表能看出来:

2026-10-04 07:01  38.4 GB  files:1091  (daily-4)     ← Qwen3.8-27B 入库
2026-10-04 23:02  38.4 GB  files:1099  (hourly-19..24, daily-3, weekly-2)
   + 7 个完全相同的快照,直到 2026-10-05 19:02
2026-10-05 20:02  38.4 GB  files:1099  (latest-1..5, hourly-1..18, ...)
   + 17 个完全相同的快照,直到 2026-10-06 13:00

已经攒了 30 个快照,而那些"完全相同"的运行每次只花几 KB 的元数据。十月初从 13.1 GB 跳到 38.4 GB,是那个 27B 模型入库 —— 一次增量上传新数据块,然后恢复平静。这是理想的备份画像:激进的调度、宽裕的保留期、可以忽略的增量成本。

压缩算法值得说一句:4bit 量化的 safetensors 本身已经很致密,任何压缩算法都不会有明显效果。选 zstd-fastest 是给目录里的 JSON/SQLite/文本文件上个便宜的保险,同时不在权重文件上浪费 CPU。

踩过的坑

验证它是否工作

KOPIA="/Applications/KopiaUI.app/Contents/Resources/server/kopia"
"$KOPIA" snapshot list /Volumes/Mate_Mini/omlx \
  --config-file ~/Library/Application\ Support/kopia/repository.config

而真正重要的验证是恢复演练:挂载一个快照(kopia mount),或者 kopia snapshot restore <id> /tmp/omlx-test,然后把 oMLX 的 base path 指到恢复出来的目录,确认模型能正常加载。没恢复过的备份只是一个假设。

← 返回所有文章