← 文章 / AI技术
Hacker News 7小时前 · 2026-09-02 08:01:14 · 4 阅读

Show HN:在 48GB Mac 上以约 12 tok/s 运行 104GB 的 Qwen3.8-Flash-Next

在一台内存放不下它的 Mac 上运行 Qwen3.8-Flash-Next。这是一个拥有 1250 亿参数的混合专家模型,4-bit 版本占用 104 GB 磁盘空间;slotstream 会从 SSD 流式读取模型,并根据你提供的内存运行。它是一个单文件 Swift 二进制程序,无需 Python。它兼容 Ollama 和 OpenAI Chat API,因此现有工具无需修改即可使用。

在 48 GB M5 Pro 上
稳定解码速度 约 12 tok/s
引擎启动 约 2 秒(只需加载 3.8 GB 的主干部分)
峰值内存 32 GB(自动调整,也可以手动限制)
磁盘上的权重 104 GB

我的 Mac 能运行吗?

你需要 Apple Silicon 芯片、macOS 14 或更高版本,以及约 110 GB 可用磁盘空间。真正先构成限制的是磁盘:无论内存多大,512 GB 的 Mac 才是比较现实的最低配置。

自动调整不会占满整台机器。不同内存配置下的占用和性能如下:

你的 Mac slotstream 占用 稳定解码速度
8 GB 8.1 GB,最低占用 约 3 tok/s,doctor 会警告系统将使用页面交换
16 GB 10 GB 约 4 tok/s
24 GB 16 GB 约 8 tok/s
32 GB 22 GB 约 9 tok/s
48 GB 及以上 33 GB(继续增加内存也没有提升,参见内存 约 12 tok/s

这些数据直接来自 slotstream doctor --sim-ram N,因此可以自行复现。只有 48 GB 这一行是在真实硬件上测得的,其余数据是根据性能曲线估算的;内存更小的 Mac 通常还配备更慢的 SSD。下载任何文件前,先运行 slotstream doctor:它会显示针对你机器的配置方案,并检查磁盘是否有足够空间存放模型权重。

安装

curl -fsSL https://raw.githubusercontent.com/carloslfu/slotstream/main/install.sh | sh

该命令会将最新版本安装到 ~/.slotstream/bin,并将其加入 PATH。升级时再次运行同一条命令即可。卸载时,执行 rm -rf ~/.slotstream,并删除 /usr/local/bin/slotstream 包装脚本,或者移除安装程序提示你添加的 PATH 配置。

各版本均由 CI 根据带标签的提交构建,并附带经过签名的构建来源信息。因此,你可以验证下载文件,而不必完全信任下载过程:

gh attestation verify slotstream-arm64.tar.gz --repo carloslfu/slotstream

也可以自己构建 main。只需安装 Command Line Tools,无需 Xcode:

git clone https://github.com/carloslfu/slotstream && cd slotstream
make build

104 GB 的下载量

二进制文件很小,但模型权重不小:24 个文件共 103.8 GB,需要下载一次。 首次使用时,serverun 会提供下载,或者也可以直接执行 slotstream pull。开始传输前,它会显示文件大小、保存位置和剩余磁盘空间, 等待确认;如果磁盘容量不足,则会直接拒绝下载。

我实际安装时花了 35 分钟。无论开启多少连接,Hugging Face 都会把传输速度限制在大约 36–57 MB/s,因此超过约 400 Mbps 后,等待时间主要取决于 Hugging Face,而不是你的网络。 100 Mbps 的宽带大约需要 2 小时 20 分钟,25 Mbps 则约需 9 小时。

中断下载也不用担心:pull 会从停止的位置继续,最多只需重新下载中断时正在传输的几个分块。 24 个文件都会使用编译进二进制文件的 sha256 哈希进行校验,因此不完整或损坏的下载不会进入引擎。 文件来自固定版本的镜像,原始仓库作为备用来源;无论从哪边下载,哈希都相同。 随时可以用 pull --verify 重新计算已有文件的哈希(我这里耗时 8 秒)。

使用方法

先来个无需启动服务器的简单测试:

slotstream run --prompt "why is the sky blue?"

其他场景可以启动 serve。它会监听 11434 端口,并实现 Ollama 客户端和 OpenAI SDK 所使用的 chat/generate 接口子集:

slotstream serve
curl localhost:11434/api/chat -d '{
  "model": "qwen3.8-flash-next:4bit",
  "messages": [{"role": "user", "content": "hello"}]
}'

Open WebUI 和 OpenAI SDK 都已针对这一接口子集完成测试(Ollama CLI 目前还不支持,详见 Status)。流式输出、CORS 以及常见的采样选项都可以正常使用。 暂不支持的功能(tools、images、JSON-schema output、logprobs)会返回明确的 400 错误,而不是被静默忽略。 所有接口、字段、默认值和错误说明都在 docs/API.md 中。

速度

解码反而是简单的部分:在 48 GB 的 Mac 上,预热后速度约为 12 token/s;上面的分档表也列出了更小内存机型的表现。真正慢的是提示词处理。所有提示词都要在生成第一个 token 前处理完,因此,8,000 个 token 在 48 GB Mac 上大约要等一分钟,在 16 GB Mac 上则要等三分钟以上。提示词加生成内容的总长度上限为 32,768 个 token(--max-context)。

在同一段对话中,这部分开销只需承担一次。后续轮次只会预填充新增内容,因此即使对话不断变长,首 token 延迟也基本不变:以 16 GB 为目标配置时,连续对话超过 8 轮,最后一轮只需 6.0 秒,而不是 25.8 秒。复用的状态与重新计算得到的状态并非逐 bit 完全一致,因此当两个 token 的概率非常接近时,回复偶尔可能会不同;如果需要精确复现,可用 --no-prefix-cache 将其关闭。

内存

不加任何参数时,slotstream 会根据你的机器自动确定配置,并显示最终选择。下面是一台 48 GB 的 Mac;之所以显示为 52,是因为这里统一按十进制 GB 计算:

slotstream memory plan (auto)
  device: 52 GB RAM(当前可回收 36.0 GB),40.2 GB Metal 工作集
  target: 此进程总计使用 33.0 GB   (覆盖设置:--memory-gb N | --max-ram-percent P)
  cache:  每层约使用 512 个 expert 中的 152 个(7280 个全局 slot = 20.1 GB pool)
  expect: 峰值约 32.0 GB,预热后解码速度约 12 token/s(根据 M5 Pro 实测基准估算)
  prefill: 每轮处理 4096 个 token(此处约 125 token/s;占用目标内存约 5.3 GB)
  reuse:  4 个对话之间最多复用 32768 个 token(约 1.2 GB),因此后续轮次只需重新预填充新增内容

自动模式会取三个限制中的最小值:33 GB、内存的 70%,以及比 Metal 工作集上限低 2 GB;如果其他应用确实正在占用内存,它还会进一步缩减配置。33 GB 的上限来自实测曲线的拐点,并不是为了“客气”:按每次增加 1 GB 的方式测试时,内存在 34 到 84 GB 之间,无论解码还是预填充,速度都没有更快。因此,128 GB 的 Mac 与 48 GB 的 Mac 会采用同样的配置。运行期间,slotstream 每 15 秒重新检查一次,并在请求之间调整缓存大小:内存压力增大时缩小,压力消退后再恢复。调整缓存大小不会改变输出字节。

如果想手动限制内存,可用 --memory-gb G 设置此进程的总内存上限(最低为 8.1 GB;如果想进行实验,也可以超过 33 GB)。--max-ram-percent P 用于调整 70% 的内存占比,--experts-per-layer / --pool-gb 则可直接设置缓存大小。运行 slotstream doctor 可以在不加载任何内容的情况下,查看这些参数分别会生成什么配置。

工作原理

模型的大部分数据存放在两个地方:68 GB 的路由专家(每层 512 个,每个 token 激活 10 个)以及 32 GB 的 n-gram 表。稠密主干只有 3.8 GB,会常驻内存。读取专家时,程序通过 pread 将其载入固定的缓存槽位池,供全部 48 层共享,因此热点层可以从冷门层借用槽位。

缓存大小只影响速度,不影响输出。使用 4 GB 和 24 GB 缓存时,贪心解码的结果在字节级完全一致;这也是持续执行的一项测试。

为什么不直接对文件使用 mmap?因为 MLX(Apple 的机器学习框架)无法只加载内存映射张量的一部分:top-10 专家聚合会计算该层的全部 512 个专家,使用 mmap 的路径会加载约 100 GB 数据,最终崩溃。标准的 mlx_lm.load() 路径甚至让这台 48 GB 内存的机器用满了 48 GB swap,却没能生成一个 token。

状态与限制

目前可以正常运行,实测设备为一台配备 48 GB 内存的 M5 Pro。更低内存规格的数据是根据性能曲线估算的,并非在真实硬件上运行得出。

  • 单模型、单进程。v0 目前只支持 qwen3.8-flash-next:4bit;引擎围绕该模型的结构设计,pull 也只识别这一个名称。每个用户都有一个锁,因此同一时间只能运行一个模型进程。
  • macOS 14 和 15 目前只测试过安装流程,尚未测试运行时。
  • Ollama CLI 目前还无法连接。ollama run(0.32)启动时会发送一个包含特定字段的 /api/show 请求,而严格验证器会拒绝这些字段,因此程序在收到第一条消息前就会停止。curl、Open WebUI 和 OpenAI SDK 均可正常工作,修复正在进行中。

推测解码

这是 0.2.0 版本新增的功能(CHANGELOG.md 中列出了各版本的完整变更)。

  • --mtp auto|on|off模型自带一个 draft head,用于预测下下个 token;slotstream 会提前生成几个 token,再通过一次批处理统一校验。其中,第一个 draft 的实测正确率为 86%。只有在 expert cache 已接近最佳容量时,它才值得启用:小容量缓存的 A/B 测试结果为 ×0.96,因此 auto 模式会在目标容量低于约 26 GB 时关闭该功能;容量更高时预期可提升 ×1.5–1.9,但这只是根据接受率计算出的理论值,目前还没有 A/B 测试结果。这个 head 会在缓存之外额外占用 1.6 GB,因此 auto 模式的上限会变为 34.6 GB。首次使用前需要执行一次转换:从官方发布包中提取 4.9 GB 数据,并在权重文件旁生成一个 1.5 GB 的 mtp.safetensors(使用仓库自带的 Python 环境,从代码仓库副本根目录运行 Tools/mtp_convert.py)。如果没有这个文件,所有运行都会默认关闭该功能。

文档

  • docs/API.md:介绍所有 endpoint、支持的字段、采样默认值,以及有意设计的 400 错误。
  • docs/TROUBLESHOOTING.md:介绍端口冲突、分页,以及如何移动或校验权重文件。
  • docs/CLI.md:列出所有命令和参数,说明内存配置项及其优先级、环境变量和文件存放位置。(运行 slotstream <command> --help 可查看相同内容,并附有更详细的说明。)
  • CHANGELOG.md:记录每个版本的变更。
  • PLAN.md:介绍设计方案和里程碑进度。
  • MEASUREMENTS.md:列出本文所有数据及其测量方法,也包括失败的实验。
  • llms.txt:为 AI agent 提供完整内容索引,内含命令、内存配置项和 API 要点;llms-full.txt 则将上述所有文档合并到一个文件中。

测试

Tools/verify.sh 是验收测试套件:验证权重来源、与版本匹配的 Python 参考实现对比结果、不同缓存大小及动态调整缓存时的字节级一致性,以及针对曾导致服务器崩溃的输入所设计的服务稳定性测试。Tools/e2e_release.sh 则测试用户真正会接触的另一部分:curl | sh 安装流程,以及安装后生成的二进制文件。不依赖权重的测试会在每次发布构建时于 CI 中运行。

许可证

MIT。Sources/SlotstreamCore/Vendored/GatedDelta.swift 移植自 mlx-swift-lm(MIT);Tools/reference/ 中内置了社区版 qwen4_exp.py,作为测试判定基准。权重来自 pipenetwork/Qwen3.8-Flash-Next-MLX-4bit,仍遵循 Qwen 社区许可证。

原始来源: Hacker News

评论 (0)