AI-modeller och plattformar

SGLang: Effektiv Exekvering av Strukturerade Språkmodellsprogram

mm
Lägg till Unite.AI bland dina föredragna källor på Google

Stora språkmodeller (LLM) används alltmer för komplexa uppgifter som kräver flera generationsanrop, avancerade prompttekniker, kontrollflöde och strukturerade in-/utdata. Men effektiva system för programmering och exekvering av dessa applikationer saknas. SGLang, ett nyligen introducerat system, syftar till att åtgärda detta genom att tillhandahålla effektiv exekvering av komplexa språkmodellsprogram. SGLang består av ett frontend-språk och en runtime. Frontenden förenklar programmeringen med primitiver för generation och parallellismkontroll, medan runtime accelererar exekveringen genom nya optimeringar som RadixAttention för KV-cacheåteranvändning och komprimerade finita tillståndsmaskiner för snabbare strukturerad utdatadekodning. Experiment visar att SGLang uppnår upp till 6,4 gånger högre genomströmning jämfört med state-of-the-art-inferenssystem på olika stora språk- och multimodella modeller, som hanterar uppgifter som agentkontroll, logiskt resonemang, few-shot-lärandebenchmark, JSON-dekodning, återvinning förstärkt generationspipeliner och multi-turn-chatt.

De senaste framstegen inom LLM-förmågor har utökat deras användbarhet, vilket möjliggör hantering av en bredare range av allmänna uppgifter och fungerar som autonoma agenter. I dessa applikationer engagerar sig LLM i multi-round-planering, resonemang och interaktion med externa miljöer. Detta underlättas genom verktygsanvändning, flera inmatningsmodaler och olika prompttekniker, såsom few-shot-lärande, självkonsekvens, skelett av tankar och träd av tankar. Dessa nya användningsfall kräver flera, ofta beroende, LLM-generationsanrop, vilket indikerar en trend att använda multi-anropsstrukturer för att slutföra komplexa uppgifter.

Denna förändring markerar en övergång från enkel chatt till en mer sofistikerad programmatisk användning av LLM, där program schemalägger och kontrollerar generationsprocesserna för LLM. Dessa program kallas “Språkmodellsprogram” (LM-program). Avancerade prompttekniker och agenta arbetsflöden faller inom ramen för LM-program. Det finns två vanliga egenskaper hos LM-program: (1) LM-program innehåller vanligtvis flera LLM-anrop med kontrollflöde för att slutföra komplexa uppgifter och förbättra den övergripande kvaliteten. (2) LM-program tar emot strukturerade indata och producerar strukturerade utdata, vilket möjliggör sammansättning av LM-program och integrering i befintliga programsystem.

I den här artikeln kommer vi att ta en djupare titt på SGLang-ramverket, undersöka dess arkitektur, analysera dess prestanda och jämföra det med state-of-the-art-ramverk. Så låt oss komma igång.

En Introduktion till SGLang

Trots den omfattande användningen av LM-program är nuvarande system för att uttrycka och exekvera dem fortfarande ineffektiva. SGLang identifierar två primära utmaningar förknippade med den effektiva användningen av LM-program:

  • Programmeringskomplexitet: Utveckling av LM-program är tråkigt och svårt på grund av den icke-deterministiska naturen hos LLM. Detta inkluderar omfattande strängmanipulation, experimentell justering av prompt, skör utdataparsing, hantering av flera inmatningsmodaler och implementering av parallellismmekanismer. Denna komplexitet minskar avsevärt läsbarheten för till och med enkla program.
  • Exekveringsineffektivitet: Exekvering av LM-program är ineffektiv på grund av redundant beräkning och minnesanvändning. State-of-the-art-inferensmotorer, optimerade för att minska latensen och förbättra genomströmningen, saknar direkt kunskap om arbetsbelastningen, vilket resulterar i betydande ineffektiviteter. Ett anmärkningsvärt exempel är återanvändning av Key-Value (KV)-cachen, som består av återanvändbara intermediära tensorer som är viktiga för generativ inferens. Nuvarande system saknar effektiva mekanismer för att underlätta KV-cacheåteranvändning över flera LLM-anrop som delar en gemensam prefix, vilket leder till onödiga beräkningar och slösad minne. Dessutom är begränsad dekodning för strukturerade utdata, såsom JSON-läge, underoptimalt eftersom befintliga system bara dekoder en token i taget.

För att åtgärda dessa utmaningar introducerar SGLang ett strukturerat generationspråk för LLM. Den grundläggande idén är att systematiskt utnyttja den multi-anropsstruktur som finns i LM-program för effektiv exekvering. Som visas i figuren nedan består SGLang av två delar: ett frontend-språk och en backend-runtime.

Frontenden förenklar programmeringen av LM-program, och runtime accelererar deras exekvering. Dessa delar kan arbeta tillsammans för bättre prestanda eller fungera oberoende av varandra.

SGLang är ett domänspecifikt språk som är inbäddat i Python, som tillhandahåller primitiver för generation (t.ex. utöka, generera, välja) och parallellismkontroll (t.ex. fork, join). Det är kompatibelt med Pythons kontrollflöde och bibliotek, vilket möjliggör utveckling av avancerade promptarbetsflöden med nativ Python-syntax. SGLang innehåller en tolk och en kompilator. Tolken hanterar prompttillståndet som en ström och skickar primitive operationer till strömmen för asynkron exekvering, vilket säkerställer korrekt kontroll över synkronisering och intra-program-parallellism. Dessutom kan SGLang-program spåras och kompilera för ytterligare optimeringar.

  • RadixAttention: Denna teknik möjliggör automatisk återanvändning av KV-cachen över flera generationsanrop. I befintliga inferensmotorer kasseras KV-cachen för en begäran efter bearbetning, vilket förhindrar återanvändning över flera anrop och bromsar exekveringen. SGLang underhåller en LRU-cache av KV-cachen inom en radix-träd, som hanterar KV-cachen som en traditionell cache och använder radix-trädet för effektiv matchning, införing och borttagning. Detta möjliggör för runtime att hantera olika återanvändningsmönster effektivt.
  • Komprimerad finit tillståndsmaskin: Denna teknik möjliggör snabbare begränsad dekodning för strukturerade utdata. Befintliga system följer begränsningar endast för nästa token, vilket gör dem till en token i taget. Istället analyserar SGLang begränsningarna och bygger en komprimerad finit tillståndsmaskin för att representera dem, vilket komprimerar en multi-token-sökväg till en enda stegsökväg när det är möjligt, och möjliggör dekodning av flera token på samma gång för snabbare hastighet.
  • API spekulativ exekvering: För API-modeller som OpenAI:s GPT-4 introducerar SGLang API spekulativ exekvering för att optimera multi-anropsprogram.

Med SGLang implementerades olika LLM-applikationer, inklusive agentkontroll, logiskt resonemang, few-shot-lärandebenchmark, JSON-dekodning, återvinning förstärkt generationspipeliner, multi-turn-chatt och multi-modalt bearbetning. Prestandan testades på modeller som Llama-7B/70B, Mistral-8x7B, LLaVA-v1.5-7B (bild) och LLaVA-NeXT-34B (video) på NVIDIA (NVDA ) A10G och A100 GPU:er. Experimentella resultat visar att SGLang uppnår upp till 6,4 gånger högre genomströmning över en bred range av arbetsbelastningar, modeller och hårdvarukonfigurationer, jämfört med befintliga programmerings- och inferenssystem, inklusive Guidance, vLLM och LMQL.

SGLang: Programmeringsmodell och Metodik

SGLang-programmeringsmodellen introduceras genom ett löpande exempel, som beskriver dess språkprimitiver och exekveringslägen, och som anger runtime-optimiseringsmöjligheter. Denna modell förenklar tråkiga operationer i multi-anropsarbetsflöden (t.ex. strängmanipulation, API-anrop, begränsningsspecifikation, parallellism) genom att tillhandahålla flexibla och sammansatta primitiver. SGLang är ett domänspecifikt språk som är inbäddat i Python.

Funktionen multi_dimensional_judge tar tre argument: `s`, `path` och `essay`. s hanterar prompttillståndet, path är bildfilens sökväg och essay är essätexten. Nya strängar och SGLang-primitiver kan läggas till tillståndet s för exekvering med +=-operatören. Först lägger funktionen till bilden och essän till prompten. Den kontrollerar sedan om essän är relaterad till bilden med hjälp av välj och lagrar resultatet i s[“related”]. Om det är relaterat, delas prompten upp i tre kopior för parallell utvärdering från olika dimensioner med hjälp av generera för att lagra resultaten i f[“judgment”]. Sedan sammanfogar den domarna, genererar en sammanfattning och tilldelar ett betyg. Slutligen returnerar den resultaten i JSON-format, enligt ett schema definierat av en reguljär uttrycksbegränsning regex. SGLang förenklar avsevärt detta program, eftersom ett motsvarande program som använder ett OpenAI-liknande gränssnitt skulle kräva 2,1 gånger så många rader kod på grund av manuell strängmanipulation och parallellismkontroll.

SGLang tillhandahåller primitiver för att kontrollera prompttillstånd, generation och parallellism, som kan användas med Python-syntax och bibliotek. Här är primitiverna:

gen: Anropar en modell för att generera och lagrar resultaten i en variabel med det namn som anges i dess första argument. Det stöder ett regex-argument för att begränsa utdata till att följa en grammatik definierad av ett reguljärt uttryck (t.ex. ett JSON-schema).

  • välj: Anropar en modell för att välja det högsta sannolikhetsalternativet från en lista.
  • += eller utöka: Lägger till en sträng till prompten.
  • [variabel_namn]: Hämtar resultaten från en generation.
  • fork: Skapar parallella grenar av prompttillståndet.
  • join: Sammanfogar prompttillståndet.
  • bild och video: Tar emot bild- och videoinmatningar.

Det enklaste sättet att exekvera ett SGLang-program är genom en tolk, där en prompt behandlas som en asynkron ström. Primitiver som utöka, generera och välj skickas till strömmen för asynkron exekvering. Dessa icke-blockerande anrop tillåter Python-kod att fortsätta köras utan att vänta på att generationen ska slutföras, liknande lansering av CUDA-kärnor asynkront. Varje prompt hanteras av en strömexekutor i en bakgrundstråd, vilket möjliggör intra-program-parallellism. Hämtning av generationsresultat kommer att blockera tills de är klara, vilket säkerställer korrekt synkronisering. Alternativt kan SGLang-program kompilera som beräkningsgrafer och exekveras med en grafexekutor, vilket möjliggör ytterligare optimeringar. Denna artikel använder tolk-läge som standard och diskuterar kompilatorresultat i Appendix D. SGLang stöder öppna modeller med sin egen SGLang Runtime (SRT), samt API-modeller som OpenAI och Anthropic-modeller.

Programmeringssystem för LLM kan klassificeras som högnivå (t.ex. LangChain, DSPy) och lågnivå (t.ex. LMQL, Guidance, SGLang). Högnivåsystem tillhandahåller fördefinierade eller auto-genererade prompt, såsom DSPy:s prompt-optimizer. Lågnivåsystem ändrar vanligtvis inte prompt, men tillåter direkt manipulation av prompt och primitiver. SGLang är ett lågnivåsystem liknande LMQL och Guidance. Följande tabell jämför deras funktioner.

SGLang fokuserar mer på runtime-effektivitet och kommer med sin egen co-designad runtime, vilket möjliggör nya optimeringar. Högnivåspråk (t.ex. DSPy) kan kompilera till lågnivåspråk (t.ex. SGLang). Integrationen av SGLang som backend i DSPy för bättre runtime-effektivitet visas senare.

Ovanstående exempel visar RadixAttention-operationer med en LRU-utvisningspolicy över nio tidpunkter, vilket visar den dynamiska tilldelningen och utvisningen av noder i svar på olika typer av begäranden, vilket säkerställer effektiv KV-cacheåteranvändning och minneshantering.

Steg 1: Radix-trädet är initialt tomt.

Steg 2: Servern bearbetar en inkommande användarbegäran “Hej” och svarar med LLM-utdata “Hej!”. Systemprompten “Du är en hjälpsam assistent”, användarbegäran “Hej!” och LLM-svaret “Hej!” konsolideras till trädet som en enda kant länkad till en ny nod.

Steg 3: En ny prompt anländer och servern hittar prefixet för prompten (dvs. den första vändningen i samtalet) i radix-trädet och återanvänder dess KV-cache. Den nya vändningen läggs till i trädet som en ny nod.

Steg 4: En ny chatsession börjar. Noden från Steg 3 delas upp i två noder för att tillåta att de två chatsessionerna delar systemprompten.

Steg 5: Den andra chatsessionen fortsätter. Men på grund av minnesbegränsningar måste en nod från Steg 4 utvisas. Den nya vändningen läggs till efter den återstående noden från Steg 4.

Steg 6: Servern tar emot en few-shot-lärandebegäran, bearbetar den och infogar den i trädet. Rotnoden delas eftersom den nya begäran inte delar något prefix med befintliga noder.

Steg 7: Servern tar emot en batch med fler few-shot-lärandebegäranden. Dessa begäranden delar samma uppsättning few-shot-exempel, så en nod från Steg 6 delas för att möjliggöra delning.

Steg 8: Servern tar emot ett nytt meddelande från den första chatsessionen. Den utvisar alla noder från den andra chatsessionen eftersom de är minst nyligen använda.

Steg 9: Servern tar emot en begäran om att sampla fler svar för frågorna i en nod från Steg 8, troligen för självkonsekvenspromptning. För att göra plats för dessa begäranden utvisas flera noder.

Detta exempel visar hur RadixAttention hanterar den dynamiska tilldelningen och utvisningen av noder i svar på olika typer av begäranden, vilket säkerställer effektiv KV-cacheåteranvändning och minneshantering.

SGLang: Utvärdering och Resultat

Resultat på Öppna Modeller

Latens- och genomströmningsresultaten visas i följande figurer. SGLang förbättrar genomströmningen med upp till 6,4 gånger och minskar latensen med upp till 3,7 gånger. Dessa förbättringar beror på KV-cacheåteranvändning, utnyttjande av parallellism inom ett enda program och snabbare begränsad dekodning.

På dessa benchmark-tester varvar cache-träfffrekvensen mellan 50% och 99%. Figur 13 (Bilaga) listar de uppnådda och optimala cache-träfffrekvenserna för alla, vilket visar att SGLang:s cache-medvetna schemaläggning närmar sig 96% av den optimala träfffrekvensen i genomsnitt.

Resultat på Större Modeller med Tensor-Parallellism

Större modeller, Mixtral-8x7B och Llama-70B, testades med tensor-parallellism på samma uppsättning benchmark-tester, och resultaten rapporteras i följande figur. Förbättringen på större modeller visar en trend liknande den som observerats på mindre modeller, vilket indikerar att SGLang:s optimering generaliserar väl till större modeller. Guidance och LMQL utelämnades på grund av brist på effektiva implementeringar av tensor-parallellism.

Resultat på Multi-Modala Modeller

SGLang har nativt stöd för multi-modala modeller med bild- och video-primitiver. Optimeringarna i denna artikel är kompatibla med multi-modala modeller. För RadixAttention beräknas hashen för inmatningsbilderna och används som nyckel i radix-trädet, vilket möjliggör återanvändning av KV-cachen för bildtoken från samma bild. LLaVA-v1.5-7B (bild) kördes på llava-bench-in-the-wild och LLaVA-NeXT-34B (video) på ActivityNet. Eftersom dessa modeller inte stöds väl av andra baseline-system användes modellförfattarnas ursprungliga implementation i Hugging Face Transformers som baseline. Som visas i följande tabell tillhandahåller SGLang en genomströmning på upp till 6 gånger högre på dessa benchmark-tester. I llava-bench-in-the-wild hanterades flera frågor om samma bild, och SGLang-runtime återanvände KV-cachen i detta fall.

Produktionsdistribution

SGLang har distribuerats i Chatbot Arena för att betjäna öppna modeller. På grund av låg trafik för vissa modeller betjänar endast en SGLang-arbetare varje modell. Efter en månad observerades en RadixAttention-cache-träfffrekvens på 52,4% för LLaVA-Next-34B och 74,1% för Vicuna-33B. Cache-träffar kom från vanliga systemmeddelanden, ofta återanvända exempelbilder och multi-turn-chatt-historik. Detta minskade den första token-latensen i genomsnitt med 1,7 gånger för Vicuna-33B.

Slutliga Tankar

I denna artikel har vi talat om SGLang, ett nyligen introducerat system som syftar till att tillhandahålla effektiv exekvering av komplexa språkmodellsprogram. SGLang består av ett frontend-språk och en runtime. Frontenden förenklar programmeringen med primitiver för generation och parallellismkontroll, medan runtime accelererar exekveringen genom nya optimeringar som RadixAttention för KV-cacheåteranvändning och komprimerade finita tillståndsmaskiner för snabbare strukturerad utdatadekodning. Experiment visar att SGLang uppnår upp till 6,4 gånger högre genomströmning jämfört med state-of-the-art-inferenssystem på olika stora språk- och multimodella modeller, som hanterar uppgifter som agentkontroll, logiskt resonemang, few-shot-lärandebenchmark, JSON-dekodning, återvinning förstärkt generationspipeliner och multi-turn-chatt.

En ingenjör till yrket, en författare av hjärtat. Kunal är en teknisk skribent med ett djupt kärlek och förståelse för AI och ML, dedikerad till att förenkla komplexa begrepp inom dessa områden genom sin engagerande och informativa dokumentation.