LLMゲートウェイの本番運用:アーキテクチャ、トレードオフ、そして痛い教訓 — カニッシュ・マヌジャ(Twilio)

AAI Engineer
Computing/SoftwareManagementInternet Technology

Transcript

00:00:00ガネシュ・マヌジャです。Twilioでプリンシパルエンジニアを務めています。まずは簡単に行手を挙げていただけますか。
00:00:20「問題が発生しました。もう一度お試しください」というメッセージを見たことがある人はどれくらいいますか?
00:00:27なるほど、ラッキーな方々と、美味しい昼食をとったばかりの方々がいらっしゃいますね。
00:00:33実は、そのシンプルなメッセージの背後には、モデルプロバイダーがダウンしているにもかかわらずメッセージを返す、非常に複雑なシステムが存在しています。
00:00:45今回は、それを本番稼働させる方法、あるいはその本番稼働について議論していきます。
00:00:50では、LLMゲートウェイとは何でしょうか?
00:00:52LLMゲートウェイは、アプリケーションと、その背後にあるモデルプロバイダーの間に位置するエントリーポイント、またはミドルウェアです。
00:00:58ルーティング、認証、フォールバック、レート制限など、考えられるあらゆるガバナンス機能を担っています。
00:01:08そして、ゲートウェイの核心にあるのは、4つの要素間のトレードオフです。
00:01:13それは、可用性、レイテンシ、ガードレール、そしてコストです。
00:01:18性能低下が発生した場合、これら4つすべてを最大化することはできません。
00:01:22何を優先するかを選択する必要があります。
00:01:25この講演を通じて、LLMゲートウェイを使用する際に、ご自身のユースケースに合わせてそのトレードオフを行えるようサポートしたいと考えています。
00:01:35また、ゲートウェイを設計する際には、顧客が満足できるように、これらの制御手段を呼び出し元や顧客に提供していただきたいのです。
00:01:46まずは可用性から始めましょう。
00:01:50モデルプロバイダーが1つだけの場合、そのプロバイダーの限界があなたの限界になります。
00:01:56相手の障害があなたの障害になるのです。
00:02:03そのため、通常のソフトウェアエンジニアリングでは、信頼性の低い依存関係に対処する方法としてリトライが行われます。
00:02:11指数バックオフやジッターを用いたリトライです。
00:02:15そして、それらすべてが失敗した場合、十分なエラーを確認した後にサーキットブレーカーが作動し、その厄介な処理の呼び出しを停止します。
00:02:24しかし、LLMにおいてはこれでは不十分です。
00:02:26LLMは、リトライを行うような高速で安価なAPIとは大きく異なります。
00:02:32LLMのAPIをリトライすると、レイテンシの許容量を急速に食いつぶしてしまいます。
00:02:38また、他に問題なく動作するモデルプロバイダーが存在する状態でサーキットブレーカーを作動させるのは理にかなっていません。
00:02:472つ目のモデルプロバイダーを使用すべきです。
00:02:48そして3つ目に、先ほど述べたように、呼び出しは低速であり費用がかかります。
00:02:53そのため、盲目的なリトライはコストとテールレイテンシを倍増させるだけです。
00:02:58では、ここでより良いアイデアとは何でしょうか?
00:03:02それは実際にはリクエストごとのフォールバックです。
00:03:05つまり、モデルプロバイダーAを試行し、モデルプロバイダーAへのリクエストが失敗した場合は、続けてモデルプロバイダーBを試行するということです。
00:03:14ここで検討すべきもう一つのオプションとして、両方のプロバイダーに並行してリクエストを送信する方法もありますが、これはコストが単に倍増するため、レイテンシに極めて強いこだわりがある場合のみに限られます。
00:03:26LLMにおいても、これらと類似したサーキットブレーキングのパターンが適用されます。
00:03:32プライベート環境がしばらくの間失敗し続けていることが分かっている場合、再度試行するのは意味がありません。
00:03:40それをロードバランサーやリクエストパスから外し、クールダウン状態にして、数分が経過した後に再び組み戻すようにします。
00:03:51ここで選択しなければならない興味深い点の一つは、エラーカウントをどこに保持するかです。
00:03:59トラフィックを処理しているインスタンスのメモリ内にエラーカウントを保持することもできますし、フリート全体でエラーカウントが共有される共有情報を使用することもできます。
00:04:12それぞれにトレードオフがあります。
00:04:14迅速なフェイルオーバーを望むのであれば、フリート全体での共有が役立ちます。
00:04:19一方、インスタンスごとのローカル状態カウンターを使用する場合の課題は、デプロイサイズを変更するたびに、設定や期待値が変わってしまう点です。
00:04:30そのため、考慮すべき事項となります。
00:04:34あの綺麗な図では実際には示されていなかった、これから説明するその他の落とし穴もあります。
00:04:39つまり、フォールバックは透過的ではないということです。
00:04:41業界はOpenAI API互換フォーマットに収束しつつありますが、依然として微妙な差異が存在すると言えます。
00:04:49そのため、フォールバックを入念にテストする必要があります。
00:04:52ツール呼び出しのスキーマ、トークン制限、停止理由などに違いが生じる可能性があるからです。
00:04:58したがって、LLMゲートウェイを用いることで、プロバイダーを跨いだフォールバックも確実に実行できるようにする正規化レイヤーを持つことができます。
00:05:08もう一つの要素はストリーミングです。
00:05:15基本的に、目の前にテキストの壁が現れるまで30秒も待ちたい人はいません。
00:05:22そのため、ストリーミングが絶対に必要とされるユースケースが存在します。
00:05:26しかし、それには代償が伴います。
00:05:27制御手段を諦めなければならないのです。
00:05:29プロバイダーAを使用すると決めたら、途中でプロバイダーAの利用を続ける必要があります。
00:05:36ストリーミングの途中でプロバイダーを変更することはできません。
00:05:39クライアントに送信されてしまった内容は、すでに確定しています。
00:05:42そして、そこで表示されるのが「問題が発生しました」というメッセージです。
00:05:46あれが表示されるのはそのメッセージです。
00:05:48それは手抜きだからではありません。
00:05:49設計上、そうなるように作られているのです。
00:05:52そしてそれはトレードオフの1つです。
00:05:54チームが何度もつまずいてきた別の点についても言及しておきたいと思います。
00:06:00彼らはプライマリプロバイダーのプロビジョニングとテストは非常に念入りに行います。
00:06:05しかし、2番目のプロバイダーであるフォールバックプロバイダーには、必ずしも同等の労力が注がれません。
00:06:11むしろ第2のプロバイダやフォールバック用プロバイダこそ、スループットやキャパシティ、余裕度をさらに高くすべきだと言えます。
00:06:21なぜなら、それが最後の防衛線だからです。
00:06:23それがダウンすれば、アプリケーションもダウンします。
00:06:29それではレイテンシについて議論しましょう。
00:06:31可用性の障害は一目瞭然です。
00:06:34障害が発生します。
00:06:36アラートが鳴ります。
00:06:37ポケットベルが鳴り響きます。
00:06:38しかし、高レイテンシは静かに発生する問題になり得ます。
00:06:42単に可用性のためだけにサービスを調整するよりも、高レイテンシ対策に注力する必要があると言えます。
00:06:49ここで1点指摘しておきます。
00:06:54ゲートウェイでは、様々なワークロードが混在して実行される場合があります。
00:06:581秒未満で完了する埋め込みリクエストが存在します。
00:07:04同じく1秒未満で完了する分類リクエストもあります。
00:07:073秒かかるチャットリクエストもあります。
00:07:10そして、非常に時間がかかる推論リクエストもあります。
00:07:13ちょっと手を挙げてください。
00:07:15サービス全体で集計されたレイテンシを計測している人は、簡単に手を挙げてください。
00:07:20まあ、それはひっかけ問題でした。
00:07:23失礼しました。
00:07:24そんなことをすべきではありません。
00:07:25意味がありませんから。
00:07:26それは嘘です。
00:07:27ゲートウェイ全体の数値ではなく、モデルごと、ルートごとにP99を追跡すべきです。
00:07:32ゲートウェイ全体の数値は、特に多様なワークロードを実行している場合には意味を持ちません。
00:07:36手を挙げた方々が、そんな計測をしていないことを願っています。
00:07:40もう一つ、何度強調してもし足りないのが、モデルクラスごと、ルートごとにタイムアウトを設定することです。
00:07:49それこそが、サイレント障害の最大の根本原因なのです。
00:07:54タイムアウトを設定していなければ、ゲートウェイは実際には処理されていないにもかかわらず、リクエストが順調に処理されていると思い込んでしまいます。
00:08:00レイテンシに関して、特にこのメッセージをお伝えして締めくくります。
00:08:05推論モデルの通常の動作時間は、実質的にチャットモデルの障害時の時間です。
00:08:09そのため、ルートごとにレイテンシを追跡することが絶対に必要です。
00:08:13さて、ここが最も頭が痛い、あるいは私に最も恐怖を与えてきたスライドですが、それは推論モデルとルーターモデルについてです。
00:08:24ここ領域では、本当にレイテンシが予測不能になります。
00:08:29そして推論モデルは予測可能な結果を返さず、通常のモデルよりもさらに非決定的です。
00:08:40多くの場合、temperatureをゼロに設定することはできません。
00:08:43同じプロンプトであっても、処理に2秒かかることもあれば60秒かかることもあります。
00:08:48本番環境において、正当な理由もないのにP99が突然60秒まで跳ね上がったという現象を私たちは目撃してきました。
00:08:53そのため、これに対する魔法のような解決策はありませんが、少なくともルートごとの推論レベルの固定から始めることをお勧めします。
00:09:03ルーターモデルに関しては、それらは背後で抽象化を隠蔽しています。
00:09:08例えば、実行するモデルを自動的に選択します。
00:09:11非決定的なシステムを相手にしつつも、可能な限りリクエストを決定的なものに近づけるよう工夫することを強くお勧めします。
00:09:23もう一つのアイデアは、テールをヘッジ(回避・保険をかける)することです。
00:09:26例えば、プライマリリクエストがレイテンシ予算のP90を消費した時点で、別のリクエストを新たに発行することができます。
00:09:37これにより、サービスのP99テールを効果的にヘッジすることができます。
00:09:44さて、これは私のお気に入りのトピックの一つです。
00:09:47モデルの安全性を保つためには、ガードレールが必要です。
00:09:53それに伴い、プロンプトインジェクション攻撃からのサービスの保護、PII(個人特定情報)フィルターの維持、有害性フィルターの適用、そしてLLMが顧客に対して暴言を吐かないようにするために、ガードレールが不可欠となります。
00:10:08その他多くの重要な目的にも役立ちます。
00:10:11しかし、モデルプロバイダーと同様に、ここにもトレードオフが存在します。
00:10:15ガードレールは、いわば別のサービスのようなものです。
00:10:18ダウンすることもあります。
00:10:19信頼性が低い場合もあります。
00:10:21だからこそ選択が必要となります。
00:10:24フェイルオープンにするか、それともフェイルクローズにするかということです。
00:10:27フェイルオープンとは、たとえガードレールがダウンしていても、リクエストの処理を継続することを指します。
00:10:32フェイルクローズとは、リクエストをブロックし、「申し訳ありませんが、利用できません」と応答することです。
00:10:36それが、ある程度可用性とセキュリティのトレードオフになるわけです。
00:10:41万能な答えというのはなく、実際はユースケースによって異なります。
00:10:45例えば、有害性フィルターが稼働していなくても、リクエストを処理し続けるといった判断が可能です。
00:10:53ですから、デフォルトの選択肢は「耐えられる最悪のケース」にすべきです。
00:11:02ガードレールが停止した際や、ガードレール自体の不安定さを管理するために、システムの挙動を改善するために実際にできることがいくつかあります。
00:11:17まず1つ目は、タイムバジェットです。
00:11:20リクエストがガード的タイミングに縛られるべきではありません。
00:11:25速度を決定づけるステップとなるのは、常にLLMであるべきです。
00:11:29そのため、タイムアウトを設定し、それらのガードレールが特定の時間予算内で実行されるようにしてください。
00:11:38もう一つの重要な要素はフォールバックです。
00:11:40ご存知かと思いますし、私もお話してきましたが、モデルプロバイダーに関しては常にフォールバックについて議論しています。
00:11:47しかしガードレールも重要なサービスであり、ガードレールプロバイダーがダウンした際にサービスを維持するため、フォールバックの検討、セカンダリプロバイダーやセカンダリチェックの導入、判定結果のキャッシュなどを検討できます。
00:12:03ガードレールに関してもう一つ浮上する興味深い選択肢は、ガードレールの配置場所です。
00:12:10一般的に、ガードレールの配置には3つの方法があります。
00:12:151つ目は、入力に対して実際にガードレールが実行されるプリフックです。
00:12:19おそらくこれが最も安全ですが、リクエストに直列のレイテンシが追加されます。
00:12:26もう1つは並列実行です。
00:12:29これは私のお気に入りの1つですが、ストリーミングは並列処理ではうまく機能しない点に注意してください。
00:12:35そのため、特に構造化出力を生成している場合は、ストリーミングを行わないでください。
00:12:40レイテンシを抑えるため、構造化出力に対してはこれらのガードレールを並行して実行するようにしてください。
00:12:46もう1つはポストフックです。
00:12:48これらは出力の監視、出力の監査などに最適です。
00:12:58ここまで、依存関係に関して問題になり得るすべてのことについてお話ししてきました。
00:13:06リクエスト経路上に、中心となる、あるいはLLMゲートウェイそのものという別の依存関係を実際に追加していることにはまだ触れていませんでした。
00:13:15私たちが苦い経験をし、そこから得た教訓がいくつかありますので、LLMゲートウェイに取り組んでいる、または使用している方と共有したいと思います。
00:13:251つ目は、共有制限です。
00:13:28APIキーがルートごと、ユースケースごとに、可能な限り細かく、想像し得る最も細かい単位で分離されていることを確認してください。
00:13:40リソースを大量消費するテナントの存在は、ここでの最大の問題の1つになり得ます。
00:13:47もう1つはロードシェディング(負荷負荷分散・負荷削減)です。
00:13:50これは、ランブックやゲームデーの一環として、使用しているゲートウェイがロードシェディングをサポートしていることを確認すべき機能です。
00:13:59リトライストーム(再試行の嵐)が発生すると、単にスケールアウトするのが非常に難しくなるからです。
00:14:03リトライストーム下にあるサービスを簡単にスケールアウトすることはできません。
00:14:07そして、これらすべてのWebサーバーには内部キューがあり、設定可能です。
00:14:13それらが制限されており、制限のないリクエストを受け入れないようになっていることを確認してください。
00:14:19カスタムロジックを導入したい場合は、負荷がかかっている状況でも最も重要なユースケースが確実に処理されるよう、ここでトラフィックの優先順位付けを行うこともできます。
00:14:29最後にお話ししたいのは、中央集権型ゲートウェイという発想そのものについてです。
00:14:38それは単一障害点になります。
00:14:40ですから、会社全体で2つのLLMのために中央ゲートウェイを設置しようと考えているなら、その理由は何なのか、見直してみることをお勧めします。
00:14:52私が気づいたのは、ほとんどのシナリオで求められているのは中央ゲートウェイではないということです。
00:14:57彼らが求めているのは中央集権的なガバナンスです。
00:15:00そして、ゲートウェイを分散させつつ、ガバナンスは一元化するという前進の道が存在します。
00:15:07そのため、トラフィックを無理に一極集中させるのではなく、プラグインやカスタムコードを活用してガバナンスを中央集権化することができます。
00:15:17ガバナンスは、コスト追跡やレートリミット管理などの形で実現でき、他にもさまざまな解決策があります。
00:15:24企業全体のために1つの中央ゲートウェイを構築し始める前に、それらを探索してみてください。
00:15:30単一のチームが管理することは可能ですが、たとえ分散型であっても、企業全体向けに単一のデプロイとして展開することはお勧めしません。
00:15:43そうは言っても、この講演を個人的な話題で締めくくりたいと思います。
00:15:47本日は息子の誕生日なのですが、私はここで見知らぬ人たちとサーキットブレーカーについて話しています。
00:15:54ですから、私とあなた方のお客さまのために、どうかインシデントを1つ防ぐことが、皆さんにできるせめてものことかと思います。
00:16:02ありがとうございました。
00:16:03何か質問があれば、どうぞ。
00:16:06.

Key Takeaway

LLMゲートウェイの設計では、可用性・レイテンシ・ガードレール・コストのトレードオフが存在するため、モデルごと・ルートごとのレイテンシ追跡やリクエストごとのフォールバックを活用した慎重なアーキテクチャ構築が不可欠である。

Highlights

  • LLMゲートウェイは、可用性、レイテンシ、ガードレール、コストという4つの要素間のトレードオフによって構成される。

  • 盲目的なリトライはコストとテールレイテンシを倍増させるため、モデルプロバイダーAから失敗時にモデルプロバイダーBへ移行するリクエストごとのフォールバックが有効である。

  • ゲートウェイ全体の数値ではなく、モデルごと、ルートごとにP99レイテンシを追跡すべきである。

  • ガードレールの配置には、直列のレイテンシを追加するが最も安全なプリフック、ストリーミングには不向きだがレイテンシを抑える並列実行、出力監視に最適なポストフックの3つの方法が存在する。

  • 企業全体向けの単一の中央ゲートウェイは単一障害点となるため、トラフィックを集中させずにプラグインやカスタムコードを活用してガバナンスを一元化することが推奨される。

Timeline

LLMゲートウェイの定義と4つのトレードオフ

  • LLMゲートウェイはアプリケーションとモデルプロバイダーの間に位置し、ルーティングや認証、フォールバックなどを担うミドルウェアである。
  • ゲートウェイの核心には、可用性、レイテンシ、ガードレール、コストという4つの要素間のトレードオフが存在する。

モデルプロバイダーがダウンしている場合でもメッセージを返す複雑なシステムの背後には、LLMゲートウェイが存在する。性能低下が発生した際、4つの要素すべてを同時に最大化することはできないため、ユースケースに応じた選択が必要となる。

可用性とフォールバック戦略

  • LLMのAPIに対する盲目的なリトライはコストとテールレイテンシを悪化させる。
  • モデルプロバイダーAの失敗時にプロバイダーBを試行するリクエストごとのフォールバックが有効な解決策となる。

単一のプロバイダーに依存すると相手の障害がそのまま自身の障害になるため、サーキットブレーカーやフォールバックが重要となる。ただし、フォールバック用プロバイダーこそスループットやキャパシティをさらに高く設定すべきである。

レイテンシの計測と管理

  • ゲートウェイ全体の集計されたレイテンシ計測ではなく、モデルごと、ルートごとにP99を追跡すべきである。
  • タイムアウトを設定しないと、ゲートウェイは処理が進んでいると誤認するサイレント障害が発生する。

多様なワークロードが混在する環境では、ゲートウェイ全体の数値に意味はない。推論モデルはtemperatureをゼロに設定できない場合もあり、処理時間が予測不能に大きく変動するため、ルートごとの徹底したレイテンシ追跡とタイムアウト設定が求められる。

ガードレールのトレードオフと配置

  • ガードレールがダウンした際に処理を継続するフェイルオープンと、リクエストをブロックするフェイルクローズのトレードオフが存在する。
  • ガードレールの配置にはプリフック、並列実行、ポストフックの3つの方法がある。

安全性を保つためのガードレール自体も別のサービスであり、ダウンする可能性がある。そのため、耐えられる最悪のケースを想定したデフォルト選択や、タイムバジェットの設定、判定結果のキャッシュ活用が必要となる。

依存関係としてのゲートウェイと教訓

  • APIキーは可能な限り細かく分離し、リソースを大量消費するテナントの影響を防ぐ必要がある。
  • 会社全体で単一の中央ゲートウェイを設置するのではなく、ゲートウェイを分散させつつガバナンスを一元化することが望ましい。

LLMゲートウェイそのものをリクエスト経路上の依存関係として追加する際には、ロードシェディングのサポートやWebサーバーの内部キューの制限確認が不可欠である。トラフィックを無理に一極集中させるのではなく、プラグインを活用した分散型アプローチが有効である。

Community Posts

View all posts