Architecture des systèmes d'IA

Vous avez exécuté une démo d’un grand modèle sur votre ordinateur portable et elle fonctionne bien, mais lorsque vous voulez en faire un véritable produit, des problèmes apparaissent :

  • Le modèle a trop de paramètres pour tenir sur un seul GPU. Que faites-vous ?

  • L’entraînement prend des semaines ; si une panne survient en cours de route, comment reprendre l’entraînement à partir d’un checkpoint ?

  • Avec des millions de requêtes utilisateur par jour, comment garantir une latence inférieure à 1 seconde ?

  • Comment collecter les retours des utilisateurs pour permettre au modèle d’évoluer en continu ?

Voilà les problèmes que l’architecture des systèmes d’IA doit résoudre.

Une démo se concentre sur sa capacité à fonctionner ; un système de production se concentre sur sa capacité à fonctionner de manière stable, efficace et à faible coût.

Caractéristiques des systèmes d’IA de niveau production : disponibilité 7x24, prise en charge de millions de requêtes simultanées, observabilité, scalabilité, reprise après sinistre fiable et coût maîtrisable.


Défis particuliers des systèmes d’IA

Par rapport aux services web traditionnels, les systèmes d’IA présentent trois défis uniques.

Défi 1 : sortie incertaine

La sortie des systèmes traditionnels est déterministe — vous saisissez 1+1, et il renvoie toujours 2.

La sortie des systèmes d’IA est probabiliste — le même prompt peut produire des résultats différents à chaque fois.

Cela pose plusieurs problèmes : comment garantir la qualité de la sortie ? comment évaluer les résultats ? comment gérer les hallucinations ?

Solutions typiques : ajouter des stratégies d'échantillonnage au niveau de la couche de sortie, un filtrage post-traitement des résultats, une boucle fermée pour le retour humain, et un vote multi-modèles.

Défi 2 : Compromis entre latence et coût

L'inférence IA nécessite beaucoup de calcul, ce qui implique une contradiction naturelle entre latence et coût.

Vous voulez de la vitesse ? Utilisez plus de GPU, les coûts grimpent.

Vous voulez économiser de l'argent ? Mettez les traitements en file d'attente, mauvaise expérience utilisateur.

Le cœur d'un système de production est de trouver un équilibre entre SLA (Service Level Agreement) et coût.

Direction de l'optimisationTechniques courantesEffet
Compression de modèleQuantification, élagage, distillationAccélération 2-4x, légère perte de précision
Optimisation de l'inférencevLLM, TensorRT, FlashAttentionAmélioration du débit de 3-10x
Conception de l'architectureTraitement par lots, mise en cache multi-niveauxCoût unitaire par requête réduit de 50%-80%

Défi 3 : Construire le volant de données

Un système d'IA n'est pas "terminé une fois lancé" ; il nécessite une itération continue.

Plus les utilisateurs l'utilisent, plus il y a de données de retour, mieux le modèle peut être entraîné, et plus les utilisateurs sont enclins à l'utiliser — c'est le volant de données.

Mais faire tourner le volant n'est pas facile : comment collecter des retours efficaces ? Comment étiqueter les données ? Comment poursuivre l'entraînement ? Comment évaluer les nouvelles versions ?

Il n'y a pas de réponses standard à ces questions, mais chaque produit d'IA à succès a sa propre conception de volant de données.


Infrastructure d'entraînement à grande échelle

L'entraînement de grands modèles avec des centaines de milliards, voire des milliers de milliards, de paramètres nécessite une infrastructure de supercalcul.

Architecture de cluster GPU

Les clusters modernes d'entraînement IA se composent généralement de centaines ou de milliers de GPU.

En prenant le GPU H100 comme exemple, un seul H100 dispose de 80GB de mémoire, avec une puissance de calcul de 1979 TFLOPS en précision FP8.

Mais un seul GPU est loin de suffire — l'entraînement de GPT-3 a utilisé environ 355 V100 et a pris 3 mois.

Une topologie de cluster typique est :

NiveauAppareilMéthode de connexionBande passante
Au sein d'une même machineGPU-GPUNVLink900GB/s
Même rackServeur à serveurInfiniBand400Gb/s
Inter-rackCommutateur à commutateurFabric InfiniBand400Gb/s

Le réseau est le goulot d'étranglement pour l'entraînement distribué. Si la bande passante de communication est insuffisante, l'utilisation du GPU peut chuter de 90% à 30%, la majeure partie du temps étant passée à attendre les données.

Interconnexion haut débit InfiniBand

L'Ethernet ordinaire est trop lent ; l'entraînement distribué utilise InfiniBand.

Caractéristiques d'InfiniBand : latence extrêmement faible (niveau microseconde), bande passante extrêmement élevée et prise en charge de RDMA (accès direct à la mémoire à distance).

RDMA permet à un GPU de lire et d'écrire directement dans la mémoire GPU d'un autre serveur sans passer par le noyau du système d'exploitation, ce qui le rend beaucoup plus rapide.

Conception du système de stockage

Les données d’entraînement se situent généralement à l’échelle du TB, voire du PB, de sorte que le système de stockage nécessite également une conception soignée.

Une architecture de stockage à plusieurs niveaux typique :

  • Données chaudes: SSD ou NVMe, stockant le lot d’entraînement actuel
  • Données tièdes: stockage distribué (par ex. Ceph, Lustre), stockant l’ensemble complet d’entraînement
  • Données froides: stockage objet (par ex. S3), stockant les données historiques et les sauvegardes

Tolérance aux pannes et points de contrôle

Un entraînement dure des semaines—que se passe-t-il si un GPU tombe en panne pendant ce temps ? Recommencer à zéro est trop coûteux.

La solution estle checkpointing—sauvegarder périodiquement l’état du modèle sur disque, et récupérer à partir du point de contrôle le plus récent si une erreur se produit.

Mais les points de contrôle ont aussi un coût : une sauvegarde peut prendre plusieurs minutes et occuper des dizaines de GB d’espace.

La stratégie habituelle est la suivante : sauvegarder toutes les quelques centaines d’étapes, conserver les points de contrôle les plus récents et nettoyer automatiquement les anciens.


Stratégies d’entraînement distribué

Un seul GPU ne peut pas accueillir un grand modèle, la tâche d’entraînement doit donc être répartie sur plusieurs GPU.

Il existe principalement trois stratégies de parallélisation : le parallélisme de données, le parallélisme de tenseurs et le parallélisme de pipeline. Combiner les trois donne le parallélisme 3D.

3D 并行策略示意图

Parallélisme de données

La stratégie la plus simple et la plus courante : chaque GPU détient une copie complète du modèle mais traite des données différentes.

Par exemple, avec 8 GPU et une taille de lot de 1024, chaque GPU traite 128 échantillons.

La propagation avant est effectuée indépendamment et, après la rétropropagation, les gradients sont collectés et moyennés, puis le modèle est mis à jour.

Le problème du parallélisme de données est que la mémoire reste le goulot d’étranglement : si le modèle est trop grand pour un seul GPU, le parallélisme de données est inutile.

Optimisation mémoire ZeRO

ZeRO (Zero Redundancy Optimizer) est une version améliorée du parallélisme de données qui permet d’économiser davantage de mémoire.

Dans le parallélisme de données classique, chaque GPU stocke l’intégralité des paramètres du modèle, des gradients et des états de l’optimiseur : c’est redondant.

L’idée de ZeRO est de partitionner ces états entre différents GPU et de les communiquer lorsque c’est nécessaire.

Étape ZeROQu'est-ce qui est partitionnéÉconomies de mémoire
ZeRO-1États de l'optimiseur~4x
ZeRO-2États de l'optimiseur + gradients~8x
ZeRO-3États de l'optimiseur + gradients + paramètresLinéaire avec le nombre de GPU

Configurer ZeRO avec DeepSpeed est simple :

{
  "train_batch_size": 1024,
  "train_micro_batch_size_per_gpu": 16,
  "optimizer": {
    "type": "Adam",
    "params": {
      "lr": 0.0001,
      "betas": [0.9, 0.95],
      "eps": 1e-8,
      "weight_decay": 0.01
    }
  },
  "zero_optimization": {
    "stage": 3,
    "allgather_partitions": true,
    "allgather_bucket_size": 2e8,
    "overlap_comm": true,
    "reduce_scatter": true,
    "reduce_bucket_size": 2e8,
    "contiguous_gradients": true,
    "stage3_prefetch_bucket_size": 1e8,
    "stage3_param_persistence_threshold": 1e5,
    "stage3_max_live_parameters": 1e9,
    "stage3_max_reuse_distance": 1e9
  },
  "gradient_clipping": 1.0,
  "fp16": {
    "enabled": true,
    "loss_scale": 0,
    "loss_scale_window": 1000,
    "initial_scale_power": 16,
    "hysteresis": 2,
    "min_loss_scale": 1
  },
  "checkpoint": {
    "tag": "example-checkpoint",
    "load_universal": true
  }
}

Cette configuration utilise ZeRO-3, qui peut répartir les états du modèle sur tous les GPU, réduisant l'utilisation de la mémoire linéairement à mesure que le nombre de GPU augmente.

Parallélisme tensoriel

Si ZeRO ne suffit toujours pas, utilisez le parallélisme tensoriel — répartissez le calcul d'une couche sur plusieurs GPU.

Les multiplications matricielles dans les Transformers peuvent être divisées par lignes ou par colonnes :

  • Divisez la matrice A par lignes en A₁ et A₂, et calculez A₁×B et A₂×B respectivement sur le GPU 0 et le GPU 1
  • Enfin, concaténez les résultats

De cette façon, chaque couche nécessite une communication, mais l’utilisation de la mémoire GPU est également réduite de moitié.

Megatron-LM est la bibliothèque de parallélisme tensoriel de NVIDIA, avec une excellente compatibilité avec PyTorch.

Parallélisme de pipeline

Le parallélisme tensoriel consiste à « découper à l’intérieur d’une couche » ; le parallélisme de pipeline consiste à « découper entre les couches ».

Par exemple, pour un modèle à 32 couches, le GPU 0 contient les 8 premières couches, le GPU 1 les 8 couches suivantes, le GPU 2 les 8 couches d’après, et le GPU 3 les 8 dernières.

Les données circulent du GPU 0 au GPU 3, comme sur une chaîne de montage d’usine.

Mais les pipelines ont un problème : la bulle — lorsque le GPU 0 commence à calculer, les GPU 1-3 sont inactifs ; lorsque les données atteignent le GPU 1, le GPU 0 redevient inactif.

La solution consiste à diviser les données en micro-batchs et à les injecter comme sur une chaîne de montage, ce qui réduit le temps de bulle.

Parallélisme 3D (DP+TP+PP)

Les trois stratégies peuvent être combinées :

  • Parallélisme de pipeline: répartir les couches du modèle entre les nœuds
  • Parallélisme tensoriel: découper le calcul intra-couche au sein d’un nœud
  • Parallélisme de données: Répliquer l'ensemble du pipeline à plus grande échelle

Par exemple, avec 64 GPU, vous pouvez planifier comme ceci :

  • 8 étapes de pipeline (PP=8)
  • Utilisez 2 GPU pour le parallélisme tensoriel au sein de chaque étape (TP=2)
  • Puis répliquez-le 4 fois pour le parallélisme de données (DP=4)
  • Total : 8 × 2 × 4 = 64 GPU

Il s'agit du parallélisme 3D — la configuration standard pour l'entraînement des grands modèles modernes.


Ingénierie des données

De bons modèles nécessitent de bonnes données — l'ingénierie des données représente plus de 60% de la charge de travail dans les systèmes d'IA.

Pipeline de collecte et de nettoyage des données

Les données d'entraînement proviennent généralement de plusieurs sources : pages web, livres, code, conversations, etc.

Flux de traitement typique :

  • Déduplication: Supprimer les documents en double ou très similaires
  • Filtrage de qualité: Supprimer le contenu de faible qualité, toxique ou biaisé
  • Unification du format: Convertir différentes sources en un format unifié
  • Tokenisation: Convertir le texte en séquences d'entrée du modèle

Déduplication des données : MinHash LSH

Calculer directement la similarité entre documents par paires est trop lent ; une approche courante consiste en MinHash + LSH (hachage sensible à la localité).

L'idée est : transformer chaque document en une courte "empreinte" ; les documents similaires ont tendance à avoir des empreintes identiques ou similaires, puis regrouper par empreinte.

Exemple

import hashlib
import re
from typing import List, Set, Dict, Tuple


def generate_shingles(text: str, k: int = 5) -> Set[str]:
    """Générer des k-shingles : séquences de k mots consécutifs Par exemple "I love example tutorial", k=2 → {"I love", "love example", "example tutorial"} # Tokenisation simple (un outil de tokenisation professionnel peut être utilisé dans des scénarios réels) """
"""Générer des signatures MinHash Utiliser plusieurs fonctions de hachage, chacune prenant la valeur minimale # Utiliser i comme graine pour générer différentes fonctions de hachage # Combiner shingle et i pour générer une valeur de hachage """
    """

    """Générer des clés LSH à l'aide de la méthode de banding Diviser la signature en plusieurs bandes, hacher chaque bande séparément # Hacher cette bande pour générer une clé """
    words = re.findall(r'\w+', text.lower())
    shingles = set()
    for i in range(len(words) - k + 1):
        shingle = ' '.join(words[i:i+k])
        shingles.add(shingle)
    return shingles


def minhash_signature(shingles: Set[str], num_hashes: int = 100) -> List[int]:
    """Dédoublonner les documents en utilisant MinHash + LSH Retourner la liste des documents dédoublonnés # Stockage : clé LSH → liste des indices de documents # Stockage : indice de document → signature # Marquer : quels documents sont des doublons # Vérifier si un document similaire existe déjà # Ce compartiment contient déjà des documents, comparer les similarités de signature une par une # Calculer la similarité des signatures (approximation de Jaccard) # Au-dessus du seuil, considéré comme un doublon # Pas un doublon, s'ajouter à tous les compartiments """
Utiliser plusieurs fonctions de hachage, chacune prenant la valeur minimale
    """

    signature = []
    for i in range(num_hashes):
        # Utiliser i comme graine pour générer différentes fonctions de hachage
        min_hash = None
        for shingle in shingles:
            # Combiner shingle et i pour générer une valeur de hachage
            h = hashlib.sha256(f"{shingle}-{i}".encode()).hexdigest()
            h_int = int(h, 16)
            if min_hash is None or h_int < min_hash:
                min_hash = h_int
        signature.append(min_hash)
    return signature


def lsh_banding(signature: List[int], bands: int = 20) -> List[str]:
    """Utilisez le bucketing (Banding) pour générer des clés LSH
Divisez la signature en plusieurs bandes et hachez chaque bande séparément.
    """

    keys = []
    rows_per_band = len(signature) // bands
    for i in range(bands):
        start = i * rows_per_band
        end = start + rows_per_band
        band = tuple(signature[start:end])
        # Générer une clé pour ce hash de bande
        band_hash = hashlib.sha256(str(band).encode()).hexdigest()[:16]
        keys.append(f"band-{i}-{band_hash}")
    return keys


def deduplicate_documents(documents: List[str],
                          threshold: float = 0.7) -> List[str]:
    """Utiliser MinHash + LSH pour dédupliquer les documents
Retourne la liste des documents dédupliqués
    """

    # Stockage : clé LSH → liste d'indices de documents
    buckets: Dict[str, List[int]] = {}
    # Stockage : indice de document → signature
    signatures: Dict[int, List[int]] = {}
    # Marquer : quels documents sont des doublons
    duplicates: Set[int] = set()

    for idx, doc in enumerate(documents):
        shingles = generate_shingles(doc)
        sig = minhash_signature(shingles)
        signatures[idx] = sig
        keys = lsh_banding(sig)

        # Vérifier si des documents similaires existent déjà
        is_duplicate = False
        for key in keys:
            if key in buckets:
                # Ce compartiment contient déjà des documents, comparer les similarités de signature une par une
                for other_idx in buckets[key]:
                    other_sig = signatures[other_idx]
                    # Calculer la similarité des signatures (approximation de Jaccard)
                    matches = sum(1 for a, b in zip(sig, other_sig) if a == b)
                    similarity = matches / len(sig)
                    if similarity >= threshold:
                        # Dépasse le seuil, considéré comme doublon
                        is_duplicate = True
                        duplicates.add(idx)
                        break
            if is_duplicate:
                break

        if not is_duplicate:
            # Pas un doublon ; s'ajouter à chaque compartiment
            for key in keys:
                if key not in buckets:
                    buckets[key] = []
                buckets[key].append(idx)

    Python est un langage concis et élégant, adapté aux débutants.
    return [doc for idx, doc in enumerate(documents) if idx not in duplicates]


# ============================================
L'apprentissage automatique permet aux ordinateurs d'apprendre des motifs à partir de données.
# ============================================
if __name__ == "__main__":
    documents = [
        Ceci est un article complètement différent.,
        "Bienvenue dans le tutoriel d'exemple, c'est un excellent endroit pour apprendre la programmation.",  # Très similaire
        "Python est un langage concis et élégant, adapté aux débutants.",
        "Python est un langage de programmation concis et élégant, très adapté aux débutants.",  # Très similaire
        "L'apprentissage automatique permet aux ordinateurs d'apprendre des motifs à partir des données.",
        "Il s'agit d'un article complètement différent.",
    ]

    print(f"Avant déduplication : {len(documents)} documents")
    deduplicated = deduplicate_documents(documents, threshold=0.6)
    print(f"Après déduplication : {len(deduplicated)} documents"\n")

    print("Documents conservés :")
    for i, doc in enumerate(deduplicated):
        print(f" [{i}] {doc}")

# Sortie :
# Avant déduplication : 6 documents
# Après déduplication : 4 documents
#
# Documents conservés :
#
#
#
#

En production réelle, des implémentations plus efficaces (comme la bibliothèque datasketch) sont utilisées, mais l'idée centrale reste la même.

Format de données : WebDataset

Les petits jeux de données peuvent être stockés de manière arbitraire, mais les jeux de données de niveau TB nécessitent un format dédié.

WebDataset est un format courant : il empaquette les fichiers dans des archives tar, chaque tar contient des milliers d'échantillons et prend en charge à la fois l'accès aléatoire et l'accès séquentiel.

Les avantages sont :

  • Réduit la pression sur le système de fichiers (des millions de petits fichiers sont lents)
  • Prend en charge les lectures en streaming, sans avoir besoin de charger l'intégralité du jeu de données en mémoire
  • Peut être chargé de manière distribuée, chaque worker lisant un tar différent

Conception du volant d'inertie des données

Le volant d'inertie des données est le rempart des produits d'IA—plus d'utilisateurs, plus de données, de meilleurs modèles, plus d'utilisateurs.

Collecte des données de retour utilisateur

Les retours sont de deux types : explicites et implicites.

  • Retour explicite: j'aime, je n'aime pas, modifications et préférences de l'utilisateur
  • Retour implicite: temps de présence, copies et session de l'utilisateur

Le retour explicite est de haute qualité mais peu abondant ; le retour implicite est l'inverse.

Un bon système de retour combine les deux—en utilisant le retour explicite pour entraîner des modèles et le retour implicite pour les tests A/B.

Annotation automatisée

L'annotation manuelle est trop coûteuse et lente ; la tendance actuelle est « d'utiliser des modèles pour annoter des modèles ».

Stratégies courantes :

  • Des modèles forts annotent des modèles faibles: utiliser des données annotées par GPT-4 pour entraîner de petits modèles
  • Bootstrap: utiliser des modèles existants pour générer des candidats, puis filtrer manuellement
  • Données synthétiques: utiliser des modèles pour générer des données d'entraînement variées

Stratégie d'entraînement continu

Les modèles ne sont pas « entraînés une fois pour toutes » ; le monde change, et les modèles doivent changer en conséquence.

Un processus d'entraînement continu typique :

  • Collecter chaque jour de nouvelles données d'interaction utilisateur
  • Effectuer une petite mise à jour une fois par semaine (SFT, ajustement supervisé)
  • Effectuer une grande mise à jour une fois par mois (pré-entraînement continu + SFT + RLHF)
  • Exécuter des tests A/B pour chaque mise à jour, et ne déployer complètement qu'après avoir confirmé l'effet

L'entraînement continu nécessite de prêter attention à l'"oubli catastrophique"—entraîné sur trop de nouvelles données, le modèle peut oublier ses capacités précédentes. La solution consiste à conserver un "tampon de rejeu" et à mélanger anciennes et nouvelles données à chaque session d'entraînement.


Architecture de plateforme d'IA d'entreprise

Une plateforme d'IA d'entreprise complète comprend généralement les composants suivants.

Registre de modèles et gestion des versions

Plus il y a de modèles, plus la gestion devient fastidieuse—un registre de modèles centralisé est nécessaire.

Le registre doit enregistrer :

  • Fichiers de modèle (poids, configuration, tokenizer)
  • Numéros de version et journaux de modifications
  • Sources de données d'entraînement et hyperparamètres
  • Métriques d'évaluation
  • Statut de déploiement

MLflow, Weights & Biases et Hugging Face Hub sont tous des outils couramment utilisés.

Magasin de caractéristiques

De nombreuses applications d'IA nécessitent l'ingénierie des caractéristiques—profils utilisateurs, comportements historiques, informations contextuelles, etc.

Le magasin de caractéristiques est un système de gestion de caractéristiques qui résout plusieurs problèmes :

  • Décalage entraînement/inférence: Incohérence entre les caractéristiques utilisées lors de l'entraînement et de l'inférence
  • Réutilisation des caractéristiques: Différents modèles peuvent partager des caractéristiques
  • Cohérence en ligne/hors ligne: Caractéristiques calculées hors ligne, lues en ligne avec une faible latence

Architecture typique : calcul par lots hors ligne avec Spark ou Flink, lectures en ligne à faible latence avec Redis ou Cassandra.

Service d'inférence en ligne/hors ligne

L'inférence est divisée en deux scénarios avec des architectures différentes :

ScénarioExigence de latenceArchitectureExemple
Inférence en ligneNiveau millisecondeAPI temps réel + traitement par lotsChatbots, recherche
Inférence hors ligneNiveau heure/jourFile d'attente de tâches par lotsModération de contenu, génération de rapports

Les services d'inférence en ligne doivent prendre en compte :

  • Traitement par lots: Combiner plusieurs requêtes et les calculer ensemble pour améliorer le débit
  • Traitement par lots dynamique: Utiliser vLLM ou Text Generation Inference pour le traitement par lots dynamique
  • Mise en cache: le cache K/V accélère la génération autorégressive ; les résultats pour les prompts populaires sont directement mis en cache
  • Équilibrage de charge: plusieurs instances de modèle, routage intelligent

Surveillance de bout en bout

Les problèmes des systèmes d’IA sont difficiles à diagnostiquer — vous avez besoin d’observabilité.

Plusieurs dimensions de surveillance :

  • Métriques système: utilisation GPU, VRAM, latence, débit, taux d’erreur
  • Métriques du modèle: longueur de sortie, taux de répétition, distribution des mots d’arrêt
  • Métriques métier: satisfaction des utilisateurs, taux de rétention, taux d’achèvement des tâches

Stack classique : Prometheus + Grafana pour les métriques, ELK pour les logs, Jaeger pour le traçage.


Système de benchmark d’évaluation

Comment savoir si un modèle s'est amélioré ou s'il a empiré ? Il vous faut un système d'évaluation.

Benchmarks de capacités générales

Benchmarks couramment utilisés dans le monde universitaire :

BenchmarkContenu du testTâches typiques
MMLUCompréhension du langage multitâcheQuestions à choix multiples sur 57 sujets
HumanEvalGénération de code164 problèmes de programmation
MBPPGénération de code974 problèmes Python
TruthfulQAFactualité817 questions, testant les hallucinations
GSM8KRaisonnement mathématique8000 problèmes de mathématiques de niveau primaire

Benchmarks chinois

De bonnes performances sur les benchmarks anglais ne signifient pas de bonnes performances en chinois ; des benchmarks spécifiques au chinois sont nécessaires :

  • C-Eval: compréhension linguistique multitâche en chinois, 13,948 questions à choix multiples
  • CMMLU: compréhension multimodale chinoise (actuellement principalement du texte)
  • AGIEval: questions du Gaokao chinois, questions d'examen de la fonction publique

Ensembles d'évaluation métier personnalisés

Les benchmarks publics sont la base, mais votre propre ensemble d'évaluation métier est plus important.

Comment construire :

  • Collectez des demandes réelles d'utilisateurs (des centaines à des milliers)
  • Étiqueter manuellement "bon/moyen/mauvais" ou les noter
  • Diviser en ensembles de test et de validation (l'ensemble de test est fixe, n'y touchez pas)
  • Exécutez-le à chaque mise à jour du modèle pour voir l'évolution des métriques

Votre ensemble d'évaluation métier est votre "étalon-or" — il est plus important que n'importe quel benchmark public.


Services d'IA multi-locataires

Si vous développez un produit ToB, le multi-locataire est un sujet incontournable.

Isolation des locataires

L'isolation comporte plusieurs niveaux :

Niveau d'isolationRessourcesAvantagesInconvénients
Isolation physiqueMachines GPU dédiéesIsolation complète, sécuriséeCoût élevé
Isolation K8sPod/Namespace dédiéÉquilibre entre coût et sécuritéNécessite l'ordonnancement
Isolation logiqueRessources partagées, contrôle des permissionsCoût le plus faibleRisque de fuite

La stratégie habituelle est : isolation physique pour les grands clients, isolation logique pour les clients de petite et moyenne taille.

Partage de modèles et gestion du fine-tuning

Une exigence courante multi-tenant : entraîner un modèle propriétaire avec mes données.

L'architecture doit prendre en charge :

  • Stockage partagé pour les modèles de base
  • L'adaptateur LoRA de chaque locataire est stocké séparément
  • Charger dynamiquement le LoRA du locataire correspondant lors de l'inférence

Cela économise beaucoup de mémoire GPU—pas besoin de charger le modèle complet pour chaque locataire.

Facturation et quotas

Les services d'IA sont coûteux, la facturation doit donc être granulaire :

  • Facturation au token (entrées et sorties calculées séparément)
  • Facturation au nombre de requêtes
  • Facturation au temps GPU (scénarios de fine-tuning)
  • Limites de quota (requêtes par minute, tokens par jour)

Reprise après sinistre et haute disponibilité

Les systèmes de niveau entreprise ne peuvent pas tomber—une conception de haute disponibilité est requise.

Déploiement multi-zone de disponibilité

L’exigence la plus fondamentale : déploiement inter-AZ (zone de disponibilité).

Par exemple :

  • Cluster primaire dans AZ A
  • Cluster de secours à chaud dans AZ B
  • Réplication asynchrone des données
  • Le répartiteur de charge bascule automatiquement le trafic

L’objectif est : si une seule AZ tombe, les services restent disponibles sans interruption et aucune donnée n’est perdue.

Instantané et restauration de modèle

Les nouvelles versions de modèle peuvent poser problème—une capacité de retour arrière rapide est nécessaire.

Stratégie :

  • Enregistrer un instantané du modèle avant chaque publication
  • Conserver les N versions les plus récentes
  • Surveiller les métriques anormales et déclencher un retour arrière automatique
  • Déploiement canari : basculer d’abord 1 % du trafic, puis déployer entièrement s’il n’y a aucun problème

Dégradation et limitation de débit

Que se passe-t-il si le trafic explose ? Il ne peut pas simplement tomber en panne — il faut un plan de secours :

  • Limitation de débitRenvoyer 429 lorsque le quota est dépassé
  • DégradationUtiliser un modèle plus petit, ou renvoyer des résultats mis en cache
  • Mise en file d’attenteRenvoyer un ID de tâche, consulter les résultats plus tard

Principe fondamental :Dégradation gracieuse, pas une indisponibilité totale.

Autres extensions