👨‍💻

WebLLMを使ってブラウザ完結かつローカルLLMでFunction callingを試してみる

に公開
1

前の記事

wllama(Wasm binding for llama.cpp)を使ってローカルLLMを使ったダッシュボードを作った
https://zenn.dev/tesla/articles/e3ec9fe5e15c9a

リポジトリ

https://github.com/tesla0225/webllm-poc

実装したこと

  • マルチプロンプト Chat — System + User を結合し、ストリーム出力(ask() in Chat.tsx
  • OpenAI 互換 Function Calltools 配列 → tool_calls JSON(weatherTool 切替トグル)
  • DL 進捗バーinitProgressCallback で重みロード%を表示(エンジン初期化ブロック)
  • クライアントキャッシュ削除 — IndexedDB & CacheStorage をワンクリックで削除(clearCache()
  • モード切替 UI — ラジオボタンで Chat / Function を選択(Chat.tsx 冒頭 JSX)

内部構成

実行パス

Service‑Worker モードでは IndexedDB を CacheStorage に置き換え、fetch ストリームで読み込みを最適化。


コード解剖(TypeScript + React)

主要部分のみ抜粋。全文はリポジトリ参照。

定数 & エンジン初期化

const MODEL_ID = "Hermes-2-Pro-Mistral-7B-q4f16_1-MLC";

const eng = await CreateMLCEngine(MODEL_ID, {
  initProgressCallback: ({ progress }) => setProgress(progress),
});
await eng.reload(MODEL_ID); // chat API が保証される

Chat と Function‑Call の切替

const baseReq =
  mode === "func"
    ? {
        messages: [{ role: "user", content: userPrompt }],
        tools: [weatherTool],
        tool_choice: "auto",
      }
    : {
        messages: [
          { role: "system", content: systemPrompt },
          { role: "user", content: userPrompt },
        ],
      };

tools 使用時はモデルが内部 System プロンプトを挿入するため、独自 System プロンプトは送らない。

レスポンス処理

const { tool_calls, content } = res.choices[0].message;
setReply(tool_calls?.length ? JSON.stringify(tool_calls, null, 2) : content ?? "(空応答)");

JSON (tool_calls) かテキストのいずれかを画面に表示。

キャッシュ削除

// IndexedDB
(await indexedDB.databases())
  .filter(d => d.name?.startsWith("mlc_llm_db"))
  .forEach(d => indexedDB.deleteDatabase(d.name!));
// CacheStorage
(await caches.keys())
  .filter(k => k.startsWith("mlc-chat-cache"))
  .forEach(k => caches.delete(k));

削除後に window.location.reload() でエンジンを再初期化。


拡張アイデア

  1. ツール追加 — Schema 定義のみでフロント完結。
  2. モデル差し替え — Gemma・Phi‑3・Llama‑3 など MLC ビルド済み。
  3. 履歴永続化 — IndexedDB にメッセージも保存。
  4. PWA 化 — SW 版は済み、manifest とアイコンを足すだけ。

まとめ

  • WASM + WebGPU + IndexedDB + Service‑Worker の純 Web 標準スタック。
  • Function Callを一応試せる

感想

Function callingが使える7Bモデルをブラウザで動かしてみたが、多分結構調整が必要そう
かなり簡単に(ほぼ1ファイル)でセットアップできたので便利

1

Discussion