Este projeto ainda está em desenvolvimento. Alguns recursos podem ainda não estar implementados e a documentação pode estar incompleta.
Um pequeno, mas poderoso sistema de inferência LLM adaptado para fins de pesquisa.
Desempenho equivalente ao vLLM com apenas 2 mil linhas de código (2% do vLLM).
Existem muitas estruturas de código aberto para servir LLM, incluindo HuggingFace Transformers, vLLM, LightLLM, DistServe e DeepSpeed-MII. Por que SwiftLLM?
A razão é que essas estruturas são adaptadas para produção , em vez de pesquisa . Eles são equipados com vários recursos, como suporte para mais de 100 modelos, vários suportes de hardware, LoRA, quantização, multimodal, cache de prefixo, pesquisa de feixe e assim por diante. Embora seja uma solução completa para produção, sua base de código é muito grande e complexa para ser entendida e modificada (por exemplo, vLLM tem mais de 100 mil linhas de código), dificultando seu uso para fins de pesquisa. Além disso, o seu fardo histórico também é um problema.
SwiftLLM foi projetado para ser um sistema de inferência LLM pequeno, mas poderoso, feito sob medida para fins de pesquisa . "Tiny" significa que mantém apenas recursos essenciais para a pesquisa, "poderoso" significa que não compromete o desempenho e, finalmente, "rápido" significa que é fácil de entender e modificar. Embora ofereça suporte a recursos básicos (veja a lista abaixo) e seja capaz de obter desempenho equivalente ao vLLM, a base de código do SwiftLLM tem menos de 2 mil linhas de código (~2% do vLLM), escrito em Python e OpenAI Triton (um DSL para escrever Kernels CUDA), facilitando a leitura, modificação, depuração, teste, extensão e pode ser facilmente integrado às suas novas e brilhantes ideias de pesquisa.
Atualmente, SwiftLLM oferece suporte aos seguintes recursos:
E planejamos adicionar suporte para os seguintes recursos no futuro:
Para manter a base de código pequena, não ofereceremos suporte aos recursos a seguir. Se quiser usá-los em seu projeto de pesquisa, talvez você precise implementá-los sozinho:
Lembre-se de que SwiftLLM NÃO é uma solução completa para produção. É aconselhável pensar nisso como uma "base" para o seu projeto de pesquisa, e você pode precisar implementar alguns recursos sozinho. Encorajamos você, meu caro pesquisador, a ler o código, compreendê-lo, modificá-lo e estendê-lo para atender às suas necessidades de pesquisa.
A arquitetura do SwiftLLM pode ser dividida em duas partes principais: o plano de controle e o plano de dados .
Resumidamente, o plano de controle decide “o que computar” ou “como agendar”, enquanto o plano de dados decide “como computar” ou “como implementar” e executa a computação concreta. Eles trabalham de maneira mestre-trabalhador: o plano de controle atua como um mestre, que realiza o escalonamento e a coordenação de alto nível e envia tarefas para o plano de dados, que atua como um trabalhador, que realiza a computação de baixo nível.
O código do plano de controle reside no diretório swiftllm/server
, incluindo componentes como Engine
, Scheduler
, o servidor API e TokenizationEngine
. O código para o plano de dados reside no diretório swiftllm/worker
, incluindo descrições do gráfico de computação (em swiftllm/worker/model.py
), implementação de camadas no modelo (em swiftllm/layers
) e os kernels OpenAI Triton ( você pode imaginar "kernels" como funções executadas na GPU (em swiftllm/kernels
).
Vamos pegar o servidor API do brinquedo (localizado em swiftllm/server/api_server.py
) como exemplo:
EngineConfig
para criar um Engine
.Engine.initialize
, onde ele cria o Scheduler
, o TokenizationEngine
e um conjunto de trabalhadores (atualmente apenas um, pois o Paralelismo Tensor não é suportado). Em seguida, ele comanda o trabalhador para executar profile_num_blocks
para calcular o número de blocos de GPU, após o qual o mecanismo comanda todos os trabalhadores para alocar seu cache KV e troca de KV.Engine.start_all_event_loops
. Em cada etapa do loop, o mecanismo consulta o agendador para obter o próximo lote de solicitações a serem computadas, comanda o trabalhador para realizar troca de entrada/saída e, em seguida, envia o lote para o trabalhador computar. Atualmente o plano de controle ( Engine
) e o plano de dados ( LlamaModel
) residem no mesmo nó. Após a implementação do Paralelismo de Tensor/Paralelismo de Pipeline, o plano de dados pode ser distribuído para vários nós.
Oferecemos duas maneiras de usar o SwiftLLM: usando o plano de controle e o plano de dados ou usando apenas o plano de dados.
Se a sua ideia for simples ou elegante o suficiente para poder ser perfeitamente integrada ao plano de controle existente, você poderá usar tanto o plano de controle quanto o plano de dados. Em outro caso, onde você gostaria de implementar uma ideia esplêndida, você só pode aproveitar o plano de dados e implementar um novo plano de controle sozinho.
Primeiro vamos configurar o ambiente:
packaging
via pip install packaging
E então vem a instalação:
git clone https://github.com/interestingLSY/swiftLLM.git
cd
no repositório ( cd swiftLLM
) e instale outras dependências via pip install -r requirements.txt
.pip install -e .
para instalar o SwiftLLM em seu ambiente.pip install -e csrc
Aqui estão alguns exemplos:
.bin
e .safetensors
são suportados. Suponha que o peso do seu modelo esteja armazenado em /data/to/weight/
.python3 examples/offline.py --model-path /data/to/weight
. Este exemplo utiliza apenas o plano de dados. Se você planeja usar o SwiftLLM sem o plano de controle, este é um bom ponto de partida.Engine
, você pode tentar python3 examples/online.py --model-path /data/to/weight
. Este é um ótimo exemplo se você planeja usar o plano de controle e o plano de dados.swiftllm/server/api_server.py
. Ele lança um servidor API e fornece uma interface semelhante a vLLM para atendimento online. Apesar de ser minúsculo (os minúsculos também podem ser adoráveis!), O SwiftLLM não compromete o desempenho. Avaliamos o SwiftLLM em vários cenários e demonstramos que o SwiftLLM pode alcançar desempenho equivalente, ou até melhor, em comparação com o vLLM.
O primeiro cenário é “uma única operação de encaminhamento”, onde alimentamos o modelo com um lote de entradas e o deixamos gerar um token de saída (equivalente a uma operação de “encaminhamento”). Esta é a operação básica da inferência LLM (tanto online quanto offline), portanto seu desempenho é crucial.
Aqui usamos o modelo LLaMA-3 7B com GPU NVIDIA A100 80G PCIE / RTX 4090 com precisão FP16. Os resultados são mostrados abaixo (quanto menor, melhor):
Pode-se observar que o SwiftLLM pode atingir desempenho equivalente (ou até mesmo superar) ao vLLM nas mesmas configurações.
O segundo cenário é "serviço online", onde iniciamos um servidor API, amostramos prompts de um conjunto de dados do mundo real e deixamos o modelo gerar conclusões. Este é o cenário onde o LLM é usado em aplicações do mundo real, como chatbots ou autocompletar código.
Aqui usamos o conjunto de dados ShareGPT para amostrar prompts e usamos um processo poisson com lambdas diferentes para simular diferentes taxas de chegada de solicitações. Os resultados são mostrados abaixo (quanto menor, melhor):
Pode-se observar que no A100 80G PCIE, o SwiftLLM pode atingir desempenho equivalente ao vLLM, enquanto no RTX 4090, o SwiftLLM supera significativamente o vLLM (principalmente por causa de nosso plano de controle ter uma sobrecarga menor).