ストーリー
田
田中VPoE
コスト構造を分析した結果、チャットボットの問い合わせの30%が類似した質問だとわかった。毎回APIを呼び出すのは無駄だ
あなた
同じ質問には過去の回答をキャッシュから返せば、APIコストを30%削減できますね
あ
田
田中VPoE
その通り。ただしLLMのキャッシュは従来のWebキャッシュとは違う課題がある。完全一致だけでなく、意味的に類似した質問にもヒットさせる「セマンティックキャッシュ」が有効だ
LLMキャッシュの種類
キャッシュ戦略の比較
| 種類 | 仕組み | ヒット率 | 実装複雑度 |
|---|
| 完全一致キャッシュ | プロンプトの完全一致 | 低(5-10%) | 低 |
| セマンティックキャッシュ | 埋め込みベクトルの類似度 | 中(20-40%) | 中 |
| プロンプトテンプレートキャッシュ | テンプレート+パラメータの一致 | 中(15-30%) | 低 |
| RAGコンテキストキャッシュ | 検索結果のキャッシュ | 高(30-50%) | 中 |
セマンティックキャッシュの実装
import hashlib
import json
import numpy as np
from openai import OpenAI
from datetime import datetime, timedelta
client = OpenAI()
class SemanticCache:
"""セマンティックキャッシュ"""
def __init__(self, similarity_threshold: float = 0.95, ttl_hours: int = 24):
self.threshold = similarity_threshold
self.ttl = timedelta(hours=ttl_hours)
self.cache: list[dict] = [] # 実運用ではベクトルDBを使用
def get(self, prompt: str) -> dict | None:
"""キャッシュから類似プロンプトの結果を検索"""
query_embedding = self._get_embedding(prompt)
now = datetime.now()
best_match = None
best_similarity = 0
for entry in self.cache:
# TTLチェック
if now - entry["timestamp"] > self.ttl:
continue
similarity = self._cosine_similarity(
query_embedding, entry["embedding"]
)
if similarity > self.threshold and similarity > best_similarity:
best_match = entry
best_similarity = similarity
if best_match:
return {
"response": best_match["response"],
"similarity": best_similarity,
"cached": True
}
return None
def set(self, prompt: str, response: str):
"""キャッシュに結果を保存"""
embedding = self._get_embedding(prompt)
self.cache.append({
"prompt_hash": hashlib.sha256(prompt.encode()).hexdigest(),
"embedding": embedding,
"response": response,
"timestamp": datetime.now()
})
def _get_embedding(self, text: str) -> list[float]:
response = client.embeddings.create(
model="text-embedding-3-small",
input=text
)
return response.data[0].embedding
def _cosine_similarity(self, a: list[float], b: list[float]) -> float:
a, b = np.array(a), np.array(b)
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))
キャッシュ設計のベストプラクティス
キャッシュの有効性判断
| 条件 | キャッシュ適性 | 理由 |
|---|
| FAQ的な問い合わせ | 高 | 同じ質問が繰り返される |
| 商品情報の問い合わせ | 高 | 商品データは頻繁に変わらない |
| パーソナライズされた推薦 | 低 | ユーザーごとに異なる結果 |
| リアルタイムデータ依存 | 低 | 在庫、価格は常に変動 |
| クリエイティブ生成 | 中 | 類似リクエストの再利用が可能 |
キャッシュ無効化(Invalidation)
| トリガー | 対応 | 例 |
|---|
| TTL超過 | 自動削除 | 24時間経過で削除 |
| データ更新 | タグベース無効化 | 商品情報更新時に関連キャッシュを削除 |
| モデル変更 | 全キャッシュクリア | プロンプト変更時にキャッシュをリセット |
| 品質問題 | 手動無効化 | 誤った回答がキャッシュされた場合 |
キャッシュの効果測定
主要メトリクス
| メトリクス | 計算式 | 目標値 |
|---|
| ヒット率 | キャッシュヒット数 / 総リクエスト数 | 20-40% |
| コスト削減率 | 削減コスト / キャッシュなし時のコスト | 15-30% |
| レイテンシ改善 | キャッシュヒット時のレイテンシ / APIコール時のレイテンシ | 10倍以上速い |
| 品質維持率 | キャッシュ返却時の品質スコア / API返却時の品質スコア | 95%以上 |
まとめ
| キャッシュ種類 | 適用場面 | 期待効果 |
|---|
| セマンティックキャッシュ | FAQ、定型問い合わせ | コスト20-40%削減 |
| テンプレートキャッシュ | 構造化された入力 | コスト15-30%削減 |
| RAGコンテキストキャッシュ | RAGシステム | 検索コスト50%削減 |
チェックリスト
次のステップへ
次はモデル選択最適化を学び、タスクに応じた最適なモデルの使い分けを習得します。
推定読了時間: 30分