モデルルーティング
1つのAPIキーで複数モデルを呼ぶ
OpenAI互換のBase URLとAPIキー1つでClaude、Gemini、DeepSeekなどを呼び出す方法。設定、モデル切り替え、費用確認、障害時の切り分けを解説します。
1つのキーですべてのモデルを呼び出す
「1つのAPIで複数のAIモデルをルーティングする」とは、アプリ側はBase URL、APIキー、リクエスト形式を1つずつ持ち、model フィールドでどの上流プロバイダーに処理させるかを決める構成です。ベンダーごとに認証情報を保存する必要がなく、新しいモデルが追加されてもクライアントを書き換えずに済みます。
実利は運用面にあります。残高が1つ、漏えいしたキーの交換が1か所、ログが1系統、モデル切り替えも1か所です。一方でゲートウェイがリクエスト経路に入るため、何を転送し、どうトークンを数えているかを検証する必要があります。本記事では最小構成、同じキーで異なるモデル系列を呼ぶ方法、請求との照合までを扱います。
モデル名を送った後に起きること
ルーティングを決める要素は通常4つです。モデル識別子、メッセージ本文、ストリーミング指定、そしてツール定義やキャッシュ制御などの任意フィールドです。ゲートウェイはモデル名を有効なチャネルと価格グループに解決し、リクエストをそのプロバイダーのネイティブ形式へ変換し、応答をSDKが期待する形式へ戻します。
本番前に確認すべき点は2つあります。第一に、モデル名にはバージョンがあります。試用環境で動く名前が、自分のキーのグループに存在するとは限りません。第二に、抽象化は無料ではありません。プロンプトキャッシュ、ツール呼び出し、構造化出力、推論トークンは、ゲートウェイが実際に転送した場合にのみ同等です。テキストが1回返っただけで互換と判断せず、依存する機能を個別に検証してください。
| フィールド | 役割 |
|---|---|
| model | どのチャネルと価格グループで処理するかを決める |
| messages / input | 上流へ送る文脈。入力トークンの主な要因 |
| stream | SSEで返すか、1つのJSONで返すか |
| tools、response_format | プロバイダー固有機能の転送が必要か |
キーを1つ用意して最初のリクエストを送る
API接続でキーを作成し、料金ページで使うモデルを確認します。最初の確認はOpenAI互換エンドポイントで構いません。対象がOpenAIのモデルでなくてもゲートウェイが変換します。初回は出力上限を低くし、ツールもキャッシュも使わずに小さく試します。
キーはコードに書かず環境変数に置きます。macOSやLinuxでは export API_ROUTE_KEY=...、Windows PowerShellでは $env:API_ROUTE_KEY="..." を使います。以下の例はチャット補完を1回送って結果を表示します。
export API_ROUTE_KEY="sk-your-key"
curl https://global.api-route.com/v1/chat/completions \
-H "Authorization: Bearer $API_ROUTE_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"messages": [{"role": "user", "content": "Name one trade-off of multi-model routing."}],
"max_tokens": 80
}'200と choices 配列が返れば、リクエストがプロバイダーに届いたことは分かります。ただしストリーミング、ツール、キャッシュ、2つ目のモデル系列が動く証明にはなりません。機能ごとに検証を足し、応答本文のモデル名と usage を確認してください。
SDKを変えずにモデル系列を切り替える
同じキーでClaude、Gemini、DeepSeek、Qwenなどの系列を呼べるのは、ゲートウェイがプロトコル間を変換しているからです。チャット形式の通信はすべて /v1/chat/completions に送り、model の値だけを変えます。リクエストと応答の形はOpenAI互換のままです。
プロンプトキャッシュや特定のベータヘッダーなどAnthropic固有の動作が必要な場合は、/v1/messages とAnthropic形式を使います。両エンドポイントは同じ残高を共有するため、1つのキーで運用できます。参照仕様:OpenAI Chat Completions と Anthropic Messages。
from openai import OpenAI
client = OpenAI(
base_url="https://global.api-route.com/v1",
api_key="sk-your-key",
)
for model in ["claude-sonnet-4-6", "gemini-3.8-flash", "deepseek-v4.1-flash"]:
reply = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": "Reply in one sentence."}],
max_tokens=60,
)
print(model, "->", reply.choices[0].message.content)const models = ["claude-sonnet-4-6", "gemini-3.8-flash"];
for (const model of models) {
const res = await fetch("https://global.api-route.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.API_ROUTE_KEY}`,
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Reply in one sentence." }],
max_tokens: 60,
}),
});
const data = await res.json();
console.log(model, "->", data.choices?.[0]?.message?.content ?? data.error?.message);
}ループで2つのモデルを呼べば、ルーティング層が期待どおり動くかを確認できます。呼び出しごとに返却モデル名とusageを記録してください。別系列へ静かにフォールバックしていても文章は自然に見えますが、品質と料金は変わっています。
プロジェクト単位ではなくリクエスト単位でモデルを選ぶ
1つのキーですべてのモデルに届くようになると、判断は「どのベンダーと契約するか」から「このリクエストはどのモデルに任せるか」へ移ります。まず通信を分類します。短い分類や抽出に最上位モデルは通常不要で、長い文脈の分析には必要です。コード生成とチャットでは優先順位が異なります。タスク別にルーティングし、ベンチマークの見出しではなく自社の評価セットで品質を測ってください。
モデル名と同じくらい価格グループが重要です。同じモデルでも既定グループと割引・企業グループでは単価が異なり、実際の支払額はキーが属するグループで決まります。宣伝されている数字で予算を組む前に、料金ページと利用ログのグループを確認してください。
| ワークロード | 最適化する対象 | 典型的な選択 |
|---|---|---|
| 分類・抽出・タグ付け | 1000回あたりの費用 | 小型で高速なモデル |
| 長文脈の分析・RAG回答 | コンテキスト長とキャッシュ費用 | 中位モデルとプロンプトキャッシュ |
| 複雑なコーディング・エージェント | 正確さとツール利用 | 最上位モデル、低い温度 |
| 一括生成 | 出力単価とスループット | 中位モデルとバッチ処理 |
ルートと請求を照合する
規模を広げる前に3点を確認します。同じキーで予定しているモデルを一覧できること、応答が要求したモデルを返すこと、ログの課金がusageと一致することです。モデル一覧が最も安価な確認で、狭いグループに固定されたキーを見つけられます。
curl -s https://global.api-route.com/v1/models \
-H "Authorization: Bearer $API_ROUTE_KEY" \
| jq -r '.data[].id' | sort次に1回の応答を利用ログの該当行と比較します。モデル、入力と出力の内訳、キャッシュ関連フィールドの有無を確認してください。キャッシュされたリクエストは読み取りを別項目で報告するはずです。報告が一切ない場合は割引ではなく未検証として扱います。モデル系列ごとに1件の記録を残すと、後の価格やルート変更に気づけます。
よくある失敗とその意味
最初の1週間の問題はモデル品質ではなく設定であることが大半です。まず確認したいエラーを表にまとめます。報告時は時刻、HTTPステータス、モデル名、リクエストIDを添え、キーそのものは貼らないでください。
| 症状 | 想定される原因 | 最初に確認すること |
|---|---|---|
| 404 モデルが見つからない | キーのグループで有効化されていない | /v1/models で一覧し、料金ページと照合する |
| 401 または 403 | キー欠落・失効・誤ったヘッダー | Authorization: Bearer を使い、露出していれば交換する |
| 400 がschemaの項目を指す | 未変換のキーワードをプロバイダーが拒否 | 該当項目を外して再試行し、パラメータを報告する |
| ストリーミングが止まる/一括で届く | プロキシのバッファリングや未対応の指定 | streamを外して再試行し、短いプロンプトで試す |
| 想定より高い | グループ違い、または読み取りではなく書き込み | usageとログ行を突き合わせ、グループを確認する |
200なのに別モデルのように振る舞う場合は、固定プロンプトで数回比較し、返却モデル名も確認してください。ばらつきは多くの場合、プロンプトではなくルーティングやフォールバックの方針に起因します。
本番運用のチェックリスト
- キーはシークレット管理か環境変数に置き、交換用の2本目を用意する。
- 浮動エイリアスではなく明示的なモデルIDを固定し、検証したバージョンを記録する。
- 設定変更のたびに、モデル系列ごとの固定スモークリクエストを送る。
- 総額だけでなく、エラー率と1リクエストあたりの費用にアラートを設定する。
- トラフィックを増やす前に、最初の請求と記録したusageを照合する。
この5点が揃えば、1つのキーと1つのBase URLでモデル系列をまたいでルーティングできます。少額の残高でアカウントを作成し、キーで利用可能なモデル一覧を確認して、クイックスタートに沿って最初のリクエストを送ってください。