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 critique qui sépare les applications LLM rentables des expériences qui drainent le budget.

Étant donné que les coûts d’API évoluent linéairement 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ées ajoutent une seconde facture liée aux jetons de complétion gaspillés lorsque l’échantillonnage est trop élevé ; paramètres d’inférence agentique pour Qwen et Gemma recueille les valeurs par défaut qui réduisent les nouvelles tentatives sans étouffer le raisonnement. Ces nouvelles tentatives deviennent coûteuses plus rapidement lorsque les boucles de réparation de la sortie structurée réécrivent l’intégralité des prompts — des schémas resserrés et des rejets de validation rapides aident, comme le montre la validation de la sortie structurée LLM en Python qui tient la route.

smart architecture

Comprendre l’économie des jetons

Avant d’optimiser, vous devez comprendre comment les jetons et la tarification fonctionnent chez les différents fournisseurs de LLM.

Bases des jetons

Les jetons sont les unités fondamentales traitées par les LLM - ils sont approximativement équivalents à 4 caractères ou 0,75 mot en anglais. La chaîne « Hello, world! » contient environ 4 jetons. Différents modèles utilisent différents tokenizers (GPT utilise tiktoken, Claude utilise le sien), donc les décomptes de jetons varient légèrement entre les fournisseurs.

Comparaison des modèles de tarification

Tarification OpenAI (en 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 exhaustive des Fournisseurs LLM cloud, y compris des détails sur la tarification, les fonctionnalités et les cas d’utilisation, consultez notre guide dédié.

Constat 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 démesuré sur les coûts.

Ingénierie de prompts pour l’efficacité

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

1. Éliminer la redondance

Exemple défavorable (127 jetons) :

Vous êtes un assistant utile. Veuillez m'aider avec la tâche suivante.
Je voudrais que vous analysiez le texte suivant et que vous me donniez
un résumé. Voici le texte que je voudrais 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

Les sorties JSON et structurées réduisent le gaspillage de jetons causé par le langage naturel verbeux.

Au lieu de :

Veuillez extraire le nom, l'âge et la profession de la 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 en :

  • Utilisant le minimum d’exemples nécessaires (1 à 3 sont généralement suffisants)
  • Gardant les exemples concis - supprimez les mots inutiles
  • Partageant des préfixes communs - réduisez les instructions répétées
# Prompt few-shot optimisé
prompt = """Classifiez le sentiment (pos/nég) :
Texte : "Excellent produit !" -> pos
Texte : "Déçu" -> nég
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 un contenu statique répété.

Fonctionnement de la mise en cache du contexte

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

Exigences :

  • Contenu mise en cache minimal : 1024 jetons (OpenAI) ou 2048 jetons (Anthropic)
  • TTL de la 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 requêtes
SYSTEM_PROMPT = """Vous êtes un IA de service client pour TechCorp.
Politiques de l'entreprise :
[Grand document de politique - 2000 jetons]
"""

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

# Les appels ultérieurs dans la TTL de la cache utilisent le prompt système mis en cache
# Payant uniquement pour le message utilisateur + sortie

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

Stratégie de sélection de modèles

L’utilisation du bon modèle pour chaque tâche est cruciale 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 - Tâches répétitives spécialisées

Modèle de routage

def route_request(task_complexity, user_query):
    """Routage vers le modèle approprié basé sur la complexité"""
    
    # Classification simple - utiliser Haiku
    if task_complexity == "simple":
        return call_llm("claude-3-haiku", user_query)
    
    # Modéré - utiliser Sonnet
    elif task_complexity == "moderate":
        return call_llm("claude-3-sonnet", user_query)
    
    # Raisonnement complexe - utiliser Opus
    else:
        return call_llm("claude-3-opus", user_query)

É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 urgentes, le traitement par lots offre des réductions de 50 % de la part de 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"requete-{i}", 
     "method": "POST",
     "url": "/v1/chat/completions",
     "body": {
         "model": "gpt-3.5-turbo",
         "messages": [{"role": "user", "content": query}]
     }}
    for i, query in enumerate(queries)
]

# Soumettre le lot (réduction 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

Étant donné que les jetons de sortie coûtent 2 à 5 fois plus cher, le contrôle de la longueur de la sortie est critique.

1. Définir le nombre maximum de jetons

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

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

response = client.chat.completions.create(
    model="gpt-4",
    messages=messages,
    stop=["END", "\n\n\n"]  # Arrêter 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 du JSON, sans explication »

Streaming pour une meilleure expérience utilisateur

Bien que le streaming ne réduise pas les coûts, il améliore les performances perçues et permet une terminaison anticipée.

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="")
        
        # Terminaison anticipée si la réponse déraile
        if undesired_pattern(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.

Modèle RAG efficace

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

Techniques d’optimisation :

  • Utiliser le découpage sémantique (pas de taille fixe)
  • Supprimer le formatage Markdown des chunks récupérés
  • Implémenter le ré-classement pour obtenir le contenu le plus pertinent
  • Envisager la résumination de chunks pour les gros documents

Mise en cache des réponses

Mettez en cache les requêtes identiques ou similaires pour éviter complètement les appels d’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 la 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 (pas identiques), utilisez des plongements vectoriels pour trouver des réponses mises en cache.

Surveillance et analyses

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} a 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 d’apprentissage compressés

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

2. Décodage spéculatif

Faites fonctionner un petit modèle avec un grand modèle pour prédire les jetons, réduisant les appels au grand modèle. Généralement, 2 à 3 fois plus rapide et réduction des coûts pour une qualité similaire.

3. Quantification

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

  • 4 bits : ~75 % de réduction de la mémoire, perte de qualité minime
  • 8 bits : ~50 % de réduction de la 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 la sélection 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 de matériel exécutant de grands modèles quantifiés.

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

  • Profiler l’utilisation actuelle des jetons et les coûts par point d’accès
  • Auditer les prompts pour la redondance - 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 requêtes
  • 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 l’entraînement fin (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 de prompts : réduction de 40 %
  • Mise en cache des réponses : taux de cache hit de 15 %

Résultats :

  • 85 % des requêtes ont évité GPT-4
  • 70 % bénéficient de la réduction de la mise en cache du 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’une dépense prohibitivement coûteuse à une scalabilité durablement viable. En mettant en œuvre la compression de prompts, la mise en cache du contexte, une sélection intelligente des modèles et la mise en cache des réponses, la plupart des applications atteignent une réduction des coûts de 60 à 80 % sans compromis sur 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 votre utilisation des jetons religieusement - ce qui est mesuré est optimisé. La différence entre une application LLM rentable et une application LLM coûteuse n’est pas la technologie, c’est la stratégie d’optimisation.

Articles liés

S'abonner

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