# switch で使う decidekit

[switch](https://github.com/osolmaz/switch) は判断モデルのためのハーネスです。タスクの各ステップでコードが選択肢を作り、モデルが 1 つ選びます。`decidekit/switch` は decidekit のデサイダーを switch のデサイダーに変えます。これで switch のドメインを、手元のマシンの 34 MB のモデルで、無料かつ API キーなしで動かせます。

```ts
import { createDecider } from "decidekit";
import { switchDecider } from "decidekit/switch";
import { run } from "@osolmaz/switch";

const decider = switchDecider(await createDecider());
const result = await run(domain, machine, decider);
```

## 答えられるもの {#what-it-answers}

| switch の質問 | Decide の判定 |
|---|---|
| `choice` | 基準のどれか 1 つ。テキストで比べます |
| `bool` | `true` か `false`。それぞれの意味で比べます |
| `score` | レベルのどれか 1 つ。説明で比べます |

画像は無視します。答えはすべてローカルなので、使用量のコストは 0 と報告されます。

## 読むものを選ぶ {#choose-what-it-reads}

エンコーダーは約 256 トークンを読み、残りを捨てます。switch のドメインでは指示と状態が大きくなりやすく、大事な部分は押し出されることがあります。`text` を渡して選んでください。

```ts
// WikiRace: compare the links with what the target is about.
switchDecider(local, { text: (state) => String(state.about_the_target) });
```

`text` がなければ、Decide は質問の指示を読み、続いて状態を `key: value` の行として読みます。

## 訓練済みヘッドと先生役 {#trained-heads-and-a-teacher}

- `heads`：質問 ID ごとの訓練済みヘッド。繰り返す質問（ルーブリックの基準、固定のメニュー）に使います。ヘッドのない質問はゼロショットで判定します。
- `teacher`：別の switch のデサイダー。たとえば switch の pi-ai デサイダー経由の Jev です。Decide の確信が `minConfidence`（デフォルト 0.9）に届かないとき、先生役が同じリクエストに答えます。その答えは 8 回答ごとに、その質問のヘッドを訓練します。繰り返す質問では先生役に聞く回数が減っていきます。質問ごとの [withFallback](/ja/decide/docs/guide-fallback) です。

## WikiRace {#wikirace}

[eval/wikirace.ts](https://github.com/debuffjp/decidekit/blob/main/eval/wikirace.ts) は switch の WikiRace の例にある 3 つのレースを、Decide のゼロショットで走らせます。読むのは目的地の冒頭の数文だけです。各ステップで現在の記事のすべてのリンクを提示します（Jev は最大 255）。目的地へのリンクがあれば直接たどります。2026-11-01 の結果で、各 1 回の実行です（Wikipedia は変わるので実行ごとに異なります）。

| レース | Decide | Jev（switch の README より） |
|---|---|---|
| Rubber duck to Moon | 2 ホップ（NASA） | 3 ホップ |
| Baseball to Sun | 7 ホップ | 4 で断念 |
| DNA to Manipuri pony | 12 ホップで敗退（"History of the horse in the Indian subcontinent" に到達） | 6 ホップ |

switch 自身の WikiRace ドメインと `run()` ループでは、1 ステップに最大 200 リンクを表示し、残りはセクションを開いて見ます。同じデサイダー（目的地の要約を読む）で、Moon に 12 ホップ、Sun に 18 ホップで到達しました。DNA to Manipuri pony は Manipur に着いたあと 40 ステップの上限に達しました。経路はさまよいます。記事を再訪し、字面が似ているものをたどります。次のセクションはこの問題を扱います。

3 つ合わせて判定にかかった時間は、ノート PC の CPU で約 4 s です。ゼロショットの Decide は目的地に意味が最も近いリンクを選ぶので、"Pony (disambiguation)" のような惜しい候補に入り込みます。タイトルの代わりに要約を読むと改善しました（タイトルでは 2 レース負けました）。計画は持ちません。そこを先生役や訓練済みヘッドが補います。

## 足りないところ {#where-it-falls-short}

ゼロショットの Decide は、選択肢を 1 つのテキストとの意味の近さで順位付けします。計画も、どこを通ったかの記憶もないので、探索では惜しい候補に入り、ループします。訓練済みヘッドは繰り返す質問についてこれを解決します。探索については、20 の WikiRace レースで 2 つの対策を試しました（[eval/wikirace-strategies.ts](https://github.com/debuffjp/decidekit/blob/main/eval/wikirace-strategies.ts)）。

| 戦略 | 勝利 | ホップの中央値 | 判定の時間 |
| --- | --- | --- | --- |
| 最も近いリンク（`decide()` の動作） | 17/20 | 5 | 22 s |
| 上位 20 のクロスエンコーダー再順位付け | 12/20 | 7 | 35 s |
| 上位 5 から 1 歩先読み（未訪問のページを読むので、ゲームでは禁止） | 19/20 | 3 | 172 s |

再順位付けは目的地と各リンクを一緒に読みますが、それでも結果は悪くなりました。このモデルは検索クエリで訓練されていて、Wikipedia のタイトル向けではないからです。先読みは最も多く勝ちましたが、未訪問のページのリンクを読みます。プレイヤーにも switch のドメインにも許されないことなので、Jev との公平な比較にはなりません。「どのページが目的地に近づくか」の感覚を良くすると、どれだけの価値があるかはわかります。超えるべき公平な結果は 17/20 です。報告やアイデアは [Discussions](https://github.com/debuffjp/decidekit/discussions) へどうぞ。