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