iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
AI Engineering

不是模型太慢,是你沒算過這筆帳:地端 LLM 工程實戰 30 天系列 第 4

Day 04 - 讀懂模型名字:35B-A3B 到底是 35B 還是 3B

  • 分享至 

  • xImage
  •  

昨天我們把壓測的姿勢擺正了。但壓測有個更早的前提——你得先決定下載哪一顆模型。於是你打開 Hugging Face 逛了一圈,書籤列變成這樣:

Qwen/Qwen3.6-35B-A3B-FP8
google/gemma-4-31B-it-qat-q4_0-gguf
stepfun-ai/Step-3.7-Flash
unsloth/DeepSeek-V4-Flash-0731-GGUF  →  DeepSeek-V4-Flash-0731-UD-Q2_K_XL.gguf

四個名字,四種長相。你真正想問的只有兩件事:我的機器跑不跑得動?該抓哪一個?

這些名字不是亂取的,是一套有文法的語言,Qwen 甚至把命名規則寫進了官方文件。拆成六個欄位之後,光看檔名就能推出八成答案,包括「35B-A3B 到底是 35B 還是 3B」。答案是都是,而這正是它好用的原因。

一個名字,六個欄位

幾乎所有開源模型的名字都能拆成六段,不一定全出現:
①家族+世代、②規模、③訓練階段與能力後綴、④日期戳、⑤量化與格式、⑥上傳者

https://ithelp.ithome.com.tw/upload/images/20260815/20183550n82JkC1RIf.png
圖 1:同一套文法,兩個真實 repo 各佔滿五欄——上排官方名字告訴你「這是什麼、被官方壓成什麼樣」,下排多了日期戳,②欄卻換成產品線標籤 Flash,一個數字都沒有。

拿到陌生型號的機械流程:
看②有沒有 A(dense 還是 MoE);看③有沒有 Base(有就別拿來聊天);
看⑤決定 runtime(GGUF 走 llama.cpp/Ollama、FP8/NVFP4 走 vLLM、MLX 給 Mac);
看⑥是官方還是社群。
能力標記(Coder/VL/Embedding)自己佔一格,位置各家沒有共識:

  • Qwen 插在①和②之間,③留給 Instruct(Qwen3-Coder-30B-A3B-Instruct);
  • Google 卻把它做成前綴黏在家族名上(medgemmaembeddinggemma)。這類例外就是「只推八成」少掉的那兩成。

A 前面管你裝不裝得下,A 後面管你跑多快

35B-A3B 是 Qwen 官方文件明訂的 MoE(Mixture of Experts)寫法:{總參數}B-A{每 token 啟用參數}BQwen3.6-35B-A3B 的 config.json 攤開來看,是 40 層、每層 256 個 expert、每個 token 只選 8 個(外加 1 個共用的)。

**A 前面的 35B 是「要載進哪一塊記憶體」的帳。**這塊記憶體是跑模型的那顆晶片能直接讀到的記憶體:N 卡是顯卡板上的 VRAM(我的 4070 Ti 一張 12GB),Mac 是 CPU/GPU 共用的統一記憶體(我的 M4 Max 標 128GB,但 GPU 拿不到全部,Day 07 算給你看)。而且整包 35B 都要進去——router 是每個 token 現場決定叫誰,你事先不知道,256 個一個都不能少放。塞不下就往系統 RAM 溢出、由 CPU 代算,那不是慢一點,是掉一個數量級,Day 01 那 45 秒的病根就在這裡。

**A 後面的 3B 是「每個 token 搬多少東西」的帳。**它跑的地方跟那 35B 是同一塊記憶體、同一顆晶片,沒有搬去別處。差別在於每生成一個 token,真正被讀出來參與運算的權重只有約 3B:256 選 8 的那批 expert,加上每層都要跑的 attention 與共用部分。而生成階段(decode)的瓶頸不是算力,是把權重從記憶體搬到運算單元的那條頻寬——一個 token 搬 3B 還是搬 35B,差十倍。所以每秒吐幾個字跟著 A 後面的數字走,不跟 35 走。

本系列那兩台主力機剛好各讀一半:24GB 的雙卡在乎 A 前面,裝不裝得下是生死線;128GB 的 Mac 在乎 A 後面,容量它有的是,但統一記憶體的頻寬有限,每個 token 只搬 3B 才跑得動。

llama.cpp 官方跑分檔在同一台 DGX Spark、同為 Q8_0 的條件下量過:Qwen3-30B-A3B(30.5B 總/3.3B 啟用)生成 61.06 t/s,Qwen2-7B dense 只有 29.43 t/s【官方:llama.cpp benches/dgx-spark/dgx-spark.md】。檔案大 4 倍,生成反而快 2 倍。

這筆紅利有邊界。人一多就會反轉:同一份跑分把併發開到 32,dense 的 7B 從 29 衝到 589 t/s,MoE 的 30B-A3B 只從 58 爬到 347。一個人問的時候 MoE 快一倍,32 個人同時問反而輸給 7B——因為每個人路由到不同 expert,一個批次合起來就把大半個 256 都叫醒了(Day 09、Day 10 算這筆)。它也只買到生成速度,買不到讀 prompt 的速度:prefill 卡在算力而非頻寬,同一份跑分裡 30B-A3B 只比 7B dense 快 1.33 倍,遠不到理論的 2.3 倍,貼整份程式碼進去問的場景優勢會縮水。至於記憶體,A 後面的數字一毛錢都不省。

②欄的數字本身還是行銷四捨五入:gemma-4-26B-A4B 官方卡自己寫總參 25.2B、啟用 3.8B,gpt-oss-120b 實際 116.8B、gpt-oss-20b 實際 21.5B,一個進位一個捨去。抓數量級可以看名字,算到 GB 就得看檔案。更早的 Mixtral-8x7B 還會直接誤導,它不等於 56B,attention 層共享,實際約 46.7B——A 記號就是被這種寫法逼出來的。

更要緊的是,**2026 年 A 記號正在退潮。**這一年的旗艦幾乎全是 MoE,名字裡卻連規模都不寫——Step-3.7-Flash 是 198B 總/約 11B 啟用、tencent/Hy3 是 295B/21B、Kimi-K3 是 2.8T/104B,全線還堅持 A 記號的只剩 Qwen,而且把它撐到了兆級(Qwen3.8-2.4T-A95B 的單位從 B 換成 T)。所以上面那條機械流程要改一個字:②欄沒有數字,不代表它小,只代表名字沒說。打開 config.jsonnum_expertsnum_experts_per_tok,30 秒的事。

也因此,型號一定要寫全。MiniMax-M3 是 428B 語言模型,MiniMax-H3 是 33B 影片生成模型,差一個字母差整個模態。

幾 B 要多少記憶體:一條乘法先抓數量級

權重佔用(GB) ≈ 總參數(B) × 每參數位元組
精度 每參數 (GB/B) 30B 級大概多少 什麼時候會遇到
BF16 / FP16 2.0 61GB HF 上沒標量化的原始權重
FP8(原生) 1.0 31GB 官方常直接發(如 Qwen3.6-35B-A3B-FP8
Q6_K ~0.84 26GB 記憶體有餘、想少虧一點
Q5_K_M ~0.73 22GB
Q4_K_M ~0.60 18GB 地端最常用,只背這一格就夠
IQ4_XS / MXFP4 ~0.57 17GB 差一點就塞不下時

0.6 這個係數我拉了 HF 的檔案清單校準過:8B 到 123B 之間,Q4_K_M 的實際係數落在 0.59 到 0.62(Llama-3.1-8B 0.613、gemma-4-12B 0.596、Qwen3.6-27B 0.605、Llama-3.3-70B 0.603、Mistral-Large-123B 0.597),誤差不超過 ±4%【推算:HF 檔案大小 ÷ 官方總參數,2026-08-15】。

為什麼不是理論值 0.5(4 bit 等於半個 byte)?K-quant 每 256 個權重要另存一組 scale,4-bit 的地板其實是 4.5 bpw;而 Q4_K_M 的那個 M 就是「有些層不壓那麼狠」,output.weight 與大約一半的 ffn_down 層會留 Q6_K。加起來整包實得約 4.8 到 5.0 bpw,換算就是 0.6。

買硬體前真正該背的是反過來這條:

Q4 跑得動的參數量(B) ≈ 你的記憶體(GB) × 1.25

1.25 就是 0.75 ÷ 0.6,先留四分之一給 KV cache 與框架,剩下的才拿去除。

你有的記憶體 Q4 大約跑得動 2026 年的對應現貨
12GB(單張 4070 Ti) 15B Gemma 4 12B,官方 QAT 檔 7.0GB
16GB 20B gpt-oss-20b,官方 MXFP4 GGUF 12.1GB
24GB(4090/我的雙卡合計) 30B gemma-4-26B-A4B 官方 QAT 14.4GB;Qwen3.6-35B-A3B 的 IQ4_XS 17.7GB 也塞得下
96GB(RTX PRO 6000) 120B gpt-oss-120b,官方 MXFP4 GGUF 63.4GB
128GB Mac(GPU 實得約 96GB) 120B DeepSeek-V4-Flash 得壓到 2-bit 才 96.8GB

這張表有五個地雷。

**這只是權重的帳,那個 ×1.25 也只對短對話有效。**KV cache 沒算進去:Qwen3-30B-A3B 在 8K context 只多吃 4%,32K 就吃掉 17%(1.25 剛好用完),開到原生 262K 時 KV 比權重本身還大【推算:每 token KV 96 KiB @FP16】。完整算式 Day 09 攤開。

**GB 不是 GiB。**HF 標的檔案大小是十進位 GB,顯卡標的 24GB 其實是 24 GiB = 25.8 GB,差 7.4%。最危險的方向是把「30B × 0.6 = 18」直接當成 18 GiB 拿去跟 nvidia-smi 比。

MoE 按 A 前面算。35B-A3B 在這張表裡是 35B,不是 3B。

**兩張 12GB 不等於一張 24GB。**要靠切分才合得起來用,切分本身有代價(Day 12);Mac 的 128GB 也不是全部給 GPU(Day 07)。

**別拿 HF 頁上的「Model size」當總參數。**那是儲存元素數,FP4 兩個 nibble 打包進一個 byte,統計就直接砍半:Step-3.7-Flash 的 BF16 版顯示 201B,同一顆的 NVFP4 版顯示 103.8B。反過來,投機解碼/MTP 模組會讓它比官方數字多幾個 B。要算記憶體,看檔案大小。

還有一個 2026 才變常見的漏抓:多模態模型的視覺塔是另一個檔。gemma-4-31B-it-qat-q4_0-gguf 的主檔 17.65GB 之外,還有一個 gemma-4-31B-it-mmproj.gguf 1.20GB,沒抓它,模型落地就只剩文字能力。

Base 不能聊天,但原因不是「檔案裡少了東西」

欄位③的訓練階段:-Base/-PT 是只做過 pre-training 的原胚;-Instruct/-IT/-it 做過 SFT,學會了「回答」這個行為;-Thinking 額外練過長推理(成本第三週專門算)。Google 用小寫 -it,Meta 和 Qwen 用 -Instruct,同義。

新手最常踩的雷是拿 Base 聊天,症狀很詭異:模型一直複述你的問題,或自顧自多生五個類似的問題。網路流傳的解釋是「Base 模型沒有 chat template」——這個解釋是錯的,而且錯得剛好會害你誤判。

實際打開 Qwen/Qwen2.5-7B(Base)的 tokenizer_config.json,裡面有完整的 ChatML 模板,<|im_start|> 這類 special token 也都在詞表裡。真正的原因在權重:它沒有在這個 template 上做過 SFT。Qwen 官方文件對 Base 的定義寫得很精準,「the pre-trained models that do not know the predefined chat template」——不是「沒有」,是「不認得」。Base 的詞表認得這些符號,但預訓練語料裡幾乎沒出現過,對權重來說就是雜訊。檔案裡的 template 是廠商附的便利貼,貼在誰身上,不代表誰看得懂。

https://ithelp.ithome.com.tw/upload/images/20260815/20183550JDrEqyHMpQ.png
圖 2:判斷順序是後綴 → model card → chat_template;2026 年最後一招已經降級成弱訊號,兩個位置都要查,而且查不到也不能定罪。

而且到了 2026,連「缺席」都不能定罪了。新版 transformers 把 template 從 tokenizer_config.json 移到獨立的 chat_template.jinja,各家搬家進度不一,更麻煩的是有些廠商乾脆不發 Jinja。我實查了五顆【官方:HF repo 檔案清單,2026-08-15】:

repo tokenizer_config.json chat_template.jinja 實際是什麼
Qwen/Qwen3.6-35B-A3B Instruct(兩處都放)
google/gemma-4-31B-it Instruct,只放新位置
google/gemma-4-31B Base
Qwen/Qwen2.5-7B Base,卻附了 template
deepseek-ai/DeepSeek-V4-Flash-0731 Instruct,兩處都沒有

第二列是新坑:照老方法只 grep tokenizer_config.json,你會把 Gemma 4 的 Instruct 判成 Base。最後一列更狠,DeepSeek 官方卡逐字寫「This release does not include a Jinja-format chat template」,改附一個 Python 編碼腳本,Kimi K3 也一樣。所以這條規則現在只剩弱訊號的份量:兩處都查,兩處都缺席也只能說「可能是 Base」;存在則什麼都推不出來。真要定案,回去讀 model card 第一段。

還有一個更陰的,「沒有後綴」在兩家的意思是相反的:Qwen3 起主線無 type 後綴代表 hybrid thinking 的 Instruct(如 Qwen3.6-35B-A3B),Gemma 4 反過來,裸名 google/gemma-4-31B 是 Base,加了 -it 才是 Instruct。同一個「什麼都沒寫」,一家能聊天、一家不能。

Distill:掛老師的名,流學生的血

DeepSeek-R1-Distill-Qwen-32B,面試和採購都高頻答錯。文法是 {Teacher}-Distill-{Student}-{Size}:DeepSeek-R1 是老師(出訓練資料),Qwen 是學生(出權重),做法是拿 R1 生成的長推理資料,對 Qwen2.5-32B-Base 做 SFT。

工程後果一句話:tokenizer、架構、context 上限,全部跟學生走,查 Qwen2.5-32B,不是查 DeepSeek-R1。但最容易漏的一項偏偏是例外——授權不跟學生走,只看各 repo 自己怎麼標:

型號 repo 自標授權【官方:HF license tag】 底模原始授權
DeepSeek-R1-Distill-Qwen-32B MIT Qwen2.5:Apache-2.0
DeepSeek-R1-Distill-Llama-70B MIT Llama 3.3:Llama Community License

兩顆都自標 MIT,法律效果卻天差地遠。Apache-2.0 夠寬鬆,DeepSeek 可以合法重授權成 MIT;Llama Community License 對衍生模型具傳染性,700M MAU 條款照樣綁在 Llama-distill 身上,MIT 標籤蓋不掉。授權要逐 repo 查到條款,連同一家、同一代都不能推:Qwen3.8-27B 是 Apache-2.0,同世代旗艦 Qwen3.8-2.4T-A95B 卻是自訂的 qwen3.8-max 授權。

另外,{Teacher}-Distill-{Student} 只是 DeepSeek 的慣例,不是業界標準。社群現在流行反過來寫,Qwen3.8-27B-Opus-Distill 這類是學生在前、老師在後,照舊規則讀會把師生對調。唯一可靠的判定是查 repo 的 base_model 欄位——它也是唯一能拆穿 Baichuan-M3-235B 其實是 Qwen 底的地方。

日期戳:前兩位大於 12,一定是年月

四位數的日期戳至少有三種讀法。Qwen 和 Mistral 用 YYMM-2507 是 2025 年 7 月,官方文件明訂);DeepSeek 用 MMDDDeepSeek-V4-Pro-0813,repo 建立日就是 2026 年 8 月 13 日);AllenAI 的 OLMo 2 用 MMYYOLMo-2-1124-13B 是 2024 年 11 月、OLMo-2-0325-32B 是 2025 年 3 月,repo 建立日都對得上)。

判別式因此只能縮小範圍、不能定案:前兩位大於 12 一定是年月;其餘一律拿 repo 的建立日對一次。0325 照「前兩位 ≤ 12、後兩位 > 12 就是月日」會被讀成 3 月 25 日,但它其實是 2025 年 3 月。

日期戳的語意是同一代的版本快照,但這層語意各家自己說了算。DeepSeek 的 V4 拿它來標「正式版」:無戳的 DeepSeek-V4-Flash 卡上寫 preview,-0731 卡上寫 official release, superseding the preview version。同一個四位數,在 Qwen 是快照,在 DeepSeek 是畢業證書。

工程規則不變:生產環境一定 pin 帶日期戳的完整名字,這是 LLM 版的「不要用 :latest tag」。麻煩的是 2026 年很多家已經沒戳可 pin——Qwen 主線改用小數點世代(3.5 → 3.6 → 跳過 3.7 → 3.8),GLM、Kimi、MiniMax、StepFun 全部改小數點,-Next 這種世代標籤(Qwen3-Coder-Next)更不承諾任何快照語意。沒戳可 pin 的時候,只能 pin commit SHA。

把開場四個名字拆給你看

檔名 ①②家族/規模 ③階段 ④日期戳 ⑤量化 一句結論
Qwen3.6-35B-A3B-FP8 Qwen 3.6 代,35B 總/3B 啟用 無後綴 = hybrid thinking Instruct 官方 FP8 37.5GB;Apache-2.0,vLLM 直上,雙卡免談
gemma-4-31B-it-qat-q4_0-gguf Gemma 4 代,31B dense(實為 30.7B) it = Instruct 官方 QAT + GGUF 4-bit 主檔 17.65GB + mmproj 1.20GB,24GB 卡剛好;Gemma 4 已改 Apache-2.0,Gemma 3 還是 Gemma Terms
Step-3.7-Flash StepFun 3.7 代,198B 總/11B 啟用 無(BF16) 402GB;名字完全看不出是 MoE,官方標的地端門檻是 128GB 統一記憶體
unsloth/…-UD-Q2_K_XL.gguf DeepSeek V4 代,Flash 檔 0731(MMDD) UD 動態 2-bit 壓到 2-bit 還要 96.8GB,這格是拿來提醒你「開源不等於跑得動」

選型單位是「repo + 檔案」,不是「模型」:第 2 列的 repo 叫 gemma-4-31B-it-qat-q4_0-gguf,裡面的檔案卻叫 gemma-4-31B_q4_0-it.gguf,順序都對調了,而同一批的 26B-A4B 檔名還把 A4B 整個吃掉,落地後認不出是 MoE。量化欄只講格式,不講品質,誰壓得好,檔名不會說。授權在六個欄位裡根本沒有位置,永遠得另外查。

今天的實驗需要什麼

不需要 GPU,一個能跑 curl 的終端機就行,只抓 config、不下載權重:

# 這顆是不是 MoE?每 token 從幾個 expert 裡選幾個?
curl -s https://huggingface.co/Qwen/Qwen3.6-35B-A3B/raw/main/config.json \
  | grep -E "num_experts|experts_per_tok"

# chat_template 的兩個位置都要查(只查第一個會把 Gemma 4 的 Instruct 誤判成 Base)
curl -s https://huggingface.co/google/gemma-4-31B-it/raw/main/tokenizer_config.json | grep -c chat_template
curl -s -o /dev/null -w "%{http_code}\n" \
  https://huggingface.co/google/gemma-4-31B-it/raw/main/chat_template.jinja

# 對照組:2024 年的 Base 模型反而在舊位置附了 template
curl -s https://huggingface.co/Qwen/Qwen2.5-7B/raw/main/tokenizer_config.json | grep -o chat_template

小結

  • 模型名字是六欄文法:家族世代/規模/訓練階段/日期戳/量化/上傳者。2026 年②④兩欄鬆動得最快,推不出來就開 config.json
  • 35B-A3B:A 前面是要載進 VRAM 或統一記憶體的總量,一個 expert 都不能少;A 後面是每個 token 實際搬動的權重量,decode 卡在頻寬,所以生成速度跟著它走,但併發一高就會被追平。
  • 記憶體換算一條乘法:Q4_K_M ≈ 總參數 × 0.6 GB;反過來,你的記憶體 × 1.25 ≈ 跑得動的 B 數。KV cache 另計(Day 09)。
  • Base 不能聊天,是權重沒在 template 上做過 SFT。chat_template 現在只是弱訊號,兩個位置都要查,查不到也不能定罪。
  • Distill 的 tokenizer/架構/context 跟學生走,授權不跟,逐 repo 查。
  • 日期戳前兩位 > 12 必是年月;沒戳可 pin 的時候,pin commit SHA。

今天刻意跳過欄位⑤裡長得最像規格的 Q4_K_M。它其實只是個檔名,同名不同上傳者,實測品質可以差 3 倍。明天 Day 05「Q4_K_M 是檔名不是規格」,把量化這一欄單獨攤開,數據和出處一起上桌。

咱們明天見。


上一篇
Day 03 - 壓測不是 for 迴圈:vllm bench serve 的正確用法
下一篇
Day 05 - Q4_K_M 是規格,不是品質保證:同名量化檔,KL 散度可以差近 3 倍
系列文
不是模型太慢,是你沒算過這筆帳:地端 LLM 工程實戰 30 天7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言