あるユーザーから、当社の翻訳プラグインが入力内容に関係なく、すべてのリクエストに対して同じキャッシュ結果を返しているという報告がありました。調査したところ、さらに深刻な事実が判明しました。プラットフォーム全体でのセマンティックキャッシュヒットの95%が誤検知(フォールスポジティブ)だったのです。199件の翻訳リクエストのうち、198件はリクエストボディが異なるにもかかわらず、すべて同じキャッシュされたレスポンスが返されていました。
長期的なエージェントの状態管理や本番環境でのリクエスト処理に関心がある方は、AIエージェントが記憶を失い続ける理由、ワンキー・チャットボットガイド、およびAI APIレート制限ガイドも併せてお読みください。
要点
- プラットフォーム全体のセマンティックキャッシュヒットの95%が誤検知であり、198件の異なるリクエストに対してすべて同じキャッシュレスポンスが提供されていました。
- 根本的な原因は構造化された入力です。固定されたテンプレートテキストが埋め込みベクトルを支配してしまうため、コンテンツが変化してもコサイン類似度がほとんど変動しません。
- 類似度のしきい値を上げても解決しません。正解と不正解のヒット分布が重なってしまうためです。セマンティックキャッシュの信頼性に関する最近の研究でも、同様のパターンが確認されています。
- 解決策は2層構造です。埋め込みを行う前に意味のあるコンテンツを抽出し、次に高速なFNV-1aフィンガープリントハッシュで各ヒットを検証します。これにより、誤検知率は約95%から5%未満に低下しました。
- モデルの選択も影響します。長いシステムプロンプトやJSONでラップされた入力は、どのモデルで補完を行うかに関わらず問題を悪化させます。キャッシュされたトラフィックをどのモデルにルーティングするか検討する際は、TokenLabのモデルディレクトリ(2026年7月7日時点)で最新のモデルオプションを確認してください。
バグ報告
報告内容は単純でした。「セマンティックキャッシュを無効にしたのに、すべての翻訳が同じ結果を返す」というものです。
3つのリクエストID、3つの異なる翻訳セグメントに対し、同一のキャッシュレスポンスが返されていました。リクエストボディは1,564バイトから8,676バイトまで様々でしたが、キャッシュされたレスポンスIDはすべて同じ chatcmpl-DG6J03nhdvcF7Ek0C8rJkjh7lN9pF でした。
当初の疑いは、ユーザーのキャッシュ設定が適用されていないことでした。しかし、これは別のデータソース同期バグ(管理パネルは一方のテーブルに書き込み、APIゲートウェイは別のテーブルを読み取っていた)であることが判明しました。それを修正しても問題の半分しか解決しませんでした。キャッシュが有効で正しく動作していても、セマンティックキャッシュは本来一致すべきでないリクエストを一致させていたのです。
本番環境のデータ
ClickHouseから24時間分のキャッシュヒットデータを抽出しました。数値は悲惨なものでした。
| モデル | 合計リクエスト数 | キャッシュヒット数 | ユニークリクエスト数 | ユニークレスポンス数 | ヒット率 |
|---|---|---|---|---|---|
| DeepSeek V4 Flash | 200 | 199 | 198 | 1 | 99.5% |
| glm-4.6-thinking | 100 | 38 | 13 | 1 | 38% |
| gpt-5-nano | 31 | 29 | 28 | 2 | 93.5% |
| gpt-oss-120b | 18 | 17 | 17 | 1 | 94.4% |
| qwen3-vl-flash | 17 | 16 | 16 | 1 | 94.1% |
198件のユニークな翻訳リクエストが、すべて同じキャッシュレスポンスを返しています。これはキャッシュではありません。定数を返す壊れた関数です。
影響を受けたすべてのモデルには2つの共通点がありました。すべてのリクエストが単一のユーザーから発信されており、固定されたシステムプロンプトテンプレートを使用しつつ、ユーザーコンテンツが変化していたことです。プラットフォームで利用可能なモデルの最新リストについては、ラインナップが頻繁に変更されるため、TokenLabのモデルディレクトリ(2026年7月7日時点)が信頼できる情報源となります。
システム内での検出方法
同じ問題を抱えているかどうかを確認するために、当社のログは必要ありません。最も迅速なシグナルは、モデルごとのレスポンスの多様性です。モデルのキャッシュヒット率が高いにもかかわらず、ユニークなレスポンスがほとんどない場合、多くの異なる質問に対して一つの回答を提供していることになります。
以下は、私たちが使用したClickHouse形式のクエリ(一般化版)です。
SELECT
model,
count() AS total_hits,
uniqExact(substring(response_body, 1, 200)) AS unique_responses,
round(uniqExact(substring(response_body, 1, 200)) / count(), 3) AS diversity_ratio
FROM request_logs
WHERE cache_hit = true
GROUP BY model
ORDER BY total_hits DESC;
健全なキャッシュであれば、diversity_ratioは1.0に近くなります。つまり、ほとんどのヒットが異なる入力に対して異なるレスポンスを返します。比率が0に近い場合、多くのリクエストが少数のキャッシュされた回答に集約されていることを意味します。実際の入力に多様性があるモデルで0.5を下回る場合は、調査する価値があります。
レスポンスボディをログに記録していない場合、より安価な代替手段もあります。ユニークなリクエストボディの数と、キャッシュから提供されたユニークなレスポンスの数を比較してください。198件のユニークなリクエストが1つのレスポンスにマッピングされている場合、キャッシュは意味を照合しているのではなく、定型文を照合しているだけです。
もう一つの兆候は、構造化されたワークロードに集中するユーザーからの苦情です。翻訳プラグイン、要約ツール、フォーム入力ツール、JSON入出力ツールなどは、可変コンテンツを固定テンプレートでラップするため、典型的な対象となります。
なぜ構造化入力で埋め込みが失敗するのか
翻訳プラグインは以下のようなリクエストを送信します。
System: "Act as a translation API. Output a single raw JSON object only.
Input: {"targetLanguage":"<lang>","title":"...","segments":[...]}"
User: {"targetLanguage":"zh","title":"Product Page",
"description":"Translate product descriptions",
"tone":"formal",
"segments":[{"text":"actual varying content here"}]}
システムプロンプトはすべてのリクエストで同一です。ユーザーメッセージはJSONオブジェクトであり、targetLanguage、title、description、toneは固定されています。変化するのはsegments[].textのみです。
セマンティックキャッシュが埋め込み用にテキストを抽出する際、システムプロンプトとユーザーメッセージを連結します。固定テンプレートがテキストの約80%を占めます。埋め込みモデル(all-mpnet-base-v2、768次元)はこれをベクトルに圧縮しますが、テンプレート構造が支配的になります。実際の翻訳コンテンツはほとんど影響を与えません。
結果として、「'Hello world'を翻訳して」と「'四半期財務報告書は収益が15%増加したことを示している'を翻訳して」の間のコサイン類似度は0.95を超えてしまいます。当社のしきい値は0.95です。すべての翻訳リクエストが最初のキャッシュエントリと一致してしまいます。
ログを掘り下げた結果、この問題が発生する3つのパターンが見つかりました。
翻訳プラグインが最悪のケースです。固定されたJSONキーと値が、実際の翻訳セグメントをかき消してしまいます。DeepSeek V4 Flashとgpt-5-nanoの両方がこれに該当しました。
コンテキスト要約アシスタントも同様の問題を抱えていました。システムプロンプトが非常に長いため、5KBから47KBに及ぶユーザーコンテンツが埋め込みにほとんど反映されませんでした。これが、glm-4.6-thinkingがすべての会話で同じ要約を返すようになった原因です。
3つ目のパターンはより微妙です。gpt-oss-120bとqwen3-vl-flashの場合、すべてのリクエストの最初の500文字が完全に同一でした。変化するコンテンツはその後に続きますが、埋め込みはすでに共有されたプレフィックスによって支配されていました。
研究が示すこと
これは新しい問題ではありません。最近の論文で定量化されています。
カリフォルニア大学バークレー校のvCacheプロジェクトでは、正解と不正解のキャッシュヒットの類似度分布が大きく重なっていることが判明しました。つまり、構造的に類似した偽のヒットと真の一致を明確に分離できる固定しきい値は存在しないということです。この発見は、私たちが本番環境で見たものと完全に一致します。翻訳プラグインの誤検知は0.95以上に集中しており、正当な言い換え一致も存在する範囲内に収まっていました。
セマンティックキャッシュの信頼性に関する他の最近の研究も同様の結論に達しています。生の埋め込み類似度はキャッシュの正確性にとって必要ですが十分なシグナルではなく、それだけに依存する本番システムは、テンプレートが多用される構造化トラフィックにおいて有意な誤検知率を覚悟すべきです。
2層の解決策
第1層はコンテンツ抽出です。埋め込みの前に、固定されたシステムプロンプトとテンプレートの足場を取り除き、可変ペイロード(周囲のJSONキーや定型文ではなく、実際のsegments[].textコンテンツ)のみを埋め込みます。これだけで、埋め込みベクトル内の信号対雑音比(S/N比)が劇的に向上します。
第2層はフィンガープリント検証です。抽出を改善しても、ほぼ重複したコンテンツは高い類似度スコアを生成する可能性があります。キャッシュヒットを提供する前に、着信リクエストとキャッシュエントリの両方の抽出済みコンテンツに対して高速ハッシュ(FNV-1aを使用)を計算します。ハッシュが完全に一致すればキャッシュを提供します。一致しない場合は、新しい補完処理を行うか、より価値の高いトラフィックであれば、バイト単位ではなく意味をスコアリングする安価な検証呼び出しにルーティングします。
間違いは、検証を完全にスキップして生のコサイン類似度を信頼することです。表にあるどの手法もそれより優れています。クエリタイプに適合する最も安価なものから始め、実際の言い換えミスを測定した段階でステップアップしてください。
これら2つの層を組み合わせることで、影響を受けたトラフィックの誤検知率を約95%から5%未満に低下させました。
セマンティックキャッシュが不適切なツールとなる場合
キャッシュは無料のエンジニアリングではなく、キャッシュする価値のないワークロードもあります。
- カーディナリティが高く、繰り返しが少ないトラフィック。例えば、ほとんどのリクエストがユニークな創作生成の場合、ヒット率が低すぎて埋め込みのオーバーヘッドを正当化できません。すべてを埋め込むコストを支払いながら、ほとんど恩恵を受けられません。
- 鮮度が重要な出力。時間依存、ライブデータ、パーソナライズされた結果、「今日」という言葉が含まれるものなどは、技術的に一致していてもキャッシュから古い回答を返す可能性があります。1時間前には正解だった回答が、今は間違っているかもしれません。
- 厳格な正確性が求められるドメイン。医療、法律、金融の回答では、1回の誤検知が節約したコストよりも大きな損失になる可能性があります。ここでキャッシュを行う場合、検証層はオプションではなく必須であり、LLMレベルのチェックのみが許容されるかもしれません。
- モデル呼び出し自体が安価な小さなプロンプト。埋め込み、類似度検索、検証には独自のコストがかかります。基盤となる補完が安価なモデルで数百トークン程度であれば、キャッシュは節約よりもコストがかかる可能性があります。
キャッシュは、反復的でテンプレートが多く、高価な補完処理で真価を発揮します。まさに誤検知が発生しやすいワークロードです。その緊張関係こそが、検証層が重要である理由です。主な目的がコスト管理であれば、キャッシュと安価なモデルルーティングを組み合わせる価値があります。価格比較やコーディングに最適なAIモデルガイドでは、トークンあたりの節約がどこから来るのかを解説しています。TokenLabのモデルディレクトリ(2026年7月7日時点)では、キャッシュあり・なしのトラフィックをどのモデルにルーティングするか検討する際の、DeepSeek V4 FlashやGemini 3.5 Flashなどの低コストルーティングの選択肢を確認できます。ルーティング計画を確定する前に、リンク先のディレクトリで現在の価格を確認してください。
なぜしきい値を上げるだけではいけないのか
当社のしきい値はすでに0.95です。上げても解決しません。問題は、実際のコンテンツが何であれ、構造的に類似した入力は0.95を超える類似度スコアを生成してしまうことです。
vCacheのデータもこれを裏付けています。正解と不正解のヒットの類似度分布が重なりすぎており、単一のカットオフでは分離できません。しきい値を0.99に上げれば、正当な言い換えに対する正当なキャッシュヒットを殺すことになりますが、翻訳JSONペイロードのような構造的に同一のリクエストは、コンテンツに関係なく0.99以上に集中したままです。しきい値はレバーではありません。入力表現こそがレバーです。第1層(コンテンツ抽出)と第2層(フィンガープリント検証)が機能し、しきい値の調整が機能しないのはそのためです。これらは比較の厳しさではなく、比較対象そのものを変更するからです。
セマンティックキャッシュを構築または保守している場合は、しきい値を正確性の保証ではなく、大まかなフィルターとして扱ってください。埋め込みがリクエストの可変部分を実際に表現するようにコンテンツ抽出と組み合わせ、さらに安価な検証ステップを追加して、埋め込みのニアミスが本番環境で誤った回答にすり替わることがないようにしてください。
キャッシュ検証層を構築する前に、TokenLabのモデルディレクトリで、フロンティアモデル、コーディングモデル、低コストルーティングモデルの現在の価格とベンチマークを比較してください。補完エンドポイントの背後にどのモデルを配置する場合でも、抽出とフィンガープリントを組み合わせるアプローチこそが、誤検知を実際に修正するものです。
よくある質問
類似度のしきい値を上げれば、セマンティックキャッシュの誤検知は解決しますか? いいえ。vCacheや関連研究によると、正解と不正解のヒット分布はしきい値の範囲全体で重なっており、カットオフを上げても、構造的に類似しているが意味的に異なるリクエストを確実にフィルタリングすることなく、正当な一致をブロックしてしまいます。
セマンティックキャッシュのヒットを検証する最も安価な方法は何ですか? 抽出された意味のあるコンテンツに対するフィンガープリントハッシュ(FNV-1aなど)は、1ミリ秒未満のレイテンシで計算でき、コストもかかりません。言い換えをキャッチすることはできませんが、ここで説明したような構造化ワークロードで最も大きな損害を与える、正確な誤検知を排除できます。
この問題は、どのモデルが補完を行うかに依存しますか? いいえ、誤検知の問題は埋め込みと照合の層にあり、補完モデルにはありません。DeepSeek V4 Flash、glm-4.6-thinking、あるいはそれ以降のモデルであっても、キャッシュが可変コンテンツとともに固定テンプレートテキストを埋め込む場合、どのモデルであっても同じ影響を受けます。キャッシュされたパイプラインをどのモデルにルーティングするか検討する際は、TokenLabのモデルディレクトリ(2026年7月7日時点)で現在のモデルの可用性を確認してください。
出典
価格確認日 2026-07-07
- TokenLab model directory2026-07-07 時点で確認
- Generative Caching for Structurally Similar Prompts and Responses2026-07-09 時点で確認
- GPTCache paper2026-07-09 時点で確認
- RedisVL semantic caching docs2026-07-09 時点で確認
- GPTCache quick start2026-07-09 時点で確認



