夜明けの山々を映す静かな湖面

128GBのMacでローカルLLMは使えるか

先日公開されたQwen3.8を、手元のMacBook Proで試してみました。ローカルLLM、つまり自分のパソコンの中だけで動くAIです。

私はこれまで、開発の主力をクラウドのAIに置いてきました。ローカルで動かすモデルは何度か試したものの、そのたびに「賢いが遅すぎる」か「速いが物足りない」のどちらかで、サブスクリプションで使っている環境を置き換えるには届きませんでした。Qwen3.8で状況が変わっているのかを知りたくて、実際にモデルを載せ、コーディングエージェントを接続して、サンプルとしてテトリスを書かせるところまでやってみました。

結果から書くと、動きました。しかもテトリスは3分43秒で完成し、ブラウザで問題なく遊べました。ただし「だから今日から全部ローカルでいい」という話にはなりません。何ができて何ができないのかを、実測値と一緒に整理します。

手元のマシン

まず環境です。

項目
機種 MacBook Pro(Apple M5 Max)
CPU / GPU 18コア / 40コア
ユニファイドメモリ 128GB
OS macOS 26.6.2

このうち、この用途で決定的に効くのはユニファイドメモリの128GBです。CPUの速さでもGPUのコア数でもありません。理由は後で出てきます。

大きいモデルを選べばよい、ではなかった

Qwen3.8には複数のモデルがあります。最初に候補を並べたとき、私は素直に「一番強いものを載せればいい」と考えていました。実際にはそうなりませんでした。

モデル 規模 128GBで動くか
Qwen3.8-Max 2.4兆パラメータ(アクティブ950億) 動かない。クラウド前提の規模
Qwen3.8-Flash-Next 1250億(アクティブ60億) これを選んだ
Qwen3.8-27B 270億(dense) 載るが、選ばなかった

注目したいのは3つ目です。27Bは一番小さく、メモリにも余裕を持って載ります。それでも選びませんでした。

参考にしたのは、同じ128GBのMacBook Proで実測した先行記事です。そこでは同一の課題に対して、Flash-Nextが58分で完了したのに対し、27Bは6時間半かけて完了しませんでした。量子化なしの状態で測り直しても、1秒あたりの生成トークン数はFlash-Nextの3分の1だったと報告されています。

理由は構造の違いです。27Bは「dense」といって、1トークン生成するたびに270億のパラメータすべてを読み出します。一方のFlash-NextはMoE(Mixture of Experts)で、内部を役割の違う多数の小さなネットワークに分け、入力ごとに必要なものだけを動かします。総量は1250億ありますが、1トークンあたり実際に計算に参加するのは60億だけです。

つまりこうです。メモリに載るかどうかを決めるのは総パラメータ数、速度を決めるのはアクティブパラメータ数。この2つが分離しているから、128GBという容量が急に効いてきます。大きな知識を抱えたまま、少ない計算で回せるモデルがちょうどこのサイズに収まるようになった、というのが今回の変化の正体だと考えています。

つまずいた2点と、先に知っておきたい1点

とはいえ、素直には進みませんでした。実際に詰まった2点と、これから同じことをする人が先に知っておくと楽な1点を書いておきます。

1. 目当ての形式が容量に収まらない

Flash-Nextには、Apple Siliconに最適化されたMLX形式と、汎用のGGUF形式があります。速度の面ではMLXが有利と聞いていたので最初にそちらを見にいったのですが、私が使いたかった版に限ると、配布されている最小のものが174GBでした。128GBには載りません。

結局GGUF形式に切り替え、97GB(90.8GiB)のものを選びました。Metalに割り当てられるメモリの上限は、先行記事の実測によれば約100GiB。ここに9GiBほどの余裕を残せる計算になります。

2. 配布元が規約同意を求めていた

選んだファイルの本家リポジトリは「gated」という設定で、匿名でダウンロードしようとすると401が返ります。規約に同意してアクセストークンを発行すれば通るのですが、トークンの受け渡しが要ります。今回は同じモデルを別の人が再量子化した、制限のないリポジトリに切り替えました。

3.(補足)97GBのダウンロードには時間がかかる

モデルのファイルは97GBあります。回線にもよりますが、数十分から数時間かかる規模です。

ここで気をつけたいのが、ダウンロード中にパソコンがスリープに入らないようにしておくことです。スリープに入ると転送も止まります。macOSなら「システム設定 → ロック画面」でスリープしない設定にするか、caffeinate コマンドを使って、取り切るまで起きたままにしておくのが確実です。

あわせて、途中から再開できるダウンロード方法を選んでおくと安心です。この規模のファイルを一度で取り切る前提で組まないほうが、気持ちが楽になります。

実測してみた

導入後、実際に測りました。数字を出す前に1つ補足があります。「このモデルは何トークン毎秒」という言い方は、文脈の長さを添えないと意味を持ちません。プロンプトを読み込む処理(プレフィル)と、1トークンずつ生成する処理(デコード)は性質が違い、どちらも文脈が長くなるほど落ちるからです。

そこで、実際の記事9,177字を読ませて要約させるという、日常の使い方に近い条件で測りました。

指標 今回の実測(M5 Max) 先行記事の実測(M4 Max・約6.5kトークン時点)
プレフィル 954.7 トークン/秒(4,860トークンを5.09秒) 417 トークン/秒
デコード 47.4 トークン/秒 25.4 トークン/秒
モデルのロード 3.2秒 (別方式で3分超)

モデルの読み込みに3.2秒、記事4,860トークンの読み込みに5.09秒。要約が書き出され始めるまで、合計8.3秒でした。

正直に言うと、この数字は予想より良いものでした。今回選んだGGUF形式は、生成を高速化する仕組み(MTP)を落とすため遅くなるはずだと考えていたからです。ところが実際には、その仕組みを使う方式の報告値とほぼ同じ水準が出ました。世代の新しいチップで前提が変わった可能性がありますが、手元で測るまで分からなかったというのが正しい理解だと思います。

要約の中身も確認しました。記事の3つの論点を取り違えずに拾っていて、私が自分で書くならこう書く、という水準でした。

コンテキストを広げる

既定のままだと、一度に扱える文脈は32,768トークンでした。モデル自身は262,144トークンまで対応しています。

コーディングに使うなら、ここは広げておく価値があります。エージェントはリポジトリのファイルを次々に読み込むので、文脈はすぐ埋まります。埋まると古いやり取りを要約に畳む処理が走り、それ自体が大きな計算になって、さらに遅くなるからです。

131,072トークンに設定し直したところ、問題なく起動しました。ただしメモリの使用量は99.5GiBまで上がり、上限の約100GiBにほぼ張り付いています。この状態のマシンは、実質そのモデル専用になります。

エージェントに接続する

モデルが動いても、それだけではコードは書けません。ファイルを読み、探し、書き換え、コマンドを走らせる「手足」が要ります。この役割を担うのがコーディングエージェントです。

今回はOpenCodeという端末向けのエージェントを使い、ローカルで動いているモデルのAPIに接続しました。設定はJSONを1つ置くだけで、5分もかかりません。

テトリスを書かせた

準備が終わったので、サンプルとして課題を出しました。要件はこうです。

  • 成果物はindex.htmlの1ファイルのみ。外部ライブラリは使わない
  • 10×20のフィールド、7種類のテトリミノ、それぞれ色を変える
  • 移動・回転・ソフトドロップ・ハードドロップ・一時停止
  • ライン消去とスコア、次のミノのプレビュー、ゲームオーバー判定
  • スコアに応じて落下速度を上げる

結果は223秒、461行のHTMLでした。

出来上がったものをブラウザで開き、実際に操作して確認しました。ハードドロップを3回入れるとスコアが0から38に増え、ミノが正しい色で積み上がり、次のミノの予告も機能していました。要件はすべて満たしていて、外部への参照はゼロでした。

面白かったのは、途中の振る舞いです。モデルは自分が書いたHTMLの壊れた箇所を見つけて、自分で直していました。属性の引用符が閉じていない1行を、後から差分で修正しています。頼んでいない自己点検です。

さらに、書いたJavaScriptの構文を検証しようとして、一時ディレクトリにファイルを書き出そうとしました。これは権限の設定が自動的に拒否しました。つまりモデルは検証しようとしたのに、環境の側が止めたわけです。能力の問題ではありませんでした。

何が変わって、何は変わらないか

ここまでを踏まえて、私なりの整理です。

変わったのは、待てる時間のうちに仕事が一周するようになったことだと思います。賢さが急に上がったというより、実用的な速度でメモリに載るモデルが、ちょうど128GBという範囲に現れた。だから読んで、書いて、確かめて、直すという流れが止まらずに回りました。先ほどの27Bとの比較が示していたのも、まさにここでした。

一方で、変わっていないこともあります。

テトリスは、ローカルLLMの実力を測る題材としては甘いです。 よく知られた題材で、学習データに似たコードが大量に含まれているはずだからです。今回わかったのは「エージェントとして手順を最後まで回せた」ことであって、「難しい仕様を正しく解釈できる」ことではありません。私が測ったのはn=1の観察です。

マシンは実質専有されます。 99.5GiBを占有している間、重い作業を並行させるのは現実的ではありません。ただしロードが3.2秒と速いので、使うときだけ載せる運用で困りませんでした。

画像は扱えません。 今回選んだ形式には画像を扱う部品が含まれておらず、テキスト専用です。

そして何より、全部をローカルに寄せる必要はないと考えています。以前の記事でも触れましたが、有効なのは大きなモデルを1台置くことではなく、仕事を分けて役割ごとに担当を決めることでした。分類や定型処理、失敗しても取り返しのつく作業はローカルへ。複雑な仕様の解釈や、広い範囲に影響する変更、難しいレビューはクラウドへ。この振り分けは、ローカルが速くなった今でも変わりません。

おわりに

「手元のパソコンでAIにコードを書かせる」は、少なくとも私の環境では実用の域に入りました。ただしそれは、適切なモデルを選び、文脈の設定を直し、エージェントを繋いだうえでの話です。どれか1つ欠けても、たぶん「遅くて使えない」という感想で終わっていました。

つまり、効いたのはモデルの性能そのものより、外側の設計でした。この構図は、AIをどこで使うにせよ同じなのだと思います。

次は、Qwen3.8でどこまでのゲームが作れるのかを検証してみたいと思います。今回のテトリスは、よく知られた題材で一周できたというだけの話でした。もう少し仕様の込み入ったものを渡したときに、どこで手が止まるのか。そこが分かれば、任せられる範囲の輪郭がはっきりするはずです。

なお、このシリーズの次の記事では、同じMacで動画生成モデルを動かせるかを先に確かめています。ゲーム作りの検証は、そのあとに回すつもりです。