Réduire les coûts des LLM : stratégies d'optimisation des jetons

Réduisez les coûts des LLM de 80 % grâce à une optimisation intelligente des tokens

Sommaire

L’optimisation des jetons est la compétence clé qui distingue les applications LLM rentables des expériences qui vident les budgets.

Les coûts des API évoluant de manière linéaire avec l’utilisation des jetons, la compréhension et la mise en œuvre de stratégies d’optimisation peuvent réduire les dépenses de 60 à 80 % tout en maintenant la qualité.

Les boucles d’agents auto-hébergés ajoutent une deuxième facture de jetons de complétion gaspillés lorsque l’échantillonnage est trop « chaud » ; les paramètres d’inférence agencique pour Qwen et Gemma recueillent les valeurs par défaut qui limitent les tentatives sans priver le raisonnement.

architecture intelligente

Comprendre l’économie des jetons

Avant d’optimiser, il est nécessaire de comprendre comment fonctionnent les jetons et la tarification auprès des différents fournisseurs de LLM.

Les bases des jetons

Les jetons sont les unités fondamentales que les LLM traitent - approximativement équivalent à 4 caractères ou 0,75 mot en anglais. La chaîne “Hello, world!” contient environ 4 jetons. Les différents modèles utilisent des tokenizers différents (GPT utilise tiktoken, Claude utilise le sien propre), donc les comptes de jetons varient légèrement entre les fournisseurs.

Comparaison des modèles de tarification

Tarification OpenAI (au 2025) :

  • GPT-4 Turbo : 0,01 $ en entrée / 0,03 $ en sortie par 1K jetons
  • GPT-3.5 Turbo : 0,0005 $ en entrée / 0,0015 $ en sortie par 1K jetons
  • GPT-4o : 0,005 $ en entrée / 0,015 $ en sortie par 1K jetons

Tarification Anthropic :

  • Claude 3 Opus : 0,015 $ en entrée / 0,075 $ en sortie par 1K jetons
  • Claude 3 Sonnet : 0,003 $ en entrée / 0,015 $ en sortie par 1K jetons
  • Claude 3 Haiku : 0,00025 $ en entrée / 0,00125 $ en sortie par 1K jetons

Pour une comparaison complète des Fournisseurs de LLM Cloud incluant les tarifs détaillés, les fonctionnalités et les cas d’utilisation, consultez notre guide dédié.

Point clé : Les jetons de sortie coûtent 2 à 5 fois plus cher que les jetons d’entrée. Limiter la longueur de la sortie a un impact disproportionné sur les coûts.

Ingénierie des prompts pour l’efficacité

Une ingénierie des prompts efficace réduit considérablement la consommation de jetons sans sacrifier la qualité.

1. Éliminer les redondances

Mauvais exemple (127 jetons) :

Vous êtes un assistant utile. Veuillez m'aider avec la tâche suivante.
J'aimerais que vous analysiez le texte suivant et me fournissiez
un résumé. Voici le texte que je souhaite que vous résumiez :
[texte]
Veuillez fournir un résumé concis des points principaux.

Optimisé (38 jetons) :

Résumez les points clés :
[texte]

Économies : Réduction de 70 % des jetons, qualité de sortie identique.

2. Utiliser des formats structurés

JSON et les sorties structurées réduisent le gaspillage de jetons dû au langage naturel verbeux.

Au lieu de :

Veuillez extraire le nom, l'âge et la profession de cette personne de ce texte
et formater votre réponse clairement.

Utilisez :

Extraire en JSON : {nom, âge, profession}
Texte : [entrée]

3. Optimisation de l’apprentissage par exemples (Few-Shot)

Les exemples few-shot sont puissants mais coûteux. Optimisez-les en :

  • Utilisant le minimum d’exemples nécessaire (1 à 3 suffisent généralement)
  • En gardant les exemples concis - supprimez les mots inutiles
  • En partageant des préfixes communs - réduisez les instructions répétées
# Prompt few-shot optimisé
prompt = """Classifiez le sentiment (pos/neg) :
Texte : "Super produit !" -> pos
Texte : "Déçu" -> neg
Texte : "{user_input}" ->"""

Pour plus de modèles d’optimisation Python et de raccourcis syntaxiques, consultez notre Aide-mémoire Python.

Stratégies de mise en cache du contexte

La mise en cache du contexte est l’optimisation la plus efficace pour les applications avec du contenu statique répété.

Comment fonctionne la mise en cache du contexte

Les fournisseurs comme OpenAI et Anthropic mettent en cache les préfixes de prompt qui apparaissent dans plusieurs demandes. Les portions mises en cache coûtent 50 à 90 % de moins que les jetons réguliers.

Exigences :

  • Contenu minimum mise en cache : 1024 jetons (OpenAI) ou 2048 jetons (Anthropic)
  • TTL du cache : 5 à 60 minutes selon le fournisseur
  • Le contenu doit être identique et apparaître au début du prompt

Exemple d’implémentation

from openai import OpenAI

client = OpenAI()

# Message système mis en cache entre les demandes
SYSTEM_PROMPT = """Vous êtes une IA de service client pour TechCorp.
Politiques de l'entreprise :
[Document politique volumineux - 2000 jetons]
"""

# Cela est automatiquement mis en cache
response = client.chat.completions.create(
    model="gpt-4-turbo",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": "Comment retourner un article ?"}
    ]
)

# Les appels suivants dans la fenêtre TTL utilisent le prompt système mis en cache
# Ne payant que pour le message utilisateur + sortie

Impact réel : Les applications avec des bases de connaissances ou des instructions longues voient une réduction de coûts de 60 à 80 %.

Stratégie de sélection du modèle

Utiliser le bon modèle pour chaque tâche est crucial pour l’optimisation des coûts.

L’échelle des modèles

  1. GPT-4 / Claude Opus - Raisonnement complexe, tâches créatives, précision critique
  2. GPT-4o / Claude Sonnet - Équilibre performance/coût, usage général
  3. GPT-3.5 / Claude Haiku - Tâches simples, classification, extraction
  4. Modèles plus petits affinés (fine-tuned) - Tâches répétitives spécialisées

Motif de routage

def route_request(complexite_tache, requete_utilisateur):
    """Route vers le modèle approprié en fonction de la complexité"""
    
    # Classification simple - utiliser Haiku
    if complexite_tache == "simple":
        return call_llm("claude-3-haiku", requete_utilisateur)
    
    # Modéré - utiliser Sonnet
    elif complexite_tache == "modéré":
        return call_llm("claude-3-sonnet", requete_utilisateur)
    
    # Raisonnement complexe - utiliser Opus
    else:
        return call_llm("claude-3-opus", requete_utilisateur)

Étude de cas : Un chatbot de service client routant 80 % des requêtes vers GPT-3.5 et 20 % vers GPT-4 a réduit les coûts de 75 % par rapport à l’utilisation de GPT-4 pour tout.

Traitement par lots

Pour les charges de travail non sensibles au temps, le traitement par lots offre des remises de 50 % chez la plupart des fournisseurs.

API par lots OpenAI

from openai import OpenAI
client = OpenAI()

# Créer le fichier par lots
batch_requests = [
    {"custom_id": f"demande-{i}", 
     "method": "POST",
     "url": "/v1/chat/completions",
     "body": {
         "model": "gpt-3.5-turbo",
         "messages": [{"role": "user", "content": requete}]
     }}
    for i, requete in enumerate(requetes)
]

# Soumettre le lot (remise de 50 %, traitement de 24h)
batch = client.batches.create(
    input_file_id=upload_batch_file(batch_requests),
    endpoint="/v1/chat/completions",
    completion_window="24h"
)

Cas d’utilisation :

  • Étiquetage et annotation de données
  • Génération de contenu pour blogs/SEO
  • Génération de rapports
  • Traductions par lots
  • Génération synthétique de jeux de données

Techniques de contrôle de la sortie

Les jetons de sortie coûtant 2 à 5 fois plus cher, le contrôle de la longueur de la sortie est critique.

1. Définir les jetons maximum

response = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    max_tokens=150  # Limite stricte empêche les coûts incontrôlés
)

2. Utiliser des séquences d’arrêt

response = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    stop=["FIN", "\n\n\n"]  # Arrêt aux marqueurs
)

3. Demander des formats concis

Ajoutez des instructions comme :

  • “Répondez en moins de 50 mots”
  • “Fournissez uniquement des points clés”
  • “Retournez uniquement JSON, sans explication”

Diffusion en continu (Streaming) pour une meilleure UX

Bien que le streaming ne réduise pas les coûts, il améliore la performance perçue et permet l’arrêt anticipé.

stream = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    stream=True
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        token = chunk.choices[0].delta.content
        print(token, end="")
        
        # Arrêt anticipé si la réponse s'écarte
        if motif_indésirable(token):
            break

Optimisation RAG

La Génération Augmentée par Récupération (RAG) ajoute du contexte, mais un RAG non optimisé gaspille des jetons.

Motif RAG efficace

def optimized_rag(requete, vector_db):
    # 1. Récupérer les chunks pertinents
    chunks = vector_db.search(requete, top_k=3)  # Pas trop nombreux
    
    # 2. Compresser les chunks - supprimer les redondances
    compressé = compress_chunks(chunks)  # Compression personnalisée
    
    # 3. Tronquer à la limite de jetons
    contexte = truncate_to_tokens(compressé, max_tokens=2000)
    
    # 4. Prompt structuré
    prompt = f"Contexte :\n{contexte}\n\nQ : {requete}\nR :"
    
    return call_llm(prompt)

Techniques d’optimisation :

  • Utiliser le chunking sémantique (pas de taille fixe)
  • Supprimer le formatage Markdown des chunks récupérés
  • Implémenter le re-ranking pour obtenir le contenu le plus pertinent
  • Envisager la summarisation des chunks pour les grands documents

Mise en cache des réponses

Mettre en cache les demandes identiques ou similaires pour éviter complètement les appels API.

Implémentation avec Redis

import redis
import hashlib
import json

redis_client = redis.Redis()

def cached_llm_call(prompt, model="gpt-4", ttl=3600):
    # Créer la clé de cache à partir du prompt + modèle
    cache_key = hashlib.md5(
        f"{model}:{prompt}".encode()
    ).hexdigest()
    
    # Vérifier le cache
    cached = redis_client.get(cache_key)
    if cached:
        return json.loads(cached)
    
    # Appeler le LLM
    response = call_llm(model, prompt)
    
    # Mettre le résultat en cache
    redis_client.setex(
        cache_key, 
        ttl, 
        json.dumps(response)
    )
    
    return response

Mise en cache sémantique : Pour les requêtes similaires (non identiques), utilisez les embeddings vectoriels pour trouver les réponses mises en cache.

Surveillance et analytique

Suivez l’utilisation des jetons pour identifier les opportunités d’optimisation.

Métriques essentielles

class TokenTracker:
    def __init__(self):
        self.metrics = {
            'total_tokens': 0,
            'input_tokens': 0,
            'output_tokens': 0,
            'cost': 0.0,
            'requests': 0
        }
    
    def track_request(self, response, model):
        usage = response.usage
        self.metrics['input_tokens'] += usage.prompt_tokens
        self.metrics['output_tokens'] += usage.completion_tokens
        self.metrics['total_tokens'] += usage.total_tokens
        self.metrics['cost'] += calculate_cost(usage, model)
        self.metrics['requests'] += 1
    
    def report(self):
        return {
            'avg_tokens_per_request': 
                self.metrics['total_tokens'] / self.metrics['requests'],
            'total_cost': self.metrics['cost'],
            'input_output_ratio': 
                self.metrics['input_tokens'] / self.metrics['output_tokens']
        }

Alertes de coûts

Configurez des alertes lorsque l’utilisation dépasse les seuils :

def check_cost_threshold(daily_cost, threshold=100):
    if daily_cost > threshold:
        send_alert(f"Coût quotidien ${daily_cost} dépassé ${threshold}")

Techniques avancées

1. Modèles de compression de prompts

Utilisez des modèles dédiés pour compresser les prompts :

  • LongLLMLingua
  • AutoCompressors
  • Jetons de compression appris

Ces outils peuvent atteindre des ratios de compression de 10x tout en maintenant une performance de tâche de 90 %+.

2. Décodage spéculatif

Exécutez un petit modèle en parallèle d’un grand modèle pour prédire les jetons, réduisant les appels au grand modèle. Généralement une accélération de 2 à 3x et une réduction des coûts pour une qualité similaire.

3. Quantification

Pour les modèles auto-hébergés, la quantification (4-bit, 8-bit) réduit la mémoire et le calcul :

  • 4-bit : ~75 % de réduction de mémoire, perte de qualité minime
  • 8-bit : ~50 % de réduction de mémoire, perte de qualité négligeable

Si vous exécutez des LLM localement, Ollama fournit une excellente plateforme pour déployer des modèles quantifiés avec une configuration minimale. Pour le choix du matériel et les benchmarks de performance, notre comparaison NVIDIA DGX Spark vs Mac Studio vs RTX-4080 montre les performances réelles sur différentes configurations matérielles exécutant de grands modèles quantifiés.

Liste de contrôle d’optimisation des coûts

  • Analyser l’utilisation actuelle des jetons et les coûts par point de terminaison
  • Auditer les prompts pour les redondances - supprimer les mots inutiles
  • Implémenter la mise en cache du contexte pour le contenu statique > 1K jetons
  • Configurer le routage des modèles (petit pour simple, grand pour complexe)
  • Ajouter des limites max_tokens à toutes les demandes
  • Implémenter la mise en cache des réponses pour les requêtes identiques
  • Utiliser l’API par lots pour les charges de travail non urgentes
  • Activer le streaming pour une meilleure UX
  • Optimiser le RAG : moins de chunks, meilleur classement
  • Surveiller avec le suivi des jetons et les alertes de coûts
  • Envisager le fine-tuning pour les tâches répétitives
  • Évaluer les modèles plus petits (Haiku, GPT-3.5) pour la classification

Étude de cas réelle

Scénario : Chatbot de support client, 100K requêtes/mois

Avant l’optimisation :

  • Modèle : GPT-4 pour toutes les requêtes
  • Jetons d’entrée moyens : 800
  • Jetons de sortie moyens : 300
  • Coût : 100K × (800 × 0,00003 + 300 × 0,00006) = 4 200 $/mois

Après l’optimisation :

  • Routage des modèles : 80 % GPT-3.5, 20 % GPT-4
  • Mise en cache du contexte : 70 % des prompts mis en cache
  • Compression des prompts : réduction de 40 %
  • Mise en cache des réponses : taux de hit de 15 %

Résultats :

  • 85 % des requêtes ont évité GPT-4
  • 70 % bénéficient de la remise du cache de contexte
  • 40 % de jetons d’entrée en moins
  • Coût effectif : 780 $/mois
  • Économies : 81 % (3 420 $/mois)

Liens utiles

Conclusion

L’optimisation des jetons transforme l’économie des LLM d’un coût prohibitif à un scaling durable. En implémentant la compression des prompts, la mise en cache du contexte, la sélection intelligente des modèles et la mise en cache des réponses, la plupart des applications atteignent une réduction de coûts de 60 à 80 % sans compromettre la qualité.

Commencez par les gains rapides : auditez vos prompts, activez la mise en cache du contexte et routez les tâches simples vers des modèles plus petits. Surveillez religieusement votre utilisation des jetons - ce qui est mesuré est optimisé. La différence entre une application LLM rentable et une coûteuse n’est pas la technologie—c’est la stratégie d’optimisation.

Articles connexes

S'abonner

Recevez de nouveaux articles sur les systèmes, l'infrastructure et l'ingénierie IA.