近年、ブラウザ上で動作するAIの可能性が大きく注目されています。特に、ユーザーのプライバシー保護やオフラインでの利用、高速な応答が求められる場面で、ローカルAIの需要は高まる一方です。Hugging Faceが提供するTransformers.jsは、このニーズに応える強力なライブラリであり、Chrome拡張機能にAI機能を組み込むための道を開きます。
本記事では、Transformers.jsをChrome拡張機能(Manifest V3)で活用し、ローカルAI機能を実装するための実践的なアーキテクチャとノウハウを深掘りします。単なる技術解説に留まらず、開発者が直面するであろう課題とその解決策、そしてユーザーにとってのメリットまでを詳細に解説し、「がじぇおた!!」読者の皆様が次世代のブラウザ体験を創造するための一助となることを目指します。

Transformers.jsでChrome拡張機能にローカルAIを実装する意義
なぜ今、Chrome拡張機能にローカルAIを実装することが重要なのでしょうか。その最大の理由は、ユーザー体験の向上とプライバシー保護にあります。
ユーザー体験の革新とプライバシーの確保
従来のAI機能は、多くの場合クラウドベースで提供されてきました。これは強力な計算リソースを利用できる反面、インターネット接続が必須であり、データが外部サーバーに送信されるというプライバシー上の懸念が常に伴います。また、API呼び出しの遅延やコストも無視できません。
Transformers.jsを活用してAIモデルをブラウザ内で直接実行することで、これらの課題を解決できます。ユーザーのデータはデバイスから離れることなく処理され、プライバシーが強固に保護されます。さらに、ネットワーク遅延の影響を受けないため、より高速でシームレスなAI体験を提供することが可能になります。オフライン環境でもAI機能が利用できる点も大きなメリットです。
Hugging Face Transformers.jsが提供する価値
Hugging FaceのTransformers.jsは、Pythonで広く利用されているTransformersライブラリのJavaScript版です。これにより、Web開発者は馴染み深いJavaScript環境で、最先端の機械学習モデルを簡単に利用できるようになります。テキスト生成、感情分析、画像認識など、多岐にわたるタスクに対応する豊富なモデルが提供されており、これらをブラウザ上で効率的に実行するための最適化が施されています。
特に、Chrome拡張機能のような制約のある環境下で、大規模なAIモデルを安定して動作させるための基盤として、Transformers.jsは非常に強力な選択肢となります。モデルの読み込み、推論の実行、キャッシュ管理といった複雑なプロセスを抽象化し、開発者がアプリケーションロジックに集中できる環境を提供します。
Manifest V3時代のChrome拡張機能アーキテクチャ
Chrome拡張機能のアーキテクチャは、Manifest V3への移行により大きく変化しました。特に、バックグラウンドスクリプトがサービスワーカーベースになったことで、AIモデルの実行環境にも影響があります。Transformers.jsを統合する上で、この新しいアーキテクチャを理解することは不可欠です。
サービスワーカー、サイドパネル、コンテンツスクリプトの役割
本プロジェクトのアーキテクチャは、以下の3つの主要なエントリーポイントで構成されています。
- バックグラウンドサービスワーカー (
background.js): 拡張機能の「頭脳」であり、コントロールプレーンです。AIモデルの初期化、推論の実行、エージェントのライフサイクル管理、ツール実行など、重い処理や共有サービスを担います。サービスワーカーは必要に応じて起動・停止されるため、モデルの状態は再初期化可能である必要があります。 - サイドパネルUI (
sidebar.html): ユーザーとのインタラクション層です。チャットの入力・出力、ストリーミング更新、設定コントロールなど、ユーザーインターフェースの表示と操作を担当します。UIは軽量に保ち、重い処理はバックグラウンドに委譲します。 - コンテンツスクリプト (
content.js): ウェブページとの橋渡し役です。DOMからの情報抽出や、ページ内の要素のハイライト表示など、ページレベルのアクションを実行します。Chromeのセキュリティ境界により、コンテンツスクリプトは直接DOMにアクセスできますが、他の拡張機能コンポーネントとは分離されています。
この分離されたアーキテクチャにより、UIの応答性を保ちつつ、セキュリティを強化し、モデルの重複ロードを防ぐことができます。例えば、会話履歴はバックグラウンドサービスワーカーで一元管理され、UIはバックグラウンドからの更新を受け取って表示を更新します。
各コンポーネント間のメッセージング
異なるランタイム間で連携するためには、メッセージングが不可欠です。本プロジェクトでは、型付けされたメッセージ(src/shared/types.tsで定義されたenum)を通じて、各コンポーネントが通信します。
- サイドパネル → バックグラウンド: モデルのチェック、初期化、エージェントの初期化、テキスト生成、メッセージ取得、クリア、特徴抽出などのタスクをリクエストします。
- バックグラウンド → サイドパネル: ダウンロードの進捗、メッセージの更新などをUIに通知します。
- バックグラウンド → コンテンツスクリプト: ページデータの抽出、要素のハイライト、ハイライトのクリアなどのアクションを指示します。
バックグラウンドサービスワーカーが唯一のコーディネーターとして機能し、サイドパネルとコンテンツスクリプトは専門のワーカーとしてアクションを要求し、結果をレンダリングするというシンプルなオーケストレーションルールが適用されます。これにより、複雑な処理の流れが整理され、デバッグやメンテナンスが容易になります。
Transformers.jsモデルの統合と効率的な運用
Transformers.jsをChrome拡張機能に統合する際、モデルの選定、推論の実行場所、そしてダウンロードとキャッシュの管理は、パフォーマンスとユーザー体験に直結する重要な要素です。
Gemma 4 E2BとMiniLMの役割分担
本拡張機能では、2種類のモデルがそれぞれの役割を担っています。
- テキスト生成 / LLM (
onnx-community/gemma-4-E2B-it-ONNX): 主に推論とツール呼び出しの決定を担当します。text-generationパイプラインとして、q4f16(4ビット量子化、float16)のデータ型で効率的に動作します。 - ベクトル埋め込み (
onnx-community/all-MiniLM-L6-v2-ONNX):feature-extractionパイプラインとして、fp32(float32)のデータ型で動作し、ウェブサイトの質問応答や履歴検索におけるセマンティック類似性検索のためのベクトル埋め込みを生成します。
このように役割を分担することで、それぞれのタスクに最適なモデルを選択し、リソースを効率的に利用しています。Gemma 4 E2Bが高度な推論と意思決定を行い、MiniLMが高速な情報検索をサポートするという連携が、拡張機能の機能を強化します。
バックグラウンドでの推論実行とキャッシュ戦略
すべての推論処理は、バックグラウンドサービスワーカー内で実行されます。これにより、以下のメリットが得られます。
- 単一のモデルホスト: すべてのタブやセッションに対して、モデルは一度だけロードされます。これにより、メモリの重複使用が避けられ、リソースが節約されます。
- UIの応答性維持: 重い推論処理がバックグラウンドで行われるため、サイドパネルUIは常にスムーズで応答性の高い状態を保てます。
- 共有キャッシュ: モデルのアーティファクトは、拡張機能のオリジン(
chrome-extension://<extension-id>)の下にキャッシュされます。これにより、拡張機能全体で共有される単一のキャッシュが実現し、モデルのダウンロードと初期化が効率化されます。
サービスワーカーはサスペンド・再起動される可能性があるため、モデルのランタイム状態は必要に応じて回復・再初期化できるように設計されています。これはManifest V3における重要な考慮事項です。
モデルのダウンロードとライフサイクル管理
モデルのライフサイクルは明示的に管理されます。
CHECK_MODELS: 既にキャッシュされているモデルを検査し、残りのダウンロードサイズを推定します。INITIALIZE_MODELS: モデルをダウンロード・初期化し、ダウンロードの進捗をUIにDOWNLOAD_PROGRESSメッセージとして通知します。
一度セットアップされたモデルインスタンスは、テキスト生成パイプライン(src/background/agent/Agent.ts)や埋め込みパイプライン(src/background/utils/FeatureExtractor.ts)で再利用されます。これにより、不要な再ロードを避け、効率的な運用が実現します。
エージェントとツール呼び出しによる高度な機能実現
単にテキストを生成するだけでなく、AIがブラウザの機能と連携して具体的なアクションを実行できるようにするためには、「ツール呼び出し」の概念が不可欠です。これにより、AIは単なるチャットボットを超え、真の「アシスタント」として機能します。
ツール呼び出しの基本とモデル連携
エージェントワークフローの基盤となるのがツール呼び出しです。これは、モデルにメッセージとツールスキーマ(名前、説明、パラメータ)を渡すことで機能します。Transformers.jsは、これらの入力からモデルのチャットテンプレートを使用してプロンプトをフォーマットします。モデルがツールを呼び出すと判断した場合、特定のツール呼び出しトークンブロックを出力します。
例えば、ユーザーが「ベルンの天気は?」と尋ねた場合、モデルは<|tool_call>call:getWeather{location:<|"|>Bern<|"|>}<tool_call|>のような出力を生成します。このモデルの出力を、実際に実行可能なツールアクションに変換するための正規化レイヤー(webMcp)とパーサー(extractToolCalls)が重要になります。
プロジェクトにおけるツールインターフェースの具体例
src/background/agent/webMcp.tsxでは、拡張機能のツールがモデルフレンドリーな形式(name、description、inputSchema、execute)に正規化されます。具体的なツールには以下のようなものがあります。
get_open_tabs: 開いているタブの情報を取得する。go_to_tab: 特定のタブに移動する。open_url: 新しいURLを開く。close_tab: タブを閉じる。find_history: 閲覧履歴を検索する。ask_website: 現在のウェブサイトの内容について質問する。highlight_website_element: ウェブサイト上の要素をハイライト表示する。
これらのツールを組み合わせることで、AIはユーザーの指示に基づいてブラウザを操作し、情報収集やタスク実行を支援できるようになります。
エージェント実行ループの設計思想
エージェントの実行ループ(Agent.runAgent)は、内部的なモデルメッセージとUIに表示されるチャットメッセージを分離して設計されています。
- 内部モデルトランスクリプト:
generator(...)で使用されるシステム/ユーザー/ツール/アシスタントのターン。 - UIトランスクリプト: ユーザーが見るメッセージ。ストリーミングされるアシスタントテキスト、ツール実行メタデータ、パフォーマンス指標を含む。
実行フローは以下のようになります。
- ユーザー入力を
chatMessagesに追加し、プレースホルダーのアシスタントメッセージを作成し、トークンをストリーミングします。 - ストリーミングされた、または最終的なモデル出力を
extractToolCalls.tsで解析し、{ message, toolCalls }を生成します。 - ユーザーに表示されるアシスタントメッセージはプレーンテキストとして保持し、ツール呼び出しはバックグラウンドで実行します。
- ツール結果をアシスタントのツールメタデータに追加し、次のプロンプトターンとして結果をフィードバックします。
- ツール呼び出しがなくなるまで繰り返し、最終的にアシスタントのコンテンツと指標を確定します。
この設計により、ユーザーとのコミュニケーションをクリーンに保ちつつ、バックグラウンドで決定論的なツールループを維持できます。
データ永続化とプライバシーへの配慮
Manifest V3環境におけるデータ管理は、セキュリティとパフォーマンスの両面で重要な考慮事項です。本実装では、データのライフサイクルとアクセスパターンに応じて、状態を適切に分割しています。
会話履歴、設定、セマンティック履歴の管理
- 会話状態 (
Agent.chatMessages): ターンごとの高速なオーケストレーションのために、バックグラウンドメモリに保持されます。これにより、UIの更新時にも一貫した状態が保たれます。 - ツール設定 (
chrome.storage.local): セッション間で設定が永続化されるように、Chromeのローカルストレージに保存されます。これは、拡張機能の設定やユーザーの好みを保存するのに適しています。 - セマンティック履歴ベクトル (
IndexedDB): 大規模なローカル検索データを保存するために、IndexedDBが使用されます。これにより、ユーザーの閲覧履歴や抽出されたウェブコンテンツから、関連性の高い情報を効率的に検索できます。 - 抽出されたページコンテンツ (
WebsiteContentManager): アクティブなURLをキーとして、バックグラウンドキャッシュに保存されます。これにより、同じページに再度アクセスした際に、コンテンツを再抽出する手間を省けます。
このデータ分割戦略により、短命な状態はメモリに、永続的な設定は拡張機能ストレージに、そして重い検索データはローカルデータベースに、とそれぞれの特性に合わせた最適な保存場所が選択されています。
必要な権限とユーザーへの信頼
拡張機能のpublic/manifest.jsonでは、以下の権限が要求されます。
sidePanel: サイドパネルUXを開き、制御するために必要です。storage: ツールや設定の状態をセッション間で永続化するために必要です。tabs+scripting: タブを認識するツールやページレベルのアクションのために必要です。host_permissions(http(s)://*/*): コンテンツの抽出やハイライトが任意のウェブサイトで機能するようにするために必要です。
権限はユーザーの信頼を定義し、Chromeウェブストアのレビューリスクにも影響します。そのため、実際に機能に必要な最小限の権限のみを要求し、推論が拡張機能のランタイム内でローカルに実行されることを明確に伝えることで、ユーザーが自身のデータ処理について理解し、安心して利用できるように配慮することが重要ですいです。
開発とデプロイのポイント
Manifest V3のChrome拡張機能を開発する上で、ビルドとパッケージングのプロセスは、各ランタイムが期待する出力形式に正確に合わせる必要があります。複雑なビルド設定は不要ですが、予測可能な出力が求められます。
ビルド設定の簡素化
vite.config.tsのようなビルドツールを使用する場合、複数のエントリーポイントを定義することが一般的です。本プロジェクトでは、以下のエントリーポイントが設定されています。
src/sidebar/index.htmlsrc/background/background.tssrc/content/content.ts
これらのエントリーポイントが、sidebar.html、background.js、content.jsといったManifestに合わせた出力名とパスになるように設定することが重要です。特にコンテンツスクリプトは、ランタイムでのチャンク読み込みの問題を避けるため、自己完結型の出力として維持する必要があります。
目標はシンプルです。Chromeの各エントリーポイントに対して1つのアーティファクトを、public/manifest.jsonが期待する正確な場所に配置することです。これにより、拡張機能のデプロイがスムーズになり、予期せぬエラーを防ぐことができます。
まとめ:Transformers.jsとMV3で実現する次世代ブラウザ体験
Transformers.jsとManifest V3のアーキテクチャを組み合わせることで、Chrome拡張機能は単なるユーティリティを超え、強力なローカルAIアシスタントへと進化します。バックグラウンドサービスワーカーがオーケストレーションとモデル実行を担い、UIは軽量に保たれ、コンテンツスクリプトがページアクセスを処理するという明確な関心事の分離が、このプロジェクト全体の成功を解き放つ鍵となります。
このアプローチは、サイドパネルを活用したコパイロット型アシスタントだけでなく、ポップアップを主体としたクイックアクションアシスタントや、タブごとに独立したエージェントなど、様々な形態のAI拡張機能に応用可能です。ユーザーのプライバシーを尊重しつつ、高速でパーソナライズされたAI体験を提供できることは、今後のWebブラウジングのあり方を大きく変える可能性を秘めています。
こんな開発者におすすめ
- Chrome拡張機能でAI機能を実装したいと考えているWeb開発者
- ユーザーデータを外部に送信せず、ローカルでAI処理を完結させたいプロジェクトの担当者
- Manifest V3の新しいアーキテクチャに合わせたAI統合のベストプラクティスを探している方
- Hugging Face Transformers.jsの可能性を最大限に引き出したいと考えているエンジニア
情報元:huggingface.co

