7 ポイント 投稿者 GN⁺ 3 시간 전 | まだコメントはありません。 | WhatsAppで共有
  • NetflixはLLMを別個のサイロとして分離せず、既存のMLインフラ上で一緒に運用し、vLLMとTritonを統合サービング基盤に接続している
  • デフォルトエンジンに選ばれたvLLMは、カスタムモデル対応、デバッグのしやすさ、拡張フック、研究環境との親和性を備え、TritonのvLLM backendによってモデルとフロントエンドの結合度も下げている
  • 既存のgRPCとOpenAI互換APIを併提供しているが、response_formatの欠落、Triton・vLLMのバージョン不一致、非標準モデル処理のような本番で露呈したギャップは自前で補完する必要があった
  • 安定したデプロイには低コストなRed-Black戦略を優先適用し、互換性のないI/O変更が避けられない場合にのみ複数バージョンを同時維持するVersioned戦略を使う
  • リクエストごとの制約をデコードループで強制するロジットプロセッサをvLLM V1のバッチ処理とマルチスレッドC++で再実装し、今後はGPU融合カーネル・非同期スケジューリング・低精度モデルへ拡張する計画である

既存MLインフラに統合したサービング構成

  • NetflixのJVMベース統合サービングシステムは、ルーティングとA/Bテスト、候補生成、特徴量取得、推論、後処理、段階別ロギングを処理し、リアルタイム経路とキャッシュされたバッチ経路の両方をサポートする
  • 呼び出し側は既存サービングシステムのgRPC経路、または新しいLLMアプリケーション向けの直接HTTP経路で推論にアクセスする
  • 実行場所はモデル規模によって異なる
    • 小さなCPUモデルは、リモート呼び出しコストを避けるためプロセス内で実行する
    • 大きなGPUモデルは、前処理・後処理をローカルで行い、推論をリモートのModel Scoring Service(MSS) に委譲する
  • MSSはXGBoost、TensorFlow、PyTorch、LLMを単一インターフェースで提供し、下層のNVIDIA Triton Inference Serverがモデルロード、バッチ処理、GPUスケジューリングを担う
  • Triton上のJava制御レイヤーは、デプロイ、バージョン管理、状態確認、オートスケーリング、マルチリージョン展開を処理する
    • モデル開発者がアーティファクトとデプロイ設定をパッケージ化すると、GPUインスタンスをプロビジョニングしてTritonを構成する
    • アップグレードは無停止方式で調整する

デフォルト推論エンジンとしてvLLMを選択

  • 初期プラットフォームでは、当時高性能でMSSのTritonとすでに統合されていたTensorRT-LLMを使っていた
  • 2025年夏には、オープンソースエンジンが特化スタックとの性能差をほぼ埋め、ワークロードも次の範囲へ広がった
    • 埋め込み生成
    • ランキングと検索のためのprefill-only推論
    • 自己回帰デコーディング
    • 段階別制約ロジックが複雑なカスタムモデル
  • これらのワークロードを再ベンチマークしたうえで、運用適合性を基準にvLLMをデフォルト経路エンジンに選定した
    • 多段コンパイルなしでカスタムモデルアーキテクチャを読み込めるため、非標準モデルの反復開発が速い
    • カスタムデコーディングロジック向けの拡張フックを提供する
    • コンパイルエンジンだった初期TensorRT-LLMより、障害や中間状態を調査しやすい
    • 研究段階ですでにvLLMに慣れているML実務者が多く、本番移行コストが下がる

TritonとvLLMのパッケージング方式

  • TritonにはPython backendとvLLM backendという2つのパッケージング経路があり、フロントエンドのアップグレードとモデルアーティファクトがどれだけ強く結び付くかが主な違いである
  • Python backendでは、開発者がパッケージング時点で入出力テンソル仕様を定義する
    • 仕様はアーティファクトに固定され、外部フロントエンドのリクエストビルダーと一致している必要がある
    • フロントエンドのアップグレードでI/Oが変わると、パッケージングコードも一緒に修正しなければならず、そうしないと実行時リクエストが失敗する
  • vLLM backendのアーティファクトは、モデル重みとトークナイザーを指すJSON設定で構成される
    • デプロイ時にTriton backendがI/Oテンソル仕様を動的に生成する
    • モデル開発者はテンソル仕様を定義する必要がなく、モデルとフロントエンドを独立して変更できる
  • デフォルト選択はvLLM backendだが、本番では2つの制約が現れた
    • バージョン不一致: Triton backendは特定のvLLM APIを前提にコンパイルされるため、両者のバージョンがずれるとbackend全体をロードできない
      • たとえばTriton 25.09はvllm.engine.metricsをimportするが、そのモジュールはvLLM 0.11.2で削除されている
      • サービスイメージ作成時に互換バージョンを固定し、モデル開発者がパッケージング段階でvLLMバージョンを上書きできないようにする必要がある
    • カスタム実行ロジック: vLLM backendは標準的なHuggingFace互換モデルと、推論ライフサイクル全体を前提としている
      • カスタム前処理・後処理、アンサンブルパイプライン、別個のトークン化などの非標準実行には、execute()を制御できるPython backendが必要である
      • 一部モデルでは、この迂回経路が引き続き必要になる

gRPCとOpenAI互換HTTP API

  • XGBoostアンサンブルから大規模LLMまで、同一のgRPC呼び出しで評価できるようにし、既存クライアントライブラリ、状態確認、デプロイパイプラインを再利用している
  • LLMエコシステムの推論エンジン、オーケストレーションフレームワーク、評価ツール、クライアントライブラリがOpenAI互換インターフェースを使うため、これをgRPCと並行して提供している
  • 同じAPIを維持するため、品質・レイテンシ・コスト・データプライバシーを理由に、ホスティングモデルからファインチューニング済みの自社ホスティングモデルへ移る際もコード変更は小さい
  • 実装にはNVIDIAのTriton OpenAI互換フロントエンドを再利用している
    • 組み込みTritonサーバーを起動する
    • TritonLLMEngineがリクエストスキーマをTriton推論リクエストに変換する
    • FastAPIでレスポンスを提供する
    • KServe HTTP/gRPCフロントエンドも同時に有効化し、Java制御レイヤーが同じTritonインスタンスへgRPCでアクセスできるようにする
  • フロントエンドがスキーマで許可したresponse_formatを、vLLMへ渡す前に黙って捨てる問題が見つかった
    • JSON出力を要求しても誘導デコーディング制約なしで実行され、不正なJSONを返す可能性があり、プラットフォームエラーも表面化しなかった
    • フロントエンドをGit subtreeとして取り込み、response_formatリクエストをvLLMの誘導デコーディングパラメータへ変換するようパッチを当てた

無停止モデルデプロイ戦略

  • GPUデプロイはCPUサービスより起動時間が長く、モデルバージョン間でI/Oスキーマまで変わり得るため、リクエストを止めないロールアウトには追加の調整が必要である
  • Red-Blackデプロイは、既存バージョンの横に新バージョンを立ち上げ、状態確認を通過したら段階的にトラフィックを切り替える
    • 新旧バージョンのスケールアップ・スケールダウンを同じ比率で進める
    • どの段階で失敗しても原子的にロールバックする
    • モデルインターフェースが安定している場合に適している
  • 新しいテンソル次元のようにI/Oスキーマが変わると、Red-Blackには調整ギャップが生じる
    • 新モデルが完全に有効化されるまでは、上位コンシューマーは設定を変えられない
    • 切り替え区間で旧形式のリクエストが新デプロイへ送られると失敗する
  • Versionedデプロイは、(modelId, modelVersion)の組ごとに独立したデプロイを維持することで、この問題を解決する
    • 複数バージョンを同時に提供するため、モデルデプロイとコンシューマー更新を分離できる
    • コンシューマーは新バージョンの完全準備後に設定を変更し、旧バージョンはレガシートラフィックを引き続き処理する
    • 非アクティブになった旧デプロイは整理するが、最新バージョンは常に保持する
    • 移行中にバージョンが重複する期間は、GPUコストが一時的に増える
  • テンソル形状のように変わり得る設定は推論モデル内に直接組み込み、バージョン非依存にして低コストなRed-Blackを使うことを推奨している
  • Versionedは、互換性のないインターフェース変更が避けられない場合にのみ使用する

起動手順とモデルキャッシュ

  • vLLM-on-Tritonインスタンスは、複数の起動段階を終えて初めてgRPCポートを開ける
  • 大規模LLMを起動する際にS3やHugging Faceから直接ダウンロードすると、コールドスタートがスケジューラ許容範囲を超えるほど長くなる
    • モデル公開時点で、モデルをAmazon FSxに事前実体化しておく
    • その後の起動過程では、オブジェクトストレージではなく高性能ファイルシステムを使う
  • OpenAI互換APIが必要なデプロイでは、Tritonをそのフロントエンドプロセス内の組み込みサーバーとして実行する
    • それ以外のデプロイでは、Tritonを独立実行する
    • 実行方式はパッケージング時にデプロイごとに設定する
  • そのほかの起動手順には、モデルパッケージの展開、Python entry_pointsによるカスタムvLLMプラグインのインストール、Prometheusマルチプロセスディレクトリの整理、エンジン準備完了までgRPCポートを閉じておくことが含まれる

TritonとvLLMメトリクスの統合

  • vLLMはPROMETHEUS_MULTIPROC_DIR.dbファイルとしてメトリクスを記録し、Tritonは別のPrometheusエンドポイントでサーバーメトリクスを提供する
  • 両システムは互いのメトリクスを認識せず、Triton内蔵ブリッジはvLLMの40超のメトリクスのうち9件しか公開しない
    • トークンスループット
    • KVキャッシュ使用率
    • プレフィックスキャッシュヒット率のような主要指標が欠けている
  • 軽量HTTPプロキシがTritonメトリクスをHTTPで取得し、Prometheus MultiProcessCollectorでディスク上のvLLMメトリクスを読み取り、1つの/metricsレスポンスに統合する
  • 既存のダッシュボードとアラートは修正なしでそのまま使える

デコーディング過程で出力制約を強制

  • 一部の本番ワークロードではトークン生成のきめ細かな制御が必要であり、推論後に不正結果を再試行・復旧する代わりに、デコードループ内で制約を適用する
  • 各制約は、生成済みトークン履歴に応じて状態が変わり、各段階で許可トークンマスクを出力する状態機械としてモデル化する
  • vLLMのカスタムロジットプロセッサインターフェースを使い、リクエストごとにルールが異なるため、個別設定されたプロセッサを割り当てる
  • 当初は機能差のためvLLM V0を使っていたが、V1が成熟した2025年第4四半期に移行した

vLLM V0で発生したスケールボトルネック

  • 最初の純Python実装は機能的には動いたが、同時リクエストが増えるとスケールしなかった
  • vLLM V0のカスタムロジットプロセッサは、リクエスト単位で実行される
    • GPUがバッチ全体のロジットを生成する
    • CPUがそれをコピーし、転送完了まで待機する
    • 各リクエストの制約ロジックを逐次実行する
  • PythonのGILのため、リクエスト単位の処理を並列化できず、ロジット処理CPU時間がバッチサイズに比例して増加し、テールレイテンシが悪化する
  • GPUのモデル順伝播が効率よくバッチ処理されても、全体レイテンシはCPUに縛られる
  • このボトルネックは単一リクエストのベンチマークでは見えず、実運用レベルの同時実行性でのみ表面化した

vLLM V1のバッチ単位処理

  • vLLM V1は、ロジット処理をリクエスト単位方式からバッチ単位へ移した
  • カスタムプロセッサをバッチデータ構造ベースで書き直し、複数リクエストのマスクをまとめて計算する
  • 性能のクリティカルパスはGILを避けるためマルチスレッド**C++**で再実装し、バッチサイズが大きくなってもロジット処理時間は一定に保たれる
  • V1 APIでは、update_state(batch_update)を通じてバッチ構成員の変化を明示的に追跡する必要がある
    • V0のリクエスト単位インターフェースより複雑である
    • 動的に変化するバッチでリクエストごとの状態を正確に維持するために必要である

状態ベース制約処理の運用強化

  • 性能ボトルネックを解消した後も、状態を持つデコーディングロジックで2つの問題が現れた
  • 部分prefill

    • V1はチャンク単位prefillingを行うため、1つのリクエストのprefillが複数エンジン段階にまたがることがある
    • BatchUpdateだけでは完全prefillと部分prefillを区別できないため、内部追跡を追加した
  • プリエンプション(preemption)

    • メモリ不足時、vLLMは一部完了済みリクエストのKVキャッシュを削除し、その後、別のプロンプトおよび出力トークン一覧で再スケジュールできる
    • これは出力トークン一覧が継続的に増えるという状態機械の前提を壊す
    • デコード段階間でトークン履歴が短くなったかを検知し、状態機械を初期化してから新しいプロンプトで再構成する

次の投資領域

  • 現在のプラットフォームは、低レイテンシ、深いカスタマイズ、既存インフラ統合を目標とし、vLLMとTriton、一貫したAPIを通じて実験から本番までつながる経路を提供している
  • バージョン固定、黙って欠落するAPIフィールド、パッケージング選択のトレードオフを補完し、プラットフォームの安定性と開発者体験を改善している
  • 次の4つの改善を計画している
    • 品質を損なわずにプロンプト長を短縮するシステムプロンプト圧縮
    • vLLM V1の非同期スケジューリング
    • CPUコードの代わりにGPU融合カーネルで実行するベクトル化ロジットプロセッサ
    • メモリ使用量を減らし、スループットを高める低精度モデル変種
  • Triton、vLLM、PyTorchなどのオープンソースMLライブラリを今後も活用し、関連コミュニティと協力していく計画である

まだコメントはありません。

まだコメントはありません。