OpenAI 互換 API ゲートウェイの背後にあるマルチテナント RAG
マルチモデル API ゲートウェイの背後に検索拡張生成を構築するための実用的なリファレンス アーキテクチャ: テナント スコープのインデックス、プロバイダー中立の検索アダプター、正規化された引用、ライフサイクル制御、コスト帰属。
顧客対応の AI アシスタントには取得拡張生成が必要ですが、リクエストが 1 つのモデル プロバイダーのネイティブ スタックではなく OpenAI 互換の API ゲートウェイを経由する場合、RAG は困難になります。ゲートウェイは、テナント データを分離し、モデル プロバイダー間で引用を保持し、インデックス付きコンテンツをスケジュールに従って削除し、埋め込み、取得、生成のコストを適切な顧客に割り当てる必要があります。
実際的な答えは、取得をファーストクラスのゲートウェイ サブシステムとして扱うことです。 1 つのプロバイダー統合内にそれを隠さないでください。取得を生成から分離し、すべてのリクエストにテナント スコープの取得コンテキストを与え、引用を返す前に正規化し、請求対象の各ステップを台帳に記録します。
リーダーの問題
多くの顧客向けに AI アシスタントを構築するチームは、通常、単純なフローから開始します。つまり、ドキュメントをアップロードし、チャンクを埋め込み、上位一致を取得し、それらのスニペットをプロンプトに入力し、モデルに回答を求めるというものです。これは、製品に複数のモデル プロバイダー、顧客レベルの請求、オフボード、監査可能性が必要になるまで機能します。
リスクは不正確な回答だけではありません。より大きな運用リスクとしては、テナントの名前空間の間違い、検証できない引用、ドキュメント削除後の古いインデックス、取得コストが一般的なインフラストラクチャの費用に消えてしまうために説明できないマージンなどがあります。
この記事では、事実、推奨事項、予測を分けて説明します。実際は、現在のプロバイダーおよびベクター データベース API によって文書化された実装機能です。推奨事項は、ゲートウェイ製品のアーキテクチャの選択です。予測では、プロバイダーの取得機能が変化し続けるため、このアーキテクチャには柔軟性が必要になる可能性があります。
リファレンス アーキテクチャ
ゲートウェイ レベルの RAG 設計には、次の 5 つのコンポーネントが必要です。
- テナント リゾルバー: は、受信 API キー、ワークスペース、顧客アカウント、またはパートナー API 顧客を正規の tenant_id にマッピングします。
- 取得プロファイル: は、以下を定義します。検索するコーパス、使用する埋め込みモデル、結果数、フィルター、再ランキング オプション、引用要件、フォールバック動作。
- 取得アダプター層: ネイティブ プロバイダーの取得、外部ベクター データベース、またはカスタム検索サービスを 1 つの内部インターフェイス経由で呼び出します。
- プロンプト アセンブリおよび生成アダプター: ベクター バックエンドの詳細を公開せずに、取得したコンテキストを選択したモデル プロバイダーに渡します。
- 使用状況および監査台帳: 埋め込み、インデックス付け、取得、プロンプト トークン、完了トークン、テナント、モデル、プロバイダー、およびトレース識別子を記録します。
最小限のリクエスト コントラクトはプロバイダー中立を保つことができます:
{
"テナントID": "テナント_123",
"モデル": "gpt 互換モデルまたはクロード互換モデル",
"retrieval_profile": "support_docs_v2",
"引用_必須": true、
「メッセージ」: [
{"role": "user", "content": "年間プランの返金ポリシーは何ですか?"}
】
}応答もプロバイダー中立である必要があります:
{
"answer": "年間プランは、設定されたポリシー期間内で返金できます...",
「引用」: [
{
"source_id": "doc_789",
"title": "請求ポリシー",
"url_or_internal_ref": "kb://billing-policy",
"chunk_id": "chunk_044",
"オフセット": {"ページ": 3},
「スコア」: 0.82、
"取得プロバイダー": "ベクトルデータベース",
"model_provider": "openai_compatibility",
「プロバイダーペイロード」: {}
}
]、
"retrieval_trace_id": "rt_456",
"請求可能なテナント": "テナント_123",
"embedding_usage": null、
"取得_使用法": {"クエリ": 1、"結果": 6}、
"model_usage": {"input_tokens": 1920、"output_tokens": 180}}事実: プロバイダーの取得機能は同一ではありません
OpenAI の Vector Store API は、作成、検索、チャンク戦略による構成、ファイル メタデータの関連付け、削除が可能なベクター ストアをサポートしています。ベクター ストア検索は、クエリ、フィルター、最大結果数、ランキング オプション、スコアしきい値、およびクエリ書き換え制御をサポートします。これらのコントロールにより、ゲートウェイ作成者はレイテンシー、関連性、コストを調整するための便利な手段を得ることができます。
OpenAI プラットフォームのデータ コントロールにより、ライフサイクル設計も重要になります。ベクター ストア内の顧客コンテンツは削除されるまで保持されます。テナントがオフボードした場合、または一時的なプロジェクトの有効期限が切れた場合、ゲートウェイは、プロバイダーが製品のビジネス スケジュールに従ってインデックス付きコンテンツを自動的に削除すると想定できません。
Anthropic は、引用の異なるパターンを公開します。アプリケーションは、ソースとタイトルのメタデータを含む検索結果コンテンツ ブロックを提供でき、引用が有効な場合、モデルは生成されたテキストに引用参照を添付できます。実際的な制約があります。検索結果の引用設定はリクエスト内でオールオアナッシングであり、検索結果ブロックはテキスト コンテンツをサポートし、引用の粒度はコンテンツがブロックに分割される方法によって異なります。
意味は直接的です。ゲートウェイは、そのプロバイダを永続的な取得権限にするつもりがない限り、そのプロバイダの取得形式をパブリック コントラクトとして公開すべきではありません。
推奨事項: 取得ではなく取得アダプタを使用してください。ロックイン
内部取得アダプター インターフェイスを作成します。ゲートウェイは、その背後で複数のバックエンドをサポートできます。
- ネイティブ プロバイダーの取得: 顧客が 1 つのプロバイダーのファイル検索またはベクター ストア機能への最速パスを必要とする場合に役立ちます。
- 外部ベクター データベース: 製品が一貫したテナント分離とライフサイクル制御により多くのモデル プロバイダーをサポートする必要がある場合に役立ちます。
- プリフェッチされた検索結果ブロック: ゲートウェイが組み立てられるときに役立ちます。テキストを取得し、それを明示的な引用を認識するコンテキストをサポートするプロバイダーに渡します。
アダプターは、バックエンドに関係なく、同じ内部構造を返す必要があります。
interface RetrievalResult {
retrievalTraceId: 文字列;
テナント ID: 文字列;
コーパスID: 文字列;
チャンク: 配列<{
ソース ID: 文字列;
タイトル: 文字列;
テキスト: 文字列;
urlOrInternalRef?: 文字列;
チャンク ID: 文字列;
オフセット?: { ページ?: 番号; byteStart?: 数値; byteEnd?: 数値; tokenStart?: 数値; tokenEnd?: 数値 };
スコア?: 数値;
メタデータ: レコード<文字列, 文字列 |番号 |ブール値>;
プロバイダペイロード?: 不明;
}>;
取得の使用法: {
プロバイダー: 文字列;
クエリカウント: 数値;
結果数: 数値;
billableUnits?: 数値;
};}これにより、生成層は、OpenAI ベクター ストア、Pinecone、Weaviate、データベース全文検索インデックス、内部ハイブリッド リトリーバーのいずれから来たのかを知らずにコンテキストを受け取ることができます。
テナントの分離はベクター クエリの前に開始されます
テナントの分離は、プロンプトの指示に依存してはなりません。これは、取得前に、ストレージ境界とクエリ境界で強制する必要があります。
Pinecone スタイルのシステムの場合、文書化されたマルチテナント パターンは、サーバーレス インデックスのテナントごとに 1 つの名前空間です。データ プレーンの操作は名前空間を対象としています。名前空間を削除するとテナントのレコードが削除されるため、テナントの分離とオフボードが簡素化されます。 Pinecone は、名前空間とメタデータ フィルタリングの間のトレードオフについても文書化しています。つまり、大規模な共有名前空間内でのフィルタリングは、名前空間スコープのクエリよりも多くのデータをスキャンし、コストがかかり、実行速度が遅くなる可能性があります。
Weaviate スタイルのシステムの場合、マルチテナントは各テナントを個別のシャードに保存するため、あるテナントのデータは別のテナントには表示されません。テナントを削除すると、関連付けられたシャードが削除されます。 Weaviate は、アクティブ、非アクティブ、オフロードなどのテナント状態もサポートしており、めったに使用されないテナントのライフサイクル オプションを作成します。
実装チェックリスト
- ユーザー指定の本文フィールドだけではなく、認証されたゲートウェイ ID から tenant_id を解決します。
- サーバー側を介して、tenant_id をベクター名前空間、シャード、またはプロバイダー ベクター ストア ID にマッピングします。
- API キー テナントと要求されたコーパス テナントが一致しないリクエストを拒否します。
- 共有パブリック コーパスをプライベート テナント コーパスから分離してください。
- テナント境界がすでに選択された後、ドキュメント タイプ、言語、製品領域、または日付範囲に対してメタデータ フィルタリングを使用します。
- ログの名前空間、シャード、コーパス ID、取得プロファイル、監査可能性のための retrieval_trace_id 。
個別の承認、個別のインデックス、または制御された集約パスを使用して、明示的な管理ワークフローのテナント間検索を予約します。クロステナント検索をメタデータ フィルターの偶発的な副作用にしないでください。
引用をゲートウェイ オブジェクトとして正規化する
引用は単なる装飾ではなく、製品の契約です。カスタマー サポート アシスタント、法的起草ツール、または社内ナレッジ アシスタントは、回答が作成された理由とサポートするテキストの出所を示す必要があります。
ゲートウェイは、引用データを独自のスキーマに正規化する必要があります。
{
"source_id": "doc_123",
"title": "返金条件",
"url_or_internal_ref": "kb://refund-terms",
"chunk_id": "chunk_006",
"オフセット": {"ページ": 2、"バイト開始": 4410、"バイト終了": 5020}、
「スコア」: 0.79、
"retrieval_provider": "weaviate",
"model_provider": "人類",
「モデルプロバイダー引用ペイロード」: {}
}正規化されたフィールドを安定した状態に保ち、プロバイダー固有の拡張を許可します。 一部のプロバイダーは、他のプロバイダーよりも豊富な引用詳細を公開します。 検索結果ブロックを引用する人もいます。 アップロードされたファイルを引用する場合もあります。 アプリケーションによっては、アプリケーションが必要とする正確なオフセット形式が提供されないものもあります。 ゲートウェイは、すべてのプロバイダーが同一の引用セマンティクスを持っていると偽ることなく、存在するものを保存する必要があります。
厳密引用モード
quote_required が true の場合、失敗時の動作を前もって定義します。 厳密モードでは、すべての事実の段落に少なくとも 1 つの引用が含まれていること、または最終解答に最小スコアしきい値を超える取得されたチャンクからの引用が含まれていることを要求できます。 選択したモデル プロバイダーが引用契約を満たすことができない場合、ゲートウェイはフェイル ファストにするか、互換性のあるプロバイダーを使用するか、構造化された拒否を返す必要があります。
これは推奨事項であり、普遍的なルールではありません。 厳密引用モードでは信頼性が向上しますが、拒否、再試行、およびフォールバックの複雑さが増加する可能性があります。 リスクの低いクリエイティブ ワークフローの場合、引用はオプションである場合があります。 顧客対応のサポートや規制された内部ワークフローの場合、ciliation_required は多くの場合、取得プロファイルの一部である必要があります。
インデックス ライフサイクルは製品機能です
RAG システムはデータを蓄積します。 一時的なアップロードが誤って永続的なものになってしまいます。 元顧客は埋め込みを残します。 製品チームはチャンク戦略を変更し、古いインデックスを再構築することを忘れています。ゲートウェイはライフサイクル制御を明示する必要があります。
推奨されるライフサイクル制御は次のとおりです。
- 一時的なコーパスの有効期限: 短期間のセッション用にアップロードされたドキュメントには、有効期限のタイムスタンプと削除ジョブが必要です。
- テナントのオフボーディング: テナントの削除では、ネームスペース、シャード、プロバイダー ベクター ストア、および関連ファイルの削除をキューに入れる必要があります。
- コールド テナントの処理:
- コールド テナントの処理: サポートされている場合、非アクティブなテナントを非アクティブまたはオフロードとしてマークして、リソースの使用量を削減できます。
- バージョン管理の再インデックス: 各チャンクの埋め込みモデル、チャンク ポリシー、パーサー バージョン、indexed_at を保存します。
- 削除ステータスの公開: パートナー API ワークフローは、ドキュメントの削除、
重要な事実は、一部のベクター ストアのコンテンツは削除されるまで保持されるということです。 アーキテクチャの推奨事項は、顧客向けの状態のない非同期ジョブに削除を埋め込むのではなく、削除を可視化してテストできるようにすることです。
3 つのコスト台帳を追跡する
RAG には、単一のトークン台帳では十分ではありません。 ゲートウェイには少なくとも 3 つの台帳が必要です。
- 埋め込みとインデックス付けのコスト: ドキュメントの解析、チャンク化、埋め込み呼び出し、ファイル ストレージ、インデックスの書き込み、インデックスの再作成。
- 取得コスト: ベクトル データベースの読み取り、ネイティブ ベクトル ストアの検索、再ランキング、クエリの書き換え、結果の拡張。
- 生成コスト:ユーザー メッセージからの入力トークンと取得されたコンテキスト、出力トークン、ツール呼び出し、再試行、フォールバック。
これは、AI コストを再販したり割り当てたりする代理店、SaaS ベンダー、社内プラットフォーム チームにとって特に重要です。 個別の台帳がないと、RAG マージンを説明するのが難しくなります。 世代の使用量が少ないテナントでも、継続的にドキュメントをアップロードしたり、大規模なコーパスのインデックスを再作成したり、広範な検索クエリを実行したりすると、コストが高くなる可能性があります。
各台帳イベントには、tenant_id、異なる場合は customer_id、API キー ID、retrieval_profile、corpus_id、モデル、プロバイダー、trace_id、および請求対象ユニットを含める必要があります。 これにより、使用状況分析により、どのテナントが高価な取得プロファイルを持っているか、どのコーパスが古いか、どのモデルが引用エラーを生成しているか、取得で返されるコンテキストが多すぎるため、どの顧客が過大なプロンプトを生成しているかなど、実用的な質問に答えることができます。
テストすべき障害モード
ゲートウェイ RAG サブシステムには、顧客が目に見える損害を引き起こす障害モードのテストが必要です。
- Missing引用: ciliation_required は true ですが、プロバイダーの応答に使用可能な引用参照が含まれていません。
- 古いインデックス: ドキュメントが更新または削除されましたが、古いチャンクが検索結果に表示されたままです。
- テナントの不一致: リクエストはテナント A に解決されますが、コーパスまたは名前空間はテナントに属しています。 B.
- 広範すぎる検索: プロファイルが返すチャンクが多すぎるため、コストが増加し、回答の質が低下します。
- チャンク サイズの不一致: チャンクが大きすぎて引用が不正確になるか、小さすぎてコンテキストの意味が失われます。
- プロバイダーの機能の不一致: あるモデルは必要な形式で引用を発行できますが、別のモデルは引用を発行できます。
- ライフサイクルの失敗: 削除が要求されましたが、プロバイダ側のストレージはアクティブなままであるか未検証のままです。
これらのテストは、1 つのプロバイダ アダプタ内だけでなく、ゲートウェイ コントラクト レベルで実行する必要があります。 目標は、取得バックエンドまたは生成プロバイダが変更された場合でも、パブリックの動作が安定していることを証明することです。
トレードオフ
ネイティブ プロバイダの取得により、アプリケーション コードを削減し、最初のバージョンを高速化できます。 その代償として、ストレージ ライフサイクル、引用形式、クエリ制御、および機能の可用性が 1 つのプロバイダーに関連付けられる可能性があります。
外部ベクトル データベースにより、運用面が追加されます。 利点は、OpenAI 互換モデル、Anthropic モデル、将来のプロバイダー間での移植性が強化されることです。 また、テナント スコープの名前空間またはシャードで、ゲートウェイがいつ請求やオフボードを担当するかを推論しやすくなります。
きめ細かいチャンクにより、引用の精度と監査可能性が向上します。 また、インデックス サイズ、取得量が増加し、アセンブリが複雑になります。 粗いチャンクはより単純ですが、厳密な引用必須モードにより、ユーザーの信頼が向上します。また、必要な引用形式を生成できないモデルをゲートウェイに処理させることになります。これは、リクエストの拒否、モデルの変更、または信頼性の低い状態で応答を返すことを意味する場合があります。
予測: 取得はよりネイティブになるが、ゲートウェイには依然として独自のコントラクトが必要です。
プロバイダネイティブの取得機能は、さらに高機能になる可能性があります。 より多くのモデルが、構造化されたソース メタデータを含む取得されたコンテキストを受け入れるようになります。 より多くの API で、ランキング制御、クエリの書き換え、引用設定が公開される予定です。 ただし、ゲートウェイ契約の必要性がなくなるわけではありません。
ゲートウェイは、テナント ID、キー管理、支出制限、使用状況分析、パートナー API ワークフロー、および顧客向けの削除約束を引き続き所有します。 プロバイダー機能はアダプター層の背後で使用できますが、製品はすべてのテナント、モデル、請求ワークフローを 1 つのプロバイダーの取得抽象化に強制するべきではありません。
実用的な結論
明示的な境界を持つゲートウェイ サブシステムとしてマルチテナント RAG を構築します。 取得する前にテナント ID を解決します。 テナント スコープの名前空間、シャード、またはベクター ストアを使用します。 取得はアダプターの背後に置いてください。 引用をゲートウェイ所有のスキーマに正規化します。 ライフサイクル状態と削除検証を追加します。 埋め込み、取得、生成のコストを個別に追跡します。
このアーキテクチャでは、製品を 1 つの取得プロバイダーに固定することなく、RAG を接地した状態に保ちます。 また、AI アシスタントがプロトタイプから顧客対応システムに移行するときに必要な運用管理 (分離、引用、移植性、ライフサイクル管理、コスト帰属など) をチームに提供します。