T-CREATOR

WebLLM チートシート:主要 API・初期化・推論・ストリーム制御 一覧

WebLLM チートシート:主要 API・初期化・推論・ストリーム制御 一覧

WebLLM を使ったブラウザ上での LLM 推論は、従来のサーバー依存型とは異なり、完全にクライアントサイドで動作します。しかし、その豊富な API と多様な設定オプションに圧倒されてしまう方も多いのではないでしょうか。

この記事では、WebLLM の主要 API を一覧化し、初期化から推論、ストリーム制御まで、実務で必要なすべての情報をチートシート形式でまとめました。手元に置いて、開発時の素早いリファレンスとしてご活用いただけます。

早見表:WebLLM API 一覧

初期化・エンジン作成 API

#API 名用途主要パラメータ戻り値
1CreateMLCEngine()エンジン初期化modelId, engineConfigPromise<MLCEngine>
2reload()モデル再読み込みmodelId, chatOptsPromise<void>
3unload()モデルアンロードなしPromise<void>

推論・チャット完了 API

#API 名用途主要パラメータ戻り値
1chat.completions.create()推論実行messages, stream, temperature などPromise<ChatCompletion> または AsyncIterable
2getMessage()現在のメッセージ取得modelId(省略可)Promise<string>
3resetChat()チャット履歴リセットkeepStats, modelIdPromise<void>

ストリーム制御 API

#パラメータ名用途設定値効果
1streamストリーム有効化true / falsetrue で AsyncIterable 返却
2stream_optionsストリームオプション{ include_usage: true }最終チャンクに usage 含める

モデル管理 API

#API 名用途使用タイミング注意点
1reload(modelId)モデル切り替え別モデル使用時既存モデルをアンロード後、新モデルをロード
2unload()全モデルアンロードメモリ解放時すべての読み込み済みモデルを解放

ユーティリティ API

#API 名用途戻り値活用場面
1getGPUVendor()GPU ベンダー名取得Promise<string>デバッグ、互換性チェック
2getMaxStorageBufferBindingSize()最大バッファサイズ取得Promise<number>メモリ制限確認

設定パラメータ(MLCEngineConfig)

#パラメータ名用途設定例
1appConfigモデルリスト設定AppConfigカスタムモデル指定
2initProgressCallback進捗コールバック(report: InitProgressReport) => void読み込み進捗表示
3logitProcessorRegistryカスタムロジット処理Map<string, LogitProcessor>出力制御

推論パラメータ(GenerationConfig)

#パラメータ名用途デフォルト値推奨範囲
1temperatureランダム性制御1.00.0 ~ 2.0
2top_p累積確率カット1.00.0 ~ 1.0
3max_tokens最大生成トークン数モデル依存モデル最大値まで
4stop停止シーケンスundefined文字列配列
5repetition_penalty繰り返しペナルティ1.01.0 ~ 2.0
6frequency_penalty頻度ペナルティ0.0-2.0 ~ 2.0
7presence_penalty存在ペナルティ0.0-2.0 ~ 2.0
8logit_biasトークンバイアスundefinedオブジェクト
9n生成数11 以上
10ignore_eosEOS トークン無視falsetrue / false

背景

ブラウザ上での LLM 推論の台頭

近年、WebGPU の登場により、ブラウザ上でも高速な機械学習推論が可能になりました。WebLLM は、この技術を活用してブラウザ内で完結する LLM 推論を実現するライブラリです。

従来のサーバーベースの LLM 推論と比較して、以下の特徴があります。

  • プライバシー保護:ユーザーデータがサーバーに送信されない
  • レイテンシ削減:ネットワーク通信が不要
  • コスト削減:サーバー費用が発生しない

WebLLM の API 設計思想

WebLLM は、OpenAI API との互換性を保ちながら、ブラウザ環境特有の要件に対応した設計になっています。初期化からモデル読み込み、推論実行まで、すべての処理が非同期で行われます。

以下の図は、WebLLM の基本的なアーキテクチャを示しています。

mermaidflowchart LR
  user["読者"] -->|アクセス| next["Next.js アプリ"]
  next -->|API 呼び出し| api["Backend API"]
  api -->|クエリ| db[("MySQL")]
  api -->|JSON| next
  next -->|HTML/JSON| user

図で理解できる要点:

  • WebLLM はブラウザ内で完結し、外部サーバーとの通信は初回モデルダウンロード時のみ
  • エンジンは WebGPU を通じて GPU アクセスし、高速推論を実現
  • モデルは IndexedDB にキャッシュされ、2 回目以降は即座にロード可能

API の多様性がもたらす柔軟性

WebLLM は、シンプルな使い方から高度なカスタマイズまで対応できる豊富な API を提供しています。しかし、その豊富さゆえに、どの API をどの場面で使うべきか迷うことも少なくありません。

課題

API 選択の複雑さ

WebLLM には、初期化、推論、ストリーム制御、モデル管理など、複数のカテゴリにわたる API が存在します。初心者にとっては、以下のような疑問が生じやすいでしょう。

  • 初期化時CreateMLCEngine のパラメータは何を指定すればよいのか
  • 推論時temperaturetop_p の適切な値は何か
  • ストリーム制御:どうすればリアルタイムで出力を表示できるのか
  • モデル切り替えreloadunload の使い分けはどうするのか

これらの疑問を解決するためには、公式ドキュメントを何度も参照する必要があり、開発効率が低下してしまいます。

パラメータ設定の最適化

推論時のパラメータ設定は、生成されるテキストの品質に直結します。しかし、各パラメータの役割と推奨値を理解していないと、期待通りの出力が得られません。

以下の図は、主要なパラメータが推論結果に与える影響を示しています。

mermaidflowchart LR
  input["入力プロンプト"] --> model["LLMモデル"]

  temp["temperature<br/>ランダム性"] --> model
  topp["top_p<br/>確率カット"] --> model
  maxtoken["max_tokens<br/>長さ制限"] --> model

  model --> output["生成テキスト"]

  style temp fill:#e1f5ff
  style topp fill:#e1f5ff
  style maxtoken fill:#e1f5ff

図で理解できる要点:

  • temperature が高いほど創造的だが不安定な出力
  • top_p で確率の低いトークンを除外し、品質を向上
  • max_tokens で生成長を制御し、コストとレスポンスのバランスを調整

ストリーム制御の実装難易度

リアルタイムで生成結果を表示するストリーム機能は、ユーザー体験を大きく向上させます。しかし、AsyncIterable の扱いに慣れていないと、実装に戸惑うことがあります。

特に、以下の点が課題となります。

  • ストリームの開始と終了の判定
  • 最終チャンクでのみ提供される usage データの取得
  • エラーハンドリングの実装

解決策

チートシート形式での整理

この記事では、WebLLM の API をカテゴリごとに整理し、一覧表形式で提供します。これにより、必要な情報を素早く見つけることができます。

WebLLM の API 体系は、以下のように分類できます。

mermaidflowchart TD
  api["WebLLM API"]

  api --> init["初期化・エンジン作成"]
  api --> inference["推論・チャット完了"]
  api --> stream["ストリーム制御"]
  api --> model["モデル管理"]
  api --> util["ユーティリティ"]
  api --> config["設定パラメータ"]

  init --> init1["CreateMLCEngine"]
  init --> init2["reload"]
  init --> init3["unload"]

  inference --> inf1["chat.completions.create"]
  inference --> inf2["getMessage"]
  inference --> inf3["resetChat"]

  stream --> st1["stream パラメータ"]
  stream --> st2["stream_options"]

  model --> mod1["reload"]
  model --> mod2["unload"]

  util --> ut1["getGPUVendor"]
  util --> ut2["getMaxStorageBufferBindingSize"]

  config --> cfg1["MLCEngineConfig"]
  config --> cfg2["GenerationConfig"]

  style init fill:#fff4e6
  style inference fill:#e3f2fd
  style stream fill:#f3e5f5
  style model fill:#e8f5e9
  style util fill:#fce4ec
  style config fill:#fff9c4

図で理解できる要点:

  • API は 6 つの主要カテゴリに分類
  • 初期化とモデル管理は reload を共有
  • 推論とストリームは密接に関連
  • 設定パラメータは各 API に横断的に適用

パラメータの推奨値と使い分け

各パラメータには、使用場面に応じた推奨値があります。以下の基準を参考にしてください。

temperature の使い分け

  • 0.0 ~ 0.3:事実ベースの回答、翻訳、要約など、正確性が求められる場面
  • 0.7 ~ 1.0:一般的な会話、バランスの取れた出力
  • 1.5 ~ 2.0:創造的な文章生成、アイデア出し

top_p の使い分け

  • 0.9 ~ 1.0:多様な表現を許容
  • 0.7 ~ 0.9:バランスの取れた出力(推奨)
  • 0.5 ~ 0.7:より保守的な出力

ストリーム実装のベストプラクティス

ストリーム機能を実装する際は、以下のパターンを活用できます。

  • for-await-of ループ:最も直感的な実装方法
  • エラーハンドリング:try-catch でストリーム中のエラーをキャッチ
  • usage データの取得:最終チャンクの判定が重要

具体例

初期化の実装例

ここからは、実際のコード例を通じて、WebLLM の各 API の使い方を見ていきましょう。

基本的な初期化

最もシンプルな初期化方法です。モデル ID のみを指定します。

typescriptimport { CreateMLCEngine } from '@mlc-ai/web-llm';

以下のコードで、エンジンを作成します。

typescript// モデルIDを指定してエンジンを作成
const engine = await CreateMLCEngine(
  'Llama-3.1-8B-Instruct-q4f32_1-MLC'
);

進捗表示付き初期化

モデルのダウンロードと読み込みには時間がかかるため、進捗を表示することでユーザー体験が向上します。

typescriptimport { CreateMLCEngine } from '@mlc-ai/web-llm';

以下のコードで、進捗コールバックを設定します。

typescript// 進捗表示用のコールバック関数を定義
const initProgressCallback = (report) => {
  // report.progress は 0.0 ~ 1.0 の値
  const percent = (report.progress * 100).toFixed(1);
  console.log(`読み込み中: ${percent}%`);
  console.log(`現在のタスク: ${report.text}`);
};

コールバックをエンジン設定に渡して初期化します。

typescript// エンジン設定を作成
const engineConfig = {
  initProgressCallback: initProgressCallback,
};

// エンジンを作成
const engine = await CreateMLCEngine(
  'Llama-3.1-8B-Instruct-q4f32_1-MLC',
  engineConfig
);

ポイントreport.progress は 0.0 から 1.0 の範囲で提供されるため、パーセンテージ表示には 100 を掛けます。

カスタムモデル設定

独自にホスティングしたモデルを使用する場合は、appConfig を指定します。

typescript// カスタムモデル設定を定義
const appConfig = {
  model_list: [
    {
      model: 'https://example.com/models/my-model',
      model_id: 'my-custom-model',
      model_lib:
        'https://example.com/libs/my-model-lib.wasm',
    },
  ],
};

設定をエンジンに適用します。

typescript// エンジン設定にカスタムモデルを含める
const engineConfig = { appConfig };

const engine = await CreateMLCEngine(
  'my-custom-model',
  engineConfig
);

推論の実装例

シンプルな推論

最も基本的な推論の実行方法です。メッセージを送信し、完全な応答を受け取ります。

typescript// メッセージ配列を作成
const messages = [
  {
    role: 'system',
    content: 'あなたは親切なAIアシスタントです。',
  },
  { role: 'user', content: 'こんにちは!' },
];

chat.completions.create メソッドで推論を実行します。

typescript// 推論を実行
const response = await engine.chat.completions.create({
  messages: messages,
});

// 応答を取得
const reply = response.choices[0].message.content;
console.log(reply);

パラメータ調整済み推論

生成品質をコントロールするため、各種パラメータを指定します。

typescript// 詳細なパラメータを指定した推論
const response = await engine.chat.completions.create({
  messages: messages,
  temperature: 0.7, // 適度なランダム性
  top_p: 0.9, // 上位90%の確率でサンプリング
  max_tokens: 512, // 最大512トークンまで生成
  frequency_penalty: 0.5, // 繰り返しを抑制
  presence_penalty: 0.2, // 多様性を促進
});

ポイントtemperaturetop_p を同時に指定することで、生成のランダム性と品質のバランスを取ります。

使用トークン数の確認

API 利用量を把握するため、使用トークン数を確認します。

typescript// 推論実行
const response = await engine.chat.completions.create({
  messages: messages,
});

レスポンスから使用統計を取得します。

typescript// 使用トークン数を取得
const usage = response.usage;
console.log(`プロンプトトークン数: ${usage.prompt_tokens}`);
console.log(`生成トークン数: ${usage.completion_tokens}`);
console.log(`合計トークン数: ${usage.total_tokens}`);

ストリーム制御の実装例

基本的なストリーム実装

ストリームを有効にすることで、生成されたテキストをリアルタイムで取得できます。

typescript// ストリームを有効化
const chunks = await engine.chat.completions.create({
  messages: messages,
  stream: true,
});

for-await-of ループでチャンクを順次処理します。

typescript// チャンクを順次処理
for await (const chunk of chunks) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) {
    // リアルタイムで画面に表示
    process.stdout.write(delta);
  }
}

ポイントdelta.content には新しく生成されたテキスト片が含まれます。

使用統計付きストリーム

ストリーム終了後に使用トークン数を取得するには、stream_options を設定します。

typescript// 使用統計を含めるオプションを指定
const chunks = await engine.chat.completions.create({
  messages: messages,
  stream: true,
  stream_options: { include_usage: true },
});

最終チャンクから統計を取得します。

typescriptlet fullText = '';
let usageData = null;

// チャンクを処理
for await (const chunk of chunks) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) {
    fullText += delta;
  }

  // 最終チャンクに usage が含まれる
  if (chunk.usage) {
    usageData = chunk.usage;
  }
}

console.log(
  `\n生成完了: ${usageData.total_tokens} トークン使用`
);

エラーハンドリング付きストリーム

ストリーム中のエラーを適切に処理します。

typescripttry {
  const chunks = await engine.chat.completions.create({
    messages: messages,
    stream: true
  });

ループ内でエラーをキャッチします。

typescript  for await (const chunk of chunks) {
    const delta = chunk.choices[0]?.delta?.content;
    if (delta) {
      process.stdout.write(delta);
    }
  }
} catch (error) {
  console.error("ストリーム中にエラーが発生:", error.message);
  // エラーハンドリング処理
}

モデル切り替えの実装例

動的なモデル切り替え

アプリケーション実行中に別のモデルに切り替えることができます。

typescript// 初期モデルでエンジンを作成
const engine = await CreateMLCEngine(
  'Llama-3.1-8B-Instruct-q4f32_1-MLC'
);

// 推論を実行
let response = await engine.chat.completions.create({
  messages: [
    { role: 'user', content: '軽量モデルでの応答' },
  ],
});

別のモデルに切り替えます。

typescript// 別のモデルに切り替え
await engine.reload('Llama-3.2-3B-Instruct-q4f16_1-MLC');

// 切り替え後のモデルで推論
response = await engine.chat.completions.create({
  messages: [
    { role: 'user', content: '新しいモデルでの応答' },
  ],
});

ポイントreload を呼び出すと、既存のモデルは自動的にアンロードされます。

メモリ解放

使用が終わったモデルをメモリから解放します。

typescript// すべてのモデルをアンロード
await engine.unload();

console.log('メモリを解放しました');

GPU 情報の取得

動作環境を確認するため、GPU 情報を取得できます。

typescript// GPUベンダー名を取得
const vendor = await engine.getGPUVendor();
console.log(`GPU: ${vendor}`);

最大バッファサイズも確認できます。

typescript// 最大ストレージバッファサイズを取得
const maxSize =
  await engine.getMaxStorageBufferBindingSize();
console.log(`最大バッファサイズ: ${maxSize} バイト`);

チャット履歴のリセット

長時間の会話では、コンテキストが肥大化します。定期的にリセットすることで、メモリ使用量を抑えられます。

typescript// 統計情報を保持したままチャット履歴をリセット
await engine.resetChat(true);

完全にリセットする場合は、以下のようにします。

typescript// 統計情報も含めて完全にリセット
await engine.resetChat(false);

ポイントkeepStatstrue にすると、トークン使用量などの統計情報は保持されます。

実践的な組み合わせ例

実際のアプリケーションでは、複数の API を組み合わせて使用します。以下は、進捗表示とストリーム出力を組み合わせた例です。

typescriptimport { CreateMLCEngine } from "@mlc-ai/web-llm";

// 進捗表示とストリームを組み合わせた実装
async function runWebLLM() {
  // 進捗表示付きで初期化
  const engine = await CreateMLCEngine(
    "Llama-3.1-8B-Instruct-q4f32_1-MLC",
    {
      initProgressCallback: (report) => {
        console.log(`初期化中: ${(report.progress * 100).toFixed(1)}%`);
      }
    }
  );

ストリーム推論を実行します。

typescript// ストリームで推論実行
const messages = [
  {
    role: 'system',
    content: 'あなたは技術的な質問に答えるAIです。',
  },
  {
    role: 'user',
    content: 'WebLLMの利点を3つ教えてください。',
  },
];

const chunks = await engine.chat.completions.create({
  messages: messages,
  stream: true,
  temperature: 0.7,
  max_tokens: 300,
});

リアルタイムで結果を表示します。

typescript  // リアルタイム表示
  console.log("\n=== 応答 ===");
  for await (const chunk of chunks) {
    const delta = chunk.choices[0]?.delta?.content;
    if (delta) {
      process.stdout.write(delta);
    }
  }

  console.log("\n=== 完了 ===");
}

runWebLLM();

まとめ

WebLLM は、ブラウザ上で完結する LLM 推論を実現する強力なライブラリです。本記事では、主要 API を以下のカテゴリに分類して整理しました。

初期化・エンジン作成では、CreateMLCEngine による基本的な初期化から、進捗表示やカスタムモデル設定まで対応できます。適切な設定により、ユーザー体験を大きく向上させることが可能です。

推論・チャット完了では、chat.completions.create を中心に、パラメータ調整による品質制御が重要です。temperaturetop_p の適切な設定により、用途に応じた最適な出力を得られます。

ストリーム制御では、stream: true の指定により、リアルタイムな応答表示を実現できます。stream_options を活用することで、使用統計も適切に取得できます。

モデル管理では、reloadunload により、動的なモデル切り替えとメモリ管理が可能です。アプリケーションの要件に応じて、柔軟にモデルを切り替えられます。

ユーティリティ APIでは、GPU 情報の取得やチャット履歴のリセットなど、運用上重要な機能が提供されています。

設定パラメータでは、MLCEngineConfigGenerationConfig の理解が、WebLLM を効果的に活用する鍵となります。

このチートシートを手元に置いて、WebLLM 開発を効率的に進めていただければ幸いです。各 API の詳細な挙動や最新の機能については、公式ドキュメントも併せてご確認ください。

関連リンク