

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 最佳實務
<a name="semantic-caching-best-practices"></a>

## 選擇可快取的資料
<a name="semantic-caching-bp-choosing-data"></a>

語意快取非常適合回應相對穩定的重複查詢，而即時或高度動態回應通常不適合快取。

使用衍生自現有應用程式內容 （例如產品 ID、類別、區域或使用者區段） 的標籤和數值篩選條件，來決定哪些查詢和回應符合快取資格，並改善快取命中項目的相關性。

## 相似性閾值調校
<a name="semantic-caching-bp-threshold"></a>

相似性閾值控制快取命中率和回答品質之間的權衡。為您的使用案例選擇平衡成本節省與準確性的閾值：


| Threshold | 命中率 | 品質風險 | 最適合 | 
| --- | --- | --- | --- | 
| 0.95 （嚴格） | 低 (\~25%) | 非常低 | 醫療、法律、金融應用程式 | 
| 0.90 （中度） | 中 (\~55%) | 低 | 一般聊天機器人 | 
| 0.80 （平衡） | 高 (\~75%) | 中低 | 常見問答集機器人、IT 支援 | 
| 0.75 （已釋放） | 極高 (\~90%) | 中 | 大量重複查詢 | 

**重要**  
從較高的閾值 (0.90–0.95) 開始，並在監控準確性時逐漸降低閾值。使用 A/B 測試來尋找工作負載的最佳平衡。

## 獨立查詢與對話
<a name="semantic-caching-bp-standalone-vs-conversations"></a>
+ **對於獨立查詢** – 直接在使用者查詢文字上套用語意快取。
+ **對於多轉對話** – 首先使用您的對話記憶體來擷取回答目前轉彎所需的關鍵事實和近期訊息。然後將語意快取套用至目前使用者訊息和擷取內容的組合，而不是內嵌整個原始對話。

## 設定快取失效期間
<a name="semantic-caching-bp-ttl"></a>

使用 TTL 控制快取回應在快取遺漏時重新產生之前提供的時間長度。


| 資料類型 | 建議的 TTL | 理由 | 
| --- | --- | --- | 
| 靜態事實 （文件、政策） | 24 小時 | 不常變更事實 | 
| 產品資訊 | 12–24 小時 | 在大多數目錄中每日更新 | 
| 一般助理回應 | 1–4 小時 | 平衡新鮮度與命中率 | 
| 即時資料 （價格、庫存） | 5-15 分鐘 | 資料經常變更 | 
| 對話內容 | 30 分鐘 | 工作階段範圍、短期 | 

```
# Set TTL with random jitter to spread out cache invalidations
import random

base_ttl = 82800  # ~23 hours
jitter = random.randint(0, 3600)  # Up to 1 hour of jitter
valkey_client.expire(cache_key, base_ttl + jitter)
```

**提示**  
設定符合您應用程式使用案例TTLs，以及資料或模型輸出變更的頻率。較長TTLs 會增加快取命中率，但會增加答案過時的風險。較短TTLs 可讓回應更新鮮，但快取命中率較低，且需要更多 LLM 推論。

## 監控和成本追蹤
<a name="semantic-caching-bp-monitoring"></a>

追蹤快取效能指標，以隨著時間最佳化語意快取：

```
def record_cache_event(valkey_client, event_type: str):
    """Track cache hits and misses using atomic counters."""
    valkey_client.incr(f"cache:metrics:{event_type}")

    # Also track hourly for time-series analysis
    from datetime import datetime
    hour_key = datetime.now().strftime("%Y%m%d%H")
    counter_key = f"cache:metrics:{event_type}:{hour_key}"
    valkey_client.incr(counter_key)
    valkey_client.expire(counter_key, 86400 * 7)  # Keep 7 days

def get_cache_stats(valkey_client) -> dict:
    """Get current cache performance metrics."""
    hits = int(valkey_client.get("cache:metrics:hit") or 0)
    misses = int(valkey_client.get("cache:metrics:miss") or 0)
    total = hits + misses
    hit_rate = hits / total if total > 0 else 0

    avg_cost_per_call = 0.015  # Example: ~$0.015 per LLM call
    savings = hits * avg_cost_per_call

    return {
        "total_requests": total,
        "hits": hits,
        "misses": misses,
        "hit_rate": round(hit_rate, 3),
        "estimated_savings_usd": round(savings, 2),
    }
```

## 記憶體管理
<a name="semantic-caching-bp-memory"></a>
+ **設定最大記憶體政策** – 在 ElastiCache 叢集`maxmemory-policy allkeys-lru`上設定 ，以在叢集達到其記憶體限制時自動移出least-recently-used快取項目。
+ **規劃容量** – 每個快取項目通常需要大約 4-6 KB （嵌入維度 × 4 位元組 \+ 查詢文字 \+ 回應文字）。1 GB ElastiCache 執行個體可以存放大約 170，000 個快取項目。
+ **針對過時的資料使用快取失效** – 當基礎資料變更時，請使用文字搜尋來尋找相關快取項目並使之失效：

  ```
  def invalidate_by_topic(valkey_client, topic_keyword: str):
      """Remove cached entries matching a topic after a data update."""
      results = valkey_client.execute_command(
          "FT.SEARCH", "semantic_cache",
          f"@query:{topic_keyword}",
          "NOCONTENT",  # Only return keys, not fields
      )
  
      if results[0] > 0:
          keys = results[1:]
          for key in keys:
              valkey_client.delete(key)
          print(f"Invalidated {len(keys)} cached entries for '{topic_keyword}'")
  ```