Redis : cache les réponses de ton LLM et arrête de payer deux fois

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom": "redis", "version": "8.1.0"}

Difficulté

Intermédiaire

Chaque appel à un grand modèle de langage coûte du temps et de l'argent. Deux secondes de latence, quelques dixièmes de centime, et ça s'additionne dès que ton app gagne des utilisateurs. Le pire ? Quand deux personnes posent la même question, tu paies deux fois pour la même réponse. Redis règle ce gaspillage en une ligne : une base de données en mémoire qui se souvient des réponses à ta place.

Redis est un cache ultra-rapide. Là où un LLM met une à deux secondes à répondre, un GET Redis prend moins d'une milliseconde. On va s'en servir pour stocker les couples question-réponse, avec une date d'expiration pour ne jamais servir de l'information périmée. À la clé : une API plus rapide et une facture qui arrête de grimper.

1. Installer Redis et son client Python

Le plus simple est Docker. Une commande, et Redis tourne en arrière-plan :

bash
docker run --name redis -p 6379:6379 -d redis

Sans Docker, installe-le directement puis démarre-le :

bash
sudo apt install redis-server   # Debian / Ubuntu
sudo pacman -S redis            # Arch / CachyOS
redis-server

Enfin, le client Python :

bash
pip install redis

2. Se connecter à Redis depuis Python

On crée un client avec decode_responses=True, pour récupérer des chaînes de caractères plutôt que des octets. Premier réflexe : vérifier que le serveur répond.

python
import redis

r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r.ping()          # True si Redis tourne

r.set("prenom", "Ada")
print(r.get("prenom"))   # Ada

3. Un appel LLM, version naïve

Voici une fonction call_llm volontairement factice : elle dort une seconde et demie pour simuler la latence d'un modèle. Remplace son corps par ton vrai appel (OpenAI, Mistral, Ollama en local), le principe du cache ne change pas.

python
import time

def call_llm(prompt: str) -> str:
    # Remplace par ton vrai appel, par exemple :
    #   from openai import OpenAI
    #   client = OpenAI()
    #   return client.chat.completions.create(
    #       model="gpt-4o",
    #       messages=[{"role": "user", "content": prompt}],
    #   ).choices[0].message.content
    time.sleep(1.5)
    return f"Réponse à : {prompt}"

4. Une clé de cache déterministe

Deux prompts identiques doivent produire la même clé, et deux prompts différents deux clés différentes. On normalise (minuscules, espaces en trop retirés) puis on hache en SHA-256. On glisse le nom du modèle dans la clé : changer de modèle invalide automatiquement les anciennes réponses.

python
import hashlib

def cache_key(prompt: str, model: str = "gpt-4o") -> str:
    digest = hashlib.sha256(prompt.strip().lower().encode()).hexdigest()
    return f"llm:{model}:{digest}"

5. La fonction qui change tout

Le cœur du tutoriel tient en dix lignes. On regarde d'abord dans le cache. Si la réponse y est, on la renvoie sans appeler le modèle. Sinon, on appelle, on stocke avec une durée de vie (ex=ttl), puis on renvoie.

python
def llm(prompt: str, ttl: int = 3600) -> str:
    key = cache_key(prompt)
    hit = r.get(key)
    if hit is not None:
        print("cache HIT — réponse instantanée")
        return hit
    print("cache MISS — appel du modèle")
    answer = call_llm(prompt)
    r.set(key, answer, ex=ttl)   # ex = durée de vie en secondes
    return answer

Teste le résultat. Le premier appel paie le modèle, le second est servi par la mémoire :

python
print(llm("Quelle est la capitale de la France ?"))   # MISS, ~1,5 s
print(llm("Quelle est la capitale de la France ?"))   # HIT,  < 1 ms

6. Les trois règles pour ne pas en abuser

Le cache n'est pas magique, et mal utilisé il sert des réponses fausses. Trois garde-fous :

D'abord, ne cache jamais une réponse non déterministe. Un modèle avec une température élevée, ou une réponse qui dépend de l'heure, du contexte utilisateur ou d'un tirage aléatoire, ne doit pas être mis en cache : tu servirais la même réponse à deux questions qui n'attendent pas la même chose.

Ensuite, choisis un TTL adapté. Une FAQ d'entreprise peut rester plusieurs jours. Une info d'actualité, quelques minutes. Le bon réglage, c'est la durée pendant laquelle la réponse reste vraie.

Enfin, sache invalider. r.delete(cache_key(prompt)) supprime une entrée précise ; r.flushdb() vide tout le cache, à réserver au développement.

python
r.delete(cache_key("Quelle est la capitale de la France ?"))
# Ou tout vider (radical, uniquement en dev) :
# r.flushdb()

Conclusion

Redis est l'un des ajouts les plus rentables à une stack IA. Une vingtaine de lignes, et tes appels répétitifs deviennent des lectures mémoire quasi gratuites : ton API répond plus vite, et ta facture arrête de gonfler à chaque redite. Bonus : comme le cache est décorrélé du modèle, tu gardes le même code en passant d'OpenAI à Ollama. La prochaine étape naturelle, c'est le cache sémantique, qui sert une réponse « assez proche » en comparant les embeddings plutôt que les mots — mais ça, c'est une autre histoire.

K

Auteur

Krugz

Développeur fullstack

Développeur fullstack qui tente, tant bien que mal, de suivre l'actualité de l'IA au milieu d'une marée d'informations imbuvables et des milliers d'outils et de modèles qui sortent chaque jour.