

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Bonnes pratiques
<a name="semantic-caching-best-practices"></a>

## Choix des données pouvant être mises en cache
<a name="semantic-caching-bp-choosing-data"></a>

La mise en cache sémantique convient parfaitement aux requêtes répétées dont les réponses sont relativement stables, tandis que les réponses en temps réel ou très dynamiques sont souvent de mauvais candidats pour la mise en cache.

Utilisez des filtres numériques et de balises dérivés du contexte d'application existant (tel que l'identifiant du produit, la catégorie, la région ou le segment d'utilisateur) pour déterminer quelles requêtes et réponses peuvent être mises en cache et pour améliorer la pertinence des accès au cache.

## Réglage du seuil de similarité
<a name="semantic-caching-bp-threshold"></a>

Le seuil de similarité contrôle le compromis entre le taux de réussite du cache et la qualité des réponses. Choisissez un seuil qui équilibre les économies de coûts avec la précision pour votre cas d'utilisation :


| Threshold | Taux de réussite | Risque de qualité | Idéal pour | 
| --- | --- | --- | --- | 
| 0,95 (strict) | Faible (\~ 25 %) | Très faible | Applications médicales, juridiques et financières | 
| 0,90 (modéré) | Moyen (\~ 55 %) | Faible | Chatbots généraux | 
| 0,80 (équilibré) | Élevé (\~ 75 %) | Faible à moyen | FAQ, bots, support informatique | 
| 0,75 (détendu) | Très élevé (\~ 90 %) | Moyenne | High-volume requêtes répétitives | 

**Important**  
Commencez par un seuil plus élevé (0,90 à 0,95), puis abaissez-le progressivement tout en contrôlant la précision. Utilisez A/B les tests pour trouver l'équilibre optimal en fonction de votre charge de travail.

## Requêtes autonomes par rapport aux conversations
<a name="semantic-caching-bp-standalone-vs-conversations"></a>
+ **Pour les requêtes autonomes** : appliquez la mise en cache sémantique directement sur le texte de la requête utilisateur.
+ **Pour les conversations à plusieurs tours** : utilisez d'abord la mémoire de votre conversation pour récupérer les informations clés et les messages récents nécessaires pour répondre au tour actuel. Appliquez ensuite la mise en cache sémantique à la combinaison du message utilisateur actuel et du contexte récupéré, au lieu d'intégrer l'intégralité du dialogue brut.

## Définition des périodes d'invalidation du cache
<a name="semantic-caching-bp-ttl"></a>

Utilisez TTL pour contrôler la durée pendant laquelle les réponses mises en cache sont servies avant qu'elles ne soient régénérées en cas d'échec du cache.


| Type de données | TTL recommandé | Justification | 
| --- | --- | --- | 
| Faits statiques (documentation, politiques) | 24 heures | Les faits changent rarement | 
| Informations sur le produit | 12 à 24 heures | Mis à jour quotidiennement dans la plupart des catalogues | 
| Réponses de l'assistant général | 1 à 4 heures | Trouvez l'équilibre entre fraîcheur et taux de réussite | 
| Real-time données (prix, inventaire) | 5 à 15 minutes | Les données changent fréquemment | 
| Contexte de conversation | 30 minutes | Session-scoped, de courte durée | 

```
# 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)
```

**Astuce**  
Définissez des TTL qui correspondent au cas d'utilisation de votre application et à la fréquence à laquelle vos données ou vos sorties de modèle changent. Des TTL plus longs augmentent les taux de réussite du cache, mais augmentent le risque de réponses obsolètes. Des TTL plus courts permettent de rafraîchir les réponses, mais réduisent les taux de réussite du cache et nécessitent davantage d'inférences LLM.

## Surveillance et suivi des coûts
<a name="semantic-caching-bp-monitoring"></a>

Suivez les indicateurs de performance du cache pour optimiser votre cache sémantique au fil du temps :

```
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),
    }
```

## Gestion de mémoire
<a name="semantic-caching-bp-memory"></a>
+ **Définissez la politique de mémoire maximale** : configurez `maxmemory-policy allkeys-lru` votre ElastiCache cluster pour expulser automatiquement les entrées de cache les moins récemment utilisées lorsque le cluster atteint sa limite de mémoire.
+ **Planification de la capacité** : chaque entrée de cache nécessite généralement environ 4 à 6 Ko (dimensions d'intégration × 4 octets \+ texte de requête \+ texte de réponse). Une ElastiCache instance de 1 Go peut stocker environ 170 000 entrées mises en cache.
+ **Utiliser l'invalidation du cache pour les données périmées : lorsque les données** sous-jacentes changent, utilisez la recherche textuelle pour trouver et invalider les entrées de cache associées :

  ```
  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}'")
  ```