Un cache sémantique répond à « comment réinitialiser mon mot de passe » avec la réponse déjà générée pour « j'ai oublié mon identifiant », parce que les deux veulent dire la même chose. Au lieu de faire correspondre la chaîne exacte d'une requête, il transforme la requête en embedding et cherche une requête stockée dont l'embedding est assez proche, puis renvoie cette réponse en cache sans appeler le modèle. Quand ça marche, vous économisez un appel de modèle en entier : aucun token, aucune latence, aucun coût. Quand il se trompe sur « assez proche », il sert une réponse pleine d'assurance à une question que l'utilisateur n'a pas posée.

Le recadrage central : un cache normal indexe sur l'identité, un cache sémantique indexe sur la similarité, et la similarité est un seuil que vous fixez, pas un fait. Ce seuil est toute la surface de risque. Réglez-le trop lâche et vous servez de mauvaises réponses ; réglez-le trop serré et vous ne mettez presque rien en cache. Tout ce qui compte pour bien exploiter un cache sémantique se résume à gérer ce curseur.

Comment ça marche, sans la magie

Le mécanisme tient en trois étapes. Transformer la requête entrante en vecteur avec un modèle d'embeddings tel qu'Amazon Titan Text Embeddings ou Cohere sur Bedrock. Chercher dans un vector store la requête déjà vue la plus proche. Si la similarité cosinus du plus proche voisin dépasse votre seuil, renvoyer sa réponse en cache ; sinon, appeler le modèle, puis stocker le nouvel embedding de requête et sa réponse pour la prochaine fois.

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

Le vector store peut être n'importe quoi que vous exploitez déjà : OpenSearch, Aurora avec pgvector, ou un index en mémoire pour un petit ensemble chaud. La partie difficile n'est jamais le stockage. C'est la valeur de THRESHOLD et ce que vous laissez entrer dans le cache en premier lieu.

Le risque de faux hit, c'est tout le jeu

Un faux hit, c'est quand deux requêtes sont proches dans l'espace des embeddings mais devraient avoir des réponses différentes. « Quelle est notre politique de remboursement pour les clients de l'UE » et « quelle est notre politique de remboursement pour les clients américains » peuvent se trouver dangereusement proches l'une de l'autre dans l'espace vectoriel tout en exigeant des réponses différentes. Un seuil lâche renvoie la réponse UE à un utilisateur américain, et le fait avec une confiance totale, parce que le modèle n'a jamais été consulté.

C'est pire qu'un cache miss normal, qui ne vous coûte qu'un appel de modèle. Un faux hit vous coûte une mauvaise réponse qui a l'air correcte. Le seuil doit donc être ajusté sur du trafic réel, pas deviné, et il devrait être biaisé vers la rigueur : un miss est bon marché, un faux hit peut devenir un ticket de support ou un problème de conformité. Mesurez le taux de faux hit sur un échantillon étiqueté avant de confier au cache quoi que ce soit qui compte.

Ce qu'il ne faut pas mettre en cache

Le cache sémantique convient à la connaissance stable, générale et partagée, et à rien d'autre. Mettez en cache la réponse à « comment exporter mes données », qui est la même pour tout le monde. Ne mettez pas en cache ce qui dépend de qui pose la question ou de quand. Quelques règles à faire respecter dans le code :

  • Ne jamais mettre en cache à travers les frontières d'identité. Indexez le cache par tenant, ou excluez tout ce qui est personnalisé. Un cache partagé qui ignore l'appelant finira par servir la réponse d'un client à un autre.
  • Ne jamais mettre en cache des réponses sensibles au temps. Les soldes, le statut de commande et l'inventaire changent sous vos pieds. Un hit périmé ici est un bug tout neuf.
  • Mettez en cache ce qui n'exige pas de récupération, pas ce qui en exige beaucoup. Si la réponse dépend de documents qui changent, mettez en cache la recherche d'embedding, pas la réponse finale.

L'invalidation est la partie que tout le monde saute

La plus vieille blague de l'informatique, c'est que l'invalidation de cache est l'un des deux problèmes difficiles, et un cache sémantique n'a pas d'exemption. Quand la vérité sous-jacente change, quand une politique est mise à jour, qu'un prix bouge, qu'un document est révisé, chaque réponse en cache qui s'appuyait sur l'ancienne vérité devient fausse et continuera d'être servie jusqu'à ce que vous l'évinciez.

Donnez aux entrées une durée de vie assez courte pour que les réponses périmées s'éteignent d'elles-mêmes, et ajoutez un chemin de purge explicite lié aux événements qui changent la vérité de terrain : publier une nouvelle version de politique devrait invalider la tranche de cache construite sur l'ancienne. Sans histoire d'invalidation, un cache sémantique ne fait pas qu'économiser des appels, il ancre discrètement votre produit dans les faits d'hier.

À retenir

Le cache sémantique est un vrai gain de coût et de latence pour les questions qui sont la même question formulée autrement, et c'est un piège pour tout ce qui est personnalisé, sensible au temps ou sujet à changement. Le mécanisme est trivial : embedder, chercher, seuiller. L'ingénierie est entièrement dans le seuil, les règles de périmètre et le chemin d'invalidation. Ajustez le seuil sur du trafic étiqueté, ne mettez en cache que la connaissance stable et partagée, et invalidez sur les événements qui font bouger la vérité. Faites ces trois choses et le cache se rembourse lui-même. Sautez-les et il sert de mauvaises réponses plus vite que le modèle n'aurait pu servir de bonnes.

À lire ensuite

Pour le côté plateforme de l'exploitation d'un vector store et de son éviction sous charge, les notes de terrain cloud vivent sur ercan.cloud, et le hub est sur ercanermis.com.