Entre em contato

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

Inteligência artificial

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

mm

Publicado

 on

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

Grandes modelos de linguagem (LLMs) são cada vez mais utilizados para tarefas complexas que exigem chamadas de geração múltipla, técnicas avançadas de prompts, fluxo de controle e entradas/saídas estruturadas. No entanto, faltam sistemas eficientes para programar e executar essas aplicações. SGLang, um sistema recém-introduzido, visa resolver isso, fornecendo execução eficiente de programas de modelos de linguagem complexos. SGLang compreende uma linguagem frontend e um tempo de execução. O frontend simplifica a programação com primitivos 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 um rendimento até 6.4 vezes maior em comparação com sistemas de inferência de última geração em vários modelos multimodais e de linguagem grande, abordando tarefas como controle de agente, raciocínio lógico, benchmarks de aprendizagem de poucos disparos, decodificação JSON, recuperação - pipelines de geração aumentada e bate-papo multivoltas.

Os avanços recentes nas capacidades LLM expandiram a sua utilidade, permitindo-lhes lidar com uma gama mais ampla de tarefas gerais e funcionar como agentes autónomos. Nessas aplicações, os LLMs se envolvem em planejamento, raciocínio e interação multifacetados com ambientes externos. Isso é facilitado pelo uso de ferramentas, múltiplas modalidades de entrada e várias técnicas de estímulo, como aprendizagem em poucas tentativas, autoconsistência, esqueleto de pensamento e árvore de pensamento. Esses novos casos de uso exigem múltiplas chamadas de geração de LLM, muitas vezes dependentes, indicando uma tendência de uso de estruturas de múltiplas chamadas para concluir tarefas complexas.

Esta mudança marca uma transição do 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 Modelo de Linguagem” (Programas LM). Técnicas avançadas de prompts e fluxos de trabalho de agentes 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 de LM recebem entradas estruturadas e produzem resultados estruturados, permitindo a composição de programas de LM e a integração em sistemas de software existentes. 

Neste artigo, iremos nos aprofundar na estrutura SGLang, explorando sua arquitetura, analisando seu desempenho e comparando-a com estruturas de última geração. Então vamos começar. 

Uma introdução ao SGLang

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

  • Complexidade de programação: O desenvolvimento de 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 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 possuem conhecimento direto da carga de trabalho, resultando em ineficiências significativas. Um exemplo notável é a reutilização do cache de valor-chave (KV), que consiste em tensores intermediários reutilizáveis, essenciais para inferência generativa. Os sistemas atuais carecem de mecanismos eficazes para facilitar a reutilização do cache KV em vários LLM chamadas que compartilham um prefixo comum, levando a cálculos desnecessários e desperdício de memória. Além disso, a decodificação restrita para saídas estruturadas, como o modo JSON, não é ideal, pois os sistemas existentes decodificam apenas um token por vez.

Para enfrentar esses desafios, a SGLang apresenta uma linguagem de geração estruturada para LLMs. A ideia central é explorar sistematicamente a estrutura de múltiplas chamadas em programas LM para uma 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 tempo de execução acelera sua execução. Essas peças podem trabalhar juntas para melhor desempenho ou funcionar de forma independente. 

SGLang é uma linguagem de domínio específico incorporada em Python, fornecendo primitivas para geração (por exemplo, estender, gen, selecionar) e controle de paralelismo (por exemplo, fork, join). É compatível com o fluxo de controle e as bibliotecas do Python, permitindo que os usuários desenvolvam facilmente fluxos de trabalho avançados de prompts com a sintaxe nativa do Python. SGLang inclui um interpretador e um compilador. O interpretador gerencia o estado do prompt 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 novas otimizações para acelerar a execução de programas LM:

  • RadixAttention: Esta técnica permite a reutilização automática do cache KV em chamadas de múltiplas gerações. Nos mecanismos de inferência existentes, o cache KV de uma solicitação é descartado após o processamento, evitando a reutilização em diversas chamadas e retardando a execuçã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 despejo eficientes. Isso permite que o tempo de execução lide com vários padrões de reutilização de forma eficiente.
  • Máquina de estados finitos compactados: esta técnica permite uma 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 compactada de estados finitos para representá-las, compactando um caminho de vários tokens em um caminho de etapa única sempre que possível, permitindo a decodificação de vários tokens de uma só vez para uma velocidade mais rápida.
  • Execução especulativa de API: para modelos somente de API como GPA-4 do OpenAI, SGLang introduz execução especulativa de API para otimizar programas de múltiplas chamadas.

Usando SGLang, vários aplicativos LLM foram implementados, incluindo controle de agente, raciocínio lógico, benchmarks de aprendizagem de poucas tentativas, decodificação JSON, pipelines de geração aumentada de recuperação, bate-papo multiturno e processamento multimodalidade. 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 um rendimento até 6.4 vezes maior em uma ampla variedade de cargas de trabalho, modelos e configurações de hardware, em comparação com sistemas de programação e inferência existentes, incluindo Guidance, vLLM e LMQL. 

SGLang: Modelo e Metodologia de Programação

O modelo de programação SGLang é apresentado através 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ções, paralelismo), fornecendo primitivas flexíveis e combiná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. 

A função juiz_multi_dimensional leva três argumentos: `s`, `caminho` e `ensaio`. s gerencia o estado do prompt, path é o caminho do arquivo de imagem e essay é o texto da dissertação. Novas strings e primitivas SGLang podem ser anexadas aos state s para execução usando o += operador. Primeiro, a função adiciona a imagem e o ensaio ao prompt. Em seguida, verifica se a redação tem relação com a imagem através do select, armazenando o resultado em s[“relacionado”]. Se relacionado, o prompt é bifurcado em três cópias para avaliação paralela de diferentes dimensões, usando gen para armazenar resultados em f[“julgamento”]. Em seguida, mescla os julgamentos, gera um resumo e atribui uma nota em letras. Por fim, retorna os resultados no formato JSON, seguindo um esquema definido por uma restrição de expressão regular regex. SGLang simplifica muito este programa, já que um programa equivalente usando uma interface semelhante à API OpenAI levaria 2.1 vezes mais linhas de código devido à manipulação manual de strings e controle de paralelismo.

SGLang fornece primitivas para controlar estado de prompt, geração e paralelismo, que podem ser usadas com sintaxe e bibliotecas Python. Aqui estão as primitivas:

gênero: 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 a seguir uma gramática definida por uma expressão regular (por exemplo, um esquema JSON).

  • select: Chama um modelo para escolher a opção de maior probabilidade em uma lista.
  • += ou estender: acrescenta uma string ao prompt.
  • [variable_name]: Busca os resultados de uma geração.
  • fork: Cria bifurcações paralelas do estado de prompt.
  • join: retorna ao estado de prompt.
  • imagem e vídeo: receba entradas de imagem e vídeo.

A maneira mais simples de executar um programa SGLang é através de um interpretador, onde um prompt é tratado como um fluxo assíncrono. Primitivos como estender, gerar e selecionar são enviados ao fluxo para execução assíncrona. Essas chamadas sem bloqueio permitem que o código Python continue em execução sem esperar o término da geração, semelhante ao lançamento de kernels CUDA de forma assíncrona. Cada prompt é gerenciado por um executor de fluxo em um thread em segundo plano, permitindo o paralelismo intraprograma. A busca dos resultados da 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 intérprete por padrão e discute os resultados do modo compilador no Apêndice D. SGLang suporta modelos de peso aberto com seu próprio SGLang Runtime (SRT), bem como modelos de API como OpenAI e modelos antrópicos.

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, Guidance, SGLang). Os sistemas de alto nível fornecem prompts predefinidos ou gerados automaticamente, como o otimizador de prompt do DSPy. Sistemas de baixo nível normalmente não alteram prompts, mas permitem a manipulação direta de prompts e primitivos. SGLang é um sistema de baixo nível semelhante ao LMQL e Guidance. A tabela a seguir compara seus recursos.

SGLang se concentra 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 em linguagens de baixo nível (por exemplo, SGLang). A integração do SGLang como backend no DSPy para melhor eficiência de tempo de execução é demonstrada posteriormente.

O exemplo acima ilustra as operações RadixAttention com uma política de despejo de LRU em nove pontos no 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 aprendizagem rápidas e amostragem de autoconsistência. Cada borda da árvore carrega um rótulo que indica 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 armazenados em cache acessados ​​durante o ponto no tempo e vermelho para nós que foram removidos.

- A árvore radix está inicialmente vazia.

- O servidor processa uma mensagem recebida do usuário “Hello” e responde com a saída LLM “Hi”. O prompt do sistema “Você é um assistente útil”, a mensagem do usuário “Olá!” e a resposta do LLM “Oi!” são consolidados na árvore como uma única aresta ligada a um novo nó.

- Um novo prompt chega e o servidor encontra o prefixo do prompt (ou seja, o primeiro turno da conversa) na árvore raiz e reutiliza seu cache KV. O novo turno é anexado à árvore como um novo nó.

- 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 chat compartilhem o prompt do sistema.

- A segunda sessão de chat continua. Entretanto, devido aos limites de memória, um nó da Etapa 4 deve ser removido. A nova curva é anexada após o nó restante da Etapa 4.

- O servidor recebe uma consulta de aprendizagem rápida, processa-a e insere-a na árvore. O nó raiz é dividido porque a nova consulta não compartilha nenhum prefixo com os nós existentes.

- O servidor recebe um lote de consultas adicionais de aprendizagem rápidas. Essas consultas compartilham o mesmo conjunto de exemplos de poucas tentativas, portanto, um nó da Etapa 6 é dividido para permitir o compartilhamento.

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

- O servidor recebe uma solicitação para obter amostras de mais respostas para as perguntas em um nó da Etapa 8, provavelmente para solicitação de autoconsistência. Para liberar espaço para essas solicitações, vários nós são removidos.

Este exemplo demonstra como RadixAttention lida com a alocação dinâmica e 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 taxa de transferência são mostrados nas figuras a seguir. SGLang melhora o rendimento 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 restrita mais rápida. 

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

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 nos modelos maiores mostra uma tendência semelhante àquela observada nos 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.

 Resultados em modelos multimodais

SGLang possui suporte nativo para modelos multimodais com 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 é calculado e usado como 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 em llava-bench-in-the-wild e LLaVA-NeXT-34B (vídeo) em ActivityNet. Como esses modelos não são bem suportados por outros sistemas de linha de base, a implementação original dos autores do modelo em Hugging Face Transformers foi usada como linha de base. Conforme mostrado na tabela a seguir, o SGLang fornece rendimento até 6x maior nesses benchmarks. No llava-bench-in-the-wild, várias questões sobre a mesma imagem foram tratadas e o tempo de execução SGLang reutilizou o cache KV neste caso.

Implantação de Produção

SGLang foi implantado no Chatbot Arena para atender modelos abertos. Devido ao baixo tráfego de 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-Next-34B e 74.1% para Vicuna-33B. Os acessos ao cache vieram de mensagens comuns do sistema, imagens de exemplo frequentemente reutilizadas e históricos de bate-papo multiturno. Isso reduziu a latência do primeiro token em uma média de 1.7× para Vicuna-33B.

Considerações Finais

Neste artigo, falamos sobre SGLang, um sistema recém-introduzido que visa resolver isso, fornecendo execução eficiente de programas de modelos de linguagem complexos. SGLang compreende uma linguagem frontend e um tempo de execução. O frontend simplifica a programação com primitivos 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 um rendimento até 6.4 vezes maior em comparação com sistemas de inferência de última geração em vários modelos multimodais e de linguagem grande, abordando tarefas como controle de agente, raciocínio lógico, benchmarks de aprendizagem de poucos disparos, decodificação JSON, recuperação - pipelines de geração aumentada e bate-papo multivoltas.

"Engenheiro de profissão, escritor de coração". Kunal é um escritor técnico com profundo amor e compreensão de IA e ML, dedicado a simplificar conceitos complexos nesses campos por meio de sua documentação envolvente e informativa.