
![]()
Servicio de modelo hecho eficiente en la nube.

MOSEC es un marco de servicio de modelos de alto rendimiento y flexible para construir backend y microservicios habilitados para modelos ML. Cierre la brecha entre cualquier modelo de aprendizaje automático que acaba de capacitar y la eficiente API de servicio en línea.
Mosec requiere Python 3.7 o superior. Instale el último paquete Pypi para Linux x86_64 o macOS x86_64/arm64 con:
pip install -U mosec
# or install with conda
conda install conda-forge::mosecPara construir desde el código fuente, instale óxido y ejecute el siguiente comando:
make package Obtendrá un archivo de rueda MOSEC en la carpeta dist .
Demostramos cómo MOSEC puede ayudarlo a alojar fácilmente un modelo de difusión estable previamente entrenado como servicio. Debe instalar difusores y transformadores como requisitos previos:
pip install --upgrade diffusers[torch] transformersEn primer lugar, importamos las bibliotecas y configuramos un registrador básico para observar mejor lo que sucede.
from io import BytesIO
from typing import List
import torch # type: ignore
from diffusers import StableDiffusionPipeline # type: ignore
from mosec import Server , Worker , get_logger
from mosec . mixin import MsgpackMixin
logger = get_logger ()Luego, construimos una API para que los clientes consulten un mensaje de texto y obtengan una imagen basada en el modelo Stable-Diffusion-V1-5 en solo 3 pasos.
Defina su servicio como una clase que herede mosec.Worker . Aquí también heredamos MsgpackMixin para emplear el formato de serialización de msgpack (a) .
Dentro del método __init__ , inicialice su modelo y colóquelo en el dispositivo correspondiente. Opcionalmente, puede asignar self.example con algunos datos para calentar (b) el modelo. Tenga en cuenta que los datos deben ser compatibles con el formato de entrada de su controlador, que detallamos a continuación.
Anule el método forward para escribir su controlador de servicio (c) , con la firma forward(self, data: Any | List[Any]) -> Any | List[Any] . Recibir/devolver un solo elemento o una tupla depende de si está configurado el lote dinámico (D) .
class StableDiffusion ( MsgpackMixin , Worker ):
def __init__ ( self ):
self . pipe = StableDiffusionPipeline . from_pretrained (
"sd-legacy/stable-diffusion-v1-5" , torch_dtype = torch . float16
)
self . pipe . enable_model_cpu_offload ()
self . example = [ "useless example prompt" ] * 4 # warmup (batch_size=4)
def forward ( self , data : List [ str ]) -> List [ memoryview ]:
logger . debug ( "generate images for %s" , data )
res = self . pipe ( data )
logger . debug ( "NSFW: %s" , res [ 1 ])
images = []
for img in res [ 0 ]:
dummy_file = BytesIO ()
img . save ( dummy_file , format = "JPEG" )
images . append ( dummy_file . getbuffer ())
return images[!NOTA]
(a) En este ejemplo devolvemos una imagen en el formato binario, que JSON no admite (a menos que esté codificado con Base64 que hace que la carga útil sea más grande). Por lo tanto, Msgpack se adapta mejor a nuestras necesidades. Si no heredamos
MsgpackMixin, JSON se usará de forma predeterminada. En otras palabras, el protocolo de la solicitud/respuesta de servicio puede ser msgpack, json o cualquier otro formato (verifique nuestras mezclas).(b) El calentamiento generalmente ayuda a asignar la memoria de GPU por adelantado. Si se especifica el ejemplo de calentamiento, el servicio solo estará listo después de reenviar el ejemplo a través del controlador. Sin embargo, si no se da ningún ejemplo, se espera que la latencia de la primera solicitud sea más larga. El
exampledebe establecerse como un solo elemento o una tupla dependiendo de lo queforwardespera recibir. Además, en el caso de que desee calentar con múltiples ejemplos diferentes, puede establecermulti_examples(demostración aquí).(c) Este ejemplo muestra un servicio de una sola etapa, donde el trabajador
StableDiffusiontoma directamente la solicitud rápida del cliente y responde la imagen. Por lo tanto, elforwardpuede considerarse como un manejador de servicio completo. Sin embargo, también podemos diseñar un servicio de varias etapas con trabajadores que realicen diferentes trabajos (por ejemplo, descargando imágenes, inferencia de modelos, postprocesamiento) en una tubería. En este caso, toda la tubería se considera el manejador de servicios, y el primer trabajador toma la solicitud y el último trabajador enviando la respuesta. El flujo de datos entre los trabajadores se realiza mediante comunicación entre procesos.(d) Dado que el lote dinámico está habilitado en este ejemplo, el método
forwardrecibirá desagradablemente una lista de cadenas, por ejemplo,['a cute cat playing with a red ball', 'a man sitting in front of a computer', ...], agregado de diferentes clientes para inferencia por lotes , mejorando el rendimiento del sistema.
Finally, we append the worker to the server to construct a single-stage workflow (multiple stages can be pipelined to further boost the throughput, see this example), and specify the number of processes we want it to run in parallel ( num=1 ), and the maximum batch size ( max_batch_size=4 , the maximum number of requests dynamic batching will accumulate before timeout; timeout is defined with the max_wait_time=10 en milisegundos, lo que significa que el Mosec de tiempo más largo espera hasta que envíe el lote al trabajador).
if __name__ == "__main__" :
server = Server ()
# 1) `num` specifies the number of processes that will be spawned to run in parallel.
# 2) By configuring the `max_batch_size` with the value > 1, the input data in your
# `forward` function will be a list (batch); otherwise, it's a single item.
server . append_worker ( StableDiffusion , num = 1 , max_batch_size = 4 , max_wait_time = 10 )
server . run ()Los fragmentos anteriores se fusionan en nuestro archivo de ejemplo. Puede ejecutarse directamente a nivel de raíz del proyecto. Primero echamos un vistazo a los argumentos de la línea de comandos (explicaciones aquí):
python examples/stable_diffusion/server.py --helpEntonces comencemos el servidor con registros de depuración:
python examples/stable_diffusion/server.py --log-level debug --timeout 30000 Abra http://127.0.0.1:8000/openapi/swagger/ en su navegador para obtener el Doc Openapi.
Y en otra terminal, pruebelo:
python examples/stable_diffusion/client.py --prompt " a cute cat playing with a red ball " --output cat.jpg --port 8000Obtendrá una imagen llamada "Cat.jpg" en el directorio actual.
Puedes consultar las métricas:
curl http://127.0.0.1:8000/metrics¡Eso es todo! ¡Acabas de alojar tu modelo de difusión estable como servicio!
Se pueden encontrar más ejemplos listos para usar en la sección Ejemplo. Incluye:
max_batch_size y max_wait_time (millisecond) se configuran cuando llama append_worker .max_batch_size no cause la fuera de la memoria en GPU.max_wait_time debería ser menor que el tiempo de inferencia por lotes.max_batch_size o cuando ha transcurrido max_wait_time . El servicio se beneficiará de esta característica cuando el tráfico sea alto.mosec instalada, puede verificar la imagen oficial mosecorg/mosec . Para el complejo caso de uso, consulte Envd.mosec_service_batch_size_bucket muestra la distribución del tamaño de lotes.mosec_service_batch_duration_second_bucket muestra la duración del lote dinámico para cada conexión en cada etapa (comienza desde recibir la primera tarea).mosec_service_process_duration_second_bucket muestra la duración del procesamiento para cada conexión en cada etapa (incluida la hora de IPC pero excluyendo el mosec_service_batch_duration_second_bucket ).mosec_service_remaining_task muestra el número de tareas de procesamiento actualmente.mosec_service_throughput muestra el rendimiento del servicio.SIGINT ( CTRL+C ) o SIGTERM ( kill {PID} ) ya que tiene la elegante lógica de apagado. max_batch_size y max_wait_time para su servicio de inferencia. Las métricas mostrarán los histogramas del tamaño del lote real y la duración del lote. Esa es la información clave para ajustar estos dos parámetros.serialize_ipc/deserialize_ipc , por lo que los datos extremadamente grandes pueden hacer que toda la tubería sea lenta. Los datos serializados se pasan a la siguiente etapa a través de la óxido de forma predeterminada, puede habilitar la memoria compartida para reducir potencialmente la latencia (Refleja redisshmipcmixin).serialize/deserialize , que se utilizan para decodificar la solicitud del usuario y codificar la respuesta. Por defecto, ambos están usando JSON. Sin embargo, las imágenes y los incrustaciones no son bien compatibles con JSON. Puede elegir msgpack que sea más rápido y binario compatible (refusión estable de referencia).mosec se adapta automáticamente al protocolo del usuario (por ejemplo, HTTP/2) desde V0.8.8. Estas son algunas de las empresas y usuarios individuales que están utilizando MOSEC:
Si encuentra este software útil para su investigación, considere citar
@software{yang2021mosec,
title = {{MOSEC: Model Serving made Efficient in the Cloud}},
author = {Yang, Keming and Liu, Zichen and Cheng, Philip},
url = {https://github.com/mosecorg/mosec},
year = {2021}
}
Agradecemos cualquier tipo de contribución. Por favor, dénos comentarios planteando problemas o discutiendo sobre discordia. ¡También puede contribuir directamente con su código y su solicitud de extracción!
Para comenzar a desarrollarse, puede usar ENVD para crear un entorno de pitón y óxido aislado y limpio. Consulte el envd-docs o build.envd para obtener más información.