Documentación

Inicio rápido con Docker

Ejecuta el SDK sin instalar Python ni PyTorch en tu equipo. Para el inicio rápido en CPU, reserva 8 GB de RAM y 10 GB de disco libre, con Docker Engine o Docker Desktop y Compose v2 o posterior.

Desde la raíz del repositorio:

docker compose run --build --rm laya

Esto construye el checkout, ejecuta la solicitud de ejemplo en CPU e imprime JSON que cubre choice, score y noul. La primera solicitud descarga el checkpoint público seleccionado de Hugging Face; no hace falta ninguna cuenta. Reserva varios minutos para su primera descarga. Los pesos se quedan en un volumen con nombre. Las ejecuciones posteriores usan docker compose run --rm laya.

Las predicciones y la confianza todavía necesitan evaluación con tu carga de trabajo. Consulta los límites de los benchmarks.

Para hosts ARM64, DGX Spark y Apple Silicon, consulta Contenedores ARM64 y DGX Spark.

GPU NVIDIA / CUDA

Instala un controlador NVIDIA compatible y configura Docker con el NVIDIA Container Toolkit. La imagen de GPU usa ruedas de PyTorch CUDA 12.8. Comprueba la capacidad de cómputo de tu GPU y el controlador contra las compilaciones compatibles de PyTorch; las tarjetas más antiguas pueden requerir una compilación distinta. Reserva espacio de disco adicional para las capas de CUDA. Las necesidades de VRAM dependen del checkpoint, el tamaño de lote y la longitud de entrada.

docker compose -f compose.yaml -f compose.cuda.yaml run --build --rm laya

La anulación selecciona la GPU 0 y usa LAYA_DEVICE=cuda por defecto. Define LAYA_GPU_ID con otro índice o UUID del host. Esa GPU aparece como dispositivo 0 dentro del contenedor. Comprueba el acceso sin descargar pesos:

docker compose -f compose.yaml -f compose.cuda.yaml run --rm laya python -c \
  'import torch; assert torch.cuda.is_available(); print(torch.cuda.get_device_name(0)); print(torch.ones(1, device="cuda").cpu())'

El ejemplo rechaza una CUDA no disponible antes de cargar un checkpoint. Laya puede aun así recaer en la CPU tras un error de memoria o de inferencia, así que inspecciona sus advertencias. Reconstruye al cambiar entre configuraciones de CPU y CUDA.

La imagen define TORCH_DISABLE_NATIVE_JIT=1. De lo contrario, PyTorch 2.14 sustituye algunas operaciones CUDA eager por kernels de Triton que compila en la primera inferencia, lo que necesita un compilador de C que la imagen slim no incorpora: el contenedor se declara saludable y luego falla todas las solicitudes (#365). Los kernels estándar dan las mismas respuestas con la misma latencia. Define la misma variable en una instalación nativa si predict falla con Failed to find C compiler.

Esto usa las reservas de GPU de Compose. Windows requiere la configuración de GPU en WSL2 compatible con Docker Desktop. Los contenedores de Apple MPS, AMD/ROCm e Intel GPU quedan fuera de este inicio rápido; usa CPU a menos que configures y valides otro backend.

Configuración

Define las variables de Compose en tu shell, en un archivo .env local o en el bloque environment del servicio. No confirmes secretos en .env. Las variables de runtime también funcionan con docker run -e; los ajustes exclusivos de Compose se identifican más abajo.

Variable Por defecto Propósito
LAYA_DEVICE cpu / cuda Unidad seleccionada por la configuración base / de GPU
LAYA_CUDA_AMP sin definir (amp_dtype del checkpoint) fp16/float16 o bf16/bfloat16 para la pasada hacia adelante en CUDA; cualquier otra cosa se ignora. No es cosmético: la sección de umbrales del README mide que bf16 cambia 3 de 864 argmax en el conjunto de paridad donde fp16 no cambia ninguno
LAYA_CPU_AMP sin definir bf16 o bfloat16 activa bf16 en la pasada hacia adelante de CPU; cualquier otra cosa la deja en fp32. Ninguna grafía de fp16 lo activa tampoco: autocast de CPU no tiene una ruta rápida de fp16 que supere a fp32, así que bf16 es la única precisión reducida que core ofrece en esta unidad
LAYA_MODEL auto Alias del Router: auto, english, multilingual, typed-decisions
LAYA_MODEL_PATH sin definir Ruta de un checkpoint compatible dentro del contenedor
LAYA_REVISION sin definir Commit, rama o etiqueta del Hub usado para cada descarga de checkpoint, o reviewed para los SHAs revisados de laya/revisions.py; un argumento revision= sigue ganando
LAYA_REQUEST_FILE solicitud incluida Ruta de la solicitud JSON dentro del contenedor
OMP_NUM_THREADS 4 Hilos de CPU; mantenlo dentro de los núcleos disponibles
HF_TOKEN / HF_TOKEN_FILE sin definir Credencial opcional de Hugging Face
LAYA_API_KEY / LAYA_API_KEY_FILE sin definir solo laya-serve: exige Authorization: Bearer <key>
LAYA_PORT 8000 solo laya-serve: puerto del contenedor, y el puerto del host publicado para él
HF_HUB_OFFLINE 0 1 usa solo checkpoints en caché
HF_HOME /home/laya/.cache/huggingface Ruta de caché; consulta el requisito de montaje más abajo
LAYA_CACHE_VOLUME caché de modelos del proyecto solo Compose: volumen de caché con nombre
LAYA_GPU_ID 0 solo Compose: índice o UUID del dispositivo NVIDIA
LAYA_TORCH_INDEX cpu / cu128 / cu130 build de Compose: índice de ruedas de PyTorch
LAYA_TORCH_VERSION 2.14.0 build de Compose: versión de PyTorch fijada

Compose reenvía las variables de runtime excepto HF_HOME, que se mantiene alineada con su montaje de caché fijo, y excepto LAYA_MPS_AMP_MIN_ROWS, la puerta de filas de MPS, que ninguna imagen de aquí puede alcanzar porque ningún contenedor de aquí puede seleccionar MPS. Si anulas HF_HOME en docker run o en tu propio archivo Compose, aporta un montaje coincidente que sea escribible por el UID 10001. Las compilaciones directas de Docker seleccionan PyTorch con --build-arg TORCH_INDEX=cu128; -e en runtime no puede cambiar la rueda instalada.

LAYA_MODEL=english OMP_NUM_THREADS=2 docker compose run --build --rm laya

docker build -t laya:local .
docker run --rm -e LAYA_MODEL=english -e OMP_NUM_THREADS=2 \
  -v laya-model-cache:/home/laya/.cache/huggingface laya:local

Para tu propia solicitud:

docker compose run --rm --volume "$PWD/request.json:/inputs/request.json:ro" \
  --env LAYA_REQUEST_FILE=/inputs/request.json laya

Para una configuración comentada con montajes de solicitud, checkpoint y archivo de secretos, consulta compose.example.yml:

docker compose -f compose.yaml -f compose.example.yml run --build --rm laya

Añade -f compose.cuda.yaml antes de run para GPUs NVIDIA. El ejemplo es una anulación de compose.yaml, así que los ajustes de caché e imagen se quedan en un solo sitio.

Archivos de secretos

HF_TOKEN_FILE lee un archivo UTF-8 montado al arrancar, recorta los espacios en blanco de los alrededores y tiene prioridad sobre HF_TOKEN. Los archivos ilegibles, vacíos o inválidos detienen el arranque sin imprimir su contenido. El archivo debe ser legible por el UID 10001. _FILE solo se aplica a los secretos admitidos, no a todos los ajustes.

Con HF_TOKEN_PATH apuntando a un archivo del host existente fuera del checkout:

docker compose run --rm --volume "$HF_TOKEN_PATH:/run/secrets/hf_token:ro" \
  --env HF_TOKEN_FILE=/run/secrets/hf_token laya

Los secretos de Docker o los volúmenes Secret de Kubernetes pueden aportar el mismo archivo. Los valores se cargan en el entorno del proceso al arrancar; reinicia después de cambiar un archivo. Nunca uses tokens como argumentos de compilación ni los incrustes en las imágenes. Los checkpoints públicos no necesitan token.

Checkpoints ajustados

Esta imagen ejecuta inferencia. El ajuste fino ocurre fuera de ella — el notebook de ajuste fino ejecuta todo el bucle en las GPUs 2xT4 gratuitas de Kaggle y exporta un checkpoint que esta imagen puede servir. El contexto y las preguntas abiertas sobre la interfaz de entrenamiento se quedan en #4 y #26.

Apunta LAYA_CHECKPOINT_PATH a un directorio absoluto del host que contenga rl_agent_config.json, model.safetensors y los archivos de tokenizador correspondientes:

docker compose run --rm --volume "$LAYA_CHECKPOINT_PATH:/models/custom" \
  --env LAYA_MODEL_PATH=/models/custom laya

Usa una copia de trabajo escribible por el UID 10001 porque el cargador puede actualizar la configuración del tokenizador. Un adaptador LoRA por sí solo no es un checkpoint completo. Deja LAYA_MODEL=auto al definir LAYA_MODEL_PATH; un alias explícito y una ruta local son mutuamente excluyentes. La respuesta para una ruta local viene del Agent y no tiene metadatos routing del Router. Estos ajustes también funcionan con la anulación de CUDA. Evalúa los checkpoints ajustados con ejemplos reservados antes de confiar en ellos.

Modelos desde ModelScope

Cuando un equipo no puede alcanzar huggingface.co, el checkpoint puede venir de ModelScope y hornearse en la imagen en tiempo de compilación. Un argumento elige qué checkpoint, y por defecto es el multilingüe. La anulación de Compose añade los argumentos de prefetch a ambos servicios y mantiene el contenedor fuera del Hub:

docker compose -f compose.yaml -f compose.http.yaml -f compose.modelscope.yaml up --build laya-serve

Para NVIDIA, añade -f compose.cuda.yaml antes de up; repite sus propios argumentos para ambos servicios, así que el orden entre las dos anulaciones no importa. Docker puro toma los argumentos directamente:

docker build --build-arg MODELSCOPE_MODEL=multilingual \
  -t laya:local .
docker run --rm -e HF_HUB_OFFLINE=1 -p 127.0.0.1:8000:8000 laya:local laya-serve

Un requisito previo en un equipo que ya ejecutó esto antes. Los pesos horneados aterrizan en $HF_HOME/hub dentro de la imagen, bajo el directorio de caché en el que compose.yaml monta el volumen model-cache (/home/laya/.cache/huggingface), y Docker siembra un volumen con nombre desde la imagen solo mientras ese volumen está vacío. Un volumen que quedó del inicio rápido basado en el Hub contiene la instantánea antigua del Hub, nunca se vuelve a sembrar, y los pesos horneados permanecen invisibles detrás de él: el cargador resuelve refs/main al commit antiguo del Hub y el contenedor responde con los pesos que ya se habían descargado, como si la reconstrucción no hubiera cambiado nada. Apunta el despliegue a un volumen de caché vacío — docker compose down --volumes con los mismos archivos Compose y el mismo LAYA_CACHE_VOLUME, o LAYA_CACHE_VOLUME=<name> para uno nuevo. Con HF_HUB_OFFLINE=1 un ref ausente o divergente es un fallo de carga sin red a la que recurrir, pero el requisito previo es el mismo.

docker/prefetch_modelscope.py lista el repositorio en modelscope.cn, descarga los archivos propios del checkpoint — el mismo conjunto que laya/agent.py pide al Hub, así que no se baja ningún checkpoint hermano — y los escribe en la caché del hub de la imagen tal como snapshot_download dispone una instantánea. Nada más cambia: Agent, el Router que construye laya-serve, laya.cli y las integraciones conservan sus ids de repositorio y los resuelven a la instantánea horneada, así que un contenedor construido así no necesita red en absoluto. El tamaño de cada archivo se comprueba contra lo que reporta el repositorio antes de publicar la instantánea, y su SHA-256 también cuando el repositorio publica uno. Una discrepancia de tamaño o de digest hace fallar la compilación. Un repositorio que no publica ningún digest deja la comprobación solo en el tamaño, que no puede detectar una sustitución del mismo tamaño.

Variable Por defecto Propósito
MODELSCOPE_MODEL multilingual (Compose); vacío en el Dockerfile Checkpoint a hornear: multilingual, english, typed-decisions o all. Vacío significa sin prefetch y la imagen sin cambios
MODELSCOPE_REVISION master Rama, etiqueta o commit de ModelScope a hornear
HF_HUB_OFFLINE 1 en la anulación de Compose 1 nunca contacta el Hub, así que se sirve la copia horneada

Un tipo se expande a la ruta de ese checkpoint dentro del repositorio incluido, que es lo que el Router y el inicio rápido de una sola vez cargan por defecto, así que una compilación que nombra un tipo lo sirve sin más cambios:

MODELSCOPE_MODEL=english docker compose -f compose.yaml -f compose.http.yaml -f compose.modelscope.yaml up --build laya-serve
MODELSCOPE_MODEL=all docker compose -f compose.yaml -f compose.http.yaml -f compose.modelscope.yaml up --build laya-serve

all es toda la familia, unos 2.4 GB de pesos. La anulación también define LAYA_MODELS=multilingual, porque LAYA_PRELOAD=1 con la lista por defecto intentaría construir todos los checkpoints y fallaría en el primero que no se horneó; define LAYA_MODELS con la lista que horneaste cuando hornees más, y MODELSCOPE_MODEL=all cuando un despliegue realmente sirva la familia.

Se pueden nombrar varios tipos a la vez — MODELSCOPE_MODEL="english multilingual" hornea ambos, unos 1.5 GB — que es lo que normalmente quiere una imagen de servicio: el Router elige entre el checkpoint inglés y el multilingüe por su cuenta, y uno que no se le dio responde 500 inference failed con does not contain 'rl_agent_config.json' en el log. Los checkpoints que comparten un repositorio siempre se hornean en una sola instantánea, porque una revisión en caché se resuelve a un único directorio; el checkpoint raíz y cada subcarpeta están ambos en ella.

Más allá de los tipos, el argumento también acepta especificaciones repo[:subfolder], separadas por comas o espacios, que es como se hornean los repositorios independientes del espejo (laya, laya-multilingual, laya-typed-decisions) o un checkpoint ajustado. Un repositorio independiente es lo que Agent("convaiinnovations/laya-multilingual") carga directamente; el valor por defecto del Router es la ruta incluida, así que un tipo es normalmente lo que quiere una imagen de servicio.

Dos detalles sobre los pins y la procedencia. La compilación imprime el commit al que está ligada la instantánea, que es la punta de la revisión horneada — pasa ese SHA como revision= o LAYA_REVISION para fijar una carga exactamente a lo horneado. Un repositorio espejo puede contener archivos de varias subidas, así que esa punta es la única clave a nivel de repositorio que hay. Los pins del lado del Hub no describen una instantánea de espejo: reviewed nombra commits de Hugging Face, y el mapa de digests SHA-256 está ligado a los hashes de artefactos del Hub, así que ninguno aplica aquí, y tampoco existe un pin de digest para una instantánea de espejo. La compilación ya rechaza una descarga que no coincide con el tamaño reportado por el espejo — y con su digest, cuando el espejo publica uno — pero esto comprueba consistencia con los metadatos del espejo, no un digest fijado de forma independiente. Los pesos vienen de la cuenta de espejo que nombre el argumento, lo que es una decisión de cadena de suministro propia que debe tomar el despliegue.

Desarrollo y limpieza

Abre un prompt de Python con docker compose run --rm laya python. Para ejecutar las comprobaciones existentes de enrutamiento/criterios y los tests de archivos de secretos contra tu checkout sin descargar pesos:

docker compose run --rm --volume "$PWD:/workspace:ro" --workdir /workspace laya \
  sh -ec 'python tests/test_router.py; python tests/test_criteria.py; python tests/test_docker_entrypoint.py'

Reconstruye con --build tras cambiar el código fuente o el ejemplo incluido. La imagen se ejecuta como UID/GID 10001. Los volúmenes con nombre nuevos heredan la propiedad del directorio de caché de la imagen; los directorios del host deben ser escribibles por ese UID. Mantén las cachés de modelos escribibles para las actualizaciones de compatibilidad del tokenizador.

--rm elimina los contenedores terminados. docker compose down conserva la caché. Para eliminar los pesos descargados, ejecuta docker compose down --volumes usando los mismos archivos Compose y el ajuste LAYA_CACHE_VOLUME. La siguiente solicitud los descarga de nuevo; no elimines una caché compartida con otro proyecto.

Servicio HTTP

La imagen incorpora laya-serve, así que la misma compilación que ejecuta el inicio rápido de una sola vez puede servir la API compatible con Jev. compose.http.yaml la añade como segundo servicio y deja laya en paz:

docker compose -f compose.yaml -f compose.http.yaml up --build laya-serve
curl -s localhost:8000/health
curl -s localhost:8000/v1/systemone -H 'content-type: application/json' \
  --data @examples/docker/request.json

Para NVIDIA, añade la anulación de CUDA. Repite los argumentos de compilación y la reserva de dispositivo para laya-serve, porque laya-serve es un servicio aparte y las anulaciones de laya nunca llegan a él:

docker compose -f compose.yaml -f compose.http.yaml -f compose.cuda.yaml up --build laya-serve

up mantiene el servicio en ejecución en primer plano; -d lo desacopla. Los pesos van al mismo volumen con nombre model-cache que el inicio rápido, así que servir tras una ejecución de inicio rápido arranca con los checkpoints ya en disco. Detén con docker compose ... down, usando los mismos archivos Compose.

El puerto se publica solo en 127.0.0.1. La API no tiene autenticación hasta que se define LAYA_API_KEY, así que define una clave antes de exponerla con LAYA_BIND_ADDRESS=0.0.0.0, y pon un proxy inverso TLS delante para clientes remotos. /health no requiere autenticación en ninguno de los dos casos, así que la comprobación de salud de abajo sigue funcionando; con una clave definida responde a un llamador no autenticado {"status": "ok"} y retiene los campos checkpoint, revision y device, que necesitan el bearer.

El servicio tiene una comprobación de salud sobre /health. El servidor precarga antes de empezar a escuchar, así que con LAYA_PRELOAD=1 un contenedor saludable tiene sus checkpoints cargados. docker compose ... up -d --wait laya-serve vuelve una vez que está saludable.

/health informa de device como la unidad en la que realmente calcula un checkpoint residente, que no siempre es lo que pidió LAYA_DEVICE: un checkpoint que quiere una GPU que no puede obtener reca en la CPU en silencio y sigue respondiendo correctamente. checkpoint_devices nombra cada checkpoint cargado, y device_is_preference es true solo mientras no hay nada residente, así que un despliegue que perdió su GPU sin hacer ruido lo dice en lugar de repetir su propia configuración.

Configuración del servidor

Estos se aplican solo al servicio laya-serve.

variable por defecto efecto
LAYA_HOST 0.0.0.0 dirección de enlace dentro del contenedor
LAYA_PORT 8000 puerto del contenedor, y el puerto del host publicado para él
LAYA_BIND_ADDRESS 127.0.0.1 dirección del host en la que se publica el puerto
LAYA_PRELOAD 0 1 construye cada checkpoint al arrancar en lugar de en la primera solicitud
LAYA_MODELS (todos) lista separada por comas a precargar: english,multilingual,typed-decisions
LAYA_THREADS OMP_NUM_THREADS limita los hilos intra-op de torch; mantenlo en o por debajo de los núcleos físicos
LAYA_AUTO_TASK 0 1 deja que el router alcance typed-decisions automáticamente
LAYA_DEFAULT_MODEL english Checkpoint al que recurre un estado sin evidencia de idioma (sin letras, o texto latino demasiado corto para identificar). Define multilingual para tráfico mayormente no inglés; un nombre que no se puede resolver detiene el contenedor al arrancar en lugar de servir una configuración que nadie pidió
LAYA_MAX_LOADED 2 Checkpoints mantenidos residentes; LAYA_AUTO_TASK hace alcanzable un tercero bajo demanda, y un tope por debajo de lo que elige el enrutamiento reconstruye uno por cada cambio
LAYA_MAX_CONCURRENT 16 solicitudes admitidas a la vez; las posteriores reciben 503 (un valor que no se parsea, o que no es positivo, recae en 16)
LAYA_LOG_LEVEL info nivel de registro de uvicorn
LAYA_API_KEY (ninguna) cuando se define, exige Authorization: Bearer <key>
LAYA_ROOT_PATH (vacío) prefijo de URL público para FastAPI detrás de un proxy inverso; el proxy debería eliminarlo antes de reenviar
LAYA_MAX_TOKEN_BUDGET 8192 tope de las anulaciones max_len y head_max_len por solicitud
LAYA_SHA256_DIGESTS (ninguno) digests JSON comprobados antes de analizar un checkpoint: {artifact: digest} para todos los checkpoints, o {model: {artifact: digest}} por checkpoint. Consulta Seguridad

Por ejemplo, define LAYA_ROOT_PATH=/laya al publicar la API bajo /laya. El proxy debe eliminar ese prefijo antes de reenviar al contenedor; este ajuste actualiza las URL generadas por FastAPI y no cambia las rutas internas /health ni /v1/systemone.

LAYA_PRELOAD usa 0 por defecto aquí en lugar del 1 del paquete, porque la precarga hace que el primer arranque descargue los tres checkpoints. Ponlo a 1 para un despliegue de larga duración para que la primera solicitud no pague la construcción.

LAYA_PORT define tanto el puerto del host publicado como el puerto al que se enlaza el servidor, así que los dos no pueden desincronizarse. Cambia un solo sitio para mover el servicio:

LAYA_PORT=9000 docker compose -f compose.yaml -f compose.http.yaml up --build laya-serve

Token bearer desde un archivo

LAYA_API_KEY_FILE se lee una vez al arrancar, se pasa a LAYA_API_KEY, y la variable _FILE se elimina antes de que el servidor haga exec. Prefiere esto a poner la clave en el entorno:

docker compose -f compose.yaml -f compose.http.yaml run --rm \
  --volume "$PWD/laya_api_key:/run/secrets/laya_api_key:ro" \
  -e LAYA_API_KEY_FILE=/run/secrets/laya_api_key \
  --service-ports laya-serve