Modèles et plateformes d’IA
SGLang : Exécution efficace de programmes de modèles de langage structurés
Les grands modèles de langage (LLM) sont de plus en plus utilisés pour des tâches complexes nécessitant plusieurs appels de génération, des techniques de prompt avancées, un contrôle de flux et des entrées/sorties structurées. Cependant, les systèmes efficaces pour la programmation et l’exécution de ces applications font défaut. SGLang, un système nouvellement introduit, vise à résoudre ce problème en fournissant une exécution efficace de programmes de modèles de langage complexes. SGLang se compose d’un langage de frontend et d’un runtime. Le frontend simplifie la programmation avec des primitives pour la génération et le contrôle de la parallélisme, tandis que le runtime accélère l’exécution grâce à des optimisations nouvelles comme RadixAttention pour la réutilisation du cache KV et des machines à états finis compressées pour une décodage de sortie structurée plus rapide. Les expériences démontrent que SGLang atteint jusqu’à 6,4 fois plus de débit que les systèmes d’inférence de pointe sur divers grands modèles de langage et multimodaux, traitant des tâches telles que le contrôle d’agent, la raisonnement logique, les benchmarks d’apprentissage à quelques exemples, la décodage JSON, les pipelines de génération augmentée de récupération et le chat à plusieurs tours.
Les progrès récents dans les capacités des LLM ont élargi leur utilité, leur permettant de gérer un plus large éventail de tâches générales et de fonctionner comme des agents autonomes. Dans ces applications, les LLM engagent dans une planification multi-ronde, un raisonnement et une interaction avec des environnements externes. Cela est facilité par l’utilisation d’outils, de multiples modalités d’entrée et de diverses techniques de prompt, telles que l’apprentissage à quelques exemples, la cohérence auto, le squelette de pensée et l’arbre de pensée. Ces nouveaux cas d’utilisation nécessitent plusieurs appels de génération LLM, souvent dépendants, indiquant une tendance à utiliser des structures multi-appels pour compléter des tâches complexes.
Ce changement marque une transition de l’utilisation simple de chat à une utilisation plus sophistiquée et programmatique des LLM, où les programmes planifient et contrôlent les processus de génération des LLM. Ces programmes sont appelés “Programmes de modèles de langage” (LM Programs). Les techniques de prompt avancées et les flux de travail agents tombent dans le cadre des programmes LM. Il existe deux propriétés communes des programmes LM : (1) Les programmes LM impliquent généralement plusieurs appels LLM entrecoupés de contrôle de flux pour compléter des tâches complexes et améliorer la qualité globale. (2) Les programmes LM reçoivent des entrées structurées et produisent des sorties structurées, permettant la composition de programmes LM et l’intégration dans des systèmes logiciels existants.
Dans cet article, nous allons plonger plus profondément dans le cadre SGLang, en explorant son architecture, en analysant ses performances et en le comparant aux cadres de pointe. Alors, commençons.
Introduction à SGLang
Malgré l’utilisation répandue des programmes LM, les systèmes actuels pour les exprimer et les exécuter restent inefficaces. SGLang identifie deux défis principaux associés à l’utilisation efficace des programmes LM :
- Complexité de programmation : Développer des programmes LM est fastidieux et difficile en raison de la nature non déterministe des LLM. Cela implique une manipulation extensive de chaînes, un réglage expérimental de prompts, un parsing de sortie fragile, une gestion de multiples modalités d’entrée et une mise en œuvre de mécanismes de parallélisme. Cette complexité réduit considérablement la lisibilité même des programmes simples.
- Inefficacité d’exécution : L’exécution des programmes LM est inefficace en raison de calculs et d’utilisation de mémoire redondants. Les moteurs d’inférence de pointe, optimisés pour réduire la latence et améliorer le débit, manquent de connaissance directe de la charge de travail, ce qui entraîne des inefficacités importantes. Un exemple notable est la réutilisation du cache KV, qui consiste en des tenseurs intermédiaires réutilisables essentiels pour l’inférence générative. Les systèmes actuels manquent de mécanismes efficaces pour faciliter la réutilisation du cache KV entre plusieurs appels LLM partageant un préfixe commun, ce qui entraîne des calculs inutiles et une perte de mémoire. De plus, la décodage contraint pour les sorties structurées, telles que le mode JSON, est sous-optimale car les systèmes existants ne décodent qu’un jeton à la fois.
Pour répondre à ces défis, SGLang introduit un langage de génération structuré pour les LLM. L’idée principale est d’exploiter systématiquement la structure multi-appel dans les programmes LM pour une exécution efficace. Comme le montre la figure suivante, SGLang a deux parties : un langage de frontend et un runtime.

Le frontend simplifie la programmation des programmes LM, et le runtime accélère leur exécution. Ces parties peuvent fonctionner ensemble pour une meilleure performance ou fonctionner de manière indépendante.
SGLang est un langage spécifique de domaine intégré à Python, fournissant des primitives pour la génération (par exemple, étendre, générer, sélectionner) et le contrôle de la parallélisme (par exemple, fork, join). Il est compatible avec le flux de contrôle et les bibliothèques Python, permettant aux utilisateurs de développer facilement des flux de travail de prompt avancés avec la syntaxe Python native. SGLang inclut un interpréteur et un compilateur. L’interpréteur gère l’état de prompt comme un flux et soumet les opérations primitives au flux pour une exécution asynchrone, assurant un contrôle approprié de la synchronisation et de la parallélisme intra-programme. De plus, les programmes SGLang peuvent être tracés et compilés pour des optimisations supplémentaires. Le runtime de SGLang propose plusieurs optimisations nouvelles pour accélérer l’exécution des programmes LM :
- RadixAttention : Cette technique permet la réutilisation automatique du cache KV entre plusieurs appels de génération. Dans les moteurs d’inférence existants, le cache KV d’une demande est supprimé après le traitement, empêchant la réutilisation entre plusieurs appels et ralentissant l’exécution. SGLang maintient un cache LRU du cache KV dans un arbre radix, gérant le cache KV comme un cache traditionnel et utilisant l’arbre radix pour un appariement, une insertion et une suppression efficaces. Cela permet au runtime de gérer efficacement divers modèles de réutilisation.
- Machine à états finis compressée : Cette technique permet une décodage contraint plus rapide pour les sorties structurées. Les systèmes existants suivent les contraintes uniquement pour le prochain jeton, ce qui les rend capables de décodage d’un jeton à la fois. Au lieu de cela, SGLang analyse les contraintes et construit une machine à états finis compressée pour les représenter, compressant un chemin multi-jeton en un chemin à une étape lorsque cela est possible, permettant la décodage de plusieurs jetons à la fois pour une vitesse plus rapide.
- Exécution spéculative API : Pour les modèles API uniquement, tels que OpenAI, SGLang introduit l’exécution spéculative API pour optimiser les programmes multi-appels.
En utilisant SGLang, diverses applications LLM ont été mises en œuvre, notamment le contrôle d’agent, la raisonnement logique, les benchmarks d’apprentissage à quelques exemples, la décodage JSON, les pipelines de génération augmentée de récupération, le chat à plusieurs tours et le traitement multi-modal. Les performances ont été testées sur des modèles tels que Llama-7B/70B, Mistral-8x7B, LLaVA-v1.5-7B (image) et LLaVA-NeXT-34B (vidéo) sur les GPU NVIDIA (NVDA ) A10G et A100. Les résultats expérimentaux montrent que SGLang atteint jusqu’à 6,4 fois plus de débit sur une large gamme de charges de travail, de modèles et de configurations matérielles, par rapport aux systèmes de programmation et d’inférence existants, notamment Guidance, vLLM et LMQL.
SGLang : Modèle de programmation et méthodologie
Le modèle de programmation SGLang est introduit à travers un exemple en cours d’exécution, décrivant son langage et ses modes d’exécution, et détaillant les opportunités d’optimisation du runtime. Ce modèle simplifie les opérations fastidieuses dans les flux de travail multi-appels (par exemple, manipulation de chaînes, appels API, spécification de contraintes, parallélisme) en fournissant des primitives flexibles et composable. SGLang est un langage spécifique de domaine intégré à Python. La figure suivante montre un programme qui évalue un essai sur une image en utilisant la méthode de prompt branch-solve-merge.

La fonction multi_dimensional_judge prend trois arguments : `s`, `path` et `essay`. s gère l’état de prompt, path est le chemin du fichier d’image et essay est le texte de l’essai. De nouvelles chaînes et des primitives SGLang peuvent être ajoutées à l’état s pour exécution en utilisant l’opérateur +=. Tout d’abord, la fonction ajoute l’image et l’essai au prompt. Elle vérifie ensuite si l’essai est lié à l’image en utilisant la sélection, en stockant le résultat dans s[“related”]. Si lié, le prompt est divisé en trois copies pour une évaluation parallèle à partir de différentes dimensions, en utilisant la génération pour stocker les résultats dans f[“judgment”]. Ensuite, il fusionne les jugements, génère un résumé et attribue une note de lettre. Enfin, il retourne les résultats au format JSON, en suivant un schéma défini par une contrainte d’expression régulière regex. SGLang simplifie considérablement ce programme, car un programme équivalent utilisant une interface similaire à OpenAI nécessiterait 2,1 fois plus de lignes de code en raison de la manipulation manuelle de chaînes et du contrôle de la parallélisme.
SGLang fournit des primitives pour contrôler l’état de prompt, la génération et la parallélisme, qui peuvent être utilisées avec la syntaxe et les bibliothèques Python. Voici les primitives :
gen : Appelle un modèle pour générer et stocke les résultats dans une variable avec le nom spécifié dans son premier argument. Il prend en charge un argument `regex` pour contraindre la sortie à suivre une grammaire définie par une expression régulière (par exemple, un schéma JSON).
- select : Appelle un modèle pour choisir l’option la plus probable à partir d’une liste.
- += ou extend : Ajoute une chaîne au prompt.
- [variable_name] : Récupère les résultats d’une génération.
- fork : Crée des copies parallèles de l’état de prompt.
- join : Réunit l’état de prompt.
- image et vidéo : Prend en charge les entrées d’image et de vidéo.
La façon la plus simple d’exécuter un programme SGLang est à travers un interpréteur, où un prompt est traité comme un flux asynchrone. Les primitives comme extend, gen et select sont soumises au flux pour une exécution asynchrone. Ces appels non bloquants permettent au code Python de continuer à s’exécuter sans attendre la fin de la génération, semblable au lancement de noyaux CUDA de manière asynchrone. Chaque prompt est géré par un exécuteur de flux dans un thread en arrière-plan, permettant la parallélisme intra-programme. La récupération des résultats de génération bloquera jusqu’à ce qu’ils soient prêts, assurant une synchronisation correcte. Alternativement, les programmes SGLang peuvent être compilés en graphes de calcul et exécutés avec un exécuteur de graphes, permettant davantage d’optimisations. Cet article utilise le mode interpréteur par défaut et discute des résultats du mode compilé dans l’Annexe D. SGLang prend en charge les modèles à poids ouvert avec son propre runtime SGLang (SRT), ainsi que les modèles API tels que OpenAI et Anthropic.
Les systèmes de programmation pour les LLM peuvent être classés en systèmes de haut niveau (par exemple, LangChain, DSPy) et en systèmes de bas niveau (par exemple, LMQL, Guidance, SGLang). Les systèmes de haut niveau fournissent des prompts prédéfinis ou auto-générés, tels que l’optimiseur de prompt de DSPy. Les systèmes de bas niveau n’altèrent généralement pas les prompts, mais permettent une manipulation directe des prompts et des primitives. SGLang est un système de bas niveau similaire à LMQL et Guidance. Le tableau suivant compare leurs fonctionnalités.

SGLang se concentre davantage sur l’efficacité du runtime et est livré avec son propre runtime conçu, permettant des optimisations nouvelles. Les langages de haut niveau (par exemple, DSPy) peuvent être compilés en langages de bas niveau (par exemple, SGLang). L’intégration de SGLang en tant que backend dans DSPy pour une meilleure efficacité du runtime est démontrée plus tard.

L’exemple ci-dessus illustre les opérations RadixAttention avec une politique d’éviction LRU sur neuf points de temps, montrant l’évolution dynamique de l’arbre radix en réponse à différents types de demandes, garantissant une réutilisation efficace du cache KV et une gestion de la mémoire.
Cet exemple démontre comment RadixAttention gère l’allocation dynamique et l’éviction de nœuds en réponse à différents types de demandes, assurant une réutilisation efficace du cache KV et une gestion de la mémoire.
SGLang : Évaluation et résultats
Résultats sur les modèles à poids ouvert
Les résultats de latence et de débit sont présentés dans les figures suivantes. SGLang améliore le débit de jusqu’à 6,4 fois et réduit la latence de jusqu’à 3,7 fois. Ces améliorations résultent de la réutilisation du cache KV, de l’exploitation du parallélisme au sein d’un seul programme et d’un décodage contraint plus rapide.

Sur ces benchmarks, le taux de cache atteint entre 50 % et 99 %. La figure 13 (Annexe) liste les taux de cache atteints et optimaux pour tous, montrant que l’approche de planification du cache de SGLang approche 96 % du taux de cache optimal en moyenne.

Résultats sur les modèles plus grands avec parallélisme de tenseur
Les modèles plus grands, Mixtral-8x7B et Llama-70B, ont été testés avec le parallélisme de tenseur sur le même ensemble de benchmarks, et les résultats sont présentés dans la figure suivante. L’accélération sur les modèles plus grands montre une tendance similaire à celle observée sur les modèles plus petits, indiquant que les optimisations de SGLang se généralisent bien aux modèles plus grands. Guidance et LMQL ont été omis en raison du manque d’implémentations efficaces du parallélisme de tenseur.

Résultats sur les modèles multi-modaux
SGLang a une prise en charge native des modèles multi-modaux avec les primitives d’image et de vidéo. Les optimisations de cet article sont compatibles avec les modèles multi-modaux. Pour RadixAttention, le hachage de l’entrée d’image est calculé et utilisé comme clé dans l’arbre radix, permettant la réutilisation du cache KV des jetons d’image provenant de la même image. LLaVA-v1.5-7B (image) a été exécuté sur llava-bench-in-the-wild et LLaVA-NeXT-34B (vidéo) sur ActivityNet. Puisque ces modèles ne sont pas bien pris en charge par les systèmes de référence, l’implémentation originale des auteurs de modèle dans Hugging Face Transformers a été utilisée comme référence. Comme le montre le tableau suivant, SGLang fournit un débit jusqu’à 6 fois plus élevé sur ces benchmarks. Dans llava-bench-in-the-wild, plusieurs questions sur la même image ont été traitées, et le runtime SGLang a réutilisé le cache KV dans ce cas.

Déploiement en production
SGLang a été déployé dans Chatbot Arena pour servir les modèles à poids ouvert. En raison d’un faible trafic pour certains modèles, un seul travailleur SGLang sert chaque modèle. Après un mois, un taux de cache RadixAttention de 52,4 % pour LLaVA-Next-34B et de 74,1 % pour Vicuna-33B a été observé. Les cache hits provenaient de messages système courants, d’images d’exemple réutilisées et d’histoires de chat à plusieurs tours. Cela a réduit la latence du premier jeton d’un facteur moyen de 1,7 pour Vicuna-33B.

Pensées finales
Dans cet article, nous avons discuté de SGLang, un système nouvellement introduit qui vise à résoudre ce problème en fournissant une exécution efficace de programmes de modèles de langage complexes. SGLang se compose d’un langage de frontend et d’un runtime. Le frontend simplifie la programmation avec des primitives pour la génération et le contrôle de la parallélisme, tandis que le runtime accélère l’exécution grâce à des optimisations nouvelles comme RadixAttention pour la réutilisation du cache KV et des machines à états finis compressées pour un décodage de sortie structurée plus rapide. Les expériences démontrent que SGLang atteint jusqu’à 6,4 fois plus de débit que les systèmes d’inférence de pointe sur divers grands modèles de langage et multimodaux, traitant des tâches telles que le contrôle d’agent, la raisonnement logique, les benchmarks d’apprentissage à quelques exemples, la décodage JSON, les pipelines de génération augmentée de récupération et le chat à plusieurs tours.












