LLM向けセマンティックキャッシング:プレフィックスキャッシングを超えたコストとレイテンシーの削減

Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
プレフィックスキャッシュは同一のプロンプトを再利用します。セマンティックキャッシュは類似のプロンプトを再利用します。具体的には、受信したリクエストを埋め込み、ほぼ同じ質問が最近回答されていれば、モデルを呼び出す代わりに保存された回答を提供します。これは、ゲートウェイが活用できるコストとレイテンシーを削減する最も効果的な手段の一つであり、「デモでは動作する」と「本番環境で安全である」とでは、主張が大きく異なる点でもあります。この記事では、その仕組み、それを制御する唯一のつまみ、誤った回答を静かに提供してしまうケース、そしてキャッシュがどこに配置されるべきかについて説明します。
バックエンドエンジニアのKabirは、 良い週と悪い週を経験しました。良い週は、Northwindのサポートアシスタントの前にセマンティックキャッシュを導入したことです。各受信質問を埋め込み、ほぼ同じ質問が最近回答されていれば、モデルを呼び出す代わりに保存された回答を返します。その結果、モデル呼び出しのボリュームは35%減少し、キャッシュヒット時のレイテンシーは約900ミリ秒から40ミリ秒未満に短縮されました。悪い週は、ある顧客が「私の荷物はどこですか?」と尋ねたところ、自信に満ちた詳細な回答を得たのですが、それは別の顧客の注文に関するものでした。2人の顧客が数分違いで意味的に同一の質問をしており、キャッシュは両方をほぼ同じベクトルに埋め込み、ヒットと判断し、最初の顧客への回答を2番目の顧客に提供してしまったのです。
キャッシュは設計通りに正確に機能していました。ただ、「私の荷物はどこですか?」という質問が、誰が尋ねるかによって意味が異なることを認識していなかっただけです。セマンティックキャッシュは、モデル呼び出しを類似性マッチングと交換するものであり、その交換の安全性は2つの点にかかっています。それは、マッチングのしきい値と、そもそもキャッシュに何を許可するかです。この記事では、その両方について説明します。
TrueFoundryのAIゲートウェイが提供するもの
この記事で説明するすべて、つまり完全一致キャッシュとセマンティックキャッシュ、ルートごとの設定可能な類似性しきい値、Kabirが冒頭で遭遇したバグが決して発生しないようにするテナントごとのスコープ設定、そしてキャッシュが実際に効果を発揮しているかどうかを示すヒット率/コスト削減のテレメトリーは、 TrueFoundryのAIゲートウェイのキャッシュ機能が ゲートウェイ設定として表現されます。リクエストに単一のヘッダーを追加するだけで有効になり、ゲートウェイはリクエストをハッシュ化し(セマンティックキャッシュの場合は最後のメッセージを埋め込み)、Redisをバックエンドとするストアと比較し、ヒットした場合はキャッシュされた応答を返します。ミスの場合は、リクエストはプロバイダーに送られ、新しい応答と埋め込みが次回のためにキャッシュされます。
正確性に関する話、つまり異なるユーザーからの意味的に類似した2つのリクエストが 決して 互いの回答を返さないようにすることは、2段階の名前空間によって組み込まれています。 レベル1は自動です。各キャッシュエントリは、呼び出し元のユーザーまたは仮想アカウントにスコープされるため、ユーザーAのリクエストがユーザーBのエントリにヒットすることは決してありません。 レベル2はオプションです。 名前空間 フィールドは、キャッシュ設定においてさらにパーティションを分割します(テナントごと、環境ごと、システムプロンプトのバージョンごと)。これは、この記事の名前空間引数が実際に必要とするものです。これらを組み合わせることで、各サービスが分離を再実装することなく、ゲートウェイレベルのセマンティックキャッシュを安全に共有できるようになります。


アプリケーションコードは変更不要です。キャッシュは単一のヘッダーを介してリクエストごとにオプトインできます。以下の例では セマンティックを使用しています。これは完全一致のスーパーセットであり(同一テキストのヒットも提供します)、0.9という控えめな開始しきい値とカスタムネームスペースを使用しています。これにより、マルチテナントアプリは自動的なユーザーごとのスコープを超えても、各テナントのキャッシュを分離できます。
セマンティックキャッシュを有効にしてゲートウェイを呼び出す(Python、OpenAI互換)
from openai import OpenAI
client = OpenAI(
base_url="https://<your-truefoundry-gateway-url>",
api_key="<your-virtual-account-token>",
)
resp = client.chat.completions.with_raw_response.create( # raw_response → see headers
model="openai-main/gpt-5.5",
messages=[{"role": "user", "content": user_question}],
extra_headers={
# Semantic is a superset of exact-match. Start strict (0.9) and tune from there.
"x-tfy-cache-config": (
'{"type":"semantic",'
'"similarity_threshold":0.9,'
'"ttl":600,'
'"namespace":"tenant-acme-faq"}'
),
},
)
print(resp.headers.get("x-tfy-cache-status")) # "hit", "miss", or "error"
print(resp.headers.get("x-tfy-cache-similarity-score")) # e.g. "0.95" on a semantic hit
print(resp.parse().choices[0].message.content)1. LLMキャッシュの3つのレイヤー(そしてこれがどれに当たるか)
「キャッシュ」には、到達範囲とリスクが大きく異なる3つの異なるメカニズムが含まれており、どのメカニズムを導入するかを正確に把握しておくことが重要です。
プロバイダープレフィックスキャッシュ は、正確で同一のプロンプトプレフィックス(呼び出し間で変更されずに繰り返されるシステムプロンプトとツール定義)を再利用します。プロバイダーは正確なプレフィックスに一致させ、繰り返される部分を大幅な割引価格で請求します。これは自動的で安全であり、当社の コンテキストエンジニアリングに関する記事で説明されています。同一のテキストにのみ一致するため、誤った回答を提供することはありません。
完全一致応答キャッシュ は、正規化されたリクエスト全体をハッシュ化し、同一のハッシュに対して保存された応答を返します。これも安全です(同一の入力には同一の出力)が、ユーザーが同じように表現することはめったにないため、ヒット率は低くなります。
セマンティックキャッシュ がここでの主題です。リクエストを埋め込み、 類似の 以前のリクエストが存在する場合にキャッシュされた応答を提供します。ここでヒット率が飛躍的に向上します。なぜなら、「私の荷物はどこですか?」や「注文はもう発送されましたか?」といった質問は、キャッシュされた回答を共有できるからです。しかし、同時にリスクも生じます。なぜなら、「類似」は完全一致ではなく、類似度しきい値によって行われる判断だからです。
2. セマンティックキャッシュの仕組み:埋め込み、照合、提供
その仕組みは3つのステップから成ります。受信したリクエストをベクトルに埋め込みます。適切なスコープ内で、ベクトルストアから最も近い以前のリクエストを検索します。最も近いリクエストの類似度がしきい値を超えていれば、保存されている応答を返します。そうでなければ、モデルを呼び出し、新しいリクエスト/応答ペアを次回のために保存します。
セマンティックキャッシュのルックアップ — 埋め込み、スコープ内検索、確信度の高いヒット時に提供
emb = embed(request.text) # ~10-30 ms
hit = vector_store.nearest(emb, scope=tenant_id) # scoped search — never global for user data
if hit and hit.score >= THRESHOLD: # the knob that governs everything
return hit.response, "cache_hit" # tens of ms, no model call
resp = call_model(request) # miss -> full model call
vector_store.put(emb, resp, scope=tenant_id, ttl=TTL)
return resp, "cache_miss"ヒットした場合、通常数百ミリ秒かかり、トークンごとに課金されるモデル呼び出しを、数十ミリ秒程度でコストもごく一部の埋め込み呼び出しとベクトルルックアップに置き換えることができます。ミスした場合、通常のモデル呼び出しに埋め込みとルックアップのレイテンシが追加されますが、これはヒットの可能性を得るための小さな代償です。このトレードオフの経済性はヒット率(セクション7)に完全に依存し、安全性はしきい値(次項)に完全に依存します。

3. 類似度しきい値がすべてを左右する
しきい値は、新しいリクエストがキャッシュされたものとどれだけ近ければヒットと見なされるかを決定し、これは精度と再現率の直接的なトレードオフです。しきい値を低く設定しすぎると(緩い一致を許容すると)、ヒット率は高くなりますが、実際には尋ねられていない質問に対する回答を提供してしまいます(誤ったヒット)。しきい値を高く設定しすぎると(ほぼ同一の表現を要求すると)、キャッシュは安全ですが、めったに機能せず、余分な手順を伴う完全一致キャッシュに近づいてしまいます。
埋め込みモデル、ドメイン、そして誤った回答がもたらすコストによって異なるため、普遍的に正しい値というものはありません。設定方法は経験的です。つまり、次のようなラベル付けされたリクエストのペアを収集します。 共有すべき と 共有すべきではない 回答を共有する、しきい値を調整し、そのルートで誤ったヒットが許容できるレベルまで減少する点を選択します。金銭、健康、身元に関わるような高リスクのルートでは、保守的なしきい値を使用するか、セマンティックキャッシュを全く使用しないことが推奨されます。ドキュメントのQ&Aや一般的な説明のような低リスクの情報提供ルートでは、より緩やかな設定が可能です。グローバルな単一の数値ではなく、ルートごとのしきい値が本番環境でのパターンです。そして、次のようなゲートウェイは、 TrueFoundryのAIゲートウェイすでにすべてのルートに配置されているため、ポリシーをサービス全体に分散させるのではなく、ルートごとに設定し、各ルートの誤ヒット率を監視するのに最適な場所です。
4. セマンティックキャッシュが誤った回答を提供するケース
核となる危険性は、述べるのは簡単ですが過小評価されがちです。それは「埋め込みが近くても意味が同じとは限らない」ということです。埋め込みは論理的な等価性ではなく、トピックの類似性を捉えます。「フランスの首都はどこですか?」と「ドイツの首都はどこですか?」は、埋め込み空間では非常に近く(同じ構造、同じドメイン、単語が1つ違うだけ)、しかし異なる回答を必要とします。再現率のために調整されたしきい値では、これらを同じ質問として扱ってしまいます。
対策は複数ありますが、単独で完璧なものはありません。保守的なしきい値は、緩い一致を減らします。エンティティとキーワードのガードは、ヒットを提供する前に主要なエンティティ(国、注文番号、製品など)が一致するかどうかを確認する機能を追加し、純粋なコサイン類似度では見逃してしまうフランス/ドイツのケースを捕捉します。名前空間ごとのキャッシュは、異なるコンテキストが衝突するのを防ぎます。そして最も信頼できる対策は上流にあります。つまり、ニアミスが危険な種類のリクエストは一切キャッシュしないことです。これについては次のセクションで説明します。セマンティックキャッシュは、既知の失敗モードを考慮して設計するツールとして扱い、どこにでも適用できる透過的な高速化手段として扱わないでください。
5. 決してキャッシュしてはならないもの
しきい値がどれほど優れていても、類似度の一致から提供するのが安全ではない応答があります。なぜなら、2つのリクエストを異なるものにする要素が、埋め込みが認識するテキストに含まれていない場合があるからです。
6. キャッシュキーの設計、スコープ設定、および無効化
セマンティックキャッシュのエントリは、テキストのみでキー付けされるわけではありません。名前空間内の埋め込みによってキー付けされ、その名前空間で正確性が保証されます。名前空間は、テキスト上は類似している2つのリクエストを、本質的に異なるものにするすべての要素をエンコードする必要があります。具体的には、テナントまたはユーザー(ユーザー固有の場合)、モデル、システムプロンプトのバージョン、およびアクティブなツールセットなどです。異なるシステムプロンプトバージョンでの2つの同一の質問は、回答を形成する指示が変更されたため、異なる質問とみなされます。
キャッシュエントリの名前空間化(図解)
# Same text in a different namespace is a different entry — by design.
namespace = f"{tenant_id}:{model}:{system_prompt_version}"
# For user-specific answers, the user/tenant MUST be in the namespace,
# so a lookup can never return another user's cached response.
vector_store.put(emb, resp, namespace=namespace, ttl=TTL)無効化には2つのトリガーがあります。1つは時間で、基盤となる真実がどれだけ速く変化するかに応じて選択されるTTL(有効期限)です。変化しやすいものには短く、安定した参照回答には長く設定されます。もう1つはバージョンで、名前空間を介して行われます。システムプロンプトのバージョンを上げたり、ツールセットを変更したりすると、キャッシュが更新され、古い設定からの古い回答が提供されることはありません。プロンプトの変更時に無効化を怠ると、一般的で気づきにくいバグにつながります。プロンプトが改善されても、TTLが期限切れになるまでキャッシュされた回答は古いものを反映し続けます。
TrueFoundryの キャッシュでは、これらすべてが x-tfy-cache-config ヘッダー(または同じフィールドを設定する一元管理されたポリシー)として扱われます。スキーマは簡潔で、制御は本セクションで説明した内容と一致しています。
マルチテナントアシスタント向けのルートごとのキャッシュ — 3つのパターン、同じスキーマ
# Route A: low-risk FAQ. Broad matching is fine; cache for 1 hour.
x-tfy-cache-config: {"type":"semantic","similarity_threshold":0.88,"ttl":3600,
"namespace":"faq:v3"}
# Route B: per-tenant support. Per-tenant namespace + stricter threshold to
# avoid cross-tenant near-misses (automatic per-user scoping ALREADY isolates
# users; the namespace partitions further along business boundaries).
x-tfy-cache-config: {"type":"semantic","similarity_threshold":0.93,"ttl":600,
"namespace":"tenant-acme:assistant:v7"}
# Route C: deterministic dev/test. Exact-match only.
x-tfy-cache-config: {"type":"exact-match","ttl":600,"namespace":"staging"}ドキュメントの しきい値に関するガイダンス は、投稿と一致しています。誤ったヒットが高コストになる非常に厳密なユースケースでは0.95~1.0、バランスの取れた会話型アシスタントでは0.85~0.95、探索的または低リスクのルートでは0.85未満です。0.9から開始し、観測された誤ヒット率に基づいて調整することが推奨されており、レスポンスヘッダー x-tfy-cache-similarity-score がそれを測定可能にします。すべてのヒットは、それがクリアしたスコアを教えてくれるため、ラベル付けされたペア全体をスキャンすることは、カスタム評価ハーネスではなく、数回のクエリで済みます。
知っておくべき実装の詳細が2つあります。 SaaS版の埋め込みモデル はOpenAIの text-embedding-3-small デフォルトではそのモードで設定できませんが、セルフホスト型デプロイでは コントロール → 設定 → セマンティックキャッシュ、そして選択されたモデルは、ゲートウェイ全体のすべてのセマンティックキャッシュ操作に適用されます。

ストアは セルフホスト型の場合、Redisです。これは、 tfy-llm-gateway HelmチャートにバンドルされているRedisか、または環境変数経由で独自のRedis(ValkeyのようなRedis互換のもの)です。埋め込みとルックアップが、回避しようとしているモデル呼び出しよりも実際に高速で安価である場合にのみキャッシュはその価値を発揮するため、どちらの選択も重要です。
投稿で述べられているネームスペースの議論のもう一つの側面は、ゲートウェイが自動化する部分です。それは レベル1の分離です。すべてのエントリは、それを作成したユーザーまたは仮想アカウントに暗黙的にスコープされるため、たとえ設定を忘れても namespace、ユーザーAのリクエストがユーザーBのキャッシュされた回答を返すことはありません。カスタム ネームスペース は 追加の パーティションであり、投稿で説明されているケース(マルチテナントアプリが1つの仮想アカウントを共有する場合、システムプロンプトのバージョン、環境など)のためのもので、2つの呼び出し元の回答の間にある唯一のものではありません。この階層化こそが、「サービス間で1つのキャッシュを共有する」ことを、自滅的な行為ではなく、擁護できるデフォルトにするものです。
7. 経済性:ヒット率、コスト、レイテンシ
セマンティックキャッシュの価値は、ある一つの数値、すなわちヒット率によって決まります。例として、あるルートが呼び出しごとにモデルコストを発生させ、キャッシュが安全な閾値で30%のヒット率を達成すると仮定します。およそ30%のリクエストがモデル呼び出しをスキップするため、そのルートのコストは30%近く減少します(生成と比較して小さい埋め込みおよびルックアップコストを除く)。まさにその30%のリクエストにおいてレイテンシが改善され、数百ミリ秒の生成から数十ミリ秒のルックアップへと短縮されるため、平均とテール(最大値)の両方が引き下げられます。
計算に関する2つの正直な注意点です。ヒット率はワークロード固有です。狭いFAQ形式のアシスタントでは30%をはるかに超えるヒット率が見られるかもしれませんが、ロングテールのクリエイティブなワークロードではほとんどヒットしないかもしれません。したがって、唯一信頼できる数値は、自身のトラフィックで測定したものです。そして、節約額は、すべてのミスに対する埋め込みコストを差し引いたものです。ヒット率が非常に低い場合、節約できる額よりも埋め込みに多く費やす可能性があります。見出しの数値を仮定するのではなく、コミットする前にキャッシュ可能な割合を測定してください。キャッシュを TrueFoundry’s AI Gateway の背後で実行することで、そもそもそれが測定可能になります。ヒット率と、それが回避する費用が、コストアトリビューション作業による呼び出しごとのコストの隣に表示されるため、節約額は予測ではなく、観測された数値となります。
8. キャッシュの場所:ゲートウェイ vs. アプリケーション
セマンティックキャッシュはアプリケーション内に置くこともできますが、ルーティングや信頼性に適用されるのと同じ理由で、ゲートウェイの方がより強力なデフォルトとなります。ゲートウェイはすでにすべてのリクエストを処理しており、キャッシュは各サービスで再実装されるのではなく、サービス間で共有されます。また、キャッシュが実際に効果を発揮しているかどうかを測定するために必要な、呼び出しごとのコストとレイテンシのテレメトリをすでに保持しています。
キャッシュを TrueFoundry’s AI Gateway で実行することは、テナントごとのスコープを強制する(コールドオープンが発生しないようにする)単一の場所であり、ヒット率、削減されたコスト、削減されたレイテンシを確認できる単一の場所であり、そして、 <a href="https://www.truefoundry.com/blog/llm-cost-attribution-and-optimization" target="_blank">コストアトリビューションに関する投稿</a> からのコストアトリビューションビューと同じように、チームごと、ルートごとのキャッシュ済みと未キャッシュの分割を表示します。このシリーズ全体で繰り返される役割分担は次のとおりです。ゲートウェイは共有され、スコープが設定され、観測可能なキャッシュを提供します。アプリケーションは、どのルートをどの閾値でキャッシュするのが安全かというポリシー決定を所有します。なぜなら、「私の配達はどこ?」がパーソナライズされており、「返品期間は?」がそうではないことを知っているのはアプリケーションだけだからです。
9. FAQ
これは、コンテキストエンジニアリングに関する投稿で説明されているプロンプトキャッシュとはどう違うのですか?
その投稿では、プロバイダーのプレフィックスキャッシュについて説明しました。これは、同一のシステムプロンプトのプレフィックスを請求割引で再利用するもので、正確なテキストに一致するため、誤った回答を提供することはありません。セマンティックキャッシュは再利用します 類似 リクエストを埋め込むことで、ヒット率の向上と誤ヒットのリスクの両方をもたらします。設定としては、すべての呼び出しで静的プレフィックスをキャッシュし、安全なルートでのみ応答全体をセマンティックキャッシュする、というものです。
類似度しきい値はどのように選べばよいですか?
経験的に、ルートごとに設定します。回答を共有すべきリクエストペアと共有すべきでないリクエストペアのラベル付きセットを作成します。そして、しきい値を試行錯誤し、そのルートで誤った回答がもたらすコストを考慮した上で、許容できる誤ヒット率にまで低下する点を選択します。重要度の高いルートでは、保守的なしきい値を設定するか、セマンティックキャッシュを使用しません。重要度の低い情報提供ルートでは、より緩やかな設定が可能です。単一のグローバルなしきい値は、ほとんどの場合、特定のルートでは不適切です。
パーソナライズされたものを安全にキャッシュできますか?
キャッシュネームスペース内で、明示的なユーザーごと(またはテナントごと)のスコープを設定した場合に限ります。これにより、検索で他のユーザーの応答が返されることはありません。それでも、時間的制約には注意が必要です。パーソナライズされた、時間的制約のある、ステートフルな、または重要度の高い応答の場合、セマンティックキャッシュしないのが安全なデフォルトです。ユーザーのスコープなしでパーソナライズされた回答がキャッシュされると、コールドオープンが発生します。
システムプロンプトを変更すると、キャッシュはどうなりますか?
キャッシュを無効化する必要があります。そうしないと、TTLが期限切れになるまで古いプロンプトによって形成された回答が提供され続けます。クリーンな方法は、システムプロンプトのバージョンをキャッシュネームスペースに含めることです。これにより、プロンプトが変更されるとキャッシュが自動的に更新され、古いエントリは二度と一致しなくなります。
ゲートウェイか、それともアプリケーションか?
メカニズムについてはゲートウェイが担当します。共有キャッシュ、テナントごとのスコープ設定、そしてそれが機能しているかどうかを示すヒット率/コスト/レイテンシの可観測性などです。ポリシー(どのルートがキャッシュ可能か、どのしきい値でキャッシュするか)についてはアプリケーションが担当します。その判断には、ゲートウェイが持たないドメイン知識が必要だからです。
カビールのキャッシュは悪いアイデアではありませんでした。スコープが設定されていなかっただけです。セマンティックキャッシュは、類似の質問が実際に回答を共有するルートにおいて、コストとレイテンシの真の削減をもたらします。そして、それを安全にするための原則は、どの質問がそれに該当するかをルートごとに把握することです。
TrueFoundryについて
TrueFoundryのAIゲートウェイ は、アプリケーションと1,600以上のモデル(OpenAI、Anthropic、Google、AWS Bedrock、Azure OpenAI、および自社ホスト型モデルを含む)の間に位置し、単一のOpenAI互換APIの背後で動作するエンタープライズグレードのコントロールプレーンです。これにより、この記事で紹介されているキャッシュ戦略が、サービスごとのコードではなく設定として実現されます。 完全一致キャッシュとセマンティックキャッシュ 単一の x-tfy-cache-config ヘッダー、ルートごとの類似度しきい値とTTL、ユーザーごと/仮想アカウントごとの自動分離、マルチテナントアプリおよびプロンプトバージョン用のオプションのネームスペースパーティショニング、そしてSaaSとセルフホストの両方で同じように機能するRedisバックエンドストレージ(オンプレミスで埋め込みモデルを設定可能)を提供します。
ゲートウェイはすでにすべてのリクエストを処理し、すべての呼び出しに対して完全なトレースを出力するため、キャッシュも他のすべてと同様に同じビューで測定可能になります。 x-tfy-cache-status、キャッシュされたトレースID、および実際の類似度スコアが各応答に付与され、コスト削減およびレイテンシー削減ダッシュボードに集約されます。このゲートウェイは、ロールベースアクセス制御(RBAC)、仮想アカウント、予算とレート制限、フォールバックとリトライ、ガードレール、可観測性ダッシュボードも追加します。SaaSとして、VPC内、オンプレミス、またはエアギャップ環境でデプロイされ、SOC 2、HIPAA、ITARに準拠しており、GartnerのAIゲートウェイ市場ガイドで評価されています。詳細については、 キャッシュに関するドキュメント または AIゲートウェイの概要 をご覧ください。
参考文献
- TrueFoundry AIゲートウェイ — キャッシュと可観測性
- OpenAI — プロンプトキャッシュ(完全一致プレフィックス層)
- Anthropic — プロンプトキャッシュ(cache_control)
NorthwindとKabirは例示です。埋め込みベースのキャッシングの仕組み、類似度しきい値の精度/再現率の挙動、および埋め込みが近いからといって意味が同じとは限らないという失敗モードは、この技術の一般的な特性です。具体的な数値 — 35%の呼び出し削減、ヒット時の900ミリ秒から40ミリ秒へのレイテンシー、30%のヒット率の例、10〜30ミリ秒の埋め込みコスト — は、トレードオフを説明するための代表的な概算値であり、測定値ではありません。セマンティックキャッシングを本番環境で有効にする前に、ご自身のキャッシュ可能な割合と誤ヒット率を測定してください。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.














.webp)
.webp)


.png)

.png)














