Este proyecto aún está en desarrollo. Es posible que algunas funciones aún no estén implementadas y que la documentación esté incompleta.
Un sistema de inferencia LLM pequeño pero potente diseñado para fines de investigación.
Rendimiento equivalente a vLLM con solo 2k líneas de código (2% de vLLM).
Existen muchos marcos de código abierto para el servicio LLM, incluidos HuggingFace Transformers, vLLM, LightLLM, DistServe y DeepSpeed-MII. ¿Por qué SwiftLLM?
La razón es que esos marcos están diseñados para la producción , en lugar de la investigación . Están equipados con numerosas funciones, como más de 100 soportes de modelos, varios soportes duros, LoRA, cuantificación, multimodal, almacenamiento en caché de prefijos, búsqueda de haces, etc. Si bien es una solución todo en uno para producción, su base de código es demasiado grande y compleja para comprenderla y modificarla (por ejemplo, vLLM tiene más de 100.000 líneas de código), lo que dificulta su uso con fines de investigación. Además, su carga histórica también es un problema.
SwiftLLM está diseñado para ser un sistema de inferencia LLM pequeño pero potente diseñado para fines de investigación . "Pequeño" significa que solo conserva las características que son esenciales para la investigación, "poderoso" significa que no compromete el rendimiento y, finalmente, "rápido" significa que es fácil de entender y modificar. Si bien admite funciones básicas (consulte la lista a continuación) y puede lograr un rendimiento equivalente a vLLM, la base de código de SwiftLLM tiene menos de 2k líneas de código (~2% de vLLM), escritas en Python y OpenAI Triton (un DSL para escribir Kernels CUDA), lo que facilita su lectura, modificación, depuración, prueba, ampliación y puede integrarse fácilmente con sus novedosas y brillantes ideas de investigación.
Actualmente, SwiftLLM admite las siguientes funciones:
Y planeamos agregar soporte para las siguientes funciones en el futuro:
Para mantener el código base pequeño, no admitiremos las siguientes funciones. Si desea utilizarlos en su proyecto de investigación, es posible que deba implementarlos usted mismo:
Recuerde que SwiftLLM NO es una solución todo en uno para producción. Se recomienda pensar en ello como una "base" para su proyecto de investigación, y es posible que deba implementar algunas funciones usted mismo. Le animamos, querido investigador, a leer el código, comprenderlo, modificarlo y ampliarlo para que se ajuste a sus necesidades de investigación.
La arquitectura de SwiftLLM se puede dividir en dos partes principales: el plano de control y el plano de datos .
En pocas palabras, el plano de control decide "qué calcular" o "cómo programar", mientras que el plano de datos decide "cómo calcular" o "cómo implementar" y realiza el cálculo concreto. Trabajan en forma de maestro-trabajador: el plano de control actúa como un maestro, que realiza la programación y coordinación de alto nivel y envía trabajos al plano de datos, que actúa como un trabajador, que realiza el cálculo de bajo nivel.
El código para el plano de control reside en el directorio swiftllm/server
, incluidos componentes como Engine
, Scheduler
, el servidor API y TokenizationEngine
. El código para el plano de datos reside en el directorio swiftllm/worker
, incluidas descripciones del gráfico de cálculo (en swiftllm/worker/model.py
), la implementación de capas en el modelo (en swiftllm/layers
) y los núcleos OpenAI Triton ( Puedes imaginar "kernels" como funciones ejecutadas en la GPU) (en swiftllm/kernels
).
Tomemos como ejemplo el servidor API de juguetes (ubicado en swiftllm/server/api_server.py
):
EngineConfig
para crear un Engine
.Engine.initialize
, donde crea el Scheduler
, el TokenizationEngine
y un conjunto de trabajadores (actualmente solo uno, ya que no se admite el paralelismo tensorial). Luego ordena al trabajador que ejecute profile_num_blocks
para calcular la cantidad de bloques de GPU, después de lo cual el motor ordena a todos los trabajadores que asignen su caché KV y su intercambio KV.Engine.start_all_event_loops
. En cada paso del ciclo, el motor consulta al programador sobre el siguiente lote de solicitudes para calcular, ordena al trabajador que realice el intercambio de entrada/salida y luego envía el lote al trabajador para que lo calcule. Actualmente el plano de control ( Engine
) y el plano de datos ( LlamaModel
) residen en el mismo nodo. Una vez implementado el paralelismo tensorial/paralelismo de canalización, el plano de datos se puede distribuir a varios nodos.
Ofrecemos dos formas de usar SwiftLLM: usando tanto el plano de control como el plano de datos, o usando solo el plano de datos.
Si su idea es lo suficientemente simple o elegante como para integrarse perfectamente en el plano de control existente, puede utilizar tanto el plano de control como el plano de datos. En otro caso, cuando desee implementar una idea espléndida, sólo podrá aprovechar el plano de datos e implementar un nuevo plano de control usted mismo.
Primero configuremos el entorno:
packaging
mediante pip install packaging
Y luego viene la instalación:
git clone https://github.com/interestingLSY/swiftLLM.git
cd
en el repositorio ( cd swiftLLM
) e instale otras dependencias mediante pip install -r requirements.txt
.pip install -e .
para instalar SwiftLLM en su entorno.pip install -e csrc
A continuación se muestran algunos ejemplos:
.bin
como el formato .safetensors
. Suponga que el peso de su modelo está almacenado en /data/to/weight/
.python3 examples/offline.py --model-path /data/to/weight
. Este ejemplo utiliza únicamente el plano de datos. Si planea utilizar SwiftLLM sin el plano de control, este es un buen punto de partida.Engine
, puede probar python3 examples/online.py --model-path /data/to/weight
. Este es un gran ejemplo si planea utilizar tanto el plano de control como el plano de datos.swiftllm/server/api_server.py
. Lanza un servidor API y proporciona una interfaz similar a vLLM para servicio en línea. A pesar de ser pequeño (¡los pequeños también pueden ser adorables!), SwiftLLM no compromete el rendimiento. Hemos evaluado SwiftLLM en varios escenarios y demostramos que SwiftLLM puede lograr un rendimiento equivalente, o incluso mejor, en comparación con vLLM.
El primer escenario es "una única operación directa", donde alimentamos el modelo con un lote de entradas y le permitimos generar un token de salida (equivalente a una operación "directa"). Esta es la operación básica de la inferencia LLM (tanto en línea como fuera de línea), por lo que su desempeño es crucial.
Aquí utilizamos el modelo LLaMA-3 7B con GPU NVIDIA A100 80G PCIE / RTX 4090 con precisión FP16. Los resultados se muestran a continuación (cuanto más bajo, mejor):
Se puede ver que SwiftLLM puede lograr un rendimiento equivalente (o incluso superior) al de vLLM con la misma configuración.
El segundo escenario es el "servicio en línea", donde iniciamos un servidor API, tomamos muestras de mensajes de un conjunto de datos del mundo real y dejamos que el modelo genere finalizaciones. Este es el escenario en el que LLM se utiliza en aplicaciones del mundo real como chatbots o finalización de código.
Aquí usamos el conjunto de datos ShareGPT para muestrear solicitudes y usamos un proceso de Poisson con diferentes lambdas para simular diferentes tasas de llegada de solicitudes. Los resultados se muestran a continuación (cuanto más bajo, mejor):
Se puede ver que en A100 80G PCIE, SwiftLLM puede lograr un rendimiento equivalente a vLLM, mientras que en RTX 4090, SwiftLLM supera significativamente a vLLM (principalmente porque nuestro plano de control tiene una sobrecarga más baja).