超絶久々のブログ更新です。
前回の記事が2020年なので、なんと6年ぶり😅 久々に書きたくなるくらい、面白い検証ができたので、まとめておきます。
Mac Studioを買いました
Mac Studio(M5 Ultra/ユニファイドメモリ256GB)を買いました😁
買った目的はだいたい以下の5つです。
- ローカルLLMを試したい
- 256GBあれば、200GB級の量子化モデルでもメモリに載る
- クラウドのAPIを使わずにどこまで実用になるのか、自分の手で確かめたかった
- 開発機のリプレイス
- メインの開発機がM1 MaxのMacBook Proで、そろそろ古くなってきた
- Dockerのコンテナを複数立ち上げてRSpecを回す、みたいな日常の作業でも余裕が欲しくなっていた
- 外からClaude Codeを操作したい
- 家に据え置きのマシンでClaude Codeを常時動かしておき、外出先からリモートで指示を出して進めたい
- 持ち歩くノートではなく、家で動き続けるマシンが欲しかった
- Claudeのトークンを節約したい
- 普段は複数のクライアントと仕事していて、Claude Team(プレミアム)のアカウントを払い出してもらっているところはそれを、そうでないところは個人契約のClaude Ultraを使っている
- ただTeamのアカウントは、5時間ごとのセッションの利用上限にすぐ達してしまうので、トークンのやりくりが欠かせない
- 実は今の開発スタイルも、FableをPM役、Opusを実装役として棲み分けて、間の受け渡しを人(私)が中継しているのは、トークン量の節約対策だったりする
- ローカルLLMに任せられる作業があれば、その分Claudeのトークンを節約できるのでは?という期待があった
- オーケストレーター構成を試したい(そこにローカルLLMを加えたい)
- 普段の開発では、実はまだオーケストレーター構成をしっかり組んでいない
- 前述の人による中継が地味に面倒なので、私はFableとだけ話せば済むオーケストレーター構成を試したい
- せっかくなら、その下で動く実装ワーカーにローカルLLMを活用できないか?
※この記事に出てくるClaudeのモデル(Fable/Opus/Sonnet)は、どれもClaude Codeで使える最新の5系(Fable 5.1、Opus 5.5、Sonnet 5.5)です。以降はバージョンを省いて書きます。
この記事は、主に4つめと5つめ、つまり「ローカルLLMを開発ワーカーとして使えるのか?」を検証した記録です。
11月1日から3日にかけて、5つのフェーズに分けて段階的に測りました。 ちなみに、検証の方針の相談にはChatGPTも活用しつつ、計画から先(ハーネスの実装・実行・集計)は完全にすべてClaude Codeに任せています。
先に結論
- 今は「Claudeだけ」で回すのが一番速く、一番安い
- Opusを指揮役に、Sonnetのワーカーを並列で回す構成
- ローカルLLMの候補はGLM-5.3-Flash一択
- 完走すれば、Sonnetとほぼ同じ水準のPRを出してくる
- ただし1件あたりの時間はSonnetの4〜15倍かかり、大きめの課題では2回に1回、途中で手詰まりになった
- Qwen3-Coder-Nextは、速いけど開発ワーカーとしては厳しい
- 生成は110 tok/sとGLMより速く、メモリも48GBで済む
- ただ、普段のチケットのような自然言語の課題文だと品質が崩れ(一定品質は33%)、試行ごとの結果も揺れる
- Claudeが仕様を整理してあげれば持ち直すけど、その手間(費用)をかけるならClaudeが自分で解いたほうが安くて速い
- ただしClaude Codeのハーネスとの相性も効いていたので、Qwen向けのエージェントで試し直す余地はある
- 「Claudeが仕様を整理して、ローカルLLMが実装して、Claudeがレビューする」というハイブリッド構成は、費用でも速度でもClaude単独に負けた
- Claudeが指揮やレビューに使うトークンが、Claudeが自分で解くトークンを上回ってしまう
- なのでGLMは、急がない小〜中の課題を夜間に流す補助レーンという位置付けに落ち着きました
- 手詰まりになったらSonnetに回す前提
期待していた構成は、見事に割に合わないという結果に😅
以下、どう測って、なぜこの結論になったのかを書いていきます。
環境
Mac Studioのスペック
| 項目 | 内容 |
|---|---|
| モデル | Mac Studio(Apple M5 Ultra) |
| CPU | 30コア(Superコア10+Performanceコア20) |
| GPU | 64コア(Metal 4) |
| ユニファイドメモリ | 256GB |
| ストレージ | SSD 2TB |
| OS | macOS 27.2 |
ユニファイドメモリなので、CPUとGPUで同じ256GBを使います。 GPUに常駐(wired)させられるメモリの上限は、既定のままで約240GiBありました。200GB級のモデルでも、設定をいじらずに載るということです。
検証の条件
| 項目 | 内容 |
|---|---|
| ローカルLLM | Qwen3-Coder-Next(4bit/8bit)、GLM-5.3-Flash(4bit相当の量子化+MTP) |
| 実行系 | Ollama 0.40、mlx-lm/mlx-vlm、oMLX |
| 比較対象 | Claude Opus、Claude Sonnet(Claude Code) |
| 課題 | 業務で開発しているRailsアプリの、マージ済みの実際のPR |
ローカルLLMをClaude Codeから使うときは、ANTHROPIC_BASE_URLをローカルの推論サーバ(Anthropic互換の/v1/messages)に向けて、モデルだけ差し替えました。
こうするとハーネス(Claude Code自体、ツール、hooks、権限の設定)は同じまま、モデルだけを比べられます。
ただ、Claude向けに作られたハーネスにローカルLLMを載せる形なので、この方式自体がボトルネックになっていないかは気になるところ。 これは後述の「ハーネスがボトルネックになっていないか?」で、ログを見直して検証しています。
Phase 0:まずは単体の速度と品質
最初は、モデル単体の速度と、小さなコーディング課題・技術QAでの品質を測りました。
| モデル(量子化) | 実行系 | 生成(tok/s) | prefill(tok/s) | メモリ | 小課題 |
|---|---|---|---|---|---|
| Qwen3-Coder-Next(q4_K_M) | Ollama | 101.6 | 3,432 | 55GB | 3/5 |
| Qwen3-Coder-Next(q8_0) | Ollama | 91.6 | 3,571 | 89GB | 3/5 |
| Qwen3-Coder-Next(4bit) | mlx-lm | 110.4 | 4,832 | 48GB | 4/5 |
| GLM-5.3-Flash(4bit) | mlx-vlm | 3.8 | 13〜29 | 208GB | 計測不能 |
| GLM-5.3-Flash(oQ4e+MTP) | oMLX | 69〜73 | 2,471 | 182GB | 5/5 |
※prefillは約3万トークンの入力で計測(GLMのoMLXだけ10万トークン、mlx-vlmは1,000トークン程度で落ちたので参考値)。小課題は小さなコーディング課題5問の正解数です。
分かったことは以下です。
- 同じ4bitなら、MLXのほうがGGUF(Ollama)より速い
- 生成で9%、prefillで41%速く、メモリも少なくて済んだ
- Qwenは8bitにしても品質が上がらなかった
- 間違え方(明示した境界条件の読み落としや知識の誤り)が4bitと同じ
- 弱点は量子化の誤差じゃなくて、モデル自体にあるっぽい
- Qwenを使うならMLXの4bitが一番割が良い
- GLM-5.3-Flashは、実行系次第で20倍近く速度が変わった
- mlx-vlmだと3.8 tok/sしか出ず、1,000トークン程度の入力でGPUのメモリが足りなくなって落ちる
- M5 Ultra向けの公開レシピに従ってoMLXをソースからビルドし、MTP(複数トークンの先読み)の層を載せた量子化モデルを使うと、70 tok/s前後まで出た
- 品質も5問中5問正解
ということで、ここから先はGLMが本命になりました。
ハマったところ
動く壁紙のデコーダが104GBのメモリを抱えていた
GLMをロードしている途中で、プロセスがOSに強制終了されました。
調べると、macOSの動画デコード用のサービス(VTDecoderXPCService)が、ログインから10時間ほどで104GBまで膨らんでいました。
実体はGPUドライバが確保したまま使っていないメモリで、プロセスを終了させても、メモリを逼迫させても戻らず、結局再起動するしかありませんでした。
当初は、新しいMacへの移行直後で裏で走っていた写真や動画の解析を疑っていました。 ところが記事を書きながら改めて調べ直すと、犯人は動く壁紙(Aerial)っぽい。
- 再起動から約1日半で、同じサービスがまた7.2GBまで膨らんでいた
- 直近1時間でこのサービスにデコードを頼んでいたのは、動く壁紙の拡張(
WallpaperAerialsExtension)だけ。約1分ごとに、4KのHEVC動画のデコードを始め直していた - 増え方にはムラがあるけど、測った1分間では約200MB増えていた(104GBになったときは、10時間の平均で1分あたり約180MB)
- 写真や動画の解析からのデコードは、この1時間で0件
試しに壁紙を風景の静止画(Sonoma)に変えてみたところ、7.2GBまで膨らんでいたメモリがその場で22MBまで戻り、それ以降は増えなくなりました。 1分ごとに走っていたデコードもぴたりと止まったので、少なくとも今回の膨張は動く壁紙が犯人で確定。最初の104GBも同じ原因だろうと見ています。
しかもこの動く壁紙、私が自分で選んだものではなく、macOSの初期設定のままなんですよね。 デフォルトの壁紙を(しかも誰も見ていない画面の裏で)流しておくだけで、10時間で100GB超のメモリを持っていかれることがあるって…Appleさん、それはちょっとひどくないですか?😇 256GB積んだMacだから気づけたけど、16GBのMacだったら「なんか最近重いな」で済まされてそう。
Apple Communityにも、壁紙の動画拡張がRAMとCPUを大量に使う、VTDecoderXPCServiceがメモリを解放しないといった報告がいくつかあります(Appleが不具合として認めたものは見つけられませんでした)。
256GBあっても、条件次第で100GB単位で持っていかれるので馬鹿になりません。
大きなモデルを載せる前には、footprintやtop -o memでこの手の常駐プロセスを確認するようにしました。
GPUのwired上限は触らない
GLMが落ちたとき、GPUに常駐できるメモリの上限(iogpu.wired_limit_mb)を引き上げる手も検討しました。
ただ、OSに残るメモリが10GB程度になって固まるおそれがあったのでやめました。
結局、実行系をoMLXに変えたら、既定の上限(約240GiB)のままで動きました。
ダウンロードが遅いと思ったらWi-Fiが2.4GHzだった
モデルは1つで数十〜200GBあります。 最初は合計で12MB/sしか出なくて、調べたら2.4GHzのSSIDにつながっていました。5GHzにしたら約4倍の44MB/sになり、他の通信と取り合わなければ90MB/sを超えました(ありがち)。
Hugging FaceからのダウンロードはHF_XET_HIGH_PERFORMANCE=1を付けるのが一番速く、Ollamaと同時に落とすと帯域を取り合うだけなので、1本ずつ流すのが正解でした。
Phase 1:実案件のPRをClaude Codeのハーネスで解かせる
単体のベンチだけだと、実務で使えるかは分かりません。
そこで、業務で開発しているRailsアプリの、マージ済みのPRを課題にしました。
- PRの直前の状態のコードを渡して、PRで入った変更を自然言語の課題文にして解かせる
- 採点には、そのPRで追加されたspecを隠しテストとして使う(モデルからは見えない)
- ワーカーはClaude Code(
claude -p)で、モデルだけを差し替える
まず7件のPRで試したところ、隠しテストの合格はOpusが7/7(全体5.4分)、GLMが7/7(33.7分)、Qwen(MLX 4bit)が6/7(5.8分)でした。
思ったより差がつかず、課題が小さすぎることが分かりました。
Phase 2〜3:オーケストレーター構成にローカルLLMを混ぜると得なのか?
ここが本題です。 期待していたのは以下のような構成でした。
- Claude(Opus)が課題を読んで、仕様を整理して、受け入れテストを書く
- ローカルLLMが実装する(API費用0)
- Claudeがレビューして、問題があれば差し戻す
課題を18件に増やしました。内訳はバグ修正、複数ファイルにまたがる変更、性能改善、マイグレーションです。 課題文は、普段のチケットに近い自然言語で書いています。
品質の基準は「隠しテストに合格し、既存のテストを壊さず、rubocopの違反が0件」です。
| 構成 | 一定品質 | 処理量(件/時) | Claude費用(1件) |
|---|---|---|---|
| Opus単独 | 16/18 | 110 | $0.93 |
| Sonnet単独 | 16/18 | 199 | $0.36 |
| GLM単独 | 16/18 | 13 | $0 |
| Qwen単独 | 12/36 | 4.8 | $0 |
| 分業:Opus+Qwen | 20/36 | 4.8 | $3.79 |
| 分業:Sonnet+Qwen | 10/18 | 4.5 | $2.02 |
| 分業:Opus+GLM | 15/18 | 6.0 | $3.59 |
※「分業」は、Claudeが仕様整理・受け入れテスト・レビューを担当し、ローカルLLMが実装する構成です。
※並列数はClaude単独が4、GLMが1、Qwenが8。Qwen単独と「分業:Opus+Qwen」は2試行(36ジョブ)です。費用はAPI換算です。
※「分業:Opus+GLM」は、レビューが欠陥3件を見逃して通しています(後述)。
結果は、期待をきれいに裏切るものでした😭
- ハイブリッド構成は、どれもOpus単独より1件あたり2〜4倍高く、処理量は1/20(Sonnet単独と比べると差はもっと開く)
- Claudeが仕様整理・受け入れテスト・レビューに使う費用(1件$2〜4)が、Claudeが自分で解く費用($0.36〜0.93)を上回る
- そのうえローカルの実装は遅い
- Sonnet単独は、Opus単独と同じ品質を39%の費用・1.8倍の速さで出した
- 実装のワーカーはSonnetで十分
- GLM単独は、品質ではClaudeと並んだ(API費用は0)
- ただし処理量は1時間に13件で、Sonnetの1/15
- 1本の推論でGPUが約90%張り付くので、並列にしても速くならない
- 推論の量(effort)を最大からhighに下げると2.7倍速くなって、実務の課題での合否は変わらなかった
- Qwenは、課題文が自然言語になると崩れた
- 仕様を明示した課題文なら78%通るのに、自然言語の課題文だと50%まで落ちて、試行ごとの揺れも大きい
- Claudeが仕様を整理すると83%まで戻るけど、その費用でClaudeが自分で解いたほうが安くて速くて品質も高い
Claudeのレビューだけでは品質ゲートにならない
もう1つ、大事な発見がありました。
OpusはQwenの実装の欠陥を、1巡目のレビューで9件中9件見つけました。 ところがGLMの実装の欠陥は、3件中3件見逃してapproveしたんですよね。
Qwenの欠陥は、テストの不足や明らかな仕様違反といった「見て分かる」形で出ます。 一方GLMの欠陥は、筋の良い実装の中に紛れていて、レビュー役は細かい指摘だけで通してしまう。
レビューの精度は、レビューされる側のモデルによって大きく変わるということです。
なので、LLMのレビューとは独立に、テスト(自動チェック)を品質ゲートとして置く必要があります。 人のレビューでも同じことは言えますが、LLM同士だとより顕著でした。
Phase 4:普段のClaude Codeのハーネスで、SonnetとGLMを比べる
ここまでは、ベンチ用に絞ったハーネスで測っていました。
最後は、普段の自分のClaude Codeの環境をできるだけそのまま再現して、SonnetとGLMを比べました。
- CLAUDE.mdとメモリ、hooks、serenaとcontext7のMCP、pre-commitをそのまま使う
- CIの失敗は1回だけ差し戻す
- 課題は小・中・大を1件ずつ
- 小:クエリの性能改善
- 中:運用監視まわりの機能追加
- 大:複数ファイルにまたがるセキュリティ系の新機能
- どれも受け入れテストを先に作って凍結しておく
- 採点は2段
- 1段目は自動チェック(受け入れテスト、RSpec全件で新しい失敗がないこと、rubocop、brakeman)
- 2段目はOpusとFableによる品質の採点(モデル名は伏せる)
- 実際にマージされたPRも伏せた候補として混ぜて、採点の基準がずれていないかの確認に使う
- 判定の基準(継続/限定運用/撤退)は、実行前に決めて固定しておく
| 構成 | 等級(小/中/大) | 採用可能 | 完走できず | 時間の中央値(小/中/大) |
|---|---|---|---|---|
| Sonnet | AAA/AAA/AAA | 9/9 | 1 | 1.8/3.1/7.7分 |
| GLM | AA/SA/AF | 5/6 | 1 | 26.9/13.2/33.5分 |
| 参考:実際のPR | A/S/S | — | — | — |
※Sonnetは普段のハーネス、GLMはGLM向けに調整したハーネスでの結果です。
※等級はS/A/B/Fの4段階で、SとAを採用可能としています。
※「完走できず」は、ターン数の上限に達したり、成果をコミットせずに終わったりした件数です。
- 完走したものは、GLMもSonnetと同じ水準
- 採点者はモデル名を知らないまま、GLMのPRにもAやSを付けていた
- GLMの失敗の型は「ターン数の使い切り」
- 大の課題で、普段のハーネスで試した1回を含む3回のうち2回が、上限の200ターンに達した(Sonnetは8〜57ターンで終わる)
- 同じ失敗を繰り返しているわけではなく、作業そのものに多くのターンを使っている。空回り検出の仕組みは一度も発火しなかった
- 速度は1件で4〜15倍の差
- Sonnetは4並列で回せるので、採用可能なPRの処理量で比べると約1/20
- 普段のハーネスだと、1リクエストのコンテキストは平均で約9.2万トークンもあった
- CLAUDE.md、メモリ、ツールの定義が積み上がるため
- それでもoMLXのプレフィックスキャッシュの命中率が98.9%あって、prefillはボトルネックにならなかった
判定は「限定運用」でした。
ただ、これはきわどい判定です。 大の課題の2試行がAとFで同数になり、「同数なら低いほうを採る」という事前に決めておいた規則でF扱いになりました。高いほうを採っていれば「継続」でした。
とはいえ、どちらに倒しても言えることは同じです。 GLMは完走すれば使えるPRを出すけど、大きな課題では安定せず、遅い。
ベンチを作るときに気をつけたこと
実案件のリポジトリでベンチを回すと、評価そのものより、公平さと安全の確保のほうに手間がかかりました。
正解に到達できないようにする
課題のリポジトリは、PRの直前の履歴から作った独立のリポジトリにして、remoteを外しました。 正解のコミットにもPRのブランチにも到達できないことを確かめています。
後続のドキュメントやメモリに設計が書き残されていることもあるので、出題前にそれも除きました。
さらに、ワーカーのツール呼び出しをすべてhookで検査して、正解の置き場所、他の試行、ホームディレクトリ、外部への通信を拒否しています。 わざと「参考の正解」と書いた目印のファイルを置いて誘導してみても、到達は0件でした。
共有の開発環境を壊さない
実はPhase 1の準備の途中で、ベンチを組んでいたClaude Codeが、共有のgemのvolumeにbundle installを流してしまい、他の作業ツリーが使うgemが消えるという事故がありました。共有のテストDBを作り直してしまったこともあります😓
それ以降は、ワーカーごとに専用のテストDBを用意して、依存の導入やプロセスの停止をhookで禁止しました。
外部に作用するツールを外す
Claude Codeには、通知や定期実行、他のセッションへの送信など、外部に作用する組み込みツールがあります。
無人のワーカーでは--disallowedToolsで外しました。外部サービスのMCPも外しています。
LLMの採点だけに頼らない
前述の通り、LLMのレビューは見逃します。 自動チェックを必ず先に置き、採点では正解のPRも伏せた候補として混ぜて、採点がちゃんと機能しているかを確かめました。
判定の基準は先に決める
結果を見てから閾値を動かすと、どんな結論にでも寄せられちゃいます。 今回は判定表を実行前に固定して、きわどかった点も含めて記録に残しました。
ハーネスがボトルネックになっていないか?
ANTHROPIC_BASE_URLでモデルだけ差し替える方式は、条件を揃えやすい反面、「Claude向けに作られたハーネスにローカルLLMを載せている」とも言えます。
ハーネス側が足を引っ張っていないか、ログを見直して確かめました。
- 時間の大部分はモデルの推論
- Phase 4でGLMのセッションが動いていたのは約3.2時間で、推論サーバの処理時間も同じくらい(約3.1時間、予備実験の分を含む概算)
- Claude Code側の処理やツールの実行がボトルネックになっているわけではない
- プロトコル変換の失敗はほぼない
- GLMのツール呼び出しで、引数の形式エラーは1,232回中8回(0.6%)、APIエラーは0件
- 補助的な呼び出しも含めて、全リクエストがちゃんとGLMに届いていた
- 長いコンテキストはキャッシュで吸収できていた
- 1リクエストの平均は約9.2万トークンと重いけど、プレフィックスキャッシュの命中率が98.9%
- effortの受け渡しは連携の穴だった
- Claude Codeから送る推論量(effort)の指定を推論サーバが無視していたので、サーバ側でhighに固定して回避した(これで2.7倍速くなった)
- ただしQwenは、ハーネスとの相性が結果に効いていた
- Phase 3(自然言語の課題文)で、Qwenはツール呼び出しの25%がエラー。その約6割は「許可していないコマンドを何度も実行しようとして拒否された」もの
- GLMやClaudeは約5〜7%。ベンチ用に絞った権限設定に、Qwenだけがうまく適応できず、ターンを浪費していた
ということで、GLMについては「Claude Code経由だから遅い・失敗する」わけではなく、ボトルネックはモデル自体の推論量と生成速度というのが今の見立てです。 一方Qwenの評価は「Claude Codeのハーネス込み」の結果で、Qwen向けのエージェントなら違う結果になる可能性があります。
費用
Claude側の費用は、3日間でAPI換算で約$276でした(Phase 1〜2が約$26、Phase 3が$164、Phase 4が$86)。 実際にはサブスクリプションの利用枠の範囲で回していて、Phase 4では週の利用率が7ポイント増えた程度です。
意外だったのは、一番お金がかかったのが採点だったこと。 Fableで採点すると1件$2.2かかり、Phase 4の採点だけで$54になりました。
一方、実運用でSonnetのワーカーが1件のPRを作る費用は$0.76です。 つまり、GLMで節約できるのは1件あたりこの$0.76だけなんですよね。
ローカル側の費用は0としていますが、電気代は計っていません。GLMが動いている間はGPUが約90%に張り付きます。
まとめ:当初の目的に対する答え
ローカルLLMを試したい → 試せた
256GBあれば、GLM-5.3-Flashを実用的な速度(70 tok/s前後)で常駐させられます。ただし1本で182GBを占有します。 モデルの性能も大事ですが、実行系(mlx-vlmかoMLXか)で20倍近く変わることのほうが印象に残りました。
Claudeのトークンを節約したい/オーケストレーター構成を試したい → ローカルLLMを混ぜるのは今は割に合わない
期待していた「Claudeが指揮してローカルが実装」の形は、費用でも速度でも割に合いませんでした。
これから組むオーケストレーター構成は、当初考えていた「Fableとだけ話す」形ではなく、「Opusとだけ話す」形にするつもりです。指揮役の下で動く実装ワーカーはまずClaude(Sonnet)を並列で回し、品質ゲートはテストとレビューの2段に。
Fableは、ここぞという高度なレビューにだけ使うのがトークン効率が良さそうです。 今回も、Fableでの採点はOpusの約8倍の費用がかかったのに、2者の判定は21件中18件で一致しました。一方で、Opusが書いた受け入れテストの重大な不備を見つけたのはFableでした。 トークンの節約という意味でも、GLMに任せて浮くのはSonnetで1件あたり$0.76程度でした。 それでも、Teamのアカウントで5時間の利用上限に達したときの逃げ道にはなるので、利用枠が逼迫したとき、急がない夜間のバッチ、コードを外部に出したくない場面の補助レーンとしてGLMは残しておきます。
開発機のリプレイス/外からClaude Codeを操作したい → 据え置きの256GB機の恩恵が大きい
こちらはローカルLLMの結果に関係なく、恩恵が大きいです。 今回の検証も、DockerでRSpecを並列に回しながら182GBのモデルを常駐させ、Claude Codeのセッションを何本も動かして進めました。M1 MaxのMacBookではとてもできない使い方です。
もともと、「最大のモデルを動かすこと」ではなく、「最高品質のモデルを、実用的な速度で、長時間安定して動かすこと」を目標にしていました。
その観点では、今のところの最適解はクラウドのClaudeで、ローカルLLMは「いざというときの予備」という結論です。
次に試すなら
検証の条件についてChatGPTにも相談してみたところ、以下の3つを提案されました。
- 失敗した課題をAPI直叩きで再実行して、モデル自身の問題かClaude Code連携の問題かを切り分ける
- 同じモデル・量子化・コンテキスト長で推論サーバを比べて、改善の余地を測る
- Claude Code以外のエージェントでも同じ課題を試して、ハーネスへの依存度を測る
前述のログの見直しを踏まえると、優先度はこんな感じかなと思っています。
- 推論サーバの比較・チューニング(優先度:高)
- 時間の大部分が推論なので、効くとしたらここ
- 短い入力では70 tok/s(10万トークンの入力でも64 tok/s)出るのに、実務では中央値43 tok/sまで落ちていた。この差の原因(MTPの当たり率、thinkingの量、並行処理の影響など)を切り分けたい
- ただしGPUはすでに張り付いているので、伸び代は数割程度と見ている
- Claude Code以外のエージェントで試す(優先度:中)
- Qwenは独自のツール呼び出し形式を持ち、Qwen Code向けに調整されているので、Qwenの評価はやり直す価値がありそう
- GLMは、開発元(Z.ai)がClaude Codeから使う手順を公式に案内しているくらいなので、ハーネスを変えて劇的に良くなる可能性は低そう
- 失敗した課題をAPI直叩きで再実行する(優先度:低)
- GLMの失敗は、プロトコルのエラーではなく「作業に200ターンを使い切る」型だったので、API直叩きで切り分けられることは少なそう
- そもそもツールを使わずに解ける課題ではないので、結局何かしらのエージェントのループが要る
とはいえ、ローカルLLMの進歩はめちゃくちゃ速いので、新しいモデルや実行系が出たら、同じハーネスでまた測ってみようと思います😃
所感
改めて振り返ると、こういう検証をまるごとAIにやらせられるのは、すごい時代になったなぁと思います。
計画を立てて、ハーネスを実装して、ベンチマークを回して、集計してレポートにまとめる。私がやったのは、方針の相談と、要所での判断くらいでした。 そもそもこのブログ記事も、AIに書かせています(6年ぶりの更新がこれというのも、なんとも今っぽい😅)。
それと、結果を眺めていて想起されたのが、人のチームの話です。
- 1人でやった方が速い vs チームでやった方がスケールする
- Claudeが仕様を整理してローカルLLMに実装させる分業は、指示やレビューのコストが重くて、Claudeが1人で解いた方が速くて安かった
- 人のチームでよく聞く「説明してお願いするくらいなら、自分でやった方が早い」そのものなんですよね
- 少数精鋭のエンジニア vs 多数の一般的なエンジニア
- Qwenを8並列で回しても、GLM1本やSonnetの品質と処理量には届かなかった
- 数を増やしても、仕様の読み違いや手戻りで、かえってコストが膨らむ
- できる人のPRほどレビューが甘くなる
- レビュー役のOpusは、Qwenの分かりやすいミスは全部見つけたのに、GLMの筋の良い実装に紛れた欠陥は見逃した
- これも人のレビューでありがちな話
人の組織なら、ここでエンジニアリングマネジメントの出番です。 役割の分け方、委譲の粒度、コミュニケーションのコスト、品質を担保する仕組み、チームの規模と生産性の関係…。これまで人のチームのために磨かれてきた考え方が、そのままAIのチーム編成の悩みにも重なって見えます。
では、メンバーが人ではなくAIになったとき、これまでのエンジニアリングマネジメントの考え方は、どこまでそのまま応用できて、どこをどう発展させていく必要があるんだろう?
「クリエイティブが輝ける組織をエンジニアリングする」をテーマに掲げてきた身としては、その「組織」にAIが加わった今、改めてじっくり向き合っていきたい問いです。
参考文献
この一連の検証で参照したものをまとめておきます。
モデル
- zai-org/GLM-5.3-Flash:GLM-5.3-Flashの公式。チャットテンプレートの確認に使用
- dfp-official/GLM-5.3-Flash-oQ4e-mtp:oMLXで動かした量子化モデル本体
- Vontra/GLM-5.3-Flash-MLX-4bit-MTP:MTPの層の移植元
- mlx-community/GLM-5.3-Flash-4bit:mlx-vlmで最初に試した4bit版
- orcarouter/GLM-5.3-Flash-MLX:3bit/2bit版のサイズと精度の比較
- mlx-community/Qwen3-Coder-Next-4bit:MLX版のQwen3-Coder-Next
- Ollama: qwen3-coder-next:Ollama版(q4_K_M/q8_0)のQwen3-Coder-Next
- Ollama: glm-5.3-flash:Ollama版のGLM-5.3-Flash(クラウド版のみでローカルでは動かせなかった)
実行系・ツール
- oMLX:GLM-5.3-Flashを実用速度で動かせた推論サーバ
- oMLX PR #4086:GLMのツール呼び出しが無限ループする不具合の修正
- oMLX PR #3944:GLM-5.3のprefillの改善
- mlx-lm:MLX版Qwenの実行、wiredの上限やKVキャッシュの設定の確認
- mlx-vlm:GLM-5.3-Flashを最初に動かした実行系
- Ollama:GGUF版Qwenの実行
- Ollama: Anthropic compatibility:Anthropic互換APIでClaude Codeからつなぐ方法
成功事例・既知の問題
- sethforprivacy/GLM-5.3-Flash-M5-Ultra-oMLX:M5 UltraでGLM-5.3-Flashを動かすレシピ。今回はこれを再現した
- oMLX Benchmarks:oMLXでの速度の実測例
- fireside-labs/m5-ultra-llm-benchmarks:M5 UltraでのローカルLLMのベンチマーク
- mlx-vlm issue #2254:M3 Ultra(512GB)でGLM-5.3-Flashが約29 tok/s出たという報告
ダウンロードの高速化
- Hugging Face: Using Xet Storage:Xetでのダウンロードの設定
- huggingface_hub issue #4893:太い回線だと、既定の並列数では
hf downloadの速度が出ないという報告 - xet-core issue #883:大きなモデルのダウンロード中にXetが止まるという報告
Claude Code
- Claude Code: LLM gateway configuration:
ANTHROPIC_BASE_URLで接続先を差し替える方法 - Claude Code: Environment variables:Claude Codeの環境変数
- Pairing Claude Code with Local Models(KDnuggets):Claude CodeをローカルLLMとつなぐ方法と、ツール呼び出しの注意点
- Claude Code with local models(runlocalai):Ollama・LiteLLM・llama.cppでClaude Codeを動かすガイド
- Z.ai: Other tools:GLMをClaude Codeなどのツールから使う公式の案内
- How to Access Qwen 3 Coder(Novita):Qwen CodeがQwen3-Coder向けにツール呼び出しを調整しているという話
- Use Qwen3-Coder-Next in Claude Code(Novita):Qwen3-Coder-NextをClaude Codeから使う方法
macOS(動く壁紙とVTDecoderXPCService)
- VTDecoderXPCService memory leak(Apple Community):VTDecoderXPCServiceがメモリを解放しないという報告
- wallpapervideoextension in Sonoma uses lots of RAM and CPU(Apple Community):壁紙の動画拡張がRAMとCPUを大量に使うという報告
- VTdecoderxpcservice takes 600% cpu(Apple Community):スクリーンセーバーの最中にCPUを600%使うという報告



















