セマンティックキャッシュは「パスワードをリセットするには」という質問に、すでに「ログインを忘れた」に対して生成した回答を返す。両者が同じ意味だからだ。リクエストの文字列を厳密に照合する代わりに、リクエストを埋め込み、十分に近い埋め込みを持つ保存済みリクエストを探し、モデルを呼び出さずにそのキャッシュされた回答を返す。うまく機能すれば、モデル呼び出しをまるごとスキップできる。トークンもレイテンシもコストもゼロだ。しかし「十分に近い」の判断を誤ると、ユーザーが尋ねていない質問に自信満々な答えを返してしまう。

核心となる捉え直し方はこうだ。通常のキャッシュは同一性でキー化するが、セマンティックキャッシュは類似度でキー化し、類似度は事実ではなく自分が設定するしきい値だ。そのしきい値こそがリスク面全体だ。緩く設定すれば誤った答えを返し、厳しく設定すればほとんど何もキャッシュできない。セマンティックキャッシュをうまく運用することのすべては、このダイヤルを管理することに尽きる。

魔法抜きの仕組み

メカニズムは3ステップだ。受信したリクエストをAmazon Titan Text EmbeddingsやBedrock上のCohereなどの埋め込みモデルでベクトルに変換する。ベクトルストアで、過去に見た最も近いリクエストを検索する。最近傍のコサイン類似度がしきい値を上回っていれば、そのキャッシュ済み応答を返す。そうでなければモデルを呼び出し、次回のために新しいリクエストの埋め込みと応答を保存する。

vec = embed(request)
hit = vector_store.nearest(vec)
if hit and hit.similarity >= THRESHOLD:
    return hit.cached_response      # no model call
answer = model.invoke(request)
vector_store.put(vec, answer)
return answer

ベクトルストアはすでに運用しているものなら何でもいい。OpenSearch、pgvectorを使ったAurora、小さなホットセット向けのインメモリインデックスなどだ。難しいのはストレージではなく、常にTHRESHOLDの値と、そもそも何をキャッシュに入れることを許すかだ。

誤ヒットのリスクがすべてを決める

誤ヒットとは、2つのリクエストが埋め込み空間上で近いにもかかわらず、異なる答えが求められる場合を指す。「EU顧客の返金ポリシーは何か」と「US顧客の返金ポリシーは何か」は、異なる応答を要求しながらもベクトル空間上では危険なほど近くに位置しうる。緩いしきい値は、US顧客にEUの答えを返し、しかもモデルが一切参照されていないため、完全な自信を持ってそれを行う。

これは通常のキャッシュミスよりも悪い。ミスは単にモデル呼び出しのコストがかかるだけだ。誤ヒットは正しく見える間違った答えというコストを生む。だからしきい値は推測ではなく実際のトラフィックに対してチューニングすべきであり、厳しさに寄せるべきだ。ミスは安く済むが、誤ヒットはサポートチケットやコンプライアンス問題になりうる。何か重要なものにキャッシュを信用させる前に、ラベル付けされたサンプルで誤ヒット率を測定すること。

キャッシュしてはいけないもの

セマンティックキャッシュは安定した、一般的な、共有知識には合うが、それ以外には合わない。「データをエクスポートするには」という質問への答えはキャッシュせよ。誰にとっても同じだからだ。誰が尋ねているか、あるいはいつ尋ねているかに依存するものは何もキャッシュしてはならない。コードで強制する価値のある経験則:

  • アイデンティティの境界を越えてキャッシュしない。キャッシュはテナントごとにキー化するか、パーソナライズされたものはすべて除外する。呼び出し元を無視した共有キャッシュは、いずれ1つの顧客の答えを別の顧客に返すことになる。
  • 時間依存の答えをキャッシュしない。残高、注文状況、在庫はあなたの意図とは無関係に変化する。ここでの古びたヒットは新種のバグだ。
  • 検索を伴わないものをキャッシュし、検索が重いものはキャッシュしない。答えが変化する文書に依存する場合、最終的な応答ではなく検索ルックアップをキャッシュすること。

みんなが飛ばす部分、無効化

キャッシュの無効化は計算機科学における2つの難問の1つだというのは昔からのジョークだが、セマンティックキャッシュも例外ではない。根底の真実が変わったとき、ポリシーが更新されたとき、価格が動いたとき、文書が改訂されたとき、古い真実に依存していたキャッシュ済みの答えはすべて間違いになり、退避させるまで返され続ける。

古い答えが自然と期限切れになる程度に短いTTLをエントリに設定し、真実を変えるイベントに紐づけた明示的なパージ経路を追加すること。新しいポリシーバージョンの公開は、古いバージョンに基づいて構築されたキャッシュの一部を無効化すべきだ。無効化の仕組みがなければ、セマンティックキャッシュは呼び出しを節約するだけでなく、製品を静かに昨日の事実に固定してしまう。

結論

セマンティックキャッシュは、表現が違うだけで同じ質問に対しては、コストとレイテンシの両面で本当の勝利だが、パーソナライズされたもの、時間依存のもの、変化しうるものに対しては自爆装置になる。メカニズムは単純だ。埋め込み、検索、しきい値。エンジニアリングはすべてしきい値、スコープのルール、無効化の経路にある。しきい値はラベル付けされたトラフィックに対してチューニングし、安定した共有知識だけをキャッシュし、真実を動かすイベントで無効化すること。この3つをやればキャッシュは元が取れる。飛ばせば、モデルが正しい答えを出すよりも速く間違った答えを返すようになる。

次に読む

負荷下でのベクトルストアの運用とその退避に関するプラットフォーム側の話は、クラウドのフィールドノートがercan.cloudにあり、ハブはercanermis.comにある。