Netflix の LLM サービングスタック構築
本文の状態
日本語全文を表示中
詳細モードで約22分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
TLDR AI
Netflix は、LLM の完全なスタックを既存の生産環境内で自社運用し、CPU/GPUのハイブリッド構成やTritonを活用した独自の推論基盤を構築・公開した。
AI深層分析を開く2026年7月21日 01:11
AI深層分析
キーポイント
独自インフラでのフルスタック運用
Netflix は外部API依存から脱却し、モデルデプロイメントから推論までを既存の生産環境内で完結させる戦略を採用している。
JVMベースの統一サービングシステム
ルーティング、A/Bテスト、特徴量取得、推論、後処理を一貫して処理するJVMベースのシステムが中核を担い、gRPCとHTTPの両経路をサポートしている。
GPUリソースの効率的な管理
小規模モデルはインプロセスで実行し、大規模モデルはModel Scoring Service (MSS) を介してNVIDIA Triton Inference Serverに委譲するハイブリッド構成を採用している。
Java制御平面による運用自動化
デプロイ、バージョン管理、ヘルスチェック、自動スケーリングをJavaの制御平面が担い、ゼロダウンタイムでのアップグレードを実現している。
重要な引用
Netflix went further — we run the full stack ourselves, from model deployment through inference, inside our existing production environment rather than a separate ML silo.
MSS is the shared inference backend, supporting XGBoost, TensorFlow, PyTorch, and LLMs behind a unified interface, with NVIDIA Triton Inference Server underneath managing model loading, batching, and GPU scheduling.
編集コメントを表示
編集コメント
Netflixが公開したこの技術記事は、LLMの運用コストと制御性を両立させるための具体的なアーキテクチャ設計を示しており、業界全体におけるオンプレミスおよびハイブリッド推論戦略の標準化に寄与する可能性が高い。特に既存Java基盤との統合事例は、大規模システムを持つ企業にとって非常に参考になる実装パターンである。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
10 分程度でお読みいただけます
3 日前に投稿
--
*AI Platform の Model Runtime チームおよび Inference チームより*
イントロダクション
多くの組織は、ホストされた API を通じて LLM(大規模言語モデル)を利用しています。しかし Netflix ではさらに一歩踏み込み、モデルのデプロイメントから推論までを、既存のプロダクション環境内で完結させています。ML 専用のサイロ(閉じた領域)に任せるのではなく、自前でフルスタックを運用しているのです。
これらの判断の中には、直感的でないものもあれば、本番環境での負荷がかかるまでそのトレードオフが明らかにならなかったものもありました。
この記事では、特に代替案が真剣に検討されたポイント——エンジン選定、モデルのパッケージ化、API サーフェスの設計、デプロイメント戦略、そして出力制約の強制——に焦点を当てます。単に何を作ったかだけでなく、「なぜそう決めたのか」、そして設計段階では予測できなかった本番環境が教えてくれた教訓をお伝えします。
アーキテクチャ概要
Netflix におけるメンバー規模の ML(機械学習)は、JVM ベースの統一されたサービングシステムによって支えられています。このシステムは、下流の消費者向けにエンドツーエンドの流れを処理します。具体的には、ルーティングや A/B テストロジック、候補生成、特徴量フェッチ、推論、ポストプロセッシング、そして各段階でのログ出力までを一貫して担当しています。
リアルタイム処理とキャッシュされたバッチ処理の両方をサポートしています。図 1 は、現在の呼び出し元が推論にアクセスする 2 つの方法を示しています。1 つは、このサービングシステムを経由する gRPC パスです。もう 1 つは、新しい LLM ドライブ型アプリケーションで使用される直接 HTTP パスです。
推論の実行場所はモデルによって異なります。小規模な CPU モデルはプロセス内で実行され、リモート呼び出しのオーバーヘッドを回避します。一方、大規模なモデルには GPU が必要であり、サービングシステムは前処理と後処理をローカルで処理しつつ、推論自体はリモートの「Model Scoring Service (MSS)」に委譲します。
MSS は共有推論バックエンドとして機能し、XGBoost、TensorFlow、PyTorch、LLM を統一されたインターフェースの背後でサポートしています。その下層には NVIDIA Triton Inference Server が配置され、モデルの読み込み、バッチ処理、GPU スケジューリングを管理しています。
Triton の上には Java で書かれた制御プレーンが構築されており、デプロイ、バージョン管理、ヘルスチェック、自動スケーリング、複数リージョンへの展開を担当します。モデル作成者はアーティファクトをパッケージ化してデプロイ設定を行い、制御プレーンが GPU インスタンスの割り当てや Triton の構成を行い、ダウンタイムゼロでのアップグレードを実現するためのオーケストレーションを行います。
Press enter or click to view image in full size
Figure 1. Serving Architecture Overview
デザイン判断と実装
このプラットフォームを形作っているのは、エンジン、パッケージ化、API サーフェス、展開の 4 つの判断です。これらは依存関係の順序で提示されており、それぞれの判断が次の判断に制約を与えます。
vLLM を舗装されたパス(標準)エンジンとして採用
当初、このプラットフォームは TensorRT-LLM を基盤にしていました。当時、高性能な推論エンジンであり、すでに MSS で使用されている計算バックエンドである Triton とも統合されていました。
2025 年夏までに、状況は二点大きく変化しました。まず、オープンソースの推論エンジンが専用スタックとの性能差をほぼ埋めたことです。次に、私たちのワークロード構成が多様化し、埋め込みベクトルの生成やランク付け・検索のためのプレフィルのみを行う推論、自己回帰的なデコーディング、そしてステップごとの複雑な制約ロジックを持つカスタムモデルが含まれるようになったことです。
こうした多様なワークロードを踏まえて再ベンチマークを行った結果、運用上の適合性を重視し、vLLM を標準化された推論エンジンとして採用しました。選定理由は以下の通りです。
- 多段階のコンパイルパイプラインを経ずにカスタムモデルアーキテクチャを読み込めるため、非標準的なモデルに対する開発サイクルが短縮される。
- カスタムのデコーディングロジックに対応するための拡張フックが用意されており、後述する制約付きデコーディングの実装に不可欠である。
- デバッグ性が高く、コンパイル済みのエンジン(以前の TensorRT-LLM)と比較して、失敗の原因や中間状態の調査が容易である。
- 親和性が良いこと。多くの ML プラクティショナーが研究段階で vLLM を利用しており、研究から本番環境への移行コストを大幅に削減できた。
Triton への vLLM の統合
vLLM を採用したことで、次なる課題はモデルをどのようにパッケージ化するかでした。Triton では二つの方法が用意されていますが、この選択は保守性に大きな影響を与えます。具体的には、モデルのアーティファクトとフロントエンドのアップグレードとの結合度をどう制御するかが鍵となります。
Python ベースエンドでは、パッケージ作成時に明示的な入力・出力テンソル仕様が定義されます。この仕様はアーティファクトに凍結されるため、サードパーティベンダーのフロントエンドがリクエストビルダーで期待する内容と一致している必要があります。そのため、I/O 仕様に関わるすべてのフロントエンドアップグレードには、パッケージコードとの調整変更が不可欠です。対応しないと、実行時にリクエストが失敗します。
vLLM ベースエンドでは、アーティファクトはモデルの重みとトークナイザーを指す単なる JSON 設定ファイルに過ぎません。Triton の vLLM バックエンドがこの設定を読み込み、デプロイ時に I/O テンソル仕様を動的に生成します。著者はこれらの仕様を手動で定義することはありません。その結果、モデルとフロントエンドは独立して進化できます。
vLLM ベースエンドがアーキテクチャ上では正しいデフォルトです。しかし、本番環境で二つの問題が発生しました:
Triton と vLLM のバージョン不一致の問題です。Triton の vLLM バックエンドは、特定の vLLM API 仕様に合わせてコンパイルされています。両者のバージョンがズレると、例えば Triton 25.09 が vLLM 0.11.2 で削除された vllm.engine.metrics モジュールをインポートしようとして、バックエンド自体が起動しなくなります。そのため、プラットフォーム側はサービスイメージを作成する際に互換性のあるバージョンを固定(ピン留め)し、モデル作成者がパッケージング時に vLLM のバージョンを上書きできないように制御する必要があります。
カスタムモデルロジックについてはどうでしょうか。vLLM バックエンドは標準的な HuggingFace 互換のモデルを想定しており、推論ライフサイクル全体を処理します。一方、事前処理や事後処理のカスタマイズが必要だったり、アンサンブルパイプラインや独自トークナイゼーションなど非標準的な実行が必要なモデルは、Python バックエンドを使用する必要があります。これにより execute() 関数に対する完全な制御権を得られますが、この機能(エスケープハッチ)は今後も特定のモデル群に対して必要不可欠であり続けるでしょう。
Ecosystem-Compatible HTTP Frontend
エンジンとパッケージングの設計が決まったところで、次は外部からの呼び出し経路について考えます。システム設計における重要な目標の一つは、LLM モデルを特別扱いしないことです。XGBoost のアンサンブルモデルであれ大規模な LLM であれ、すべて同じ gRPC コールでスコアリングされます。これにより、クライアントライブラリ、ヘルスチェック、デプロイパイプラインを共通化して再利用できます。現在、LLM エコシステムにおいて OpenAI 互換 API が事実上の標準インターフェースとなっています。推論エンジン、オーケストレーションフレームワーク、評価ツール、そしてクライアントライブラリすべてがこの仕様に従っているため、gRPC と並行して OpenAI 互換 API を追加のフロントエンドとして公開することになりました。
実験から本番環境への移行における成果は、ホスト型モデルからファインチューニングを施したセルフホスト型モデルへ移行する際(品質、レイテンシ、コスト、データプライバシーのいずれかの目的で)に顕著です。API はそのままに、コードの変更も最小限で済みます。
Netflix Technology Blog の記事をあなたのメールボックスへ
このライターからの更新を受け取るには、Medium に無料で登録してください。
サインインを高速化するために、ログイン情報を記憶します。
API の背後では、実装において NVIDIA の Triton OpenAI 互換フロントエンド が再利用されています。埋め込まれた Triton サーバーを起動し、これを TritonLLMEngine でラップしてリクエストスキーマを Triton の推論リクエストに変換し、FastAPI を介してレスポンスを提供します。同時に KServe の HTTP/gRPC フロントエンドも有効化されており、同じ Triton インスタンスは Java コントロールプレーンからも gRPC 経由でアクセス可能です。
Triton のフロントエンドを直接採用したことで、一つの課題が浮き彫りになりました。スキーマで受け入れられる response_format が、vLLM に到達する前に静かに捨てられていたのです。その結果、JSON 出力を要求する呼び出し元は、ガイダンス付きデコーディングの制約なしに処理が進み、プラットフォーム側からエラーが報告されることなく不正な JSON が返される事態が発生しました。私たちはこのフロントエンドを git-subtree でフォークし、パッチを適用して、リクエスト時に response_format を vLLM のガイダンス付きデコーディングパラメータに変換するように修正しました。
デプロイ戦略
API サーフェスとエンジンが整った今、残る課題は新バージョンをリクエストの中断なくロールアウトする方法です。GPU 環境でのデプロイは CPU サービスに比べて起動までに時間がかかり、さらにモデルのバージョン間で入出力スキーマが変更される可能性もあるため、調整が必要になります。このプラットフォームでは、2 つの戦略を提供しています。
Red-Black デプロイは、新しいバージョンを現在のバージョンと並行して展開します。新しいインスタンスがヘルスチェックに合格すると、トラフィックは段階的に切り替わります。具体的には、新しいバージョンのスケーリングアップと古いバージョンのスケーリングダウンが同率で行われます。もしいずれかのステップで失敗した場合、システムは即座に原子ロールバックを実行します。モデルインターフェースが安定している場合、Red-Black は最適な選択肢です。
しかし、本番環境では、新しいバージョンの展開に伴って I/O スキーマの変更(例えばテンソルの次元変更など)が必要になった際、調整不足が露呈しました。この場合、アップストリームの消費者は新しいモデルが完全に稼働するまで設定を更新できず、移行期間中に「古い」リクエストを「新しい」デプロイメントに送信して失敗してしまうのです。
Versioned はこのギャップを埋めるために設計されました。これは、すべての (modelId, modelVersion) ペアに対して独立したデプロイメントを維持する仕組みです。複数のバージョンが同時にサービスを提供することで、モデルの展開と消費者側の更新を切り離します。具体的には、消費者は新しいバージョンが完全に準備されるまで設定変更を待ち、その間も古いバージョンはレガシーなトラフィックを引き続き処理し続けます。プラットフォームは一定期間アクティビティがないと古いデプロイメントをクリーンアップしますが、最新バージョンは常に保持されます。この方式のトレードオフは、移行期間の重複に伴う一時的な GPU コストの増加です。
変数設定(テンソル形状など)を推論モデルに直接埋め込み、バージョン非依存化することで、より安価な Red-Black パスを利用可能にすることを推奨します。Versioned は、避けられない破壊的インターフェース変更が必要な稀なケースに限定して使用すべきです。
オペレーション上の注意点
上記の4つの決定事項に加え、設計段階では想定されていなかった2つの運用上の課題があります。これらは本番環境で直面した問題です。
ブートシーケンス
vLLM-on-Triton インスタントを起動し、gRPC ポートが利用可能になるまでには、いくつかの調整された手順が必要です。そのうち2つは通常のフローとは異なります。
- モデルのキャッシュ処理:大規模な LLM を起動時に S3 や Hugging Face から直接ダウンロードすると、コールドスタート時の遅延がスケジューラが許容する範囲を超えてしまいます。そのため、モデル発表時点で Amazon FSx 上にモデルを事前展開(マテリアライズ)し、ウォームスタート時にはオブジェクトストレージではなく高パフォーマンスなファイルシステムから読み込むようにしています。
- Embedded モードとスタンドアロンモードの切り替え:OpenAI 互換 API を必要とする場合、Triton は OpenAI 互換フロントエンドプロセス内に埋め込まれたサーバーとして動作します。それ以外の場合はスタンドアロンで稼働します。この設定は、パッケージ化時に各デプロイごとに個別に構成されます。
残りのブートシーケンスは機械的な手順です。モデルパッケージの展開、Python entry_points を介したカスタム vLLM プラグインのインストール、Prometheus のマルチプロセスディレクトリのクリーンアップ、そしてエンジンが準備完了するまで gRPC ポートをゲート制御することを行います。
ユニファイドメトリクスエンドポイント
上記の Prometheus の整理から、より広範な観測性のギャップが浮かび上がります。vLLM は .db ファイルとして PROMETHEUS_MULTIPROC_DIR にメトリクスを出力し、Triton は独自の Prometheus エンドポイントを介してサーバーレベルのメトリクスを報告しています。しかし、両者は互いの存在を認識しておらず、Triton 内蔵のブリッジが表面化するのは vLLM の 40 種類以上のメトリクスのうちわずか 9 種のみです。トークンスループット、KV キャッシュ利用率、プレフィックスキャッシュヒット率といった重要な指標が見落とされています。
そこで私たちは、両者を統合する軽量な HTTP プロキシを追加しました。このプロキシは HTTP を介して Triton のメトリクスを取得し、Prometheus の MultiProcessCollector を用いてディスク上の vLLM メトリクスを読み取り、統合された出力を返します。既存のダッシュボードやアラート設定も変更なしで動作可能です。
大規模な制約付きデコーディングの詳細
Netflix の一部生産ワークロードでは、トークン生成に対するきめ細やかな制御が不可欠です。推論後にビジネスロジックを適用して無効な生成物を処理し、再試行や修復を行うのではなく、デコードループ内部に制約を組み込みます。これにより、モデルは構造的にコンプライアンスを満たす出力を生成します。
実装は vLLM のカスタム logits プロセッサインターフェースを通じて行います。各制約は状態機械としてモデル化され、生成されたトークンの履歴に応じて進化し、各ステップでトークンの有効性を示すマスクを出力します。リクエストごとに独自の構成済みプロセッサが割り当てられます。なぜなら、異なるリクエストには異なるルールが適用されるからです。
このシステムをスケールさせる過程では、2 つのエンジンバージョンを経験しました。当初は vLLM V0 にデプロイしましたが、機能に不足があったため、V1 が成熟した 2025 年第 4 四半期に移行しています。以下の 2 つの小節では、移行前の状況と移行後の改善点を対比して解説します。
なぜ最初の導入がスケールしなかったのか
当初の純粋な Python 実装は機能面では問題ありませんでしたが、スケーラビリティのボトルネックに直面しました。vLLM V0 ではカスタムロジットプロセッサがリクエストごとに実行されます。具体的には、GPU がバッチ全体のロジットを生成した後、CPU がそれらをコピーして転送完了を待機し、その後、制約ロジックが各リクエストに対して順次処理されます。Python の GIL(グローバルインタプリタロック)が並列化を阻害するため、この処理は逐次的にならざるを得ません。
その結果、ロジット処理にかかる CPU 時間はバッチサイズに比例して直線的に増加し、レイテンシの尾部(遅延するケース)が悪化します。モデルの順方向計算自体は GPU で効率的にバッチ処理されているにもかかわらず、エンドツーエンドのレイテンシが CPU 依存の状態になってしまいます。これは単一リクエストでのベンチマークでは見えないボトルネックであり、実際の並行処理下で初めて顕在化する問題です。
Figure 2 では、この逐次的な処理パターンが視覚的に確認できます。
Press enter or click to view image in full size
図 2:vLLM V0 を使用した CPU 上でのロジットプロセッサの逐次実行
vLLM V1 でバッチレベル設計が可能に
構造的な改善は、vLLM V1 の登場で実現しました。ここではロジット処理をバッチレベルに移行しています。カスタムプロセッサを書き換え、バッチレベルのデータ構造上で動作するようにし、複数のリクエストに対してマスク計算を一括で行えるようにしました。また、ホットパス(頻繁に実行される経路)は C++ で再実装し、マルチスレッド化によって GIL(グローバルインタプリタロック)の影響を回避しています。
V1 の API では、バッチ構成の変化を update_state(batch_update) を通じて明示的に追跡する必要があります。これは V0 の個々のリクエストごとのインターフェースよりも複雑ですが、動的に変化するバッチ内で状態を正しく保つために不可欠な設計です。図 3 に示す通り、vLLM V1 ではバッチサイズが大きくなってもロジット処理にかかる時間は一定に保たれています。
(画像をクリックまたは Enter キーを押して全サイズで表示)
図 3:vLLM V1 を使用した CPU 上でのバッチ化されたロジットプロセッサの実行
運用面での強化
これでパフォーマンスがボトルネックになることはなくなりました。しかし、デコードループ内の状態保持型制約ロジックにより、設計段階では想定していなかった 2 つの問題が発生しました。
- パーシャルプリフィル。V1 ではチャンク化されたプリフィルを行うため、リクエストは複数のエンジンステップにわたってプリフィルされます。BatchUpdate には、リクエストが完全にプリフィルされたのか部分的なままなのかを区別する粒度がないため、内部での追跡機能を追加しました。
- プリーエンプション(割り込み)。メモリ圧力がかかると、vLLM は部分的に完了したリクエストの KV キャッシュを退去させ、異なるプロンプトと出力トークンリストで後から再スケジュールすることがあります。これにより、「出力トークンリストは単調増加する」という状態機械の前提が崩れます。そこで、デコードステップ間でトークン履歴が縮小した場合を検知し、状態機械をリセットして新しいプロンプトから再初期化するようにしています。
まとめ
私たちは、低レイテンシ、深いカスタマイズ性、既存インフラとの統合といった広範な生産環境での ML 要件に対応する LLM サービングプラットフォームの構築を目指しました。その結果、vLLM と Triton を基盤とし、一貫した API の背後に統合されたシステムが完成しました。これは、ML プラクティショナーが実験から本番環境へ迅速に進めるための高速パスを提供するように設計されています。
教訓は往々にして細部にありました——バージョンの固定(pinning)、目に見えない API のギャップ、パッケージ化におけるトレードオフなどです。これらに対処したことで、プラットフォームは実質的に堅牢になり、開発者体験も滑らかになりました。今後の投資先には、私たちが摩擦が生じると予想される領域が反映されています:
システムプロンプトの圧縮により、品質を損なうことなくプロンプト長を短縮します。
vLLM V1 の非同期スケジューリングを実装しました。また、CPU 上のコードではなく融合された GPU カーネルとして動作するベクトル化ロジットプロセッサを導入しています。さらに、メモリフットプリントの削減とスループットの向上を図るため、低精度モデルバリアントも活用しています。
この分野は日々進化しており、私たちはオープンソースコミュニティとの緊密な連携を継続してまいります。
貢献者
本システムは、Netflix の AI Platform オrg に所属する多くのチームによる緊密な協力と多大な貢献の結晶です。特に、Liping Peng はモデルパッケージングワークフローの設計・開発を担当し、Triton と vLLM を MSS に統合して LLM serving の統一パスを実現しました。
Hakan Baba、Nicolas Hortiguera、ZQ Zhang は、全生産モデルにおける GPU 容量計画、システムパフォーマンスチューニング、アプリケーション統合、観測性(オバザビリティ)、A/B テストの準備状況、および運用卓越性の取り組みを主導しました。Santino Ramos は vLLM を生産環境のモデルで利用可能にし、制約付きデコーディングのパフォーマンスを最適化しました。
Binh Tang はカスタムモデル serving の初期バージョンを開発し、さまざまな LLM serving フレームワークのベンチマークを行いました。Lanxi Huang と Daneo Zhang は、ユーザーによるセルフサービスを実現するための serving 開発ツールを構築しました。
Lingyi Liu は全体のシステムアーキテクチャと中核的な技術決定を主導し、Abhishek Agrawal と Shaojing Li が管理リーダーシップを発揮して、方向性の整合性、優先順位の付け方、そして実行の確保を行いました。
謝辞
本稿は、Triton、vLLM、PyTorch など、オープンソースの機械学習ライブラリを大きく活用して作成されました。コミュニティの皆様、特に各チームや貢献者の方々に深く感謝いたします。また、Netflix AI のメンバーシステム部門のパートナーチームには、モデリング分野における緊密な連携とイノベーションに多大なるご協力をいただき、心より御礼申し上げます。
AI算出
技術分析ainew評価高い
記事は特定の企業(Netflix)の具体的な技術実装と設計判断を詳述しており、AI/ML の中核テーマであるため関連性は最高です。新規性については、既存のクラスターに同様の詳細なアーキテクチャ解説がないため独自情報として評価されますが、ベンダー導入事例という性質上、世界初の画期的発表(1.0)よりは技術的深みを持つ追報・分析(0.75)と判断しました。検索機会については「LLM サービング」や「vLLM」という明確な製品名が含まれるため高評価です。日本関連性は、Netflix の事例が日本の開発者にとって参考にはなるものの、日本固有の規制や企業発表ではないため低めです。
6つの評価軸を見る
- AI関連度
- 100
- 情報源の信頼性
- 50
- 新規性
- 75
- 調べる価値
- 75
- 重複の少なさ
- 100
- 日本での有用性
- 25
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み