ローカルLLMが実力より劣って見える理由 — 量子化・KVキャッシュ・Attentionバックエンドの落とし穴

はじめに

オープンウェイトモデルの実用ラインが上がり、手元で 27B クラスを回す選択肢が現実的になった。一方で「ベンチマークの数字ほど賢くない」「クラウドの同じモデルより明らかに雑」という体感の食い違いを踏む人も増えている。

2026年8月24日、Hacker News で最上位に上がった Level1Techs フォーラムの投稿 Why your local LLM feels dumber than it is は、この食い違いの原因をモデル側ではなく推論スタック側に置いた。同じ重みを別の設定で回し、トークン単位でどれだけ選択が入れ替わるかを計測している。

本記事では、その計測結果のうち再現性が確認できるものを整理し、なぜ「同じモデルなのに結果が変わる」のかという数値計算上の背景、そして自分の環境で何を疑うべきかを扱う。

何が計測されたのか

投稿の中心にあるのは、top-1 トークンの反転率という指標だ。参照実装(BF16)と比較対象を同じ入力で走らせ、各位置でモデルが最も高い確率を割り当てたトークンが何%入れ替わるかを数える。これは perplexity のような集約値と違い、「どこで分岐が起きたか」を位置ごとに追える。

計測から浮かんだ要因は主に4つある。

1. 重み量子化の方式 — 同一モデルを5方式で比較した結果、BF16 を基準に FP8(公式チェックポイント、E4M3 ブロックスケーリング)は良好、INT8 W8A16 が一次配布の FP8 を上回るという逆転が起きている。一方 NVFP4 は最下位で、88k トークン付近で反転率が約50%に達したと報告されている。AWQ W4A16 は中間だが、ツール呼び出しで誤った CLI 構文を実行する失敗を出した。

2. KV キャッシュの量子化精度 — BF16 / INT8 / INT4 の比較で、INT8 は誤りを出しても後続で復帰するのに対し、INT4 はツール呼び出しの失敗から復帰しなかった。

3. Attention バックエンド — FlashAttention 2 / FlashInfer / Triton の切り替えだけで、選択されるトークンが分岐する。投稿の例では、ネットワーク機器のインターフェース名が GigabitEthernet0/0/1.201 から GigabitEthernet0/1/4 に化け、その後の復旧コマンドまで別物になった。

4. テンソル並列度 — TP1 で通ったツール呼び出しが TP2 で失敗し、TP4 で再び通る。投稿者は NCCL のグラフまで追って集団通信の実装差に帰着させている。

加えて、いわゆる abliterated / uncensored 派生モデルの副作用も測られている。反転率は派生元によって 0.7% 台から 5.8% 台まで開き、最も荒い派生では PostgreSQL のポート番号 5432 が 543ql に化けるといった、運用コマンドそのものの破壊が観測された。

なぜ同じ重みで結果が変わるのか

直感に反するが、浮動小数点の加算は結合則を満たさない。(a + b) + c と a + (b + c) は一般に一致しない。GEMM(行列積)カーネルは総和をどの順序・どの粒度で畳み込むかを性能都合で決めており、実装が変われば同じ数式でも下位ビットが変わる。

通常この差は無視できる。問題は、上位2候補のロジットが接近している位置では、下位ビットの差がそのままどちらを選ぶかをひっくり返す点にある。一度別のトークンを選べば、そこから先の文脈は別物になる。ツール呼び出しの引数のように「1トークン違えば実行結果が変わる」箇所では、微小な数値差が機能的な失敗に直結する。

同じ構造は推論エンジン側でも知られている。Thinking Machines Lab の Defeating Nondeterminism in LLM Inference は、非決定性の主因が乱数ではなくバッチ不変性の欠如にあると指摘した。同じシーケンスでも、同時に処理されている他リクエストの量によって chunked prefill の分割が変わり、reduction 順序が変わる。同ラボは RMSNorm・行列積・Attention をバッチ不変なカーネルで置き換え、1,000 回の同一プロンプトで 1,000 回同じ出力を得ている。つまり「実装差が結果を変える」は再現済みの現象であり、今回の計測はそれを量子化・並列度・バックエンドの軸に広げたものと読める。

KV キャッシュ INT4 の件も、フォーラムの単発報告では終わっていない。lmdeploy の Issue #4743 では、Qwen3-Coder-30B を --quant-policy 4 で起動するとツール呼び出しパーサが構造化出力を取り出せなくなり、成功率が 83.3% から 0% に落ちたと報告されている。--quant-policy 8(INT8)では正常。モデルが期待される XML タグ形式を出力しなくなるという症状で、独立した環境で同じ傾向が出ている。

長コンテキストでの挙動にも一貫した傾向がある。量子化 LLM の評価研究では、4k トークン以上の入力は weight-only 量子化と KV キャッシュ量子化に対して短文より敏感で、weight-only の劣化幅は長文で顕著に大きくなるとされる。一方 weight-activation 量子化は長文でも劣化幅が広がりにくい。ベンチマークの多くが短い入力で測られていることを考えると、「ベンチは良いのに実務で崩れる」体感の説明としてつじつまが合う。

エンジニアへの影響 — 何を疑うべきか

まず設定の一致を潰す。 モデルカードには推奨サンプラ設定とチャットテンプレートが書かれている。temperature や top-p が推奨から外れているだけで挙動は変わり、投稿は「温度を下げすぎると Qwen が THINK 出力から抜けられずループする」という具体例を挙げている。チャットテンプレートの不一致は特に静かに効くので、実際に送られている文字列をログで確認する価値がある。

次に量子化の選び方を見直す。 VRAM に収めるための 4bit は、収まりはするが失敗モードが変わる。ツール呼び出しや長文の構造化出力が主用途なら、W4A16 より W8A16 を優先し、KV キャッシュの INT4 は避ける。KV キャッシュは INT8 までなら実務上ほぼ無害という報告が多く、INT4 は回転(Hadamard 変換など)を伴う手法でないと崩れやすい。VRAM を削る順番としては、重みより先に KV キャッシュを削るのは分が悪い。

評価は自分のワークロードで行う。 ゼロショットの知識クイズで並べても、上記の失敗モードは一切見えない。長コンテキストのツール呼び出し、ドメイン固有の手順実行、構造化出力のパース成功率 — 実際に流す形に近いタスクで、パス率を数える。lmdeploy の事例のように「成功率 83.3% → 0%」という形で出れば、原因の切り分けは一気に楽になる。

派生モデルは出所で選ぶ。 検閲解除系の派生は、狙った振る舞い以外の場所も動かす。データセット・シード・探索設定を開示している派生ほど反転率が低いという傾向が出ており、開示の有無は実質的な品質指標として機能している。

そして最後に、投稿が置いている前提は身も蓋もないが有用だ — 完全に一致する実装は存在しない。目標は正解の再現ではなく、自分のスタック固有の失敗モードを把握しておくことにある。

まとめ

  • ローカル LLM の体感品質の低下は、モデル性能ではなく推論スタックの設定差から生じる部分が大きい
  • 重み量子化方式・KV キャッシュ精度・Attention バックエンド・テンソル並列度のいずれもトークン選択を変え、ツール呼び出しのような 1 トークン精度が要る用途で機能的な失敗になる
  • 原因は浮動小数点加算の非結合性と reduction 順序の違い。Thinking Machines のバッチ不変カーネルの成果が、同じ構造の問題であることを裏づけている
  • 実務指針は W8A16 優先 / KV キャッシュ INT4 回避 / モデルカード準拠のサンプラ・テンプレート / 自分のワークロードでのパス率計測
  • 長コンテキストは短文より量子化に敏感で、短い入力のベンチマークからは劣化が見えない

オープンウェイトモデルの性能が上がるほど、差を決めるのはモデル選定ではなく推論環境の詰めになる。まずは手元の設定がモデルカード通りかを確認するところから始めたい。

今日のその他のニュース

AI アシスタントが 2021 年の Dart を書き続ける理由 — r/FlutterDev の投稿が、原因を知識カットオフだけでなく「学習データ中に存在する Flutter コードの多数派が古い」ことに求めている。新しい書き方は統計的に少数派なので出力されにくい。対策は最新 API ドキュメントを明示的にコンテキストへ入れること。同日 Qiita に上がった Context7 MCP Server の解説が、この問題を MCP 経由で解く手段になる。

「Rust を超絶丁寧に教えてくれる君.md」がはてブ 176users — 所有権・借用・ライフタイムを AI に丁寧に説明させるための指示プロンプトを gist で公開したもの。Rust 教材としてだけでなく、難所のある概念を LLM に教えさせるプロンプト設計のサンプルとして転用できる。

Stop Using Conventional Commits — feat: fix: 系の規約がチェンジログ自動生成以外の価値を生んでいるか、という問題提起。記事本体よりコメント欄が本番で、「semantic-release と組めば意味が出る」「規約より PR タイトルの質」といった実運用の温度感が集まっている。導入を迷う段階なら賛否の論拠を一度に拾える。

ソース