Inteligență artificială
SGLang: Execuție Eficientă a Programelor de Modele de Limbaj Structurate
Modelele de limbaj mari (LLM) sunt din ce în ce mai utilizate pentru sarcini complexe care necesită multiple apeluri de generare, tehnici avansate de promptare, flux de control și intrări/ieșiri structurate. Cu toate acestea, sistemele eficiente pentru programarea și executarea acestor aplicații lipsesc. SGLang, un sistem nou introdus, își propune să abordeze această problemă prin oferirea unei execuții eficiente a programelor complexe de modele de limbaj. SGLang cuprinde un limbaj de frontend și un runtime. Frontend-ul simplifică programarea cu primitive pentru generare și control al paralelismului, în timp ce runtime-ul accelerează executarea prin optimizări noi, cum ar fi RadixAttention pentru reutilizarea cache-ului KV și mașini finite comprimate pentru decodarea mai rapidă a ieșirilor structurate. Experimentele demonstrează că SGLang atinge până la 6,4× mai multă performanță în comparație cu sistemele de inferență de ultimă generație pe diverse modele de limbaj mari și multimodale, abordând sarcini precum controlul agenților, raționamentul logic, benchmark-urile de învățare în câteva exemple, decodarea JSON, pipeline-urile de generare augmentate cu recuperare și chat-ul multi-turn.
Avansările recente în capacitățile LLM au extins utilitatea lor, permițându-le să gestioneze o gamă mai largă de sarcini generale și să funcționeze ca agenți autonomi. În aceste aplicații, LLM-urile se angajează în planificare multi-turn, raționament și interacțiune cu medii externe. Acest lucru este facilitat prin utilizarea unor instrumente, multiple modalități de intrare și diverse tehnici de promptare, cum ar fi învățarea în câteva exemple, auto-consistența, scheletul de gândire și arborele de gândire. Aceste noi cazuri de utilizare necesită multiple apeluri LLM, adesea dependente, indicând o tendință de a utiliza structuri multi-apele pentru a finaliza sarcini complexe.
Această schimbare marchează o tranziție de la utilizarea simplă a chat-ului la o utilizare mai sofisticată și programatică a LLM-urilor, unde programele planifică și controlează procesele de generare ale LLM-urilor. Aceste programe sunt denumite “Programe de Modele de Limbaj” (LM Programe). Tehnicile avansate de promptare și fluxurile de lucru agenților se încadrează în domeniul de aplicare al programelor LM. Există două proprietăți comune ale programelor LM: (1) Programele LM implică de obicei multiple apeluri LLM, interspersate cu flux de control, pentru a finaliza sarcini complexe și a îmbunătăți calitatea generală. (2) Programele LM primesc intrări structurate și produc ieșiri structurate, permițând compunerea programelor LM și integrarea lor în sisteme software existente.
În acest articol, vom face o analiză mai profundă a cadrului SGLang, explorând arhitectura sa, analizând performanța sa și comparându-l cu cadrele de ultimă generație. Deci, să începem.
Introducere în SGLang
În ciuda utilizării extinse a programelor LM, sistemele actuale pentru exprimarea și executarea lor rămân ineficiente. SGLang identifică două provocări principale asociate cu utilizarea eficientă a programelor LM:
- Complexitatea programării: Dezvoltarea programelor LM este o sarcin dificilă și laborioasă din cauza naturii non-deterministe a LLM-urilor. Acest lucru implică manipularea extinsă a șirurilor, reglarea experimentală a prompturilor, analiza fragilă a ieșirilor și implementarea mecanismelor de paralelism. Această complexitate reduce semnificativ lizibilitatea chiar și a programelor simple.
- Ineficiența executării: Executarea programelor LM este ineficientă din cauza calculului redundant și a utilizării memoriei. Motoarele de inferență de ultimă generație, optimizate pentru a reduce latența și a îmbunătăți debitul, lipsesc cunoașterea directă a sarcinii de lucru, ceea ce duce la ineficiențe semnificative. Un exemplu notabil este reutilizarea cache-ului KV, care constă în tensori intermediari reutilizabili esențiali pentru inferența generativă. Sistemele actuale lipsesc mecanisme eficiente pentru a facilita reutilizarea cache-ului KV între multiple apeluri LLM care împărtășesc un prefix comun, ceea ce duce la calcule inutile și la irosirea memoriei. De asemenea, decodarea constrânsă pentru ieșiri structurate, cum ar fi modul JSON, este suboptimă, deoarece sistemele existente decodifică doar un token odată.
Pentru a aborda aceste provocări, SGLang introduce un limbaj de generare structurat pentru LLM-uri. Ideea de bază constă în exploatarea sistematică a structurii multi-apele din programele LM pentru executarea eficientă. Așa cum se arată în figura următoare, SGLang are două părți: un frontend de limbaj și un runtime.

Frontend-ul simplifică programarea programelor LM, iar runtime-ul accelerează executarea lor. Aceste părți pot lucra împreună pentru o performanță mai bună sau pot funcționa independent.
SGLang este un limbaj specific de domeniu încorporat în Python, care oferă primitive pentru generare (de exemplu, extinde, gen, selectează) și control al paralelismului (de exemplu, fork, join). Este compatibil cu controlul de flux și cu bibliotecile Python, permițând utilizatorilor să dezvolte fluxuri de lucru avansate de promptare cu sintaxă Python nativă. SGLang include un interpretor și un compilator. Interpretorul gestionează starea promptului ca un flux și trimite operațiuni primitive către flux pentru executare asincronă, asigurând controlul corespunzător al sincronizării și paralelismului intra-program. De asemenea, programele SGLang pot fi urmărite și compilate pentru optimizări suplimentare.
- RadixAttention: Această tehnică permite reutilizarea automată a cache-ului KV între multiple apeluri de generare. În motoarele de inferență existente, cache-ul KV al unei cereri este eliminat după procesare, ceea ce împiedică reutilizarea între multiple apeluri și încetinește executarea. SGLang menține un cache LRU al cache-ului KV într-un arbore radix, gestionând cache-ul KV ca pe un cache tradițional și utilizând arborele radix pentru împerechere, inserare și eliminare eficientă. Acest lucru permite runtime-ului să gestioneze diverse modele de reutilizare în mod eficient.
- Mașină finită comprimată: Această tehnică permite decodarea mai rapidă a ieșirilor structurate. Sistemele existente urmează constrângerile doar pentru următorul token, permițând decodificarea unui token odată. În schimb, SGLang analizează constrângerile și construiește o mașină finită comprimată pentru a le reprezenta, comprimând un drum multi-token într-un drum cu un singur pas, atunci când este posibil, permițând decodificarea mai multor tokeni deodată pentru o viteză mai mare.
- Execuție speculativă API: Pentru modelele API, cum ar fi OpenAI GPT-4, SGLang introduce execuția speculativă API pentru a optimiza programele multi-apele.
Utilizând SGLang, diverse aplicații LLM au fost implementate, inclusiv controlul agenților, raționamentul logic, benchmark-urile de învățare în câteva exemple, decodarea JSON, pipeline-urile de generare augmentate cu recuperare, chat-ul multi-turn și procesarea multi-modală. Performanța a fost testată pe modele, inclusiv Llama-7B/70B, Mistral-8x7B, LLaVA-v1.5-7B (imagine) și LLaVA-NeXT-34B (video) pe GPU-uri NVIDIA A10G și A100. Rezultatele experimentale arată că SGLang atinge până la 6,4× mai multă performanță pe o gamă largă de sarcini de lucru, modele și configurații de hardware, în comparație cu sistemele de programare și inferență existente, inclusiv Guidance, vLLM și LMQL.
SGLang: Model de programare și metodologie
Modelul de programare SGLang este introdus printr-un exemplu de lucru, descriind primitivele sale de limbaj și modurile de executare, și evidențiind oportunitățile de optimizare la nivel de runtime. Acest model simplifică operațiunile laborioase din fluxurile de lucru multi-apele (de exemplu, manipularea șirurilor, apelurile API, specificarea constrângerilor, paralelismul) prin oferirea unor primitive flexibile și compozabile. SGLang este un limbaj specific de domeniu încorporat în Python.

Funcția multi_dimensional_judge ia trei argumente: `s`, `path` și `essay`. s gestionează starea promptului, path este calea fișierului imagine, iar essay este textul eseului. Noi șiruri și primitive SGLang pot fi adăugate la starea s pentru executare utilizând operatorul +=. Mai întâi, funcția adaugă imaginea și eseul la prompt. Apoi, verifică dacă eseul este legat de imagine utilizând select, stocând rezultatul în s[“related”]. Dacă este legat, promptul este bifurcat în trei copii pentru evaluare paralelă din diferite dimensiuni, utilizând gen pentru a stoca rezultatele în f[“judgment”]. Următorul, combină judecățile, generează un rezumat și atribuie o notă literară. În final, returnează rezultatele în format JSON, urmând un schema definită de o constrângere de expresie regulată regex. SGLang simplifică semnificativ acest program, deoarece un program echivalent utilizând o interfață similară cu OpenAI ar necesita 2,1× mai multe linii de cod din cauza manipulării manuale a șirurilor și controlului paralelismului.
SGLang oferă primitive pentru controlul stării promptului, generării și paralelismului, care pot fi utilizate cu sintaxă și biblioteci Python. Iată primitivele:
gen: apelează un model pentru a genera și stochează rezultatele într-o variabilă cu numele specificat în primul argument. Suportă un argument `regex` pentru a constrânge ieșirea să urmeze o gramatică definită de o expresie regulată (de exemplu, un schema JSON).
- selectează: apelează un model pentru a alege opțiunea cu cea mai mare probabilitate dintr-o listă.
- += sau extinde: adaugă un șir la prompt.
- [nume_variabilă]: preia rezultatele unei generări.
- fork: creează bifurcări paralele ale stării promptului.
- join: reunește starea promptului.
- imagine și video: primesc intrări de imagine și video.
Cel mai simplu mod de a executa un program SGLang este prin intermediul unui interpretor, unde un prompt este tratat ca un flux asincron. Primitive precum extinde, gen și selectează sunt trimise către flux pentru executare asincronă. Aceste apeluri non-blocante permit codului Python să continue rularea fără a aștepta sfârșitul generării, similar cu lansarea kernel-urilor CUDA în mod asincron. Fiecare prompt este gestionat de un executor de flux într-un fir de fundal, permițând paralelismul intra-program. Preluarea rezultatelor generării va bloca până când acestea sunt gata, asigurând sincronizarea corectă. Alternativ, programele SGLang pot fi compilate ca grafuri computaționale și executate cu un executor de graf, permițând optimizări suplimentare.
Sistemele de programare pentru LLM-uri pot fi clasificate în sisteme de nivel înalt (de exemplu, LangChain, DSPy) și sisteme de nivel scăzut (de exemplu, LMQL, Guidance, SGLang). Sistemele de nivel înalt oferă prompturi predefinite sau generate automat, cum ar fi optimizatorul de prompturi DSPy. Sistemele de nivel scăzut nu alterează în general prompturile, dar permit manipularea directă a prompturilor și primitivelor. SGLang este un sistem de nivel scăzut, similar cu LMQL și Guidance.

SGLang se concentrează mai mult pe eficiența runtime și vine cu un runtime co-proiectat, permițând optimizări noi. Limbajele de nivel înalt (de exemplu, DSPy) pot fi compilate în limbaje de nivel scăzut (de exemplu, SGLang). Integrarea SGLang ca backend în DSPy pentru o eficiență mai bună a runtime-ului este demonstrată mai târziu.

Exemplul de mai sus ilustrează operațiunile RadixAttention cu o politică de evacuare LRU la nouă puncte de timp, arătând evoluția dinamică a arborelui radix în răspuns la diverse cereri. Aceste cereri includ două sesiuni de chat, un lot de întrebări de învățare în câteva exemple și mostre de auto-consistență. Fiecare muchie a arborelui poartă o etichetă care denotă un șir sau o secvență de tokeni. Nodurile sunt colorate pentru a reflecta stări diferite: verde pentru noduri nou adăugate, albastru pentru noduri cache accesate în timpul punctului de timp și roșu pentru noduri evacuate.
Acest exemplu demonstrează modul în care RadixAttention gestionează alocarea dinamică și evacuarea nodurilor în răspuns la diverse tipuri de cereri, asigurând reutilizarea eficientă a cache-ului KV și gestionarea memoriei.
SGLang: Evaluare și rezultate
Rezultate pe modele cu greutate deschisă
Rezultatele latenței și debitului sunt prezentate în figurile următoare. SGLang îmbunătățește debitul cu până la 6,4× și reduce latența cu până la 3,7×. Aceste îmbunătățiri rezultă din reutilizarea cache-ului KV, exploatarea paralelismului în cadrul unui singur program și decodarea mai rapidă a ieșirilor structurate.

Pe aceste benchmark-uri, rata de lovire a cache-ului variază de la 50% la 99%. Figura 13 (Anexa) listează ratele de lovire a cache-ului atinse și optime pentru toate acestea, arătând că abordarea de programare conștientă de cache a SGLang se apropie de 96% de rata de lovire optimă în medie.

Rezultate pe modele mai mari cu paralelism tensorial
Modelele mai mari, Mixtral-8x7B și Llama-70B, au fost testate cu paralelism tensorial pe același set de benchmark-uri, iar rezultatele sunt raportate în figura următoare. Accelerarea pe modele mai mari arată o tendință similară cu cea observată pe modele mai mici, indicând că optimizările SGLang se generalizează bine la modele mai mari. Guidance și LMQL au fost omise din cauza lipsei unor implementări eficiente ale paralelismului tensorial.

Rezultate pe modele multi-modale
SGLang are suport nativ pentru modele multi-modale cu primitivele de imagine și video. Optimizările din acest articol sunt compatibile cu modelele multi-modale. Pentru RadixAttention, hash-ul intrării de imagine este calculat și utilizat ca cheie în arborele radix, permițând reutilizarea cache-ului KV al tokenilor de imagine din aceeași imagine. LLaVA-v1.5-7B (imagine) a fost rulat pe llava-bench-in-the-wild, iar LLaVA-NeXT-34B (video) pe ActivityNet. Deoarece aceste modele nu sunt bine susținute de sistemele de bază, implementarea originală a autorilor de modele în Hugging Face Transformers a fost utilizată ca sistem de bază. Așa cum se arată în tabela următoare, SGLang oferă un debit de până la 6× mai mare pe aceste benchmark-uri. În llava-bench-in-the-wild, au fost gestionate multiple întrebări despre aceeași imagine, iar runtime-ul SGLang a reutilizat cache-ul KV în acest caz.

Dezvoltare de producție
SGLang a fost implementat în Chatbot Arena pentru a servi modele cu greutate deschisă. Din cauza traficului scăzut pentru unele modele, doar un lucrător SGLang deservește fiecare. După o lună, s-a observat o rată de lovire a cache-ului RadixAttention de 52,4% pentru LLaVA-Next-34B și 74,1% pentru Vicuna-33B. Lovirile de cache proveneau din mesaje sistem comune, imagini exemple frecvent reutilizate și istoricul de chat multi-turn. Acest lucru a redus latența primului token cu o medie de 1,7× pentru Vicuna-33B.

Gânduri finale
În acest articol, am discutat despre SGLang, un sistem nou introdus, care își propune să ofere o execuție eficientă a programelor complexe de modele de limbaj. SGLang cuprinde un limbaj de frontend și un runtime. Frontend-ul simplifică programarea cu primitive pentru generare și control al paralelismului, în timp ce runtime-ul accelerează executarea prin optimizări noi, cum ar fi RadixAttention pentru reutilizarea cache-ului KV și mașini finite comprimate pentru decodarea mai rapidă a ieșirilor structurate. Experimentele demonstrează că SGLang atinge până la 6,4× mai multă performanță în comparație cu sistemele de inferență de ultimă generație pe diverse modele de limbaj mari și multimodale, abordând sarcini precum controlul agenților, raționamentul logic, benchmark-urile de învățare în câteva exemple, decodarea JSON, pipeline-urile de generare augmentate cu recuperare și chat-ul multi-turn.












