本文へスキップ

構成要素 ​

decidekit のすべての部品を 1 ページにまとめました。何をするか、どこにあるか、それを形作った数字、続きの読み先を示します。数式は仕組みを、各部品の使い方はガイドを読んでください。

text ──► encoder (bge-small, 384 numbers) ──┬──► zero-shot: cosine to each label's name or description ──► softmax
                                            └──► trained head: one softmax layer, calibrated temperature
                                                         │
                       withFallback: below minConfidence ask an LLM ──► answer becomes a training example ──► retrain

1. エンコーダー ​

何をするか: テキストを 384 個の数へ変え、意味の近いテキストを近くに集めます。デフォルトは 8 ビットの重み(34 MB)の Decide Small(debuffjp/decide-small)で、onnxruntime の wasm ビルド上の transformers.js が動かします。平均プーリングで正規化します。

場所: src/index.ts の createDecider()。

数字: Node で 1 テキスト 3.2 ms、バッチで 1.1 ms。スレッドありの Chrome で判定 1 回の中央値 7.7 ms、p95 13.8 ms。3 から 5 ポイントの精度のために all-MiniLM-L6-v2(23.7 MB、Chrome で約 1.8 倍速い)ではなくこちらを選びました。gte-small はゼロショットの確信度を較正できなかったので見送りました。

続き: ヘッドを訓練する(モデルの比較)、仕組み。

2. ゼロショットのスコア計算 ​

何をするか: テキストを各選択肢と比べ、類似度を確率に変えます。名前だけのラベルはテキストとして読みます("card_arrival" は "card arrival")。説明付きラベル({ card_arrival: "My card still hasn't arrived." })は名前と説明の良いほうでスコアを出します。softmax の温度はモデルごとに固定で、bge-small の名前は 0.03、説明付きラベルは 0.025、他のモデルは 0.05 です。

場所: src/index.ts の score()。src/describe.ts の describeLabels() は LLM に説明を書かせます。

数字: dev 分割で、名前だけは 66%(BANKING77)と 73%(CLINC150)、説明付きは 72% と 83%。LLM のプロンプトと違って、選択肢の順序で答えは変わりません(Llama 3.1 8B はラベルの順序で 9 ポイント動きました)。

続き: 仕組み、確信度としきい値。

3. 訓練済みヘッド ​

何をするか: 固定した埋め込みの上の softmax 層 1 つで、ラベルごとに重みベクトルとバイアスを持ちます。訓練は各ラベルを例の平均と名前(重み 1)から始め、勾配降下で調整します。取り分けた例でエポック数を選び、すべての例で訓練し直します。

場所: src/index.ts の train()、src/head.ts の fitHead()。

数字: 0.2 では BANKING77 はラベルごとに 5 例で 83.7%、全 10,003 例で 93.1%。CLINC150 は 90.2% と 96.3%(eval/results-h14.json)。0.2 より前は 82.3%、90.7%、89.6%、94.4% です(eval/results-bge-small.json)。出荷したヘッドは 90.6% と 95.0% で、CLINC150 のものは検証分割でも訓練しています(heads/README.md)。77 ラベルのヘッドは 156 KB。BANKING77 全体の訓練はブラウザのワーカーで 228 s かかります。

続き: ヘッドを訓練する。

4. 較正 ​

何をするか: confidence が額面どおりの意味を持つようにします。ヘッドは取り分けた答えで温度を当てはめます(200 未満なら 5 分割で、すべての例を 1 回ずつ取り分けます)。ゼロショットは上記のモデルごとの固定温度を使います。

場所: src/head.ts の fitHead() の末尾、src/index.ts の TEMPERATURES。

数字: 較正誤差は、ラベルごとに 10 例以上のヘッドで 0.01 から 0.03、BANKING77 のラベルごとに 5 例で 0.07(最も緩いところ)、ゼロショットで 0.02 から 0.04。

続き: 確信度としきい値。

5. LLM から学ぶ ​

何をするか: withFallback() は confidence >= minConfidence ならローカルで答え、そうでなければあなたの ask を呼びます。答えはそれぞれ訓練例になり、retrainEvery があれば自分で再訓練します。

場所: src/fallback.ts。

数字: 説明付きの BANKING77 の 12 ラベルに実際の Llama 3.1 8B の答えを使うと、送る割合は 30%(ゼロショット)から 19% に下がりました。CLINC150 でラベル名だけから始めると、完璧な先生役のもとで、LLM に送る割合は 10 回の再訓練で 68% から 16% に下がりました(bge-small。all-MiniLM-L6-v2 は 67% から 14.5%)。先生役の質は重要です。20% 間違える先生役では 52% に留まりました。BANKING77 の全 77 ラベルで 15% 間違える先生役だと、送信は 64% のままでしたが、calibrateOn(ラベルごとに正しい例 2 つ)で 24% になりました。ラベルから始めると、今はデフォルトでゼロショット自身の確信した答えで較正し(31%)、テキストがすべてのラベルから遠いときに LLM の null の答えを NONE として学びます。LLM にも同じラベルの説明を渡し(Llama 3.1 8B:84% から 90%)、ラベルは安定した、グループ分けした順序で並べてください。

続き: LLM へのフォールバック。

6. ブラウザのワーカー ​

何をするか: エンコーダーの wasm はページに順番を渡さないので、ブラウザでは Web Worker で動かします。createWorkerDecider() は同じ decide()、decideMany()、train() を持ち、terminate() が加わります。

場所: src/browser.ts(ページ側)、src/worker.ts(ワーカー側)。

数字: メインスレッドでの BANKING77 の訓練はページを 171 s 止めました。ワーカーでは最長の停止は 18 ms でした。各呼び出しにメッセージのやり取りで約 1 ms かかります。

続き: ブラウザで使う。

7. クロスオリジン分離 ​

何をするか: 次の 2 つのヘッダーでページはクロスオリジン分離されます。Cross-Origin-Opener-Policy: same-origin と Cross-Origin-Embedder-Policy: credentialless です。すると onnxruntime の wasm が複数のスレッドを使えます。

数字: all-MiniLM-L6-v2 で、ある実行(2026-10-31)で判定時間の p95 は 14.3 ms から 7.8 ms になりました。その後の分離ありの実行では 7.7 ms でした。

続き: ブラウザで使う。

8. バンドラーとダウンロードサイズ ​

何をするか: ワーカーは new Worker(new URL("./worker.js", import.meta.url), { type: "module" }) で起動します。Vite、webpack 5、esbuild ベースのツールが理解する形です。onnxruntime-web/webgpu から onnxruntime-web/wasm へのエイリアスで、decidekit がデフォルトで使わない WebGPU ビルドを外します。

数字: エイリアスで wasm は半分になります(23.6 MB から 12.9 MB、gzip で 3.3 MB)。最初の訪問は 34 MB のモデルと wasm です。decidekit 自体がページのバンドルに加えるのは 3.6 KB です。

続き: バンドラー。

9. キャッシュ ​

何をするか: transformers.js は最初のダウンロードのあとモデルファイルをキャッシュします(ページではブラウザの Cache Storage、Node ではローカルのフォルダ)。ゼロショットの選択肢の埋め込みは選択肢のセットごとにキャッシュされます。train() は直前の訓練セットの埋め込みを保持するので、例を少し足した再訓練ではその分だけをエンコードします。

場所: src/index.ts の optionCache と trainCache。

10. ヘッドファイル ​

何をするか: saveHead() は重みを base64 にした JSON を書き、loadHead() はそれを読みます。ページがモデルのコードを引き込まずにヘッドを読み込めるよう、エンコーダーとは別に置いています。ヘッドは訓練したモデルを記録していて、別のモデルのヘッドを decide() は拒否します。

場所: src/head-io.ts。

11. React、CLI、switch ​

  • decidekit/react:useDecider() と useDecision()。ユーザーの入力に合わせて判定し、古い答えを捨てます。React。
  • decidekit CLI:CSV や JSONL のファイルからヘッドを train し、シェルから decide します。API リファレンス。
  • decidekit/switch:switch エージェントハーネス用のデサイダー。選択、はい・いいえ、スコアの質問にローカルで答え、先生役から学ぶこともできます。switch。