Skip to content

モデルルーティング:カスタムマッピング、ワイルドカード優先順位とプリセット戦略

クライアントで書いた model は、必ずしも Antigravity Tools がアップストリームにリクエストする際の「物理モデル」とは限りません。モデルルーティングのやることはシンプル:「対外的に安定したモデル名」を「内部的に実際に使うモデル」にマッピングし、結果をレスポンスヘッダ X-Mapped-Model に入れて、期待どおりのルートを通ったかを確認しやすくします。

このレッスンでできること

  • UI で proxy.custom_mapping を設定(正確マッピング + ワイルドカードマッピング)
  • 1 つのルールがどのようにマッチしたかを明確に説明(正確 > ワイルドカード > デフォルトマッピング)
  • ワンクリックでプリセットルールを適用し、迅速に OpenAI/Claude クライアントに対応
  • curl -iX-Mapped-Model を検証し、「なぜ私が思ったルーティングにならなかったか」を特定

現在の悩み

  • クライアントは常に gpt-4o を書きたいが、アップストリームでは特定の Gemini モデルに安定して落としたい
  • 多くのバージョン付きモデル名(例:gpt-4-xxxx)があり、毎回手動でマッピングを追加したくない
  • リクエストは成功したが、実際にはどの物理モデルが動いているか不明

この方法をいつ使うか

  • チームに「固定された対外モデルセット」を提供し、アップストリームのモデル変動をシールドしたい
  • 複数の OpenAI/Claude モデル名を少数のコストパフォーマンスの高いモデルに統一ルーティングしたい
  • 401/429/0 token のトラブルシューティング中、マッピング後の実際のモデルを確認したい

🎒 始める前の準備

このレッスンで 2 つのキーワード

  • custom_mapping:あなたの「カスタムルールテーブル」。キーはクライアントから渡されるモデル名(またはワイルドカード pattern)、値は最終的に使用するモデル名(出典:src/types/config.ts)。
  • ワイルドカード *:モデル名のバッチマッチに使用(例:gpt-4*)。マッチ実装は大文字小文字を区別する(出典:src-tauri/src/proxy/common/model_mapping.rs)。

コアコンセプト

バックエンドがリクエストを処理する際、まず mapped_model を計算します:

  1. まず custom_mapping正確一致があるか確認(key が model と完全一致)
  2. 次にワイルドカード一致を試行:「* 文字がより多い」ルールを選択(より具体的なルールが優先)
  3. どちらもマッチしない場合、システムデフォルトマッピングに進む(例:一部の OpenAI/Claude モデルエイリアスから内部モデルへのマッピング)

この mapped_model はレスポンスヘッダ X-Mapped-Model に書き込まれます(少なくとも OpenAI handler はそうします)。これを使えば「私が書いた model が最終的に何になったか」を確認できます。

ホットリロードの意味論(再起動不要)

リバースプロキシサービスが実行中の場合、フロントエンドが update_model_mapping を呼び出すと、バックエンドはすぐに custom_mapping をメモリ内の RwLock に書き込み、同時に永続化設定にも保存(出典:src-tauri/src/commands/proxy.rssrc-tauri/src/proxy/server.rs)。

さあ、一緒にやってみよう

ステップ 1:API Proxy ページで「モデルルーティング」カードを見つける

なぜ モデルルーティングの設定エントリは UI 内にあります。設定ファイルを手動で編集する必要はありません。

Antigravity Tools を開く → API Proxy ページ → 下にスクロール。

期待される結果:タイトルが「モデルルーティングセンター」に似たカードが表示され、右上に 2 つのボタン:「プリセットマッピング適用」と「マッピングリセット」(出典:src/pages/ApiProxy.tsx)。

ステップ 2:「正確マッピング」を 1 つ追加(最も制御可能)

なぜ 正確マッピングの優先順位は最高で、「この 1 つのモデル名をこの 1 つの物理モデルに落としたい」場合に適しています。

「マッピング追加」エリアで:

  • Original には対外的に公開するモデル名を入力、例:gpt-4o
  • Target はドロップダウンからターゲットモデルを選択、例:gemini-3-flash

Add をクリック。

期待される結果:マッピングリストに gpt-4o -> gemini-3-flash が表示され、保存成功のトーストがポップアップ。

ステップ 3:「ワイルドカードマッピング」を 1 つ追加(バッチ覆盖)

なぜ 多くのバージョン付きモデル名がある場合(例:gpt-4-turbogpt-4-1106-preview)、ワイルドカードを使うと重複設定を大幅に削減できます。

もう 1 つのマッピングを追加:

  • Original:gpt-4*
  • Target:gemini-3-pro-high

期待される結果:リストに gpt-4* -> gemini-3-pro-high が表示される。

ルール優先順位の「罠」

gpt-4o が同時に正確ルール gpt-4o とワイルドカードルール gpt-4* の両方を満たす場合、バックエンドはまず正確一致を優先(出典:src-tauri/src/proxy/common/model_mapping.rs)。

ステップ 4:ワンクリックでプリセットルールを適用(迅速な互換性)

なぜ 主な目的が「一般的な OpenAI/Claude モデル名に迅速に対応」する場合、プリセットが一括のワイルドカードルールを直接入力できます。

「プリセットマッピング適用」をクリック。

期待される結果:リストに複数のルールが追加され、以下のような内容が含まれる(出典:src/pages/ApiProxy.tsx):

json
{
  "gpt-4*": "gemini-3-pro-high",
  "gpt-4o*": "gemini-3-flash",
  "gpt-3.5*": "gemini-2.5-flash",
  "o1-*": "gemini-3-pro-high",
  "o3-*": "gemini-3-pro-high",
  "claude-3-5-sonnet-*": "claude-sonnet-4-5",
  "claude-3-opus-*": "claude-opus-4-5-thinking",
  "claude-opus-4-*": "claude-opus-4-5-thinking",
  "claude-haiku-*": "gemini-2.5-flash",
  "claude-3-haiku-*": "gemini-2.5-flash"
}

ステップ 5:X-Mapped-Model でルーティングが有効か確認

なぜ 「設定が書き込まれた」ことを確認したいだけでなく、「リクエストが本当にこのルールに従った」ことを確認したい。最も手間のかからない方法は X-Mapped-Model を見ることです。

bash
curl -i http://127.0.0.1:8045/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role": "user", "content": "hi"}]
  }'
powershell
$resp = Invoke-WebRequest "http://127.0.0.1:8045/v1/chat/completions" -Method Post -ContentType "application/json" -Body '{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "hi"}]
}'
$resp.Headers["X-Mapped-Model"]

期待される結果:レスポンスヘッダに X-Mapped-Model: ... がある。ステップ 2 で gpt-4ogemini-3-flash に正確マッピングした場合、ここで対応する値が見えるはず(レスポンスヘッダ書き込みは src-tauri/src/proxy/handlers/openai.rs 参照)。

ステップ 6:「純粋なデフォルトマッピング」に戻る必要がある場合、custom_mapping をリセット

なぜ トラブルシューティング時、通常はまず「カスタムルールの影響」を除外したい。custom_mapping をクリアするのが最も直接的なロールバック手段。

「マッピングリセット」をクリック。

期待される結果:マッピングリストがクリアされる。その後リクエストすると、カスタムルールにマッチしない場合、システムデフォルトマッピングに進む(出典:src/pages/ApiProxy.tsxsrc-tauri/src/proxy/common/model_mapping.rs)。

チェックポイント ✅

  • [ ] UI で custom_mapping ルールを追加/削除できる
  • [ ] 正確ルールがワイルドカードルールより優先される理由を説明できる
  • [ ] curl -i または PowerShell で X-Mapped-Model を読める

よくある落とし穴

シナリオあなたがするかもしれないこと(❌)推奨される方法(✓)
ワイルドカードが有効にならないGPT-4* を書いて gpt-4-turbo にマッチすることを期待小文字で gpt-4* を使用;バックエンドのワイルドカードマッチは大文字小文字を区別する
2 つのワイルドカードがどちらもマッチgpt-*gpt-4* を同時に書き、どちらに進むかわからないより具体的なルールをより「長く」し、非 * 文字がより多くなることを確認
ルールは正しいように見えるが変わらないレスポンス body しか見ず、レスポンスヘッダを見ないcurl -iX-Mapped-Model を確認(これはバックエンドが明示的に返す結果)
2 つのルールが「同じ具体性」* 文字数が同じ 2 つのワイルドカードルールを書くこのような設定は避けること;ソースコードのコメントは、この場合の結果が HashMap の走査順序に依存し、不安定になる可能性があると説明(出典:src-tauri/src/proxy/common/model_mapping.rs

このレッスンのまとめ

  • proxy.custom_mapping は「対外モデル名 → 物理モデル」を制御するメインエントリ
  • バックエンドルーティング優先順位は:正確一致 > ワイルドカード一致(より具体的が優先)> システムデフォルトマッピング
  • X-Mapped-Model は最も信頼性の高い検証手段であり、トラブルシューティング時はまずこれを見る

次のレッスン予告

次のレッスンでは クォータガバナンス:Quota Protection + Smart Warmup の組み合わせ戦術(対応章:advanced-quota)を解説します。


付録:ソースコード参考

クリックしてソースコードの位置を展開

更新日時:2026-01-23

機能ファイルパス行番号
設定フィールド:proxy.custom_mapping(フロントエンド型)src/types/config.ts6-20
UI:書き込み/リセット/プリセット(update_model_mapping 呼び出し)src/pages/ApiProxy.tsx371-475
UI:モデルルーティングカード(プリセットマッピング適用 / マッピングリセット / リストと追加フォーム)src/pages/ApiProxy.tsx1762-1931
バックエンドコマンド:ホットリロードと custom_mapping の永続化src-tauri/src/commands/proxy.rs344-365
サーバー状態:custom_mappingRwLock<HashMap<..>> で保存src-tauri/src/proxy/server.rs16-53
ルーティングアルゴリズム:正確 > ワイルドカード(より具体的が優先)> デフォルトマッピングsrc-tauri/src/proxy/common/model_mapping.rs180-228
ワイルドカードマッチ:複数 * をサポートし、大文字小文字を区別src-tauri/src/proxy/common/model_mapping.rs134-178
リクエスト内で mapped_model を計算(例:OpenAI handler)src-tauri/src/proxy/handlers/openai.rs154-159
---------

キー関数

  • resolve_model_route(original_model, custom_mapping):モデルルーティングメインエントリ(src-tauri/src/proxy/common/model_mapping.rs 参照)