Tech

SGLang: Execução Eficiente de Programas de Modelo de Linguagem Estruturada

Grandes modelos de linguagem (LLMs) são cada vez mais utilizados para tarefas complexas que exigem múltiplas chamadas de geração, técnicas avançadas de prompting, fluxo de controle e entradas/saídas estruturadas. No entanto, faltam sistemas eficientes para programar e executar esses aplicativos. O SGLang, um sistema recém-introduzido, visa resolver isso fornecendo execução eficiente de programas complexos de modelos de linguagem. O SGLang compreende uma linguagem de front-end e um tempo de execução. O front-end simplifica a programação com primitivas para controle de geração e paralelismo, enquanto o tempo de execução acelera a execução por meio de novas otimizações como RadixAttention para reutilização de cache KV e máquinas de estado finito compactadas para decodificação de saída estruturada mais rápida. Experimentos demonstram que o SGLang atinge até 6,4 × maior rendimento em comparação com sistemas de inferência de última geração em vários modelos de linguagem grande e multimodais, lidando com tarefas como controle de agente, raciocínio lógico, benchmarks de aprendizado de poucos disparos, decodificação JSON, pipelines de geração aumentada por recuperação e bate-papo multi-turn.

Avanços recentes em capacidades de LLM expandiram sua utilidade, permitindo que eles lidem com uma gama mais ampla de tarefas gerais e funcionem como agentes autônomos. Nessas aplicações, os LLMs se envolvem em planejamento multi-rodadas, raciocínio e interação com ambientes externos. Isso é facilitado pelo uso de ferramentas, múltiplas modalidades de entrada e várias técnicas de solicitação, como aprendizado de poucos disparos, autoconsistência, esqueleto de pensamento e árvore de pensamento. Esses novos casos de uso necessitam de múltiplas chamadas de geração de LLM, frequentemente dependentes, indicando uma tendência de uso de estruturas multi-chamadas para concluir tarefas complexas.

Essa mudança marca uma transição de um simples bate-papo para um uso programático mais sofisticado de LLMs, onde os programas agendam e controlam os processos de geração de LLMs. Esses programas são chamados de “Programas de Modelo de Linguagem” (Programas LM). Técnicas avançadas de prompting e fluxos de trabalho de agente estão dentro do escopo dos programas LM. Existem duas propriedades comuns dos programas LM: (1) os programas LM normalmente envolvem múltiplas chamadas LLM intercaladas com fluxo de controle para completar tarefas complexas e melhorar a qualidade geral. (2) os programas LM recebem entradas estruturadas e produzem saídas estruturadas, permitindo a composição de programas LM e integração em sistemas de software program existentes.

Neste artigo, vamos nos aprofundar no framework SGLang, explorando sua arquitetura, analisando seu desempenho e comparando-o com frameworks de última geração. Então, vamos começar.

Apesar do uso generalizado de programas LM, os sistemas atuais para expressá-los e executá-los permanecem ineficientes. O SGLang identifica dois desafios primários associados ao uso eficiente de programas LM:

  • Complexidade de programação: Desenvolver programas LM é tedioso e difícil devido à natureza não determinística dos LLMs. Isso envolve manipulação extensiva de strings, ajuste experimental de prompts, análise sintática de saída frágil, manipulação de múltiplas modalidades de entrada e implementação de mecanismos de paralelismo. Essa complexidade reduz significativamente a legibilidade até mesmo de programas simples.
  • Ineficiência de execução: a execução de programas LM é ineficiente devido à computação redundante e ao uso de memória. Os mecanismos de inferência de última geração, otimizados para reduzir a latência e melhorar o rendimento, não têm conhecimento direto da carga de trabalho, resultando em ineficiências significativas. Um exemplo notável é a reutilização do cache Key-Worth (KV), que consiste em tensores intermediários reutilizáveis ​​essenciais para inferência generativa. Os sistemas atuais não têm mecanismos eficazes para facilitar a reutilização do cache KV em várias chamadas LLM que compartilham um prefixo comum, levando a computações desnecessárias e desperdício de memória. Além disso, a decodificação restrita para saídas estruturadas, como o modo JSON, é subótima, pois os sistemas existentes decodificam apenas um token por vez.

Para lidar com esses desafios, o SGLang introduz uma Linguagem de Geração Estruturada para LLMs. A ideia central é explorar sistematicamente a estrutura de múltiplas chamadas em programas LM para execução eficiente. Conforme mostrado na figura a seguir, o SGLang tem duas partes: uma linguagem front-end e um tempo de execução back-end.

O front-end simplifica a programação de programas LM, e o runtime acelera sua execução. Essas partes podem trabalhar juntas para melhor desempenho ou funcionar de forma independente.

SGLang é uma linguagem específica de domínio incorporada em Python, fornecendo primitivas para geração (por exemplo, lengthen, gen, choose) e controle de paralelismo (por exemplo, fork, be a part of). É compatível com o fluxo de controle e bibliotecas do Python, permitindo que os usuários desenvolvam fluxos de trabalho de prompting avançados facilmente com a sintaxe nativa do Python. SGLang inclui um interpretador e um compilador. O interpretador gerencia o estado do immediate como um fluxo e envia operações primitivas ao fluxo para execução assíncrona, garantindo o controle adequado sobre a sincronização e o paralelismo intraprograma. Além disso, os programas SGLang podem ser rastreados e compilados para otimizações adicionais. O tempo de execução do SGLang propõe várias otimizações inovadoras para acelerar a execução de programas LM:

  • RadixAttention: Esta técnica permite a reutilização automática do cache KV em várias chamadas de geração. Em mecanismos de inferência existentes, o cache KV de uma solicitação é descartado após o processamento, impedindo a reutilização em várias chamadas e retardando a execução. O SGLang mantém um cache LRU do cache KV dentro de uma árvore radix, gerenciando o cache KV como um cache tradicional e usando a árvore radix para correspondência, inserção e remoção eficientes. Isso permite que o tempo de execução manipule vários padrões de reutilização de forma eficiente.
  • Máquina de estado finito compactada: esta técnica permite decodificação restrita mais rápida para saídas estruturadas. Os sistemas existentes seguem restrições apenas para o próximo token, tornando-os capazes de decodificar um token por vez. Em vez disso, o SGLang analisa as restrições e constrói uma máquina de estado finito compactada para representá-las, compactando um caminho multitoken em um caminho de etapa única sempre que possível, permitindo a decodificação de vários tokens de uma vez para maior velocidade.
  • Execução especulativa de API: para modelos somente de API, como o GPT-4 da OpenAI, o SGLang introduz a execução especulativa de API para otimizar programas de múltiplas chamadas.

Usando o SGLang, vários aplicativos LLM foram implementados, incluindo controle de agente, raciocínio lógico, benchmarks de aprendizado de poucos disparos, decodificação JSON, pipelines de geração aumentada por recuperação, bate-papo multi-turno e processamento multimodal. O desempenho foi testado em modelos incluindo Llama-7B/70B, Mistral-8x7B, LLaVA-v1.5-7B (imagem) e LLaVA-NeXT-34B (vídeo) em GPUs NVIDIA A10G e A100. Os resultados experimentais mostram que o SGLang atinge uma taxa de transferência até 6,4× maior em uma ampla gama de cargas de trabalho, modelos e configurações de {hardware}, em comparação com sistemas de programação e inferência existentes, incluindo Steering, vLLM e LMQL.

SGLang: Modelo e Metodologia de Programação

O modelo de programação SGLang é introduzido por meio de um exemplo em execução, descrevendo suas primitivas de linguagem e modos de execução, e delineando oportunidades de otimização de tempo de execução. Este modelo simplifica operações tediosas em fluxos de trabalho de múltiplas chamadas (por exemplo, manipulação de strings, chamadas de API, especificação de restrição, paralelismo) ao fornecer primitivas flexíveis e componíveis. SGLang é uma linguagem específica de domínio incorporada em Python. A figura a seguir mostra um programa que avalia um ensaio sobre uma imagem usando o método de solicitação branch-solve-merge.

2 4

A função juiz multidimensional leva três argumentos: `s`, `caminho` e `ensaio`. s gerencia o estado do immediate, path é o caminho do arquivo de imagem e essay é o texto do ensaio. Novas strings e primitivas SGLang podem ser anexadas ao estado s para execução usando o += operador. Primeiro, a função adiciona a imagem e o ensaio ao immediate. Em seguida, ela verifica se o ensaio está relacionado à imagem usando choose, armazenando o resultado em s(“relacionado”). Se relacionado, o immediate é bifurcado em três cópias para avaliação paralela de diferentes dimensões, usando gen para armazenar resultados em f(“julgamento”). Em seguida, ele mescla os julgamentos, gera um resumo e atribui uma nota de letra. Por fim, ele retorna os resultados no formato JSON, seguindo um esquema definido por uma restrição de expressão common expressão common. O SGLang simplifica muito este programa, pois um programa equivalente usando uma interface semelhante à API OpenAI ocuparia 2,1 vezes mais linhas de código devido à manipulação guide de strings e ao controle de paralelismo.

O SGLang fornece primitivos para controlar o estado do immediate, geração e paralelismo, que podem ser usados ​​com a sintaxe e bibliotecas do Python. Aqui estão os primitivos:

gen: Chama um modelo para gerar e armazena os resultados em uma variável com o nome especificado em seu primeiro argumento. Ele suporta um argumento `regex` para restringir a saída para seguir uma gramática definida por uma expressão common (por exemplo, um esquema JSON).

  • choose: chama um modelo para escolher a opção de maior probabilidade de uma lista.
  • += ou estender: acrescenta uma string ao immediate.
  • (variable_name): Busca os resultados de uma geração.
  • fork: Cria bifurcações paralelas do estado do immediate.
  • be a part of: Reingressa no estado do immediate.
  • imagem e vídeo: Receba entradas de imagem e vídeo.

A maneira mais simples de executar um programa SGLang é por meio de um interpretador, onde um immediate é tratado como um fluxo assíncrono. Primitivos como estender, gerar e selecionar são enviados ao fluxo para execução assíncrona. Essas chamadas não bloqueantes permitem que o código Python proceed em execução sem esperar que a geração termine, semelhante ao lançamento de kernels CUDA de forma assíncrona. Cada immediate é gerenciado por um executor de fluxo em um thread de segundo plano, permitindo o paralelismo intraprograma. A busca de resultados de geração será bloqueada até que estejam prontos, garantindo a sincronização correta. Alternativamente, os programas SGLang podem ser compilados como gráficos computacionais e executados com um executor de gráfico, permitindo mais otimizações. Este artigo usa o modo interpretador por padrão e discute os resultados do modo compilador no Apêndice D. O SGLang oferece suporte a modelos de peso aberto com seu próprio SGLang Runtime (SRT), bem como modelos de API, como OpenAI e modelos Anthropic.

Os sistemas de programação para LLMs podem ser classificados como de alto nível (por exemplo, LangChain, DSPy) e de baixo nível (por exemplo, LMQL, Steering, SGLang). Os sistemas de alto nível fornecem prompts predefinidos ou gerados automaticamente, como o otimizador de immediate do DSPy. Os sistemas de baixo nível normalmente não alteram os prompts, mas permitem a manipulação direta de prompts e primitivos. O SGLang é um sistema de baixo nível semelhante ao LMQL e ao Steering. A tabela a seguir compara seus recursos.

9

O SGLang foca mais na eficiência do tempo de execução e vem com seu próprio tempo de execução co-projetado, permitindo novas otimizações. Linguagens de alto nível (por exemplo, DSPy) podem ser compiladas para linguagens de baixo nível (por exemplo, SGLang). A integração do SGLang como um backend no DSPy para melhor eficiência do tempo de execução é demonstrada mais tarde.

3 4

O exemplo acima ilustra as operações RadixAttention com uma política de remoção de LRU em nove pontos de tempo, mostrando a evolução dinâmica da árvore radix em resposta a várias solicitações. Essas solicitações incluem duas sessões de bate-papo, um lote de consultas de aprendizado de poucos disparos e amostragem de autoconsistência. Cada aresta da árvore carrega um rótulo que denota uma substring ou uma sequência de tokens. Os nós são codificados por cores para refletir diferentes estados: verde para nós recém-adicionados, azul para nós em cache acessados ​​durante o ponto de tempo e vermelho para nós que foram removidos.

Passo 1: A árvore radix está inicialmente vazia.

Passo 2: O servidor processa uma mensagem de entrada do usuário “Olá” e responde com a saída LLM “Oi”. O immediate do sistema “Você é um assistente útil”, a mensagem do usuário “Olá!” e a resposta LLM “Oi!” são consolidados na árvore como uma única aresta vinculada a um novo nó.

Etapa 3: Um novo immediate chega, e o servidor encontra o prefixo do immediate (ou seja, o primeiro turno da conversação) na árvore radix e reutiliza seu cache KV. O novo turno é anexado à árvore como um novo nó.

Passo 4: Uma nova sessão de bate-papo começa. O nó da Etapa 3 é dividido em dois nós para permitir que as duas sessões de bate-papo compartilhem o immediate do sistema.

Etapa 5: A segunda sessão de bate-papo continua. No entanto, devido a limites de memória, um nó da Etapa 4 deve ser despejado. O novo turno é anexado após o nó restante da Etapa 4.

Etapa 6: O servidor recebe uma consulta de aprendizado de poucos disparos, processa-a e insere-a na árvore. O nó raiz é dividido porque a nova consulta não compartilha nenhum prefixo com nós existentes.

Passo 7: O servidor recebe um lote de consultas de aprendizado de poucos disparos adicionais. Essas consultas compartilham o mesmo conjunto de exemplos de poucos disparos, então um nó da Etapa 6 é dividido para habilitar o compartilhamento.

Passo 8: O servidor recebe uma nova mensagem da primeira sessão de chat. Ele despeja todos os nós da segunda sessão de chat, pois eles são usados ​​menos recentemente.

Passo 9: O servidor recebe uma solicitação para amostrar mais respostas para as perguntas em um nó da Etapa 8, provavelmente para solicitação de autoconsistência. Para abrir espaço para essas solicitações, vários nós são despejados.

Este exemplo demonstra como o RadixAttention lida com a alocação dinâmica e a remoção de nós em resposta a diferentes tipos de solicitações, garantindo a reutilização eficiente do cache KV e o gerenciamento de memória.

SGLang: Avaliação e Resultados

Resultados em modelos de peso aberto

Os resultados de latência e throughput são mostrados nas figuras a seguir. O SGLang melhora o throughput em até 6,4× e reduz a latência em até 3,7×. Essas melhorias resultam da reutilização do cache KV, da exploração do paralelismo dentro de um único programa e da decodificação mais rápida e restrita.

4 4

Nesses benchmarks, a taxa de acerto do cache varia de 50% a 99%. A Figura 13 (Apêndice) lista as taxas de acerto do cache alcançadas e ótimas para todos eles, mostrando que o agendamento com reconhecimento de cache do SGLang se aproxima de 96% da taxa de acerto ótima em média.

5 4

Resultados em modelos maiores com paralelismo tensorial

Modelos maiores, Mixtral-8x7B e Llama-70B, foram testados com paralelismo tensorial no mesmo conjunto de benchmarks, e os resultados são relatados na figura a seguir. A aceleração em modelos maiores mostra uma tendência semelhante à observada em modelos menores, indicando que a otimização do SGLang generaliza bem para modelos maiores. Orientação e LMQL foram omitidos devido à falta de implementações eficientes de paralelismo tensorial.

6 5

Resultados em modelos multimodais

O SGLang tem suporte nativo para modelos multimodais com as primitivas de imagem e vídeo. As otimizações neste artigo são compatíveis com modelos multimodais. Para RadixAttention, o hash das imagens de entrada é computado e usado como a chave na árvore radix, permitindo a reutilização do cache KV dos tokens de imagem da mesma imagem. LLaVA-v1.5-7B (imagem) foi executado no llava-bench-in-the-wild e LLaVA-NeXT-34B (vídeo) no ActivityNet. Como esses modelos não são bem suportados por outros sistemas de linha de base, a implementação authentic dos autores do modelo em Hugging Face Transformers foi usada como linha de base. Conforme mostrado na tabela a seguir, o SGLang fornece uma taxa de transferência até 6× maior nesses benchmarks. No llava-bench-in-the-wild, várias perguntas sobre a mesma imagem foram tratadas, e o tempo de execução do SGLang reutilizou o cache KV neste caso.

7 2

Implantação de produção

O SGLang foi implantado no Chatbot Enviornment para atender modelos de peso aberto. Devido ao baixo tráfego para alguns modelos, apenas um trabalhador SGLang atende cada um. Após um mês, foi observada uma taxa de acerto de cache RadixAttention de 52,4% para LLaVA-Subsequent-34B e 74,1% para Vicuna-33B. Os acertos de cache vieram de mensagens comuns do sistema, imagens de exemplo frequentemente reutilizadas e históricos de bate-papo multi-turn. Isso reduziu a latência do primeiro token em uma média de 1,7× para Vicuna-33B.

8

Pensamentos finais

Neste artigo, falamos sobre o SGLang, um sistema recém-introduzido que visa abordar isso fornecendo execução eficiente de programas de modelos de linguagem complexos. O SGLang compreende uma linguagem de frontend e um tempo de execução. O frontend simplifica a programação com primitivas para geração e controle de paralelismo, enquanto o tempo de execução acelera a execução por meio de novas otimizações como RadixAttention para reutilização de cache KV e máquinas de estado finito compactadas para decodificação de saída estruturada mais rápida. Experimentos demonstram que o SGLang atinge uma taxa de transferência até 6,4 × maior em comparação com sistemas de inferência de última geração em vários modelos de linguagem grande e multimodais, lidando com tarefas como controle de agente, raciocínio lógico, benchmarks de aprendizado de poucos disparos, decodificação JSON, pipelines de geração aumentada por recuperação e bate-papo multi-turn.

join the future newsletter Unite AI Mobile Newsletter 1

Artigos relacionados

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button