Chrome内蔵LLM(Prompt API)はタダのAPIではない
訪問者のGPUで動く、結果を信用できない計算 — だから補助にだけ使う
Chromeでこの2行が動く。
const session = await LanguageModel.create()
const answer = await session.prompt("このコメントは誹謗中傷?")
APIキーもサーバーもない。最初はタダのGPT APIに見える。結論から言うと違う。これは訪問者のGPUで動く、結果を信用できないクライアント側の計算だ。この記事を読めば、このAPIをどこに使ってよくてどこに使ってはいけないか、1つの基準で分けられるようになる。
きっかけは韓国のYouTubeチャンネル「コーディングアップル」の動画(Chromeがこっそり入れる2GBのファイル)だった。自分で確かめたくて、JSテスト用のアプリにセクションを1つ足した。
ダウンロードと利用は別々に動く
availability() は何もダウンロードしない。ページ読み込み時に呼んでも安全だ。実際の準備は create() で始まり、取得が必要な場合はユーザーのクリック(user activation)の中で呼ぶ必要がある。セッションは会話履歴を持つので、判定のように毎回独立させたい処理は clone() で分けて使う。responseConstraint にJSON Schemaを渡せば出力形式を強制できる。
実際に測ってみた(2026-09-19、macOS・Chrome 152・フラグなし)
モデルは数か月前から入っていた。 プロフィールフォルダの OptGuideOnDeviceModel/ 配下に weights.bin が4.27GB、日付は2026-04-27。ボタンを押す5か月前だ。動画の「こっそり入るファイル」はこれだった。
downloadable は「ファイルがない」という意味ではなかった。 ページ読み込み時は downloadable だったのに、create() の後も weights.bin の日付は変わらなかった。何もダウンロードしていない。代わりに create() に18秒かかり、その瞬間に program_cache.bin ができた。ダウンロードではなくGPU向けの準備(シェーダーのコンパイル)に見える。
通常のChromeで出てきたのはGemini Nanoだった。 manifestのモデル名は v3Nano。動画で言っていたGemma 4(約2GB)は自分の環境では確認できなかった。なのでGemma 4の品質についてはこの記事では書かない。
翻訳は英語を経由する。 韓国語→日本語を頼んだら、取得されたのは en_ko(75MB)と en_ja(76MB)の2組だった。韓国語→英語→日本語の2段翻訳だ。言語N個に対してモデル2N個で済むのはいいが、敬語の段階のように英語にないニュアンスが途中で落ちうる。日韓翻訳には不利な作りだ。
誹謗中傷判定は理由と結論が食い違った。
{"toxic": true, "category": "insult",
"reason": "特定の相手に外見について肯定的な表現を使っており、侮辱的な意味を含んでいる。"}
(韓国語の出力を訳したもの)「肯定的な表現」なのに「侮辱」。responseConstraint のおかげでJSONの形は守られたが、中身は信用できない。下の基準の実例だ。
サーバーAPIと比べると
| サーバーのLLM API | Chrome内蔵LLM | |
|---|---|---|
| コスト | 自分が払う(トークン課金) | 自分は0円。代わりに訪問者の電気・GPU・ディスクが払う |
| 入力データ | サーバーに出ていく | 端末の外に出ない |
| 結果の信頼 | 自分のサーバーが出した値 | DevToolsでいくらでも書き換えられる |
| 使える人 | ブラウザを問わない | デスクトップのChromeで、スペック条件あり。Android・iOSは未対応 |
| モデル | 選べる | ブラウザが用意したもの(自分の環境はGemini Nano) |
スペック条件はかなり高い。公式ドキュメントでは、プロフィールのあるディスクに22GBの空き、VRAMは4GB超が必要とされている。訪問者全員が使えると思ってはいけない。
基準は1つ — クライアントが結果をごまかしても誰も損しないか
| 使い道 | 判定 | 理由 |
|---|---|---|
| コメント送信前の「ちょっと強くない?」警告 | 使う | ごまかしても本人が損するだけ。サーバー側の検証は別に置く |
| 誹謗中傷のブロック(サーバー検証の代わり) | 使わない | JS 1行で回避される |
| ブログ画像のalt提案 | 使う | 間違えても書き手が直す |
| 読む人向けの翻訳・要約 | 使う | 結果を見る人=計算した人 |
| ポイント・ランキング・課金判定 | 使わない | ごまかすと得をする |
| 機能全体をこれに頼る | 使わない | Chrome以外のユーザーは何も使えない。フォールバック必須 |
一言でいえば、補助(assist)には使い、判定(enforce)には使わない。
判定が必要ならサーバー側でやる。サーバーで速く安く判定だけするモデルなら、Jev のような選択肢もある。
機能をブラウザ内で動かすかサーバーに送るかを決める段階なら、negabaroに相談してもらって構わない。こうした境界線を引く仕事を実際のサービスでやってきた。
キーコンセプト
ページ読み込み時は availability() だけ — 何もダウンロードしない
create() はユーザーのクリックの中で — downloadable ならここで準備が始まる
判定のように毎回独立させたいなら clone() でセッションを分ける
形式は responseConstraint で守り、中身は信用しない
Chrome以外のユーザー向けのフォールバックを必ず置く
メリット
- ✓ 推論コスト0 — サーバー・APIキー・課金がない
- ✓ 入力が端末の外に出ない
デメリット
- ✗ 結果を信用できない — クライアントが書き換えられる
- ✗ デスクトップのChromeと高いスペックでしか動かない
- ✗ 翻訳が英語を経由し、敬語のようなニュアンスが落ちうる