跳到正文
Hacker News· kerenskiy·· 10 天前AI 评分60

lily-qwen3.8-flash-next 发布:面向 Apple Silicon 的 Metal 推理服务

Lily-Qwen3.8-Flash-Next

AI 导读

lily-qwen3.8-flash-next 是一个面向 Apple Silicon 的 Metal 推理服务,只服务 Qwen3.8-Flash-Next 一个模型,由 Perplexity 的 lily 引擎移植并针对该模型调优。

正文 · AI 翻译

译文尚不完整,完整内容请切换到原文。

lily-qwen3.8-flash-next 是一个面向 Apple Silicon 的 Metal 推理服务器,只服务一个模型:Qwen3.8-Flash-Next。它是 Perplexity 的 lily 的一个分支,后者是一个用于 Qwen3.6-35B-A3B 的紧凑 Metal 引擎,解码速度比 mlx-lm 快约 30%(他们的文章)。

这个分支将该引擎移植到 Qwen3.8-Flash-Next 并针对该模型进行调优:手写 Metal 内核、流水线化解码步骤、使用模型自带草稿头的投机解码、跨请求和重启缓存对话,以及一个让模型只需一半内存即可运行的专家缓存。

在同一台机器和相同提示词下,与 Unsloth 的 llama.cpp 分支相比,预填充快 2.7 到 4.2 倍,解码快 2.1 到 3.6 倍,上下文越长优势越明显(对比,2026-09-17)。

有两个检查点,都主要是 4 位:q4-xl(推荐)将每个 token 都要经过的稠密张量保持为 8 位,在长智能体回合中明显更可靠;q4 更快,单请求解码快几个百分点,批量请求快约 15%。模型页面有详细信息。

运行它

你需要一台 M5 或更新机型(Apple GPU 家族 10)、macOS 26、由 rust-toolchain.toml 固定的 Rust 工具链,以及 128 GB 统一内存,或者使用专家缓存时的 64 GB(见 更小的机器)。

hf download fabiogreter/Qwen3.8-Flash-Next-lily-q4-xl \
  --local-dir ~/models/Qwen3.8-Flash-Next-lily-q4-xl

cargo build --release --locked

./target/release/lily --model ~/models/Qwen3.8-Flash-Next-lily-q4-xl \
  --bind 127.0.0.1:8000 --max-seq 131072

服务器在模型加载期间以 503 loading 响应 /health,约 25 秒后开始服务,同时 n-gram 表在后台继续加载。--help 列出了所有标志。服务器也可以作为 launchd 服务运行,见此处:tools/service/README.md。

API 兼容 OpenAI(/v1/chat/completions、/v1/completions、/v1/models,支持工具和 reasoning_content),并针对 opencode 开发。最多 --max-batch 个请求(默认 4 个)一起解码。思考默认开启,并配有思考控制,防止模型无休止推理:思考预算(low 和 medium 努力程度下为 8 000 token,xhigh 下为 16 000)并在其之前进行提醒,而在推理过程中发起的工具调用会结束思考。每个响应都带有一个 timings 对象,包含预填充和解码速率、缓存 token 数和草稿接受率;tools/opencode-plugin-timings/ 在 opencode 中显示它们。API 的详细信息、批处理和思考控制:docs/server.md。

性能

M5 Max,40 核 GPU,128 GB,通过 HTTP 使用真实文本提示词(本仓库的文档和代码),256 个贪婪 token 的新文本,三次重复的中位数,2026-10-07。oMLX 的行是其在 M5 Max 128 GB 上 oQ4e 转换的已发布数据,来自 0.7.0 发行说明中的图表,并非我们测量;该图表未说明其采样方式,也未说明其生成是否使用了 MTP。

每秒 token 数 4K 上下文 16K 32K 64K
预填充 q4-xl 2 219 2 370 2 373 2 180
预填充 q4 2 158 2 208 2 240 2 205
预填充 oMLX 0.7.0,已发布 2 768 2 844 2 366
解码 q4-xl,2 个草稿 101 101 94 94
解码 q4,2 个草稿 103 100 99 99
解码 q4-xl,无草稿 73 73 69 68
解码 q4,无草稿 87 82 85 79
生成 oMLX 0.7.0,已发布 93.0 87.1 75.9

单请求解码每步使用模型自带草稿头的两个草稿;批量请求解码不使用草稿。解码从 4K 到 64K 损失很小,因为稀疏注意力内核将上下文成本控制在单步的一小部分。

In actual use with opencode, prefill is often slower than this, because most turns are short and fixed per-request costs dominate. Decode is typically faster: agent output (tool calls, paths, code repeated from the context) is easy for the draft head to predict, so more drafts are accepted than on these prompts, and decode has stayed above 100 tok/s beyond 200K tokens of context, because a step grows only slowly with context. Method, noise and the full record: docs/performance.md.

The model

Qwen3.8-Flash-Next is Qwen's qwen4_exp preview architecture: 48 layers, 36 of them Gated DeltaNet with a fixed-size recurrent state and 12 sparse attention with an indexer that picks 512 blocks per query, a 512-expert MoE with 10 active, a four-stream gated residual, a 32 GB hashed n-gram embedding, a multi-token-prediction head and a vision tower.

The server runs either of two conversions of it, made by tools/convert/convert_qwen38_flash_next.py from the BF16 weights with the vision tower kept in bf16. Both keep the routed experts and the n-gram tables, about 95 % of the bytes, at 4 bits:

  • q4-xl (recommended, 106.9 GB) keeps attention, the shared expert, the LM head and the embedding at 8 bits. On long agent turns the 4-bit model more often announces its next step and ends the turn without making the tool call; on a captured opencode turn, sampled 30 times each with the thinking controls on, 23 of 30 samples went on to a tool call on q4-xl against 18 on q4. Of the 8-bit sets tried, the attention tensors carried the difference. The draft head keeps a 4-bit path, so drafting costs what it does on q4 while the trunk, which verifies every draft, decides the output.
  • q4 (105.5 GB) is 4-bit apart from a small set of routing and mixing tensors, and is faster when requests decode without drafts, for example several at once (see Performance).

This is one prompt, not a task-level evaluation. The layout and the 8-bit groups are documented in docs/qwen38-flash-next-checkpoint-format.md.

Exactness

The fork is not logit-identical to other engines, and for this model no two bf16 engines are: small rounding differences flip near-tie choices in its expert router and sparse attention. On the same 4-bit weights as the MLX port, the fork's output differs from MLX's by a mean KL of about 2e-3 from 1K to 32K of context, as much as MLX differs from itself when only its prefill chunk size changes. Method and numbers: tools/README.md.

Caching

Prompt state is cached in three tiers; clients see them only as cached_tokens in the usage block.

  1. Resident sessions. Each conversation's state stays in GPU memory within a budget, so continuing it costs only the new tokens. A re-sent last turn (a regenerated or re-tokenized answer) rewinds the session in place; edits further back and other conversations fork a copy instead of overwriting it. Long answers carry checkpoints of their own, so a prompt that diverges inside one resumes near the divergence.
  2. Disk. Sessions evicted from GPU memory move to disk and come back in about a second per few gigabytes. They survive restarts.
  3. 持久前缀。同一 agent 的多次运行共享一段前导内容(系统提示、工具 schema、仓库指令),并在用户消息处产生分歧,因此任何一次运行都无法恢复另一次运行的检查点。当共享部分超出某次运行可恢复位置至少 1 024 个 token 时,服务器会将其单独存储,之后每次运行都从那里开始。

图像按其内容进行标识,因此两张不同的截图永远不会共享缓存状态。规则见:docs/architecture.md,“The session cache”。

速度是如何实现的

一个解码步骤每 token 大约读取 4.4 GB 的权重和状态,因此解码受带宽限制。预填充每 4 096 个 token 的块读取一次权重,受计算限制。

来自 Perplexity:Metal 内核基础(改编自 MLX 的 4 位权重流式传输、张量运算 GEMM、MoE、Gated DeltaNet 和注意力内核)、运行时着色器编译器,以及一个带有 token 前缀缓存的小型服务器。

此分支新增:

  • Qwen3.8-Flash-Next 图及其转换器:带索引器的稀疏注意力、超连接、分页 n-gram 表、草稿头、视觉塔。
  • Metal 4 传输:每步一个命令缓冲区、层级屏障、解码步骤停驻在 GPU 事件上,使主机脱离关键路径,以及诸如接受的草稿数量等控制流在 GPU 上决定。
  • 使用模型自身头部的推测解码,在请求采样时精确无误。
  • 解码内核经过调优,使一步的运行时间在其读取链可流式传输的 10% 到 15% 以内(带宽限制,已计入爬升时间)。
  • 在张量运算上进行预填充:对相邻查询所选内容的并集进行稀疏注意力、分块 Gated DeltaNet 扫描,以及为专家 GEMM 提供更好的分块。
  • 面向半内存机器的专家缓存。
  • 每个请求一个活动断言,因此没有窗口的服务器在持续负载下也能保持其 GPU 性能。
  • 会话缓存和完整的 OpenAI 请求接口。

传输、停驻、推测解码、缓存和专家缓存适用于任何模型和框架,包括 MLX;稀疏注意力和循环状态的工作则特定于该架构家族。详细说明见 docs/architecture.md;尝试过什么、放弃了什么以及原因见 docs/performance.md。

更小的机器

在更小的机器上,lily 会自动采用专家缓存,仅将最常用的专家保留在 GPU 内存中,其余从磁盘流式传输。专家使用情况在运行时被跟踪,因此缓存会适应你的使用方式。随后缓存的配置会被保存到磁盘,并在下次运行时复用。

在 RAM 和磁盘之间移动专家当然会耗费时间。在一台模拟的 64 GB 机器上,测得预填充约为 930 tok/s,解码约为 50-65 tok/s。此模式下推测解码处于关闭状态,因为它需要额外的专家读取,从而拖慢进程。请注意,实际性能可能更差,因为还需要额外的 RAM 来保存会话 KV 缓存。如果有人想在真实的 64 GB 机器上测试,欢迎反馈。低于 64 GB 可能不切实际。

缓存会根据物理内存自行调整大小;--memory-gb 64 则按 64 GB 规划,这也是在更大机器上尝试该模式的方法。详情见:docs/low-ram-experts.md。

转换检查点

转换器需要一个包含 mlx、safetensors、numpy、torch、torchvision、pillow 和 transformers 的 Python 环境,以及一个 Metal 设备。

uv venv --python 3.13 .venv
uv pip install --python .venv/bin/python mlx safetensors numpy torch torchvision pillow \
    "transformers @ git+https://github.com/huggingface/transformers"

.venv/bin/python tools/convert/convert_qwen38_flash_next.py \
    --src ~/models/Qwen3.8-Flash-Next --dst ~/models/Qwen3.8-Flash-Next-lily-q4

为 q4-xl checkpoint(--dst ~/models/Qwen3.8-Flash-Next-lily-q4-xl)添加 --q4-xl。在 M5 Max 上大约需要一分钟。--layers 4 会写入测试所用的小型 checkpoint。tools/README.md 中有其他标志和参考测试框架。

测试

cargo test --locked

针对 CPU 参考运行内核测试、着色器编译测试和 API 测试;它们需要 Metal 设备,但不需要 checkpoint。需要 checkpoint 的测试默认被忽略,并需要 LILY_MODEL_DIR_FLASH;四层转换对所有测试来说都足够了。CONTRIBUTING.md 中有各项门禁,以及在相信一次绿色运行之前需要了解的两件事。

许可证

Apache-2.0。NOTICE 记录了上游版权以及内核改编自的 MLX 和 MLX-LM 代码。模型及其转换遵循 Qwen 的许可证,已在 checkpoint 的卡片上说明。

来源:Hacker News · github.com