1. はじめに
「OpenAI互換API」を謳うサービスは増えています。
よく語られるのは、「openai パッケージを使ったコードがほぼそのまま動く」という利便性です。
しかし、Multi-AI Runtimeを作る側から見ると、もう一つ重要な点があります。
推論プロバイダを、Runtime全体の構造を大きく変更することなく差し替え候補にできるのか?
という点です。
この記事では、自作しているProvider-neutralなMulti-AI Runtime(以下「Runtime」)に、OpenAI互換のChat Completions APIを提供する「さくらのAI Engine」を実際に接続し、以下を検証しました。
- Live APIとして本当に動くか
- Runtime側の共通契約を変更せずに接続できるか
- 既存のプロバイダ選択・ルーティングロジックを再利用できるか
- 「差し替え可能」と言える範囲はどこまでか
Live APIへの実リクエストと、Fake/注入クライアントによる決定的なローカルテストを分けて検証しています。
2. なぜ「OpenAI互換」を検証したかったのか
Multi-AI Runtimeを自作していると、
Provider A向けのコードを流用すればProvider Bも簡単に追加できる
という話はよく出てきます。
しかし実際には、
- 認証
- リクエスト形式
- レスポンス形式
- トークン使用量の取得
- プロバイダ識別
- Runtime側の登録
- プロバイダ選択
- ルーティング
- 金銭コスト集計
まで考える必要があります。
そのため、「OpenAI互換」という言葉だけで、どこまで本当に互換なのかは分かりません。
今回は、
設定変更だけで済むのか、それとも小さなアダプタが必要なのか。さらに、その先のRuntime機能まで再利用できるのか。
この境界線を実装とLive APIの両方から確認することにしました。
3. 検証したRuntimeの最小構成
今回扱う部分だけに絞ると、Runtimeの構造は概ね次のようになっています。
Application / Runtime Request
|
v
AIProvider Contract
|
v
Provider Selection
/ \
/ \
Existing Sakura
Provider AI Engine
AIProvider Contract
すべてのプロバイダアダプタが満たす共通インターフェースです。
概念的には、
invoke(request) -> response
という形になっていて、レスポンスには、
- プロバイダ名
- モデル名
- 生成内容
- prompt tokens
- completion tokens
などを共通形式で保持します。
Provider Selection
Runtimeに登録された複数のプロバイダ/モデル候補から、条件に合うものを選択する層です。
この層から見ると、既存プロバイダもSakuraも、同じ契約を満たす「候補」の一つにすぎません。
4. さくらのAI Engineをどう接続したか
最初に考えたのは、
既存のOpenAI用アダプタを設定変更だけで使えないか
という方法でした。
しかし、既存アダプタをそのまま使うと問題があります。
特に重要なのが、
- 接続先のBase URL
- 「どのプロバイダが応答したか」というProvider Identity
です。
単純にOpenAI用アダプタのBase URLだけを変更すると、実際にはSakuraへ送信しているにもかかわらず、Runtime内部ではOpenAIの応答として扱われる可能性があります。
これは将来的に、
- コスト集計
- Observability
- Audit
- Routing
- Provider別統計
などを行う際に不正確になります。
そこで今回は、OpenAI Python SDK自体はそのまま利用しながら、
- Sakura AI Engine用Base URL
provider_name = "sakura"
を持つ、数十行程度の薄いアダプタを実験的に追加しました。
つまり、Sakura向けに新しい通信プロトコルを実装したわけではありません。
OpenAI互換だからこそ、同じSDK・同じChat Completions形式を利用し、差分を薄いProvider Adapterへ閉じ込めることができた
という構成です。
5. OpenAI Python SDKからLive接続してみる
まずRuntime全体の検証とは切り離し、OpenAI Python SDKを使って実際に接続できるか確認しました。
概念的には次のようなコードです。
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["SAKURA_AI_TOKEN"],
base_url="https://api.ai.sakura.ad.jp/v1",
)
response = client.chat.completions.create(
model="gpt-oss-120b",
messages=[
{
"role": "user",
"content": "Reply with exactly: SAKURA_OK",
}
],
max_tokens=128,
)
print(response.choices[0].message.content)
今回の検証条件は以下です。
| 項目 | 内容 |
|---|---|
| API | OpenAI互換 Chat Completions |
| Base URL | https://api.ai.sakura.ad.jp/v1 |
| SDK | OpenAI Python SDK 3.3.1 |
| Model | gpt-oss-120b |
実際のAccount Tokenは環境変数から注入し、コード・ログ・記事には含めていません。
6. Live APIの実測結果
Live APIへのリクエストは、無償枠内で合計2回実施しました。
| 項目 | Request #1 | Request #2 |
|---|---|---|
max_tokens |
10 | 128 |
| 応答内容 | None |
SAKURA_OK |
prompt_tokens |
75 | 75 |
completion_tokens |
10 | 77 |
total_tokens |
85 | 152 |
| latency | 2.192 s | 1.751 s |
finish_reason |
未取得 | stop |
Request #2では、期待した
SAKURA_OK
がそのまま返りました。
したがって、今回の条件では、
OpenAI Python SDK → Sakura AI Engine → gpt-oss-120b → Chat Completions Response
という一連のLive接続を確認できました。
一方、Request #1では max_tokens=10 としたところ、completion tokensは10消費されていましたが、可視コンテンツは None でした。
ここで注意したいのは、原因を断定できないことです。
例えば内部的な推論処理との関係なども考えられますが、今回のレスポンスからはその内訳を確認できませんでした。
そのため、本記事で確認できた事実は、
この実験では、
max_tokens=10のときは可視コンテンツが返らず、max_tokens=128のときは期待したSAKURA_OKが返った。
というところまでです。
また、レイテンシについても2回しか測定していないため、性能比較として統計的な意味を持つものではありません。
あくまで今回のLive Verificationにおける観測値です。
7. Provider-neutral Runtimeへ載せてみる
Live接続を確認した後、実験用Sakura AdapterをRuntimeへ接続しました。
ここからは外部APIを何度も呼び出す必要がないため、Fake/注入クライアントを使った決定的なローカルテストで確認しています。
確認したのは主に次の点です。
- Sakura Adapterが既存のAIProvider契約を満たす
- ProviderRequestをそのまま受け取れる
- 共通形式のProviderResponseを返せる
- Token Usageを共通形式へ変換できる
-
provider_name = "sakura"としてOpenAIとは別のProviderとして識別できる - 既存のProvider Registryへ登録できる
- 既存のProvider Selection / Routingロジックから選択できる
結果として、共通のAIProvider Contract自体を変更する必要はありませんでした。
RegistryやProvider Selectionのコア実装も変更していません。
必要だったのは、
Sakura用の薄いAdapterと、Sakuraを候補として登録する設定
です。
8. 「差し替え可能」のどこまで確認できたか
ここは今回の検証で特に重要だった部分です。
「OpenAI互換だから差し替え可能だった」と一言でまとめると、実際に確認した範囲以上のことを主張してしまいます。
そこでEvidenceを分けます。
| 区分 | 検証内容 | 状態 |
|---|---|---|
| LIVE VERIFIED | Sakura認証、OpenAI SDK互換、Chat Completions、応答内容、Token Usage、Latency | 実APIで検証済み |
| DETERMINISTIC / LOCAL | AIProvider契約、Registry登録、Provider Identity、既存Routing | Fake/注入Clientで検証済み |
| OPEN ITEM | Monetary Cost Accounting、Classification-aware Policy、正式なRepositoryへの取り込み | 未完了 |
したがって、
「Runtime側は何も変更しなくてよかった」
という表現は正確ではありません。
正確には、
- Sakura専用の薄いProvider Adapterは追加した
- 既存のAIProvider Contractは変更不要だった
- Registryのコア実装は変更不要だった
- Provider Selection / Routingのコア実装も変更不要だった
という結果です。
つまり、
アダプタ1つと登録設定を追加することで、既存のProvider-neutralなRuntime構造をそのまま利用できた
というのが今回確認できた範囲です。
9. Cost Accountingで見つかった課題
Provider呼び出しとRoutingまでは問題なく機能しました。
しかし、その先にある金銭コスト集計では別の問題が見つかりました。
Runtimeでは、Provider/Modelごとの料金情報を使ってToken Usageから金銭コストを計算します。
今回の sakura / gpt-oss-120b については、その価格定義をRuntime側へまだ登録していません。
そのため、金銭コスト集計を含む完全な実行パスはそこで停止します。
これは今回の実装における不具合というより、
価格が分からないProviderを暗黙に「0円」として処理しない
というRuntime側の設計によるものです。
今回の検証では、この部分を無理に回避せずOpen Itemとして残しました。
ここから得られた教訓はシンプルです。
API呼び出しの互換性(Provider Portability)と、金銭コスト集計の互換性(Cost Portability)は別の関心事である。
「OpenAI互換だからAPIを呼べる」ということと、「既存RuntimeのCost Accountingまで自動的に対応できる」ということは同じではありません。
10. Data Residency / Governanceへの応用可能性
さくらのAI Engineでは、公式サービスページで、モデルの実行・通信について「すべて国内クラウドで完結」「外部へのデータ送信なし」と説明しています。
また、モデル提供元にも送られず、学習利用の心配がない旨も説明されています。
出典:
これらは、さくらインターネットによる公式サービス説明を紹介するものであり、本記事が独自に法的・セキュリティ上の保証を行うものではありません。
こうした特性は、将来的にProvider SelectionへData Classificationを組み合わせる際にも興味深いと感じました。
例えば概念的には、
PUBLIC
-> external provider eligible
INTERNAL
-> domestic provider eligible
RESTRICTED
-> local model only
のようなRouting Policyを考えられます。
今回検証したRuntimeには、複数Providerを候補として登録し選択する仕組みがあります。
そのため、このようなClassification-aware Routingの土台として利用できる可能性があります。
ただし重要なのは、今回このポリシーを実装したわけではないという点です。
今回確認したのはProviderを登録・選択できるところまでであり、
- データ分類の自動判定
- 分類に基づくProvider制限
- Data Residency Policyの強制
は今回の検証範囲には含まれていません。
「土台として使える可能性がある」ことと「すでに実装済みである」ことは分けて考える必要があります。
11. OpenAI互換APIの価値について考えたこと
今回の検証で特に面白かったのは、
「OpenAI互換」の価値は、単にSDKの書き方が似ていることだけではない
という点でした。
Provider-neutralな契約をRuntime側に持っている場合、OpenAI互換APIは新しいProviderを既存システムへ追加するための共通境界として機能します。
今回の場合、
Application
|
AIProvider Contract
|
Provider Selection
|
+---------+---------+
| | |
OpenAI Sakura Other Provider
のように、Sakuraを「特別な外部サービス」として扱うのではなく、複数ある推論Providerの一つとして扱うことができました。
この構造であれば、別のOpenAI互換サービスについても、
薄いAdapter + Provider登録
という同じパターンを再利用できる可能性があります。
一方で今回、OpenAI互換だけでは解決しないものも明確になりました。
例えば、
- Monetary Cost Accounting
- Data Classification
- Governance Policy
- Provider-specific Policy
- Data Residency Enforcement
などです。
つまりOpenAI互換APIは非常に便利ですが、それだけでMulti-AI Runtime全体のPortabilityが完成するわけではありません。
API CompatibilityはProvider Portabilityの重要な一部ではあるものの、Runtime Portability全体ではない。
というのが今回の検証から得た結論です。
12. まとめ
今回の検証では、以下を確認しました。
- さくらのAI EngineへOpenAI Python SDKからLive接続できた
-
gpt-oss-120bから実際にSAKURA_OKを取得できた - Token UsageもOpenAI互換レスポンスとして取得できた
- Sakura専用の薄いProvider Adapterを追加することで、既存のAIProvider Contractを変更せず接続できた
- 既存のRegistry / Provider Selection / Routingのコア実装を変更せずSakuraを候補として扱えた
- Provider PortabilityとCost Portabilityは別問題であることを確認した
- Data Residency / Governanceを考慮したProvider Routingへ発展させられる可能性がある一方、そのPolicy自体は今回未実装である
「OpenAI互換だから差し替え可能」という表現は便利ですが、実際には、
API互換
↓
Provider Adapter
↓
共通Provider Contract
↓
Routing
↓
Cost Accounting
↓
Governance
と複数の層があります。
今回確認できたのは、このうちAPI互換 → Provider Adapter → 共通契約 → Routingまでです。
金銭コスト集計やClassification-aware Governanceについては、次の課題として残りました。
「差し替え可能」と言うときに、どの層まで差し替え可能なのかを分けて検証することが重要だと、今回改めて感じました。
参考
今回の検証で使用したRuntimeに関連するプロトタイプについては、ハッカソンで制作した以下のProtoPediaページでも公開しています。
ProtoPedia — Phantom Runtime Lite
さくらのAI Engine:
本記事はQiitaの「OpenAI・Anthropic互換APIを無料で使おう!『さくらのAI Engine』3,000リクエスト使い切りチャレンジ」への参加記事です。