Modely a platformy AI
SGLang: Efektivní provedení strukturovaných programů jazykových modelů
Velké jazykové modely (LLM) se stále více využívají pro komplexní úkoly, které vyžadují více generativních volání, pokročilé techniky vyvolání, řízení toku a strukturované vstupy/výstupy. Nicméně, efektivní systémy pro programování a provádění těchto aplikací chybí. SGLang, nově zavedený systém, se snaží tento problém vyřešit poskytováním efektivního provedení komplexních programů jazykových modelů. SGLang se skládá z frontendového jazyka a runtime. Frontend zjednodušuje programování pomocí primitiv pro generaci a řízení paralelismu, zatímco runtime urychluje provedení pomocí nových optimalizací, jako je RadixAttention pro opětovné použití KV cache a komprimované konečné automaty pro rychlejší dekódování strukturovaných výstupů. Experimenty prokázaly, že SGLang dosahuje až 6,4× vyšší propustnosti ve srovnání se stávajícími systémy inference na různých velkých jazykových a multimodálních modelech, řešících úkoly, jako je řízení agentů, logické uvažování, few-shot learning benchmarky, dekódování JSON, generace s podporou načtení a multi-turn chat.
Poslední pokroky v možnostech LLM rozšířily jejich využití, umožňující jim zpracovávat širší rozsah obecných úkolů a fungovat jako autonomní agenti. V těchto aplikacích LLM provádějí vícekolové plánování, uvažování a interakci s externími prostředími. To je usnadněno pomocí nástrojů, více vstupních modalit a různých technik vyvolání, jako je few-shot learning, sebe-konzistence, kostra-mysli a strom-mysli. Tyto nové použití vyžadují více, často závislých, LLM generativních volání, ukazujících trend používání multi-volání struktur pro dokončení komplexních úkolů.
Tento posun označuje přechod od jednoduchého chatu k více sofistikovanému programovému využití LLM, kde programy řídí a kontrolují generativní procesy LLM. Tyto programy se nazývají “Language Model Programs” (LM Programy). Pokročilé techniky vyvolání a agentic workflows spadají do rozsahu LM programů. Existují dvě společné vlastnosti LM programů: (1) LM programy obvykle zahrnují více LLM volání proložených s řízením toku pro dokončení komplexních úkolů a zlepšení celkové kvality. (2) LM programy přijímají strukturované vstupy a produkují strukturované výstupy, umožňující kompozici LM programů a integraci do stávajících softwarových systémů.
V tomto článku se budeme zabývat frameworkem SGLang, prozkoumáme jeho architekturu, analyzujeme jeho výkon a porovnáme ho se stávajícími frameworky. Takže začněme.
Úvod do SGLang
Navzdory širokému využití LM programů zůstávají současné systémy pro jejich vyjádření a provedení neefektivní. SGLang identifikuje dvě hlavní výzvy spojené s efektivní utilizací LM programů:
- Komplexita programování: Vývoj LM programů je únavný a obtížný kvůli nedeterministické povaze LLM. To zahrnuje rozsáhlou manipulaci s řetězci, experimentální ladění vyvolání, křehkou analýzu výstupu, zpracování více vstupních modalit a implementaci paralelismu. Tato komplexita významně snižuje čitelnost i jednoduchých programů.
- Neefektivní provedení: Provedení LM programů je neefektivní kvůli redundanci výpočtu a využití paměti. Stávající systémy inference, optimalizované pro snížení latence a zlepšení propustnosti, postrádají přímou znalost pracovní zátěže, což vede k významným neefektivnostem. Značný příklad je opětovné použití KV cache, která se skládá z opakovaně použitelných mezilehlých tensorů, nezbytných pro generativní inference. Stávající systémy postrádají efektivní mechanismy pro usnadnění opětovného použití KV cache přes více LLM volání, která sdílejí společný prefix, což vede k zbytečným výpočtům a plýtvání pamětí. Kromě toho je omezené dekódování pro strukturované výstupy, jako je režim JSON, suboptimální, protože stávající systémy dekódují pouze jeden token najednou.
Pro řešení těchto výzev SGLang zavádí strukturovaný generativní jazyk pro LLM. Základní myšlenka spočívá v systematickém využití multi-volací struktury v LM programech pro efektivní provedení. Jak je ukázáno na následujícím obrázku, SGLang se skládá ze dvou částí: frontendového jazyka a backendového runtime.

Frontend zjednodušuje programování LM programů, zatímco runtime urychluje jejich provedení. Tyto části mohou pracovat společně pro lepší výkon nebo fungovat nezávisle.
SGLang je doménově specifický jazyk vložený do Pythonu, poskytující primitivy pro generaci (například extend, gen, select) a řízení paralelismu (například fork, join). Je kompatibilní s Pythonovým řízením toku a knihovnami, umožňující uživatelům vyvíjet pokročilé workflows vyvolání snadno pomocí nativního Python syntaxe. SGLang zahrnuje interpret a kompilátor. Interpret spravuje stav vyvolání jako proud a předává primitivní operace do proudu pro asynchronní provedení, zajišťující řádnou kontrolu nad synchronizací a intra-programovým paralelismem. Kromě toho lze programy SGLang sledovat a kompilovat pro další optimalizace.
- RadixAttention: Tato technika umožňuje automatické opětovné použití KV cache přes více generativních volání. Ve stávajících systémech inference je KV cache požadavku odstraněna po zpracování, bránící opětovnému použití přes více volání a zpomalující provedení. SGLang udržuje LRU cache KV cache v radix stromu, spravující KV cache jako tradiční cache a využívající radix strom pro efektivní shodu, vložení a odstranění. To umožňuje runtime zpracovat různé vzorce opětovného použití efektivně.
- Komprimovaný konečný automat: Tato technika umožňuje rychlejší omezené dekódování pro strukturované výstupy. Stávající systémy následují omezení pouze pro následující token, umožňující dekódovat pouze jeden token najednou. SGLang analyzuje omezení a vytváří komprimovaný konečný automat pro jejich reprezentaci, komprimující více-tokenovou cestu do jedné krokové cesty, kdykoli je to možné, umožňující dekódování více tokenů najednou pro rychlejší rychlost.
- API spekulativní provedení: Pro API-only modely, jako je OpenAI GPT-4, SGLang zavádí API spekulativní provedení pro optimalizaci multi-volání programů.
Pomocí SGLang byly implementovány různé LLM aplikace, včetně řízení agentů, logického uvažování, few-shot learning benchmarků, dekódování JSON, generace s podporou načtení, multi-turn chatu a multi-modální zpracování. Výkon byl testován na modelech, včetně Llama-7B/70B, Mistral-8x7B, LLaVA-v1.5-7B (obraz) a LLaVA-NeXT-34B (video) na NVIDIA (NVDA ) A10G a A100 GPU. Experimentální výsledky ukazují, že SGLang dosahuje až 6,4× vyšší propustnosti napříč širokým rozsahem pracovních zátěží, modelů a hardwarových konfigurací, ve srovnání se stávajícími programovacími a inferenčními systémy, včetně Guidance, vLLM a LMQL.
SGLang: Programovací model a metodika
Programovací model SGLang je představen prostřednictvím běžného příkladu, popisujícího jeho jazykové primitivy a režimy provedení, a naznačujícího runtime optimalizační příležitosti. Tento model zjednodušuje únavné operace v multi-volacích workflows (například manipulaci s řetězci, API volání, specifikaci omezení, paralelismus) poskytováním flexibilních a komponovatelných primitiv. SGLang je doménově specifický jazyk vložený do Pythonu. Následující obrázek ukazuje program, který vyhodnocuje esej o obraze pomocí metody branch-solve-merge.

Funkce multi_dimensional_judge bere tři argumenty: `s`, `path` a `essay`. s spravuje stav vyvolání, path je cesta k obrazu a essay je text eseje. Nové řetězce a SGLang primitivy mohou být připojeny ke stavu s pro provedení pomocí operátoru +=. Nejprve funkce přidá obraz a esej ke stavu vyvolání. Poté zkontroluje, zda je esej související s obrazem pomocí select, a uloží výsledek v s[“related”]. Pokud je související, stav vyvolání je rozvětven do tří kopií pro paralelní vyhodnocení z různých dimenzí, pomocí gen pro uložení výsledků v f[“judgment”]. Dále spojí soudy, vygeneruje souhrn a přiřadí písmenné hodnocení. Nakonec vrátí výsledky v JSON formátu, podle schématu definovaného regulárním výrazem regex. SGLang značně zjednodušuje tento program, protože ekvivalentní program pomocí OpenAI API-like rozhraní by vyžadoval 2,1× více řádků kódu kvůli manuální manipulaci s řetězci a řízením paralelismu.
SGLang poskytuje primitivy pro kontrolu stavu vyvolání, generaci a paralelismu, které lze použít s Pythonovou syntaxí a knihovnami. Zde jsou primitivy:
gen: Volá model pro generaci a ukládá výsledky do proměnné se jménem specifikovaným v jeho prvním argumentu. Podporuje argument regex pro omezení výstupu na gramatiku definovanou regulárním výrazem (například JSON schéma).
- select: Volá model pro výběr nejvyšší pravděpodobnosti možnosti z seznamu.
- += nebo extend: Připojuje řetězec ke stavu vyvolání.
- [proměnná_name]: Načte výsledky generace.
- fork: Vytvoří paralelní větve stavu vyvolání.
- join: Spojí stav vyvolání.
- image a video: Přijímají obrazové a video vstupy.
Nejjednodušší způsob provedení programu SGLang je prostřednictvím interpretu, kde stav vyvolání je zpracován jako asynchronní proud. Primitivy, jako extend, gen a select, jsou předány do proudu pro asynchronní provedení. Tyto neblokující volání umožňují Pythonový kód pokračovat v běhu bez čekání na dokončení generace, podobně jako spuštění CUDA jader asynchronně. Každý stav vyvolání je spravován streamovým vykonavatelem v pozadí, umožňujícím intra-programový paralelismus. Načtení výsledků generace bude blokovat, dokud nejsou připraveny, zajišťující řádnou synchronizaci. Kromě toho lze programy SGLang zkompilovat jako komputační grafy a provést s grafickým vykonavatelem, umožňujícím další optimalizace.
Systémy pro programování LLM lze klasifikovat jako vysoké úrovně (například LangChain, DSPy) a nízké úrovně (například LMQL, Guidance, SGLang). Vysoké úrovně poskytují předdefinované nebo automaticky generované vyvolání, jako je DSPy optimizer vyvolání. Nízké úrovně obvykle nemění vyvolání, ale umožňují přímou manipulaci s vyvoláním a primitivy. SGLang je nízkou úrovní podobnou LMQL a Guidance. Následující tabulka porovnává jejich funkce.

SGLang se zaměřuje více na runtime efektivitu a přichází se svou vlastní navrženým runtime, umožňujícím novým optimalizacím. Vysoké úrovně jazyků (například DSPy) lze zkompilovat do nízkých úrovní jazyků (například SGLang). Integrace SGLang jako backendu v DSPy pro lepší runtime efektivitu je demonstrována později.

Předchozí příklad ilustruje operace RadixAttention s LRU vyprázdněním napříč devíti časovými body, ukazující dynamický vývoj radix stromu v reakci na různé požadavky. Tyto požadavky zahrnují dvě chatovací sezení, dávku few-shot learning dotazů a self-konzistentní vzorkování. Každá hrana radix stromu nese štítek označující podřetězec nebo sekvenci tokenů. Uzly jsou barevně kódovány pro odlišení různých stavů: zelená pro nově přidáné uzly, modrá pro cached uzly přístupné během časového bodu a červená pro uzly, které byly vyprázdněny.
Krok 1: Radix strom je inicializován jako prázdný.
Krok 2: Server zpracovává příchozí uživatelskou zprávu “Hello” a odpovídá s LLM výstupem “Hi”. Systémový prompt “You are a helpful assistant”, uživatelská zpráva “Hello!” a LLM odpověď “Hi!” jsou konsolidovány do stromu jako jeden hrany spojený s novým uzlem.
Krok 3: Nový prompt přichází a server najde prefix požadavku (tj. první kolo konverzace) v radix stromu a opětovně využije jeho KV cache. Nové kolo je připojeno ke stromu jako nový uzel.
Krok 4: Nové chatovací sezení začíná. Uzel z kroku 3 je rozdělen na dva uzly, aby umožnil dvěma chatovacím sezením sdílet systémový prompt.
Krok 5: Druhé chatovací sezení pokračuje. Nicméně, kvůli omezením paměti, musí být uzel z kroku 4 vyprázdněn. Nové kolo je připojeno po zbývajícím uzlu z kroku 4.
Krok 6: Server obdrží few-shot learning dotaz, zpracuje ho a vloží do stromu. Kořenový uzel je rozdělen, protože nový dotaz nesdílí žádný prefix s existujícími uzly.
Krok 7: Server obdrží dávku dalších few-shot learning dotazů. Tyto dotazy sdílejí stejnou sadu few-shot příkladů, takže uzel z kroku 6 je rozdělen pro sdílení.
Krok 8: Server obdrží novou zprávu z prvního chatovacího sezení. Vyprázdní všechny uzly ze druhého chatovacího sezení, protože jsou nejméně nedávno použité.
Krok 9: Server obdrží požadavek na vygenerování více odpovědí pro otázky v uzlu z kroku 8, pravděpodobně pro self-konzistentní vyvolání. Pro uvolnění místa pro tyto požadavky jsou vyprázdněny více uzlů.
Tento příklad demonstruje, jak RadixAttention zpracovává dynamické přidělování a vyprázdnění uzlů v reakci na různé požadavky, zajišťující efektivní opětovné použití KV cache a správu paměti.
SGLang: Evaluace a výsledky
Výsledky na modelech s otevřenými váhami
Latence a propustnost výsledků jsou ukázány v následujících obrázcích. SGLang zlepšuje propustnost až o 6,4× a snižuje latenci až o 3,7×. Tyto zlepšení jsou výsledkem opětovného použití KV cache, využití paralelismu v rámci jednoho programu a rychlejšího omezeného dekódování.

Na těchto benchmarcích se míra zásahu cache pohybuje od 50% do 99%. Obrázek 13 (Příloha) uvádí dosažené a optimální míry zásahu cache pro všechny z nich, ukazující, že SGLangův cache-aware scheduling se blíží 96% optimální míře zásahu v průměru.

Výsledky na větších modelech s tensorovým paralelismem
Větší modely, Mixtral-8x7B a Llama-70B, byly testovány s tensorovým paralelismem na stejné sadě benchmarků, a výsledky jsou uvedeny v následujícím obrázku. Zrychlení na větších modelech ukazuje trend podobný tomu, který byl pozorován na menších modelech, ukazující, že SGLangova optimalizace se dobře generalizuje na větší modely. Guidance a LMQL byly vynechány kvůli nedostatku efektivní implementace tensorového paralelismu.

Výsledky na multi-modálních modelech
SGLang má nativní podporu pro multi-modální modely s primitivy pro obraz a video. Optimalizace v tomto článku jsou kompatibilní s multi-modálními modely. Pro RadixAttention je hash vstupních obrazů vypočten a použit jako klíč v radix stromu, umožňující opětovné použití KV cache obrazových tokenů ze stejného obrazu. LLaVA-v1.5-7B (obraz) byl spuštěn na llava-bench-in-the-wild a LLaVA-NeXT-34B (video) na ActivityNet. Protože tyto modely nejsou dobře podporovány jinými systémy, byla použita původní implementace autorů modelů v Hugging Face Transformers jako baseline. Jak je ukázáno v následující tabulce, SGLang poskytuje propustnost až o 6× vyšší na těchto benchmarcích. V llava-bench-in-the-wild byly zpracovány více otázek o stejném obrazu, a SGLang runtime opětovně využil KV cache v tomto případě.

Nasazení do produkce
SGLang byl nasazen v Chatbot Arena pro službu modelů s otevřenými váhami. Kvůli nízké zátěži pro některé modely slouží pouze jeden SGLang worker pro každý model. Po jednom měsíci byla pozorována 52,4% míra zásahu RadixAttention cache pro LLaVA-Next-34B a 74,1% pro Vicuna-33B. Zásahy cache pocházely ze společných systémových zpráv, často opakovaně použitých příkladových obrazů a multi-turn chat historie. To snížilo latenci prvního tokenu v průměru o 1,7× pro Vicuna-33B.

Závěrečné myšlenky
V tomto článku jsme diskutovali o SGLang, nově zavedeném systému, který se snaží vyřešit efektivní provedení komplexních programů jazykových modelů. SGLang se skládá z frontendového jazyka a runtime. Frontend zjednodušuje programování pomocí primitiv pro generaci a řízení paralelismu, zatímco runtime urychluje provedení pomocí nových optimalizací, jako je RadixAttention pro opětovné použití KV cache a komprimované konečné automaty pro rychlejší dekódování strukturovaných výstupů. Experimenty prokázaly, že SGLang dosahuje až 6,4× vyšší propustnosti ve srovnání se stávajícími systémy inference na různých velkých jazykových a multimodálních modelech, řešících úkoly, jako je řízení agentů, logické uvažování, few-shot learning benchmarky, dekódování JSON, generace s podporou načtení a multi-turn chat.












