你看到「4.3GB RAM 跑 80B」,第一反應大概是:我的 Mac 終於不用 64GB 記憶體,也能把旗艦級開放模型留在本機?這次 Swiftlet 實測資料解讀要回答的不是模型能不能吐出第一個字,而是它要等多久、每秒能吐幾個 token、記憶體會不會隨 cache 與上下文長大,以及 SSD、耗電、熱降頻和回答品質有沒有被漂亮數字藏起來。
Swiftlet 在 2026 年 8 月初公開後,Hacker News 討論於 8 月 9 日查核是 311 points、142 comments;GitHub 專案在選題掃描當下是 462 stars、20 forks。這些數字證明大家很好奇,不等於效能已被證實。本文固定檢查 6a9440c:在 M4 16GB、macOS 26.1、Swift 6.2.4 完成 release build,repo 內建 17 個 tiny/synthetic tests 全數通過。80B 數字採 24GB M4 MacBook Air 公開紀錄;該紀錄未公布 code SHA,且早於 pinned 修補,只當現場訊號,不冒充 current commit 的獨立 benchmark。
這篇專為第一次碰本機大模型的人寫。你會學會 Apple Silicon 安裝、短問答與長上下文測試,還會看懂 TTFT、tokens/s、RAM、SSD I/O、功率與 thermal pressure。先說明實驗邊界:80B qpack 的 immutable manifest 合計 44.84GB(41.77GiB);本文機器當時僅約 45GB 可用,沒有安全下載餘裕,所以沒有虛構本機 80B 成績,而是把可重現命令、非維護者 field report/Issue 摘錄與尚未量到的項目分開呈現。
Swiftlet 實測資料先說結論:能跑,但離日用還有一段
- 能啟動:一筆外部 field report 支持。紀錄顯示 24GB M4 MacBook Air 載入 Qwen3-Next-80B,並生成至少 114 tokens;當時末尾出現特殊 token,之後的 pinned commit 才修補串流問題。
- 能互動:仍待完整驗證。短 prompt 的內建速度約 3.3–3.7 tok/s;另一輪內建 TTFT 是 14.5 秒、3.26 tok/s,但缺外部 warm TTFT 與 10 分鐘 thermal log。
- 適合日用:目前證據不足。本文查核的 README、HN 與 Issue #8/#9 未涵蓋完整長 prompt、功耗、熱降頻、裝置總 I/O 與系統化品質評測。
記住這個判斷式:本機大模型可用性 = 載得動 × 等得起 × 答得對 × 撐得久。任何一項接近零,「80B」就只剩規格成就。

Swiftlet 是什麼?MoE expert streaming 白話解釋
Qwen3-Next-80B-A3B-Instruct是 MoE(Mixture of Experts,混合專家)模型:總參數約 80B,但每次計算只啟用約 3B。Swiftlet 的做法是讓 dense core 常駐記憶體,把 routed experts 放在 SSD;每個 token 經 router 選出需要的 experts,cache 有就重用,沒有才用 pread 搬入 Metal shared buffer。
把它想成大型倉庫:傳統載入像先把所有貨搬進客廳;Swiftlet 則是收到一張訂單,才從倉庫拿這次需要的十箱。客廳變小了,但 cache miss 時會多出揀貨、儲存讀取與等待。若你想先補推論引擎的共同基礎,可讀 LLM 推論引擎白話教學;若想理解 streaming 如何用 I/O 換記憶體,可延伸看 Soup layer streaming 教學。

這個 80B 有 48 層:36 層是固定 recurrent state 的 DeltaNet,12 層仍是 full attention。Pinned ArchConfig.swift以 fp16 預算估成每 token 24KiB;但 current runtime 的 K/V cache 實際存於 Swift [Float],原始資料至少是每 token 48KiB,8K context 約 384MiB、32K 約 1.5GiB;Qwen config 的 262,144 native context 會約 12GiB,另有容器 overhead,這不是 Swiftlet 已驗證上限。DeltaNet state 則約固定 72MiB。也就是說,正確說法是「75% 層沒有成長型 KV」,不是「整個模型完全沒有 KV cache」。
4.3GB RAM 真相:cache 預算不是總記憶體上限
作者在固定版 80B qpack model card自報:24GB 基礎款 M5 MacBook、2GB expert cache、短 prompt 下,peak RAM 4.3GB、decode 4.5–5.3 tok/s、TTFT 約 5 秒。這是有條件的專案數字;prompt tokens、output 長度、cold/warm、RAM 工具與多次分布沒有一併公開,不能推成任何 Mac、任何上下文都只吃 4.3GB。
更有價值的是外部使用者的 Issue #8:一台 24GB M4 MacBook Air 把 --cache-gb 從 0.25、0.5、1、2 拉到 8,速度大致仍在 3.3–3.7 tok/s;其自報 process memory 約從 1.5、1.8、2.3、3.3 長到 9.3GB。測量方法、OS、power mode、code SHA 與逐 run timing 未交代,所以這是 anecdotal range,不是標準分布;它顯示不應把 4.3GB 當固定值。Issue #9是同一回報者的另一輪(該則未重述硬體),以 0.5GB cache、greedy、28-token prompt 顯示內建 TTFT 14.5 秒、3.26 tok/s;內部 decode 跑滿 512,當時可見輸出卻因 Unicode streaming bug 中斷。效能數字來自 6a9440c 前的原始回報;回報者後來 pull latest 並在兩個 thread 確認可見輸出修好,但未附 exact SHA,也沒有重跑 cache/速度矩陣,因此 3.3–3.7 tok/s、14.5 秒仍不是 pinned benchmark。

SSD 讀取很多,但不能直接換算磨耗
Swiftlet 本機 info qwen3-next-80b 顯示,完全沒有 expert-cache hit 時,每個 token 最多請求 480 個 experts,合計約 810MiB logical reads。這仍不是 NAND 實際讀取量:截至 pinned SHA,qpack reader用一般 open(O_RDONLY)+pread,macOS page cache 可能命中;專案 PLAN也仍把 F_NOCACHE 列為後續效能工作。因此 misses × stride 只能叫「應用層請求 bytes」,不能寫成實體 SSD reads,更不能直接換算壽命。
Apple Silicon 安裝 Swiftlet:先鎖版本,再下載 80B
準備 Apple Silicon Mac、macOS 14+、Swift 6.2+,以及至少約 60GB 可用空間;模型本體 44.84GB,Hugging Face/Xet 暫存、metadata 與 build 還要餘裕。README badge 寫 Swift 5.9+,但 pinned Package.swift明確要求 tools version 6.2,所以先跑 swift --version,不要用 badge 猜。
git clone https://github.com/leonickson1/Swiftlet.git
cd Swiftlet
git checkout 6a9440c1df33f859050f7af8523c4745dcaa3a91
swift --version
swift build -c release
swift test
.build/release/swiftlet info qwen3-next-80b
本文環境的 release build 成功,17 tests/8 suites 通過;它們主要是 tiny fixtures、GPU/CPU 與 qpack roundtrip,不能外推成完整 80B 品質驗證。下載時也要固定 Hugging Face revision,否則今天與下週的 qpack 可能不是同一份:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install 'huggingface_hub==1.8.0'
SWIFTLET_MODEL_DIR="$PWD/models/qwen3-next-80b.qpack"
hf download Leonickson/Qwen3-Next-80B-A3B-qpack \
--revision c22e9b4f07de843e3b61caa7c5544b1f7331ab3b \
--local-dir "$SWIFTLET_MODEL_DIR"
先用 0.5GB cache、greedy、短回答做 smoke test;確認終端輸出出現 [SwiftletSession] Metal model ready,才算走到預期 Metal 路徑。若看到 Metal init FAILED, falling back to CPU (heavy),這份 80B qpack smoke test 應判失敗,不要記成 CPU 跑分,因 CPU reader 不能讀 packed experts。
.build/release/swiftlet chat "$SWIFTLET_MODEL_DIR" \
"只用繁體中文回答:台北是哪個國家的首都?" \
--cache-gb 0.5 --max-new 64 --greedy
Swiftlet 實測方法:TTFT、tokens/s、RAM 要分口徑
Swiftlet 內建指標有三種不同邊界。chat/server 的 TTFT 從模型已載入、tokenization 完成後開始;Session tokens/s 只累計逐 token 的 model.step,排除 sampling、文字 decode 與 SSE。generate 的 decode 則包含 argmax、detokenize、stdout 與 model steps。它們可以診斷引擎,不能直接混進同一張跨工具排行榜。主表應另列 load time(process start → GET /v1/models 首次回 200)、warm user TTFT(request → 第一個非空 SSE content)、cold start-to-visible、end-to-end 與 wall decode rate。

第一組:短問答、長上下文與 cache sweep
- 短問答:約 64–128 input tokens,固定最多 128 output;分開量 load、warm user TTFT、cold start-to-visible、完成時間與 wall decode rate。
- 長上下文:1K、8K、10K tokens,在 10%、50%、90% 各藏一個 nonce,公開 prompt SHA-256、nonce seed/depth 與套完 chat template 後的實際 token 數。10K 超過 30 分鐘就記 timeout。
- cache sweep:
--cache-gb 0.5、1、2、4、8;每格重啟 server 是 cold app cache,同一 process warmup 後再跑五次。OS page cache 若沒重開機就標「未控制」。
啟動 server 後,把下面存成 bench_sse.py。它不用額外套件,會以第一個非空 content delta 計 warm user TTFT,並用 final usage 的 completion tokens 估 wall decode rate。因 UTF-8 tail 可能延後可見 delta,這個值只是「第一個可見字約等於第一 token」的近似;另報 end-to-end throughput。SSE chunk 不一定等於一個 token,所以不能直接數 chunks。
import json, os, time, urllib.request
payload = json.dumps({
"messages": [{"role": "user", "content": os.environ.get(
"SWIFTLET_PROMPT", "只用繁體中文列出五個蘋果品種。") }],
"stream": True, "max_tokens": 128, "temperature": 0
}).encode()
req = urllib.request.Request(
"http://127.0.0.1:8080/v1/chat/completions", payload,
{"Content-Type": "application/json"})
wall_start, t0 = time.time(), time.perf_counter()
first = None
completion_tokens = 0
with urllib.request.urlopen(req, timeout=7200) as response:
for raw in response:
if not raw.startswith(b"data: "):
continue
data = raw[6:].strip()
if data == b"[DONE]":
break
event = json.loads(data)
delta = event.get("choices", [{}])[0].get("delta", {}).get("content", "")
if delta:
now = time.perf_counter()
first = first or now
completion_tokens = event.get("usage", {}).get(
"completion_tokens", completion_tokens)
end = time.perf_counter()
decode_tps_estimate = None
if first is not None and end > first and completion_tokens > 1:
decode_tps_estimate = (completion_tokens - 1) / (end - first)
print(json.dumps({
"started_at": wall_start,
"warm_user_ttft_s": None if first is None else first - t0,
"end_to_end_s": end - t0,
"completion_tokens": completion_tokens,
"wall_decode_tps_estimate": decode_tps_estimate,
"end_to_end_tps": completion_tokens / (end - t0)
}))
SWIFTLET_PROMPT='只用繁體中文解釋 expert streaming,限 100 字。' \
python3 bench_sse.py
作者在 HN 回覆明說,現況適合 chat-length prompt,不適合 10K-token 文件;長 prompt 仍接近逐 token decode。這也是為什麼 coding agent、RAG 或整份報告,不應只看 3–5 tok/s 的 decode 數字。若你要理解 RAG 的檢索與長上下文取捨,可搭配 RAG、BM25 與 Hybrid Search 實測。
第二組:RAM、功耗與 thermal soak
/usr/bin/time -l會同時列一次完整命令的 maximum RSS 與 peak memory footprint;服務模式另用 footprint,並每五秒記 RSS/VSZ、swap usage、memory pressure 與 vm_stat。功率與 thermal pressure 用另一個終端執行:
# 終端 A:server 預設 cache 是 2GB,務必明寫
SWIFTLET_MODEL_DIR="$PWD/models/qwen3-next-80b.qpack"
.build/release/swiftlet-server \
--model "$SWIFTLET_MODEL_DIR" --port 8080 --cache-gb 2
# 終端 B:記 60 秒 idle+30 分鐘負載
SWIFTLET_BENCH_DIR="$PWD/swiftlet-bench-run"
mkdir -p "$SWIFTLET_BENCH_DIR"
SWIFTLET_PID="$(pgrep -n swiftlet-server)"
footprint --sample 0.5 --sample-duration 1860 --noCategories \
-f bytes -p "$SWIFTLET_PID" \
-j "$SWIFTLET_BENCH_DIR/footprint.json" \
> "$SWIFTLET_BENCH_DIR/footprint.txt" 2>&1 &
SWIFTLET_MEMORY_END=$((SECONDS + 1860))
(
while (( SECONDS < SWIFTLET_MEMORY_END )); do
date -u +%Y-%m-%dT%H:%M:%SZ
ps -o pid=,rss=,vsz= -p "$SWIFTLET_PID"
sysctl vm.swapusage
memory_pressure -Q | tail -n 1
vm_stat | sed -n '1,16p'
sleep 5
done
) > "$SWIFTLET_BENCH_DIR/memory-series.txt" 2>&1 &
sudo powermetrics -i 1000 -n 1860 \
-s tasks,cpu_power,gpu_power,thermal,sfi,disk \
--show-process-io --show-process-gpu --show-process-energy \
--show-plimits -o "$SWIFTLET_BENCH_DIR/powermetrics.txt"
監控不等於負載。先讓終端 B 記 60 秒 idle baseline,再開終端 C 連續送 30 分鐘 request;把 nonce 放在 user prompt 開頭,避免整段 prompt 被 conversation cache 重用。比較 JSONL 的首五分鐘與末五分鐘:
SWIFTLET_BENCH_DIR="$PWD/swiftlet-bench-run"
SWIFTLET_SOAK_END=$((SECONDS + 1800))
while (( SECONDS < SWIFTLET_SOAK_END )); do
SWIFTLET_PROMPT="$(date +%s%N)|用繁體中文列出 64 個編號冷知識。" \
python3 bench_sse.py
done >> "$SWIFTLET_BENCH_DIR/requests.jsonl"
powermetrics自己警告平均功率是估算,只適合同一台機器 A/B,不可拿 M4 Air 的估算瓦數直接比較 M5 MacBook;Energy Impact 也不是 Joules。把工具可見的 CPU/GPU 等 SoC rail estimates 積分、扣 60 秒 idle baseline,再除以 output tokens,只能叫「可見 SoC rails 的估算 J/token」;真正整機 J/token 還需要插座功率計或可靠的 battery-discharge 方法。本文 M4 的 help 沒有 smc sampler,因此能記 thermal pressure、SFI 與 power limits,不能宣稱量到晶片攝氏溫度。熱降頻要同時看到末段 tok/s 下滑與 thermal/plimits 變化,不能只憑機身變熱下結論。
第三組:SSD 裝置層與回答品質
iostat -Id -w 1只能近似整顆 block device 的總 transfer bytes;第一列是開機至今累積 totals,要丟棄,正式測試前也先跑 60 秒 idle baseline。背景下載、Spotlight、Time Machine 沒隔離,就把單一 process 的 device transfers 列為未量到;即使隔離,也不能把 block-device counters 稱為 NAND 內部 reads。fs_usage顯示 requested bytes 且 tracing 會擾動效能,適合另跑診斷,不適合和速度測試綁在一起。
correctness regression 應餵同一組 raw token IDs,用 .build/release/swiftlet generate "$SWIFTLET_MODEL_DIR" --gpu --ids '<逗號分隔 token IDs>' --max-new 32,優先對照 byte-identical MLX source checkpoint 的 greedy next-token sequence;不同 GGUF 量化的 llama.cpp 不能當 runtime oracle。也不要直接拿 Swiftlet Session --greedy比 logits,因它仍有 min-new、EOS gate 與特殊 token suppression。日用品質才走完整 chat stack,評繁中指令、算術、JSON parse、Unicode+emoji、長文重複率,以及 1K/8K/10K needle exact match。不同量化格式只能比較「模型+量化+template+sampler+runtime bundle」。想看模型能力與部署成本如何分開思考,可讀 DeepSeek 本地硬體與 API 實作。
35B 先別照 README 跑:correctness 修補尚未合併
截至 2026 年 8 月 9 日,PR #6仍是 open。current main 在 Qwen3.6-35B config 缺少 norm_topk_prob 時預設為 false;貢獻者以真實 checkpoint 報告 greedy 從第一個 token 分歧,長輸出逐步腐化,修正後 101 個 teacher-forcing IDs 對上 mlx-lm。80B config 明寫 true,不受這一個缺省問題影響。
所以本篇安裝只教 80B。想測 35B 或作者自報的 iPhone 35B,應等修補合併後 pin 新 SHA 重跑,或自行套用 PR 並把 patch SHA 寫進報告;不能把 current-main 35B 的語意品質拿去和別的引擎公平比較。
Swiftlet、MLX、llama.cpp、AirLLM 怎麼選?

這是固定版本的架構取捨,不是同機跑分:Swiftlet 6a9440c、MLX-LM 254d153、llama.cpp 0865990、AirLLM cc05a0f。
- 選 Swiftlet:你就是要研究「RAM 放不下的 Qwen hybrid MoE」能否靠 expert streaming 啟動,而且能接受高 logical read demand、慢 prefill 與早期專案風險。
- 選 MLX/mlx-lm:模型工作集放得進 unified memory,想要 Apple Silicon 原生 Python 生態、量化、微調與已具備的 batched prefill。
- 選 llama.cpp:想要廣泛 GGUF 模型、多平台與成熟工具鏈。mmap 初始 RSS 低不等於超大模型能零成本超出 RAM;工作集仍可能 paging。
- 把 AirLLM當架構對照:它以逐層 streaming 換低 GPU RAM;pinned Mac 路徑是 dense Llama MLX 實作,不能把 README 的低 VRAM 宣稱直接套到 Qwen3-Next。
最實際的選法很樸素:若你的目標是每天聊天或寫程式,先挑能完整常駐的較小模型,再用 MLX 或 llama.cpp;若你的目標是研究極限、隱私離線或驗證新型 I/O 架構,Swiftlet 才真正有趣。更多 Qwen 模型脈絡可接著看 Qwen3.8-Max 開放權重分析。
三級判定表:怎樣才算能啟動、能互動、適合日用?
為避免跑出一個 token 就宣布成功,本文先定義一套編輯門檻,並非業界標準:能啟動是無 OOM/kill,完成至少 32-token 有效回答;能互動是五次正式短問答的 warm user TTFT median ≤15 秒、wall decode estimate median ≥3 tok/s,且連續 10 分鐘沒有超過 15% 的末段掉速或 thermal/plimits 升級;適合日用則要求五次 median 短問答 TTFT ≤3 秒、8K TTFT ≤30 秒、decode ≥10 tok/s,30 分鐘末五分鐘速度至少保留首五分鐘 85%,20 題可程式判分品質集至少答對 18 題、9 組 needle 全數 exact match,且末 10 分鐘 swap used 不持續增長。
依目前公開證據,Swiftlet 80B 是「能啟動;互動的速度子條件有訊號,但完整門檻待驗;尚未證成日用」。公開 log 沒有外部 warm TTFT 與 10 分鐘 thermal,所以不能因 14.5 秒內建 TTFT、3.x tok/s 就宣告互動通過。把 80B 拉進 24GB Mac 仍是漂亮的系統工程;只是工程里程碑與讀者每天願意用的產品,評分尺不同。
Swiftlet 實測資料常見問題
1. 4.3GB RAM 是不是任何情況都不會超過?
不是。它是作者在 M5、2GB cache、短 prompt 下的自報峰值;expert cache 是 lazy-filled budget,KV 又會隨 full-attention context 增長。
2. 16GB Mac 能跑 80B 嗎?
架構上可能,本文沒有替你的 16GB 機型背書。公開成功案例是 24GB M4 Air;還要同時看可用磁碟、cache、context、其他程式與 memory pressure。
3. 3.5 tok/s 為什麼還不能證明可互動?
因為還缺外部 TTFT 與持續負載。3.5 tok/s 是初步速度訊號,但繁中體感還受 tokenizer、chunk 與等待首字影響;也不能用 SSE chunk 數冒充 token 數。
4. 長 prompt 為什麼特別慢?
因為 batched prefill 尚未完成。現行 prompt 近似逐 token 通過模型;decode 的 3–5 tok/s 不能直接推成「貼 10K 文件也只等幾秒」。
5. 大量讀 SSD 會不會很快把它燒壞?
現有資料不能這樣下結論。logical read requests、host transfers、NAND reads 與寫入耐久不是同一件事;先量裝置 I/O,再談長期影響。
6. 可以直接用 35B 代替,速度更快嗎?
先不要用 current main 做品質結論。PR #6 的 router normalization fix 仍未合併;等新 commit 或明確套 patch 後,從 greedy regression 重測。
7. Swiftlet server 能當 production OpenAI API 嗎?
不適合直接公開上線。current server 是 loopback Chat Completions 子集合、無 auth/TLS,而且請求序列化;適合本機整合與測試。
8. 新手最該先測哪一個數字?
先測 warm user TTFT:request → 第一個非空 content。它最接近模型已就緒後的對話等待;process start → GET /v1/models 首次回 200 與 cold start-to-visible 另列,接著再看 wall decode rate、peak footprint 與答案。
給新手的 7 個重點
- 把
4.3GB當特定設定結果,不是固定上限。 - 固定 code SHA、model revision、cache 與 prompt,否則結果不可重現。
- TTFT 用外部使用者視角計時,內建數字留作診斷。
- 短 prompt、長 prompt、decode 與 30 分鐘 soak 分開測。
- RAM 同時看 peak footprint、RSS、swap 與 memory pressure。
- logical expert reads 不等於物理 SSD/NAND reads。
- 先驗品質,再談速度;能吐字不代表 80B 能力被完整保留。
如果你想把這套測試方法延伸成自己的本機 AI 專案,可從 AlphaLab 課程練習完整部署與驗收,也可到 AI 專區追蹤後續推論引擎更新。
接著閱讀
左右滑動查看更多推薦
結語:Swiftlet 證明的是一條路,不是免費午餐
Swiftlet 最值得肯定的地方,是把「80B 一定要先住進 RAM」改成另一個工程問題:哪些 experts 必須現在搬、哪些可以快取、多少等待值得換多少記憶體。一筆外部 M4 Air field report 支持 80B 能在 24GB Apple Silicon 上載入並生成;它是重要現場訊號,但不是 pinned、可重複的完整 benchmark。
但回到本文的判斷式:外部紀錄支持它載得動;是否真的等得起、答得對、撐得久,仍要靠 pinned 版本的外部 TTFT、品質題、裝置 I/O 與 30 分鐘 soak 補完。若你的需求是每天用,先選能常駐的小模型;若你想研究本機推論的邊界,Swiftlet 正是一個很有意思、也很需要嚴格量測的實驗場。





