\n\n\n\nloadModel 関数は、タスク名、モデル ID、およびオプションを指定して pipeline() を呼び出します。progress_callback はダウンロード中に繰り返し発火し、ステータステキストを更新することで、ユーザーがフリーズした画面を見つめ続けることがないようにしています。モデルの読み込みが完了すると、ボタンが有効化されます。ユーザーが「Classify」をクリックすると、classifier(text) がキャッシュから同期で推論を実行します。これは通常、最新のラップトップでは 200 ミリ秒未満で完了します。結果は最初の配列要素から label と score をデストラクチャリングし、信頼度をパーセンテージ形式に変換して、色分け用の CSS クラスを適用します。\n\n## # タスク 2: ゼロショット分類\n\nゼロショット分類は、通常のテキスト分類ではできないことを実現します。つまり、学習データなしで、実行時に定義したカテゴリにテキストを分類できるのです。テキストとラベルのリスト(英語の自然言語)を渡すだけで、モデルはその言語の意味理解に基づいて、最も適切なラベルを決定します。\n\nこれは、ラベル付き例に対してモデルを訓練できない場合や、そうしたくない場合に役立ちます。実際のプロジェクトでは、ほとんどのケースでこの状況に直面します。\n\n## // 内部仕組みの解説\n\nモデルは各候補ラベルを自然言語推論(NLI)仮説として再構成します。例えば「billing issue」というラベルの場合、「This text is about a billing issue」という仮説を生成し、入力テキストによってその仮説が導かれる確率を計算します。最も高い推定スコアを持つラベルが勝利となります。この[NLI ベースのアプローチ](https://huggingface.co/tasks/zero-shot-classification)こそが、任意の記述的な英語フレーズをラベルとして使用して意味のある結果を得られる理由です。モデルはラベルの表面形式だけでなく、その意味も理解しています。\n\n出力の例:\n\nconst classifier = await pipeline('zero-shot-classification',\n 'Xenova/bart-large-mnli');\n\nconst result = await classifier(\n 'My invoice is wrong and I was charged twice.',\n ['billing', 'technical support', 'shipping', 'returns', 'account access']\n);\n\n// {\n// sequence: 'My invoice is wrong and I was charged twice.',\n// labels: ['billing', 'returns', 'account access', 'technical support', 'shipping'],\n// scores: [0.871, 0.063, 0.031, 0.022, 0.013]\n// }\n\n出力は 3 つのフィールドを持つオブジェクトです。sequence は元の入力テキスト、labels は候補ラベルをスコアの高い順に並べた配列、scores は同じ順序で並べられた信頼度スコアの配列です。両方の配列の最初の要素は常に勝者予測となります。multi_label が false の場合(デフォルト)、すべてのラベルに対するスコアの合計は約 1 になります。\n\nmulti_label を true に設定すると動作が変化し、各ラベルが競合するのではなく独立してスコアリングされるようになります。これにより、複数のラベルが同時に高いスコアを獲得することが可能になります。テキストが一度に複数のカテゴリに属する可能性がある場合にこの設定を使用してください。\n\n## // Full Working Example\n\n以下は、すべての HTML 括弧を完全にエスケープした更新済みのスクリプトブロックです。これを WordPress のカスタム HTML ブロックに直接貼り付けるだけで、コードスニペットとして完璧にレンダリングされます。\n\n\n\n\n \n \n ゼロショット分類器 -- サポートチケットルーター\n \n\n\n

サポートチケットルーター

\n

サポートチケットを貼り付けてください。学習データなしで、モデルが適切な部署へ自動的に振り分けます。

\n\n \n\n\n\n\n
Downloading model on first run...
\n
\n\n \n\n\n\nDEPARTMENTS アレイは、このシステムが必要とするすべてのルーティング設定です。トレーニングデータもラベル付けされた例も不要です。チケットが到着すると、classifier(text, DEPARTMENTS, { multi_label: false }) が内部で 5 つの帰結チェックをすべて実行し、結果をランク付けして返します。結果ループは、各部署のスコアを示す横棒グラフを構築し、ソートされた可視化により、チケットがどこへ送られるべきか、そしてモデルがどの程度確信を持っているかが一目でわかります。DEPARTMENTS アレイを全く異なるラベルに変更しても、そのアレイ以外にコードを変更する必要なく、モデルは正しくルーティングします。\n\n## # タスク 3: 質問応答\n\n **\nTransformers.js における質問応答は抽出型です。文脈としてテキストの段落を提供し、平易な英語で質問を投げかけます。モデルはその中から質問に最もよく答えるスパン(連続した文字列)を検出し、それを返します。文脈に明示的に含まれている内容を超えてテキストを生成したり推論したりすることはありません。回答は常にあなたが提供した入力の一部です。\n\nこれはドキュメントの照会に適しています。ユーザーがドキュメントを提供し、モデルがその中を探索します。\n\n出力の例:\n\nconst qa = await pipeline('question-answering', 'Xenova/distilbert-base-uncased-distilled-squad');\n\nconst result = await qa({\n question: 'What is the return window for electronics?',\n context: `Our return policy allows customers to return most items within 30 days\n of purchase. Electronics must be returned within 15 days and must be\n in original packaging. Software and digital downloads are non-refundable.`\n});\n\n// {\n// answer: '15 days',\n// score: 0.9823,\n// start: 97, // character index of answer start in context\n// end: 104 // character index of answer end in context\n// }\n\n出力には 4 つのフィールドがあります。answer は抽出された部分文字列です。score は、このスパンが質問に対する回答であるとモデルがどの程度確信しているかを示す値です。start と end は、元のコンテキスト内における文字インデックスであり、これらを使用してソーステキスト内の回答部分をハイライト表示できます。これは、長いドキュメントにおいて非常に有用な UX(ユーザーエクスペリエンス)となります。\n\n質問に対してコンテキスト内に明確な答えがない場合、score は低くなり、answer は短くランダムに見えるスパンになることがあります。信頼度が低い回答(0.3 または 0.4 を下回るもの)を「見つかりませんでした」として扱うことは、標準的なプラクティスです。\n\n## // Full Working Example\n\nDocument Q&A の記事ブロックに使用するためのエスケープ済みコードを以下に示します。これにより、script およびテンプレート内のすべての `<` や `>` 括弧が正しく処理され、サイト上できれいに表示されます。\n\n\n\n\n \n \n Transformers.js を使ったドキュメント Q&A\n \n\n\n

ドキュメント質問応答

\n

任意のドキュメントを貼り付けて、それについて質問してください。\n 回答はテキストから直接抽出されます。

\n\n \n \n\n \n \n \n
\n
\n 回答:
\n
\n
\n\n \n\n\n\nお客様は、購入日から 30 日以内であれば、ほとんどの標準商品を全額返金対象として返品できます。電子機器および周辺機器は返品期間が 15 日間と短く、対象となるためには未開封の元の包装状態で返品する必要があります。\n\n返品された商品を受領してから 3〜5 営業日以内に返金処理が行われます。元々の送料は返金されません。200 ドル以上の価値がある商品の返品を希望される場合は、返品手続きを開始する前に returns@acmecorp.com までサポートへお問い合わせください。\n\nソフトウェアライセンスおよびデジタルダウンロード商品は、いかなる場合でも返金対象となりません。ギフトカードの現金化や交換はできません。\n\nYour Question\nHow long does it take to process a refund?\nLoading model...\nDownloading model on first run...\n\nimport { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.0.2';\n\nconst contextEl = document.getElementById('context');\nconst questionEl = document.getElementById('question');\nconst statusEl = document.getElementById('status');\nconst answerBox = document.getElementById('answer-box');\nconst btn = document.getElementById('ask-btn');\n\nconst CONFIDENCE_THRESHOLD = 0.1;\n\nlet qaModel;\n\nasync function loadModel() {\n qaModel = await pipeline(\n 'question-answering',\n 'Xenova/distilbert-base-uncased-distilled-squad',\n {\n dtype: 'q8',\n progress_callback: (p) => {\n if (p.status === 'progress') {\n statusEl.textContent =\n `Downloading model: ${Math.round(p.progress ?? 0)}%`;\n }\n }\n }\n );\n\n btn.disabled = false;\n btn.textContent = 'Ask';\n statusEl.textContent = 'Model ready.';\n }\n\n async function askQuestion() {\n const context = contextEl.value.trim();\n const question = questionEl.value.trim();\n if (!context || !question) return;\n\n btn.disabled = true;\n btn.textContent = 'Thinking...';\n answerBox.style.display = 'none';\n\n const result = await qaModel({ question, context });\n\n answerBox.style.display = 'block';\n\n if (result.score < CONFIDENCE_THRESHOLD) {\n answerBox.innerHTML = `\n Answer not found\n

The model could not find a clear answer\n to this question in the provided text.

`;\n } else {\n const before = context.slice(0, result.start);\n const answer = context.slice(result.start, result.end);\n const after = context.slice(result.end);\n const highlight = `${before}${answer}${after}`;\n\n必ず JSON 形式で返してください。`translation` フィールドのみ。**他のフィールド (technical_terms 等) は一切追加しないこと** — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:\n{\"translation\": \"翻訳全文\"}\n\nconst confidence = (result.score * 100).toFixed(1);\n answerBox.innerHTML = `\n Answer: \\${result.answer}\n

Confidence: \\${confidence}%

\n
\n \n Show answer highlighted in document\n \n
\\${highlight}
\n
`;\n }\n\n btn.disabled = false;\n btn.textContent = 'Ask';\n }\n\n btn.addEventListener('click', askQuestion);\n\n questionEl.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && !btn.disabled) askQuestion();\n });\n\n loadModel().catch(err => {\n statusEl.textContent = `Error: \\${err.message}`;\n });\n script>\n\n\n\nQA パイプラインは、単なる文字列ではなく、質問とコンテキストを含むオブジェクトを受け取ります。これはタスクが要求する形式です。モデルの start フィールドと end フィールドは、コンテキスト文字列内の文字インデックスを示しており、コードはこの情報を用いて、モデルが特定した正確なスパンの周囲に タグを挿入します。
要素は、ハイライトされたコンテキストを展開可能なセクションとしてラップし、UI をすっきりと保ちます。信頼度閾値により、低品質な抽出結果が自信ありげな回答として表示されるのを防ぎます;0.1 未満の結果はすべて「見つかりませんでした」というメッセージに置き換えられます。\n\n## # 実世界での応用:サポートチケットルーティング\n\n3 つのパイプラインは、サポートチケットの分析全体を網羅しています。感情分析により顧客の気分が分かり、ゼロショット分類によって適切なチームへチケットを振り分けます。質問応答では、解析ルールや正規表現なしで必要な構造化データ(注文番号、製品名、および核心的な問題)を抽出します。\n\nこれはこれら 3 つを組み合わせた完全なサポートチケット分析ツールです。単一の HTML ファイルであり、完全に自己完結型で、詳細なコメント付きです。\n\n以下は、サポートチケット解析コードブロックの完全にエスケープされたバージョンです。レイアウトテンプレートやスクリプト設定内のすべての内部 HTML 括弧は、安全にエンティティに変換されています。このまま WordPress のカスタム HTML ブロックに貼り付けることができます。\n\n\n\n\n \n \n Support Ticket Analyzer\n \n\n\n

サポートチケット分析ツール

\n

Transformers.js によって駆動 -- ブラウザ内で完全に動作します

\n\n \n\n \n
初期化中 -- 初回実行時にモデルをダウンロードしています...
\n\n
\n
\n

感情分析

\n
--
\n
--
\n
\n\n
\n

部署

\n
\n
\n\n
\n

重要情報

\n
\n
\n
\n\n\n\n\n\nThe three pipelines load in parallel via Promise.all. This is faster than loading them sequentially because the downloads overlap. A counter tracks how many have finished, so the button only enables once all three are ready. When the user submits a ticket, all three inferences also run in parallel. The sentiment card checks whether the result is high-confidence negative and flags it as an urgent practical routing signal that requires no additional model.\n\nThe department card shows the top three candidates as score bars rather than just the winner, which gives the support team enough information to override the routing if the top score is close to the second. The QA card runs three extractive queries against the ticket body and displays the results with a confidence threshold answers below 0.1 show as \"not found\" rather than surfacing low-quality extractions.\n\n## # Performance, Limitations, and When Not to Use It\n\nTransformers.js removes the server but does not eliminate trade-offs. Knowing them up front saves you from unpleasant surprises in production.\n\n- ダウンロードサイズ。感情分析パイプラインは初回読み込み時に約 111 MB をダウンロードします。決して巨大ではありませんが、無視できるほど小さいわけでもありません。ゼロショット BART モデルはさらに大きくなります。モバイルユーザーや従量制接続のユーザーを対象とするアプリケーションでは、モデルサイズを概ね半分にするために [quantization](quantization) を使用し、モデルをプログレッシブ・エンハンスメントとして扱ってください。モデル読み込み時にユーザーインターフェースがブロックされないようにしてください。\n\n- 推論速度。最新のラップトップでは、短いテキスト分類の WASM(WebAssembly)推論には 50〜200 ミリ秒かかります。ゼロショット分類は、候補ラベルごとに 1 つずつ NLI(自然言語推論)パスを実行するため、より遅くなります。5 ラベルのゼロショット実行は通常、CPU で 1〜3 秒を要します。WebGPU がサポートされている環境では、これを大幅に短縮できます。\n\n- 推論のみ。Transformers.js ではモデルのファインチューニングやトレーニングを行うことはできません。カスタムモデルが必要なユースケースの場合(例えば、独自のラベル付きチケットで訓練された分類器など)、トレーニングはサーバー側(Python、クラウド)で行い、ONNX エクスポートをブラウザ内で実行します。\n\n- モデルの利用可能性。Hugging Face Hub にあるすべてのモデルに ONNX バージョンがあるわけではありません。互換性のあるモデルを見つけるには、Hub 上で transformers.js ライブラリタグでフィルタリングしてください。\n\n- サーバーを優先すべきタイミング:個々の項目ごとのレイテンシが重要となる数百件のテキストのバッチ処理、ブラウザ配信には大きすぎる最先端の大規模モデルが必要なタスク、またはブラウザベースの推論の開発コストがその利点を上回る単純なアプリケーションです。\n\n文脈に応じたデータ型(dtype)選択のためのクイックリファレンス:\n\n**文脈**\n**推奨される dtype**\n**理由**\n\nブラウザ、一般用途\nq8\nWASM デフォルト、サイズと精度の良好なバランス\n\nモバイルまたは低速接続\nq4\nファイルサイズの約半分、精度は 1〜3% の低下\n\nNode.js サーバーサイド\nfp32\n完全精度、ダウンロードサイズの懸念なし\n\nWebGPU 有効化\nfp16\n高速、互換性のある GPU ハードウェア上で良好な品質\n\n## まとめ\n\n**Transformers.js は、サーバーも API キーも不要で、ユーザーデータを端末から送信することなく、ブラウザ内で本番環境レベルの自然言語処理(NLP)を実現します。このチュートリアルで紹介した 3 つのパイプライン、すなわちテキスト分類、ゼロショットラベリング、質問応答は、実際の NLP ユースケースの大部分をカバーする分析領域を網羅しています。サポートチケットルーターでは、これらがどのように組み合わされて、200 行未満の HTML と JavaScript で真に有用なシステムへと変換されるかが示されています。\n\nエントリーポイントは可能な限りシンプルです:CDN からのインポート 1 つ、`await pipeline()` の呼び出し 1 つ、推論呼び出し 1 つ。まずはこの記事で最も簡単な例から始めて実行し、ゼロショットデモのラベルを変更したり、QA モデルを別のドキュメントに指させたりしてみてください。[公式 Transformers.js ドキュメンテーション](https://huggingface.co/docs/transformers.js/en/index) と [examples リポジトリ](https://github.com/huggingface/transformers.js-examples) では、要約、翻訳、固有表現認識など、より広範なタスク範囲を扱っており、すべてが同じ `pipeline()` パターンに従っています。\n\n[Shittu Olumide](https://www.linkedin.com/in/olumide-shittu/) は、最先端の技術を活用して説得力のある物語を構築することに情熱を注ぐソフトウェアエンジニアでありテクニカルライターです。細部への鋭い眼と複雑な概念を簡素化する才能を持っています。また、Shittu は [Twitter](https://twitter.com/Shittu_Olumide_) でも活動しています。","image":["https://news.ainew.jp/article/36d629c0-0218-4d57-a951-ff33cd2ba402/opengraph-image"],"datePublished":"2026-05-29T14:00:02.000Z","dateModified":"2026-05-29T15:02:52Z","url":"https://news.ainew.jp/article/36d629c0-0218-4d57-a951-ff33cd2ba402","mainEntityOfPage":"https://news.ainew.jp/article/36d629c0-0218-4d57-a951-ff33cd2ba402","inLanguage":"ja","isBasedOn":"https://www.kdnuggets.com/practical-nlp-in-the-browser-with-transformers-js","publisher":{"@type":"Organization","name":"ainew.jp","url":"https://ainew.jp","logo":{"@type":"ImageObject","url":"https://ainew.jp/logo.png"}},"author":{"@type":"Organization","name":"KDnuggets","url":"https://www.kdnuggets.com"}}