実行プログラムと拡張機能

Transformers.jsでブラウザー内のローカルLLMを実行する

入力した質問にブラウザー内で答える小さなWebアプリを作ります。

Transformers.jsはJavaScriptからAIモデルを実行するライブラリです。ONNX形式のモデルを取得すれば、ブラウザーでも回答を生成できます。この記事では4.3.0の公式例にあるLFM2.5-350Mを使い、質問入力欄と回答ボタンを作ります。

実行条件と要点
  • 静的HTMLは`localhost`またはHTTPSで配信し、ES moduleとしてTransformers.js 4.3.0を読み込みます。
  • 標準経路はCPU/WASMです。`device: 'webgpu'`は対応するブラウザーとGPUがある場合にだけ選びます。
  • 入力文はブラウザー内で動くモデルへ渡され、別の推論サーバーは呼び出しません。

ブラウザー内のローカル推論で何が変わる?

一般的なAIサイトは質問をサーバーに送り、回答を受け取ります。ブラウザー内のローカル推論では、その処理をユーザーのコンピューターが担います。Transformers.jsの`pipeline1()`を一度作り、入力文を渡すと、取得済みのモデルが同じページ内で回答を生成します。

別途Python推論サーバーを導入する必要がなく、小さなWeb機能の試作に向いています。テキスト分類や短い回答など、負荷の小さい作業から始めましょう。多数の同時利用者や大きなモデルの継続的な提供には、専用のサービングエンジンを検討します。

机の上のノートPCにTransformers.jsを実行するブラウザーとONNXモデルが表示されている場面
モデルを一度読み込むと、同じブラウザー内で質問を処理します。

4.3.0で使うモデルと実行デバイスを選ぶ

Transformers.js 4.3.0は2026年9月16日に公開されました。リリース例は`onnx-community/LFM2.5-350M-ONNX`でWebGPU2用の`q4f16`を使います。このモデルリポジトリにはCPU/WASMで選べる`q4`ファイルもありますが、`q8`ファイルは確認できなかったため、以下のコードはデバイスに応じて2つの形式から選びます。

別のONNXモデルに切り替える場合は、選んだdtypeのファイルがそのリポジトリにあることを確認してください。モデルを読み込むにはファイルと推論設定の一致が必要です。

公式資料はこのモデルの最小システムRAM3・GPU4メモリを示していません。モデルファイルのサイズだけで実行可否を判断せず、初回実行時にブラウザーのタスクマネージャーでタブのメモリ使用量を確認してください。

このモデルリポジトリで確認した実行形式とブラウザーデバイス経路です。
実行経路設定使用条件
CPU/WASM`device`を省略し、`dtype: 'q4'`を指定このリポジトリにあるq4ファイルを使う標準の推論経路
対応GPU`device: 'webgpu'`, `dtype: 'q4f16'`WebGPU adapterを取得でき、この形式に対応している場合
q8このモデルでは選ばないモデルリポジトリにq8 ONNXファイルがなく、使用できません

このモデルリポジトリで確認した実行形式とブラウザーデバイス経路です。

CPU/WASM

設定
`device`を省略し、`dtype: 'q4'`を指定
使用条件
このリポジトリにあるq4ファイルを使う標準の推論経路

対応GPU

設定
`device: 'webgpu'`, `dtype: 'q4f16'`
使用条件
WebGPU adapterを取得でき、この形式に対応している場合

q8

設定
このモデルでは選ばない
使用条件
モデルリポジトリにq8 ONNXファイルがなく、使用できません
ノートPCとワークステーションが並び、それぞれCPUとGPUの実行経路を表す場面
WebGPUを使えない場合はCPU/WASMで実行します。速度とメモリ使用量は機器ごとに異なります。

localhostで開く静的HTMLを準備する

開始に必要なのは静的ファイル2つだけです。ES moduleのCDN importを使うため、ファイルを直接開かずローカルWebサーバーで配信します。以下のloopback `localhost`はWebGPUで必要なsecure contextとして扱われます。公開環境ではHTTPSを使ってください。初回にライブラリとモデルを取得するため、インターネット接続も必要です。

新しい空のフォルダーに`index.html`と`main.js`を作成し、以下のHTMLを保存します。これはjsDelivr CDNからライブラリをmoduleとして読み込む公式ドキュメントの方法に沿っています。URLでバージョンを固定することで、CDNの既定タグが変わってもこの例では4.3.0を指定できます。

index.html — 入力と結果の表示欄
<!doctype html>
<html lang="en">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Browser-local text generation</title>
  <label>Prompt <input id="prompt" value="Reply in one short sentence: local AI runs in a browser."></label>
  <button id="run" disabled>Generate</button>
  <pre id="status">Loading model…</pre>
  <pre id="output"></pre>
  <script type="module" src="./main.js"></script>
</html>
ES moduleスクリプトが同じフォルダーの`main.js`を読み込みます。
ブラウザーのダウンロード一覧とモデルファイルのフォルダーを表示したノートPC画面
初回のネットワーク通信でライブラリと重みを取得し、その後の生成はページ内で行われます。

モデルを読み込み、一度生成する

以下の`main.js`はWebGPUを確認してからモデルを読み込みます。GPUアダプターが利用できれば`q4f16`、利用できない場合や確認中にエラーが起きた場合はCPU/WASM用の`q4`を選びます。準備ができるとGenerateボタンが有効になります。

初回はCDNからライブラリを、Hugging Face Hubからモデルファイルを取得します。この例では質問を別の推論サーバーに送らず、ブラウザー内で処理します。サービスに組み込む際は、分析やログ収集のコードが入力を送信していないかも確認してください。モデルは一度読み込み、ボタンを押すたびに同じpipelineを再利用します。

main.js — WebGPUを確認してローカルpipelineを実行
import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0';

const status = document.querySelector('#status');
const output = document.querySelector('#output');
const promptInput = document.querySelector('#prompt');
const button = document.querySelector('#run');
const modelId = 'onnx-community/LFM2.5-350M-ONNX';
let adapter = null;
try {
  adapter = await navigator.gpu?.requestAdapter() ?? null;
} catch (error) {
  console.warn('WebGPU unavailable; using CPU/WASM.', error);
}
const device = adapter ? 'webgpu' : undefined;
const dtype = adapter ? 'q4f16' : 'q4';
let generator;

try {
  status.textContent = `Loading ${modelId} (${device ?? 'CPU/WASM'}, ${dtype})…`;
  generator = await pipeline('text-generation', modelId, { dtype, ...(device ? { device } : {}) });
  status.textContent = `Ready: ${device ?? 'CPU/WASM'} / ${dtype}`;
  button.disabled = false;
} catch (error) {
  status.textContent = `Model load failed: ${error.message}`;
  console.error(error);
}

button.addEventListener('click', async () => {
  if (!generator) return;
  button.disabled = true;
  status.textContent = 'Generating…';
  try {
    const result = await generator(promptInput.value, { max_new_tokens: 48 });
    const generated = result[0]?.generated_text;
    output.textContent = typeof generated === 'string'
      ? generated
      : Array.isArray(generated)
        ? generated.at(-1)?.content ?? JSON.stringify(result)
        : JSON.stringify(result);
    status.textContent = 'Done.';
  } catch (error) {
    status.textContent = `Generation failed: ${error.message}`;
    console.error(error);
  } finally {
    button.disabled = false;
  }
});
Transformers.js 4.3.0のリリース例にあるONNXモデルと`q4f16`を使います。生成時はページ内のpipelineへ入力を渡します。

ページを配信し、結果と初回ダウンロードを確認する

ファイルを保存したフォルダーでターミナルを開き、以下のコマンドをどちらか一つ実行します。`http://127.0.0.1:8000`を開き、状態が`Ready:`になったらGenerateを押します。初回はモデルの取得に時間がかかります。準備が終わると、入力した文に対する短い結果が表示されます。

どちらのコマンドも、このコンピューターからだけ接続できるようにアドレスを限定しています。Node.jsなら一つ目、Pythonがあれば二つ目を選びます。公開サイトではHTTPSを使ってください。

サーバー起動 — Node.jsまたはPythonのどちらか
# Option A: Node.js
npx serve --listen tcp://127.0.0.1:8000 .

# Option B: Python (choose one server, not both)
python3 -m http.server 8000 --bind 127.0.0.1
どちらを選んでも`http://127.0.0.1:8000`で開きます。

モデルが開かないときは、ダウンロードとGPUエラーを確認します。

WebGPU adapterを取得できない場合はCPU/WASM用の`q4`を使います。SafariはTransformers.js 4.3.0で対応が追加されたSafari 26以降かを確認し、ほかのブラウザーでは該当バージョンのWebGPU対応を別途確認してください。adapterを取得できてもメモリ不足でモデルの読み込みに失敗する場合があります。

モデルファイルを読み込めない場合は、ブラウザー開発者ツールのNetworkでCDNまたはHubへのリクエストがブロック・失敗していないか確認します。GPU deviceエラーが出たら、ほかのタブやアプリを閉じてCPU5用`q4`で再試行するか、より小さな対応モデルを選んでください。入力後にエラーが出たら、最初のconsoleエラーとモデルID・dtype・deviceの組み合わせを記録すると再現に役立ちます。

ブラウザーでの抽出結果をJSON形式で受け取る

回答を別のプログラムに渡すときは、文章よりJSONが便利な場合があります。たとえば商品への意見から感情と話題だけを取り出せます。4.3.0の実験機能である構造化出力は、JSON Schemaでフィールドと値を制限します。現在は一度に一つの結果を生成します。

この機能には別のパッケージが必要です。以下のコードは先ほどのCDN HTMLに貼り付けず、ViteなどのモジュールバンドラーがあるWebプロジェクトで使います。依存パッケージを導入し、JavaScriptファイルにコードを追加します。結果は`JSON.parse()`で読み取り、必要なフィールドを確認してから利用してください。

バンドラープロジェクトに依存パッケージを導入
npm install @huggingface/transformers@4.3.0 @huggingface/transformers-structured-output
静的HTMLの例とは異なり、npmパッケージを解決する開発環境が必要です。
StructuredOutputProcessorで感情と話題を制約する
import { pipeline } from '@huggingface/transformers';
import { StructuredOutputProcessor } from '@huggingface/transformers-structured-output';

const generator = await pipeline('text-generation', 'onnx-community/LFM2.5-350M-ONNX', {
  dtype: 'q4f16', device: 'webgpu',
});

const processor = new StructuredOutputProcessor(generator.tokenizer, {
  type: 'json_schema',
  json_schema: {
    type: 'object',
    properties: {
      sentiment: { enum: ['positive', 'negative', 'neutral'] },
      topic: { enum: ['price', 'quality', 'delivery', 'other'] },
    },
    required: ['sentiment', 'topic'],
    additionalProperties: false,
  },
});

const result = await generator(
  [{ role: 'user', content: 'Classify this feedback: Shipping was fast, but the product is expensive.' }],
  { max_new_tokens: 48, do_sample: false, logits_processor: [processor] },
);
const jsonText = result[0].generated_text.at(-1).content;
console.log(JSON.parse(jsonText));
WebGPUに対応するブラウザーで実行します。

用語の注釈

  1. パイプライン — 入力から出力まで続く処理段階のまとまりです。段階ごとに異なるモデルやツールを使うことがあります。

    本文に戻る
  2. WebGPU — ウェブブラウザーでグラフィックスや汎用GPU計算を行うための標準APIです。対応機能はブラウザーや端末によって異なることがあります。

    本文に戻る
  3. システムRAM — プログラムの実行中にデータを一時保存するシステムメモリです。

    本文に戻る
  4. GPU — 多くの計算を並列に処理するプロセッサーです。AIモデルの実行ではモデル計算を担います。

    本文に戻る
  5. CPU — コンピューターで汎用のプログラム命令を実行する中央処理装置です。AI処理ではGPUなど他のプロセッサーと役割を分けることがあります。

    本文に戻る