⏲️

Geminiのレスポンスを爆速に! Fastly AI Accelerator でセマンティック キャッシュを試してみた

に公開

Geminiのレスポンスを爆速に! Fastly AI Accelerator でセマンティック キャッシュを試してみた

こんにちは、Google Cloud カスタマーエンジニアの Dan です。
日々お客様と生成 AI を活用したアプリケーションについて深く議論する中で、必ずと言っていいほど話題に上がる 3 つのトピックがあります。それは「レイテンシ(応答速度)」「コスト」そして「可用性(特にキャパシティ不足 [429 エラー] への対応)」です。
Gemini は非常に高性能なモデルですが、複雑な推論を毎回行えば、それなりの時間とコストがかかります。「以前と同じような質問が来たら、もっと速く、安く返せないか?」と考えるのは自然な思考だと思います。しかし、LLM への入力は自然言語であるため、全く同一の文字列が来ることは稀で、従来のキャッシュ手法ではヒット率が上がりません。
そこで今回は、この課題を解決するアプローチとして、Fastly 社が提供する「Fastly AI Accelerator」のセマンティック キャッシュ機能を、Gemini の前段に配置して検証してみました。

セマンティック キャッシュとは何か?

通常のキャッシュは一般的に「入力や条件が完全に一致した場合」にキャッシュ済みコンテンツを返します。一方、セマンティック キャッシュは、「入力の意味(セマンティクス)が近い場合」にキャッシュを返します。
例えば、「今日の東京の天気は?」という質問と、「現在の東京都の天候を教えて」という質問は、文字面は異なりますが、意図は同じです。AI Accelerator はこの「意図」をベクトル化して比較し、類似度が高いと判断すれば、バックエンドの LLM に問い合わせることなく、キャッシュされた回答を即座に返します。
これにより、以下のメリットが期待できます。

  • 高速化: LLM の推論時間をスキップできるため、レスポンスが速くなる。
  • コスト削減: LLM の API コール回数が減るため、従量課金を抑制できる。

Fastly AI Accelerator は、LLM レスポンス用に設計された、Fastly エッジ上で動作するインライン セマンティック キャッシング ソリューションです。

検証アーキテクチャ

構成は非常にシンプルです。普段アプリケーションから直接 Vertex AI の Gemini API を呼んでいる部分を、Fastly AI Accelerator のエンドポイントに向き先を変更するだけです。
今回は下図のように、LLM (Gemini 2.5 Flash) に問い合わせを行うアプリを Cloud Run functions 上に作り、直接 LLM を呼び出すパターンと、Fastly AI Accelerator を呼び出すパターンとでレイテンシやレスポンスの比較をしようと思います。

想定では、Fastly 側で受けたリクエストは、まず Fastly Edge 上でセマンティック キャッシュを確認し、キャッシュにヒットしなければ Gemini へリクエストを転送(プロキシ)、ヒットすればキャッシュからレスポンスを返却するため、その際のレスポンス時間が大幅に短くなるはずですし、意味的に近しい問い合わせ時と同じ結果が返って来るはずです。

検証コード(抜粋)

Fastly AI Accelerator の設定方法は、[AI Accelerator ページについて]を参照して下さい。
Fastly AI Accelerator を使用して Gemini を直接呼び出す場合は、Fastly の API トークンとエンドポイントを初期化時に設定します。
Fastly AI Accelerator の Gemini 向け設定方法はヘルプページには現時点で以下のように記載がありますが、これは非推奨となった Vertex AI SDK の生成 AI モジュールを利用した例ですので、現在の推奨である Google GenAI SDK に修正した版を後述します。

project_region = "<GCP-REGION>"
project_id = "<GCP-PROJECT-ID>"
vertexai.init(
location=project_region,
      project=project_id,
  api_endpoint=f"ai.fastly.app/{project_region}-aiplatform.googleapis.com",
      api_transport='rest',
      request_metadata=[("fastly-key", f"<FASTLY-KEY>")]
)
model = GenerativeModel("gemini-2.5-flash")
print(model.generate_content("Why is the sky blue?"))

推奨である Google GenAI SDK に修正した版は以下です。

以下のように LLM モデルの初期化を行います。http_options が追加の設定項目となります。fastly-key には Fastly の API トークンを設定します。その他、設定可能なヘッダー方法は上記 AI Accelerator のページをご参照下さい。
このように、アプリケーション側に複雑な実装を加えることなくキャッシュを実装できる点は開発者フレンドリーですね。

client = genai.Client(
   vertexai=True,
   project=PROJECT_ID,
   location=LOCATION,
   http_options={
       'base_url': "https://ai.fastly.app/us-central1-aiplatform.googleapis.com",
       'headers': {
           'fastly-key': '**************',
           'x-semantic-threshold': '0.95',
           'Cache-Control': '300'
       }
   }
)

検証シナリオと結果

では、実際にどのような挙動になるのか試してみましょう。今回は、文章(テレビを見るシチュエーション)に含まれるキーワードを抽出するような処理を Gemini にしてもらい、効果を測定してみます。具体的には以下のようなプロンプトを渡しています。{input_text} がユーザーから送られてくる文章です。

   prompt = f"""
   以下の文章は今 動画視聴サービスを利用しているユーザーの今の気分を表しています。この文章からユーザーの気分を表すキーワードを推定し、カンマ区切りのリスト形式で返してください。
   他の説明や前置きは不要です。キーワードのみを返してください。
   文章:
   「{input_text}」
   キーワード:
   """

では、ユーザーからのリクエストを受けて Gemini への問い合わせを行うアプリを東京(asia-northeast1)リージョンの Cloud Run functions に実装し、Cloud Shell ターミナルから下記のようにリクエストを送信し、リクエスト送信からレスポンス受信までの時間を計測します。

curl -s -w "\n--- Measurement ---\nTotal Time: %{time_total}s\n" -X POST https://XXXXXXXXXXXXXXXX.asia-northeast1.run.app   -H "Authorization: Bearer $(gcloud auth print-identity-token)"   -H "Content-Type: application/json"   -d '{"text": "ここに Gemini に解析させたい文章を登録します"}' 

Fastly AI Accelerator なし

パターンA: 質問「ご飯を食べながら見たい」

結果:

試行回数 レイテンシ (秒) Gemini の回答
1 回目 4.877752 ["ながら見", "気軽", "リラックス"]
2 回目 3.987346 ["ながら見", "リラックス", "気軽", "BGM代わり", "食事のお供"]
3 回目 3.891390 ["ながら見", "食事", "リラックス", "気軽", "BGM"]
4 回目 5.341187 ["リラックス", "まったり", "気軽"]
5 回目 7.274845 ["ながら見", "気軽", "リラックス"]

これは、一般的な Gemini 2.5 Flash の応答速度です。キャッシュがないため、毎回処理時間がかかります。また今回のように Gemini の回答が毎回異なるようなことも起きえます。

パターンB: 質問「ご飯中に見たい」

結果:

試行回数 レイテンシ (秒) Gemini の回答
1 回目 3.023176 ["ながら見", "気軽"]
2 回目 3.959473 ["ながら見", "リラックス", "気軽"]
3 回目 4.502829 ["ながら見", "リラックス", "気軽"]
4 回目 7.794118 ["ながら見", "リラックス", "気軽", "食事中"]
5 回目 4.433782 ["ご飯", "食事", "ながら見", "ながら視聴"]

パターン A と似た文章の場合でも結果は同様です。本来であれば、このような似た意味の問い合わせに対してもパターン A の結果を迅速に返すことができれば、ユーザー体験的にも Gemini 利用コスト的にも良くなります。

Fastly AI Accelerator あり

ここからが本番です。全く同じ質問が来た場合、少し言い方を変えた場合、意味的に異なる言い方の場合を見てみます。

パターンA: 質問「ご飯を食べながら見たい」

結果:

試行回数 レイテンシ (秒) Gemini の回答
1 回目 3.485236 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
2 回目 0.321951 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
3 回目 0.119753 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
4 回目 0.446630 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
5 回目 0.424102 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
6 回目 0.332105 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]

一回目はキャッシュがないため、 Fastly AI Accelerator を使わない場合と同等レベルの応答時間がかかっています。しかし、二回目以降はキャッシュから返却されているため、大幅な応答時間の削減(90.6%削減 [2~5回目平均 0.328109 秒/1 回目 3.485236秒] )が実現され、結果も常に固定されます。

パターンB: 質問「ご飯中に見たい」

結果:

試行回数 レイテンシ (秒) Gemini の回答
1 回目 1.692908 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
2 回目 0.433821 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
3 回目 0.446573 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
4 回目 0.312021 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
5 回目 0.343162 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]
6 回目 0.316343 ["食事中", "ながら見", "気軽", "リラックス", "集中不要"]

パターン A と似た意味の問い合わせだった場合も、キャッシュがない場合に比べて高速に結果を返却できています。では実際にキャッシュから返却されているか、Fastly のコンソールで確認しましょう。

合計 11 回、キャッシュから返却されていることが分かります。Fastly が「これはさっきのの質問と同じ意図だ」と判断し、一回目の Gemini の回答を即座に返してくれているようです。
一回目のみ、他に比べて若干時間がかかっているのは、パターン A で保存された既存キャッシュとの類似度を計算しており、二回目以降はキャッシュキーが一致するために高速にレスポンスが返却されているのだと考えられます。
このレベルの速度改善だと、ユーザー体験としては「爆速」になったと感じられるのではないでしょうか。
似た意味かどうかの判断閾値は x-semantic-threshold ヘッダーで変更できるので、どのレベルまで同じ意味として扱うか検証は必要なものの許容レベルを調整できるのはありがたいですね。

パターンC: 質問「リゾートホテルの部屋でくつろぎながら見たい」

結果:

試行回数 レイテンシ (秒) Gemini の回答
1 回目 4.504395 ["くつろぎ", "リラックス", "非日常", "贅沢", "癒し"]
2 回目 0.330475 ["くつろぎ", "リラックス", "非日常", "贅沢", "癒し"]
3 回目 0.251789 ["くつろぎ", "リラックス", "非日常", "贅沢", "癒し"]
4 回目 0.130694 ["くつろぎ", "リラックス", "非日常", "贅沢", "癒し"]
5 回目 0.324774 ["くつろぎ", "リラックス", "非日常", "贅沢", "癒し"]

今回のように、パターン A, B と意味的に異なる場合は、キャッシュではなくオリジンから返されていることが分かります。この場合でも二回目以降はキャッシュから返却されています。

キャッシュのメトリクス

前述のグラフのように、キャッシュの利用状況等の統計情報は、Fastly のコンソール画面で確認可能です。レスポンスがキャッシュもしくはオリジンから返却されている数の他、トークン数やレイテンシ等も確認できるのは良いですね。ページには以下のグラフが表示されます。

  • Total requests: AI Accelerator に送信されたリクエストの合計数。
  • Tokens served from cache: キャッシュから配信されたレスポンスに基づく、キャッシュから配信されたトークンの推定数。トークンは LLM の課金単位であり、その実際の測定値はベンダーと LLM のバージョンによって異なります。
  • Estimated time saved: キャッシュからのレスポンスに基づく、節約された時間の推定値 (分単位)。
  • Requests: アカウント全体で集計された AI Accelerator のリクエストの合計数。
  • Tokens: キャッシュまたはオリジンから提供されるトークンの推定数。
  • Origin Latency Percentiles: オリジンのレイテンシのパーセンタイル概算値。

効果測定まとめ

今回の結果から、以下のような結果が得られることが分かりました。検証前の想定通り、似た問い合わせに対してはレイテンシが大幅に削減できています。

指標 Gemini 直接 Fastly + Gemini 改善率
平均レイテンシ 4.91 sec 0.35 sec 92% 短縮

その他、補足情報

キャッシュのパージ

Fastly AI Accelerator のページにある通り、現時点でベータ版提供ですが、API トークンにpurge_all スコープを設定して下記コマンドを実行すれば、すべてのキャッシュをパージすることができます。

コード(抜粋)

curl -X POST -H "Fastly-Key: YOUR_FASTLY_TOKEN" https://api.fastly.com/ai_accelerator/expire

マルチモーダル データの対応状況

Gemini 2.5 モデルはマルチモーダル LLM のため、PDF/画像/動画等の処理を行う場合もあります。Fastly AI Accelerator はマルチモーダル処理についてもキャッシュとして処理することが可能でした。同じ画像でも質問内容を変えると異なる結果が返ってきていることから、トークン量が多い画像にキャッシュキーが引っ張られるわけではないです。

コード(抜粋)

   input_text = request_json["text"]

   image_path = "https://goo.gle/instrument-img"
   image_bytes = requests.get(image_path).content
   image = types.Part.from_bytes(
       data=image_bytes, mime_type="image/jpeg"
   )
       response = client.models.generate_content(
           model="gemini-2.5-flash",
           contents=[
               input_text,
               image
           ],
           config=types.GenerateContentConfig(
               temperature=0,
               max_output_tokens=1024
           )
       )

入力画像

レスポンス

試行回数 レイテンシ (秒) Gemini の回答
1 回目 8.738313 壮麗なパイプオルガン
2 回目 0.564545 壮麗なパイプオルガン
3 回目 0.765763 壮麗なパイプオルガン
4 回目 0.751302 壮麗なパイプオルガン
5 回目 0.862880 壮麗なパイプオルガン
6 回目 0.738978 壮麗なパイプオルガン

メトリクス

Vertex AI Global Endpoint は非対応

Vertex AI では、全体的な可用性が向上し、リソース不足(429)エラーを減らすことが可能になる Global Endpoint 機能を提供しています。下記コードのように Global Endpoint のエンドポイントを指定した場合、現時点(2025/11時点)では非対応でした。エラーにはなることはなく、結果は取得できているため、キャッシュされずに都度オリジンにリクエストを転送されます。現在 Fastly AI Accelerator を使用するの場合は、特定リージョンを指定することが推奨になります。

# Vertex AIを初期化
vertexai.init(
   project=PROJECT_ID,
   location='global',
   api_endpoint="ai.fastly.app/global-aiplatform.googleapis.com",
   api_transport='rest',
   request_metadata=[
       ("fastly-key", "*************"),
       ("x-semantic-threshold", "0.98"),
       ("Cache-Control", "300")
       ]
)
# 使用するGeminiモデルを定義
model = GenerativeModel("gemini-2.5-flash")

レスポンス

試行回数 レイテンシ (秒) Gemini の回答
1 回目 6.730049 ["食事中", "ながら見", "リラックス", "気軽"]
2 回目 5.038484 ["ながら見", "リラックス", "気軽"]
3 回目 3.675558 ["ながら見", "食事中", "リラックス", "気軽"]
4 回目 9.236576 ["リラックス", "気軽"]
5 回目 7.873883 ["ながら見", "リラックス", "気軽"]

料金

Fastly の Web ページ https://www.fastly.com/pricing に記載があります。コストメリットの判断には LLM 呼び出し費用との比較が必要ですが、LLM 呼び出し費用は一般的にトークン量ベースである一方、Fastly AI Accelerator はリクエスト課金なため、トークン量が大きいが類似度が高いリクエストが多い場合にコストメリットが出やすい料金体系と言えます。もちろん、LLM 呼び出し費用が高いモデルでもコストメリットの恩恵を受けることができます。
ただ、繰り返しになりますが、Fastly AI Accelerator のメリットはキャッシュによるレスポンス高速化と可用性の強化によるユーザー体験(UX)の向上ですので、費用だけではなくそのあたりも含めて利用を検討されることが望ましいです。

まとめ

検証の結果、Fastly AI Accelerator を Gemini と組み合わせることで、アプリケーション側に複雑な実装を加えることなく、劇的なパフォーマンス改善(とコスト削減)が見込めることが分かりました。
特に、チャットボットの「よくある質問」や、社内ドキュメント検索など、類似した質問が多く寄せられるユースケースでは、セマンティック キャッシュの効果は絶大だと思います。
Google Cloud の強力な AI モデルを、より効率的に、より多くのユーザーに届けるための選択肢として、Fastly のようなパートナーソリューションを組み合わせてみるのは非常に有効なアプローチと言えるでしょう。ぜひご検討下さい!そして利用を希望される際は、ぜひお近くの Google Cloud 担当までご連絡下さい!!

Google Cloud Japan

Discussion