TIP
← 記事

開発

59GBの国産32B MoE「LLM-jp-4」を16GBのM2 Macで動かす——1バイトも増やさず2ビット崩壊を解消した「Project Pyrite」

2026/10/29

1. 16GB Mac における「32B MoE」というスイートスポット

ローカルLLMを Mac(Apple Silicon 16GB 統合メモリ)で動かす際、これまでは「8B〜9B の 4ビット量子化(約5.5〜6.5GB)が快適、13B〜14B が上限」というのが定石だった。

しかし、MoE(Mixture-of-Experts) アーキテクチャはこの前提を覆すポテンシャルを持っている。国立情報学研究所(NII)を中心とする LLM-jp が公開した llm-jp/llm-jp-4-32b-a3b-base は、総パラメータ数こそ 31.8B(約320億) だが、各トークンで実際に計算される活性パラメータは 128個のエキスパートのうち上位8個(約3.0B相当) に過ぎない。

Apple Silicon の推論速度は「1トークンあたりにメモリから GPU へ読み出す重みのバイト数」で決まる。もし 32B MoE を 16GB メモリに収めることができれば、「知識の引き出しは 32B クラスでありながら、推論速度は 3B クラス並みに速い」 という理想的なローカルLLM環境が手に入る。

問題はサイズだ。元の BF16 モデルは 59.06 GiB あり、4ビット量子化でも約 16.5 GiB となって 16GB Mac ではスワップが発生して使い物にならない。16GB Mac の安全上限(context_len=4096 時にピーク 11.25 GiB 以下)に収めるには、2ビット領域(約 9.81 GiB) まで圧縮する必要がある。

2. 単純な2ビット量子化で起きる「反復ループ崩壊」

ところが、mlx-lm でエキスパート層を一括して 2-bit (group_size=64) に量子化すると、サイズは 9.8105 GiB(10,533,950,464 bytes) に収まるものの、日本語生成で深刻な品質劣化が起きる。

たとえば、ことわざ「急がば回れ」の由来を尋ねると、標準2ビットモデルは以下のように同じ文を無限に繰り返すループ崩壊を起こしてしまう:

【標準 2-bit Baseline の出力】 …室町時代の連歌師・宗長が詠んだ和歌に由来する。宗長が京都から駿河へ帰る際、琵琶湖を渡る船に乗るか、遠回りをして陸路を行くか迷った末に詠んだ歌である。宗長が京都から駿河へ帰る際、琵琶湖を渡る船に乗るか…(※4回連続ループ)

そこで私たちが立ち上げた 「Project Pyrite」 では、ひとつの厳格なルールを課した。 「標準 2-bit モデルと 1バイトの狂いもない完全同一サイズ(10,533,950,464 bytes)のまま、どこまで元の BF16 モデルの知能を取り戻せるか?」 である。

3. 鍵は「後半層の down_proj」と「ルータの8ビット保護」

16GB の M2 Pro 上で 59GB の BF16 教師モデルを1層ずつストリーミング実行し、全 32層 × 3射影 × 128エキスパート = 12,288個の行列 について、実際の日本語トークンが通過した際の量子化誤差を計測した。すると、極めて明確な偏りが浮かび上がった。

  1. SwiGLU の外れ値を直撃で受ける後半層 down_proj の感度爆発 MoE の各エキスパートは gate_proj、up_proj、down_proj の3つの射影で構成される。gate_proj と up_proj の出力は SwiGLU 活性化関数で掛け合わされるため、ここでスパースな巨大外れ値(Activation Outlier)が発生する。その外れ値を直接入力として受け取り、残差ストリームへ書き戻す 後半層(第21〜31層)の down_proj は、他の層の 3〜8倍 も量子化誤差に敏感だったのである。
  2. わずか 9.8 MiB で守れる MoE ルータ(mlp.gate) 128個のエキスパートのうちどれを選ぶかを決めるルータ行列は、全32層合わせても全体の 0.1%未満 しかない。ここを 8-bit(合計 0.0098 GiB) で保護するだけで、エキスパート本体が2ビット化されていても BF16 原モデルとの Top-8 エキスパート選択一致率が平均 98.25%(最低層でも 96.73%)維持される ことが判明した。

4. 「1バイトも増やさない」等価交換レシピと結果

MLX のアフィン量子化では、グループサイズを 64(実効 2.50 bit)から 128(実効 2.25 bit)に広げると、スケール・バイアスのメタデータ容量が浮く。 そこで、比較的感度の低い gate_proj と up_proj を group_size=128 に変更して 629,145,600 bytes(0.5859 GiB) の予算を捻出し、その同じ 629,145,600 bytes を使って高感度な down_proj 等を 3-bit (group_size=64) へ昇格させた。

モデル構成総テンソル容量日本語 Held-out KL ($\downarrow$)日本語 Held-out PPL ($\downarrow$)Top-1 一致率 ($\uparrow$)
BF16 原モデル(教師)59.06 GiB0.00007.45100.0%
標準 2-bit Baseline (2bit_g64)9.8105 GiB (10,533,950,464 B)0.358310.8472.2%
Pyrite 6a(層・射影混合 / mlx-lm 標準互換)9.8105 GiB (10,533,950,464 B)0.3190 (-10.98%)10.3573.2%
Pyrite 6b(Expert単位ティアリング)9.8105 GiB (10,533,950,464 B)0.2791 (-22.11%)9.9075.2%

結果として、1バイトも同じサイズのまま KL ダイバージェンスは最大 -22.11% 減少し、先ほどの「急がば回れ」のプロンプトでも反復ループが完全に消え、宗長の和歌(「もののふの矢橋の船は速けれど急がば回れ瀬田の長橋」)と琵琶湖・比叡山おろしの背景まで正確に解説できるようになった。

さらに 16GB M2 Pro 上で Metal の Wired Limit を 11.0 GiB に設定して全重みをオンメモリ常駐させると、34〜49 tokens/sec という軽快な速度で 32B MoE の推論が可能となった。作成したモデルは masahiroid/llm-jp-4-32b-a3b-base-Pyrite-2bit-MLX として Hugging Face で公開している。