Sat. Nov 26th, 2022

Inicie una API web para difusión estable en menos de 45 segundos

Una cabra negra imaginaria generada por Stable DiffusionStable Diffusion es un modelo de difusión latente de texto a imagen, hecho posible gracias a una colaboración con Stability AI y Runway. Cuenta con capacidades de síntesis de texto a imagen de última generación con requisitos de memoria relativamente pequeños (10 GB). Stable Diffusion presenta varias mejoras sobre otros modelos de Diffusion para lograr esta eficiencia, pero estas innovaciones están más allá del alcance de esta publicación; una publicación futura cubrirá cómo entrenar un modelo de Diffusion en TensorFlow y detallará técnicamente su funcionamiento interno. Divam Gupta portó Stable Diffusion a TensorFlow/Keras a partir de pesos originales, y esta publicación se enfoca en cómo ejecutarlo en una imagen de Docker con una API web simple y compatibilidad con GPU.Hecho de la diversión: La imagen destacada en esta publicación también fue generada por Stable Diffusion.

¿Como funciona?

Decidí ejecutarlo en una GPU de TensorDock Marketplace. Debería funcionar en otras máquinas con pocos o ningún cambio necesario, pero es un resultado directo de mis experimentos con TensorDock Marketplace lanzado recientemente. Actualmente está en Public Alpha, pero ya me gusta su idea innovadora para democratizar el acceso a la informática de alto rendimiento. Lanzada además de su asequible servicio Core Cloud GPU, la edición Marketplace sirve como un mercado que reúne a clientes y proveedores de GPU. Los anfitriones, es decir, aquellos que tienen GPU de repuesto, pueden alquilarlas a clientes, incluidos investigadores independientes, nuevas empresas, aficionados, manitas, etc., a precios increíblemente económicos. Según TensorDock, esto también permite que los anfitriones obtengan ganancias mineras de 2x a 3x. Y, para un mejor propósito que la extracción de criptos sin sentido. Los servidores se pueden personalizar para la memoria RAM requerida, vCPU y disco asignado, y los tiempos de arranque son demasiado cortos, alrededor de ~ 45 segundos. Puede optar por comenzar con una imagen mínima de Ubuntu con controladores NVIDIA y Docker ya instalados, o puede saltar a experimentos con imágenes completas con controladores NVIDIA, Conda, TensorFlow, PyTorch y Jupyter configurados. Elijo trabajar con Docker en lugar de Conda o entornos virtuales para aislar mis proyectos de IA, y comenzaré con una imagen mínima con Docker instalado en TensorDock Marketplace. una imagen acoplable. Luego, proporcionaré una descripción paso a paso de cómo servirlo en una GPU TensorDock. Si desea estar en funcionamiento en 45 segundos, puede saltar directamente a la sección “Ok, muéstrame cómo ejecutar”, o puede optar por consultar el repositorio de GitHub.

¡Dockerizemos!

TensorFlow proporciona imágenes de Docker oficiales prediseñadas para cada versión para iniciar su Dockerfile. Si tiene NVIDIA Container Runtime configurado y prefiere una imagen de Docker habilitada para GPU de TensorFlow, puede ejecutar su código de TensorFlow con compatibilidad con GPU al instante sin tener problemas con CUDA o CUDNN. Afortunadamente, las imágenes mínimas de Ubuntu de TensorDock vienen con compatibilidad con NVIDIAContainerRuntime. Para Difusión estable, comenzamos nuestro Dockerfile con tensorflow/tensorflow:2.10.0-gpu. Luego instalamos los requisitos de Stable Diffusion y FastAPI para servir una API web. Finalmente, copiamos app.py que contiene la API web y lo configuramos para que se ejecute en el inicio del contenedor: desde tensorflow/tensorflow:2.10.0-gpuRUN apt update && \
instalación apt -y git && \
pip install –no-cache-dir Pillow==9.2.0 tqdm==4.64.1 \
ftfy==6.1.1 expresiones regulares==2022.9.13 tensorflow-addons==0.17.1 \
fastapi “uvicornio[standard]” git+https://github.com/divamgupta/stable-diffusion-tensorflow.gitWORKDIR /appCOPY ./app.py /app/app.pyCMD uvicorn –host 0.0.0.0 aplicación:aplicación

Compose para facilitar la configuración y el lanzamiento

Docker es aún mejor cuando tiene un archivo docker-compose.yml. Por lo tanto, puede simplemente ejecutar docker compose up para poner todo en funcionamiento con un solo comando. Destaca especialmente cuando se trabaja con varios contenedores, pero también es bastante útil para administrar un solo contenedor. El siguiente archivo docker-compose.yml define varias variables de entorno y las pasa al contenedor. También permite el acceso a la GPU dentro del contenedor y configura la red de Docker correctamente según se requiera en TensorDock Marketplace. Es posible que deba eliminar esta sección con respecto a la red en otras plataformas versión: “3.3” servicios:
aplicación:
imagen: myusufs/estable-difusión-tf
construir:
contexto: .
ambiente:
# configure env vars a su gusto
– ALTURA=512
– ANCHO=512
– MIXED_PRECISION=no
puertos:
– “${PUBLIC_PORT?Puerto público no configurado como variable de entorno}:8000”
volúmenes:
– ./datos:/aplicación/datadeploy:
recursos:
reservas:
dispositivos:
– controlador: nvidia
cuenta: 1
capacidades: [ gpu ]redes:
defecto:
conductor: puente
conductor_opciones:
com.docker.network.driver.mtu: 1442

Hora de codificar

Ahora estamos listos para codificar nuestra API web. Comenzamos con las importaciones requeridas y luego creamos un generador de imágenes, así como una aplicación FastAPI con variables de entorno pasadas por docker-compose.yml.import os
tiempo de importación
importar uuid de fastapi importar FastAPI
de fastapi.Exceptions importar HTTPException
de fastapi.responses importar FileResponse
de imagen de importación PIL
desde pydantic import BaseModel, Field
de stable_diffusion_tf.stable_diffusion importar Text2Image
desde tensorflow import keraheight = int(os.environ.get(“ANCHO”, 512))
ancho = int(os.environ.get(“ANCHO”, 512))
precisión_mixta = os.environ.get(“PRECISIÓN_MIXTA”, “no”) == “sí” si precisión_mixta:
keras.mixed_precision.set_global_policy(“mixed_float16″)generator = Text2Image(img_height=height, img_width=width, jit_compile=False)app = FastAPI(title=”API de difusión estable”)Luego, definimos cuerpos de solicitud y respuesta para nuestro /generate punto final Los valores se explican por sí mismos, por lo que no hay necesidad de palabras adicionales here.class GenerationRequest(BaseModel):
prompt: str = Field(…, title=”Mensaje de entrada”, description=”Mensaje de entrada para representar”)
scale: float = Field(default=7.5, title=”Scale”, description=”Escala de guía incondicional: eps = eps(x, vacío) + escala * (eps(x, cond) – eps(x, vacío))” )
pasos: int = Campo (predeterminado = 50, título = “Pasos”, descripción = “Número de pasos de muestreo dim”)
seed: int = Field(predeterminado=Ninguno, title=”Seed”, description=”Opcionalmente, especifique una semilla para obtener resultados reproducibles”)class GenerationResult(BaseModel):
download_id: str = Field(…, title=”Descargar ID”, description=”Identificador para descargar la imagen generada”)
time: float = Field(…, title=”Tiempo”, description=”Duración total de la generación de esta imagen”)Finalmente, es hora de escribir nuestros puntos finales. El punto final /generate aceptará un mensaje de texto, así como varios valores de configuración para controlar la generación, y responderá con la ID única de la imagen generada. Luego, la imagen se puede descargar a través del punto final /download. Las imágenes generadas se guardan en un directorio configurado como volumen de Docker en [email protected](“/generate”, response_model=GenerationResult)
def generar (req: GenerationRequest):
inicio = hora.hora()
id = str(uuid.uuid4())
img = generador.generar(req.prompt, num_steps=req.steps, incondicional_guidance_scale=req.scale, temperatura=1, batch_size=1, seed=req.seed)
ruta = os.ruta.join(“/aplicación/datos”, f”{id}.png”)
Imagen.fromarray(img[0]).guardar(ruta)
alapsed = time.time() – startreturn GenerationResult(download_id=id, time=alapsed)@app.get(“/download/{id}”, answers={200: {“description”: “Imagen con ID proporcionada”, “content”: {“image/png” : {“example”: “No hay ningún ejemplo disponible”.}}}, 404: {“description”: “Imagen no encontrada”}})
descarga definida asíncrona (id: str):
ruta = os.ruta.join(“/aplicación/datos”, f”{id}.png”)
si os.path.exists (ruta):
devuelve FileResponse(ruta, media_type=”imagen/png”, nombre de archivo=ruta.split(os.ruta.sep)[-1])
más:
generar HTTPException(404, detalle=”No existe tal archivo”)

Ok, muéstrame cómo correr

No deje que la cantidad de pasos lo asuste: es solo un recorrido detallado paso a paso de todo el proceso, desde el registro hasta la realización de solicitudes. No debería tomar más de ~ 10 minutos. Regístrese e inicie sesión en TensorDock Marketplace. Vaya a la página de pedido y elija una máquina física que ofrezca una GPU con al menos 10 GB de memoria. Sugeriría uno que ofrezca RTX 3090. Esto abrirá un modelo que le permitirá configurar su servidor. Mis sugerencias son las siguientes:Seleccione la cantidad de cada modelo de GPU: 1 x GeForce RTX 3090 24 GBSeleccione la cantidad de RAM (GB): 16Seleccione la cantidad de vCPU: 2Marque las casillas de verificación para hasta 15 reenvíos de puertos. Podrá acceder a su servidor a través de estos puertos. En “Personalizar su instalación”, seleccione “Ubuntu 20.04 LTS”. Elija una contraseña para su servidor y asígnele un nombre, por ejemplo, “stable-diffusion-api” Presione “Implementar servidor” y listo! Su servidor estará listo en segundos. Cuando vea la página de éxito, haga clic en “Siguiente” para ver los detalles. Busque la dirección IPv4 de su servidor. Esta puede ser una IP real o un subdominio como mass-a.tensordockmarketplace.com. Encuentre el puerto externo asignado al puerto interno 22. Usará este para acceder a su servidor mediante SSH. Podría ser algo así como 20029, por ejemplo. Conéctese a su servidor usando estas credenciales, por ejemplo: ssh -p 20029 [email protected]@tensordockmarketplace.comDocker ya está configurado para el acceso GPU, pero necesitamos configurar la red Docker para hacer externo solicitudes. Clone este repositorio y cd en él: git clone https://github.com/monatis/stable-diffusion-tf-docker.git && cd stable-diffusion-tf-dockerCopy daemon.json sobre el /etc/docker existente /daemon.json y reinicie el servicio. No se preocupe, esto solo agrega una configuración para el valor de MTU. Sudo cp ./daemon.json /etc/docker/daemon.jsonsudo systemctl restart docker.serviceEstablezca una variable de entorno para el puerto público que desea usar, ejecute Redacción Docker. Nuestro archivo docker-compose.yml lo recogerá de las variables de entorno y debería ser uno de los reenvíos de puertos que configuró, por ejemplo, 20020.export PUBLIC_PORT=20020docker compose up -dUna vez que esté en funcionamiento, vaya a http:// mass-a.tensordockmarketplace.com:20020/docs para la interfaz de usuario de Swagger proporcionada por FastAPI. Use POST /generate endpoint para generar imágenes con Stable Diffusion. Responderá con un ID de descarga. Presione el punto final GET /download/ para descargar su imagen.

Conclusión

Pudimos ejecutar Stable Diffusion, uno de los modelos de última generación de texto a imagen, en una GPU en la nube de TensorDock Marketplace. Es muy asequible y, por lo tanto, adecuado para experimentación y proyectos paralelos. Continúo usándolo para uno de mis proyectos paralelos, y una publicación posterior brindará un recorrido paso a paso de un trabajo de capacitación en TensorDock Marketplace.