文档导航

Docker 快速开始

Docker 快速开始

不必在主机上安装 Python 或 PyTorch 就能运行 SDK。CPU 快速开始请预留 8 GB 内存和 10 GB 空闲 磁盘,并装好 Docker Engine 或 Docker Desktop 以及 Compose v2 或更新版本。

在仓库根目录执行:

docker compose run --build --rm laya

这会构建当前 checkout,在 CPU 上运行示例请求 并打印覆盖 choice、score 和 noul 的 JSON。第一次请求会下载选定的公开 Hugging Face checkpoint;不需要账号。首次下载请留出几分钟。 权重留在具名卷里。之后的运行用 docker compose run --rm laya。

预测结果和置信度仍需在你自己的工作负载上评估。见 基准限制。

ARM64 主机、DGX Spark 和 Apple Silicon 见 ARM64 与 DGX Spark 容器。

NVIDIA GPU / CUDA

装好兼容的 NVIDIA 驱动,并用 NVIDIA Container Toolkit 配置 Docker。GPU 镜像使用 PyTorch CUDA 12.8 wheel。对照 PyTorch 支持的构建检查你 GPU 的计算能力和驱动; 较老的卡可能需要另一种构建。为 CUDA 层预留额外的磁盘空间。显存需求取决于 checkpoint、批大小 和输入长度。

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

这个 override 选择 GPU 0,并把 LAYA_DEVICE=cuda 设为默认。把 LAYA_GPU_ID 设为另一个 主机索引或 UUID。那块 GPU 在容器内显示为设备 0。不下权重也能检查访问是否正常:

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())'

示例在加载 checkpoint 之前会先拒绝不可用的 CUDA。遇到内存或推理错误后,Laya 仍可能回退到 CPU,所以要留意它的警告。在 CPU 和 CUDA 配置之间切换时要重新构建。

镜像设置了 TORCH_DISABLE_NATIVE_JIT=1。否则 PyTorch 2.14 会把一些 eager CUDA 算子替换成 Triton 内核,并在第一次推理时编译它们,而这需要一个 slim 镜像里没有的 C 编译器:容器报告健康, 然后每个请求都失败(#365)。原装内核给出同样的答案、同样的延迟。裸机安装如果 predict 报 Failed to find C compiler,也请设置同一个变量。

这里用的是 Compose GPU 预留。Windows 需要 Docker Desktop 支持的 WSL2 GPU 设置。Apple MPS、AMD/ROCm 和 Intel GPU 容器不在这个快速 开始范围内;除非你另外配置并验证了后端,否则请用 CPU。

配置

在 shell、本地 .env 文件或服务的 environment 块里设置 Compose 变量。不要把密钥提交进 .env。运行时变量也可以通过 docker run -e 使用;仅限 Compose 的设置下面会标出。

变量 默认值 用途
LAYA_DEVICE cpu / cuda 由基础 / GPU 配置选择的设备
LAYA_CUDA_AMP 未设置(checkpoint 的 amp_dtype) CUDA 前向用 fp16 还是 bf16。不是装饰性的:README 的阈值一节测出,在 fp16 一次 argmax 都不翻转的对等集上,bf16 翻转了 864 个中的 3 个
LAYA_CPU_AMP 未设置 bf16 让 CPU 前向使用 bf16;其他任何值都保持 fp32
LAYA_MODEL auto Router 别名:auto、english、multilingual、typed-decisions
LAYA_MODEL_PATH 未设置 容器内兼容的 checkpoint 路径
LAYA_REVISION 未设置 每次 checkpoint 下载所使用的 Hub commit、分支或 tag,或 reviewed 表示用 laya/revisions.py 里经过复核的 SHA;revision= 参数仍然优先
LAYA_REQUEST_FILE 内置请求 容器内的 JSON 请求路径
OMP_NUM_THREADS 4 CPU 线程数;不要超过可用核心
HF_TOKEN / HF_TOKEN_FILE 未设置 可选的 Hugging Face 凭据
LAYA_API_KEY / LAYA_API_KEY_FILE 未设置 仅 laya-serve: 要求 Authorization: Bearer <key>
LAYA_PORT 8000 仅 laya-serve: 容器端口,以及为它发布的宿主机端口
HF_HUB_OFFLINE 0 1 表示只用缓存的 checkpoint
HF_HOME /home/laya/.cache/huggingface 缓存路径;见下面的挂载要求
LAYA_CACHE_VOLUME 项目模型缓存 仅 Compose: 具名缓存卷
LAYA_GPU_ID 0 仅 Compose: NVIDIA 设备索引或 UUID
LAYA_TORCH_INDEX cpu / cu128 / cu130 Compose 构建: PyTorch wheel 索引
LAYA_TORCH_VERSION 2.14.0 Compose 构建: 固定的 PyTorch 版本

Compose 会转发运行时变量,但 HF_HOME 除外 —— 它与固定的缓存挂载保持一致;LAYA_MPS_AMP_MIN_ROWS (MPS 行数门限)也除外,因为这里没有任何镜像能触及它,这里也没有容器能选中 MPS。如果在 docker run 或你自己的 Compose 文件里覆盖 HF_HOME,请提供一个配套的、UID 10001 可写的 挂载。直接 Docker 构建用 --build-arg TORCH_INDEX=cu128 选择 PyTorch;运行时的 -e 改不了已 安装的 wheel。

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

用你自己的请求:

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

要看一份带注释、挂载了请求、checkpoint 和密钥文件的配置,见 compose.example.yml:

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

NVIDIA GPU 在 run 前加上 -f compose.cuda.yaml。这个示例是 compose.yaml 的 override, 所以缓存和镜像设置只放在一处。

密钥文件

HF_TOKEN_FILE 在启动时读取一个挂载的 UTF-8 文件,去掉首尾空白,优先级高于 HF_TOKEN。 读不到、为空或非法的文件会阻止启动,且不打印其内容。该文件必须对 UID 10001 可读。_FILE 只 适用于受支持的密钥,不是每项设置都行。

当 HF_TOKEN_PATH 指向 checkout 之外一个已存在的宿主机文件时:

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

Docker secrets 或 Kubernetes Secret 卷也能提供同一个文件。值在启动时载入进程环境;改文件后需 重启。绝不要把 token 用作构建参数或烤进镜像里。公开 checkpoint 不需要 token。

微调后的 checkpoint

这个镜像跑推理。微调在它之外进行 —— 微调 notebook 在 Kaggle 免费的 2xT4 GPU 上跑完整个循环,导出一个这个镜像能服务的 checkpoint。关于训练接口的 背景和待决问题留在 #4 和 #26。

把 LAYA_CHECKPOINT_PATH 指向一个绝对宿主机目录,里面要有 rl_agent_config.json、 model.safetensors 和匹配的 tokenizer 文件:

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

请用 UID 10001 可写的工作副本,因为加载器可能会更新 tokenizer 配置。单有 LoRA 适配器不算一个 完整的 checkpoint。设置 LAYA_MODEL_PATH 时把 LAYA_MODEL=auto 留着;显式别名和本地路径互不 相容。本地路径的响应来自 Agent,没有 Router 的 routing 元数据。这些设置对 CUDA override 也 适用。请在留出样本上评估微调后的 checkpoint,再决定是否依赖它。

开发与清理

用 docker compose run --rm laya python 打开一个 Python 提示符。想在不下载权重的情况下,对 你的 checkout 跑现有的路由/判定标准检查和密钥文件测试:

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'

改动源码或内置示例后,用 --build 重新构建。镜像以 UID/GID 10001 运行。新建的具名卷继承镜像 缓存目录的属主;宿主机目录必须对该 UID 可写。模型缓存要保持可写,以便做 tokenizer 兼容性更新。

--rm 会删除已完成的容器。docker compose down 保留缓存。要删除已下载的权重,用同样的 Compose 文件和 LAYA_CACHE_VOLUME 设置运行 docker compose down --volumes。下一个请求会重新 下载它们;不要删掉与其他项目共享的缓存。

HTTP 服务

镜像自带 laya-serve,所以跑一次性快速开始的那次构建也能提供兼容 Jev 的 API。 compose.http.yaml 把它加为第二个服务,不动 laya:

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

NVIDIA 再叠上 CUDA override。它要为 laya-serve 重复构建参数和设备预留,因为 laya-serve 是一个单独的服务,针对 laya 的 override 到不了它:

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

up 让服务在前台运行;-d 转到后台。权重进到和快速开始同一个具名的 model-cache 卷,所以 快速开始跑过之后再起服务,checkpoint 已经在磁盘上了。用同样的 Compose 文件,通过 docker compose ... down 停止。

端口只在 127.0.0.1 上发布。在设置 LAYA_API_KEY 之前 API 没有认证,所以用 LAYA_BIND_ADDRESS=0.0.0.0 暴露它之前先设一个 key,并为远程客户端在前面放一个 TLS 反向 代理。两种情况下 /health 都不需要认证。

服务对 /health 有健康检查。服务器在开始监听前先预加载,所以 LAYA_PRELOAD=1 时,一个健康的 容器其 checkpoint 已经加载好了。docker compose ... up -d --wait laya-serve 会在它健康后 返回。

/health 报告的 device 是常驻 checkpoint 实际计算所用的设备,它不总是 LAYA_DEVICE 要求的 那个:一个想要 GPU 却拿不到的 checkpoint 会静默回退到 CPU,仍然给出正确的答案。 checkpoint_devices 列出每个已加载的 checkpoint,device_is_preference 只在没有任何常驻 checkpoint 时为 true,于是一个悄悄丢了 GPU 的部署会说出来,而不是把自己配置里的东西原样 回声。

服务器配置

这些只适用于 laya-serve 服务。

变量 默认值 作用
LAYA_HOST 0.0.0.0 容器内的绑定地址
LAYA_PORT 8000 容器端口,以及为它发布的宿主机端口
LAYA_BIND_ADDRESS 127.0.0.1 端口发布所在的宿主机地址
LAYA_PRELOAD 0 1 表示启动时就构建每个 checkpoint,而不是首次请求时
LAYA_MODELS (全部) 要预加载的逗号列表:english,multilingual,typed-decisions
LAYA_THREADS OMP_NUM_THREADS 限制 torch 进程内线程数;保持在物理核心数或以下
LAYA_AUTO_TASK 0 1 让路由器能自动触达 typed-decisions
LAYA_MAX_LOADED 2 保持常驻的 checkpoint 数;LAYA_AUTO_TASK 让第三个可按需触达,而上限低于路由实际选择时,每次切换都会重建一个
LAYA_MAX_CONCURRENT 16 一次可接纳的请求数;更晚的会拿到 503(无法解析或非正数的值会回退到 16)
LAYA_LOG_LEVEL info uvicorn 日志级别
LAYA_API_KEY (无) 设置后要求 Authorization: Bearer <key>
LAYA_ROOT_PATH (空) 在反向代理之后时,FastAPI 的公开 URL 前缀;代理应在转发前把它剥掉
LAYA_MAX_TOKEN_BUDGET 8192 对每请求 max_len 和 head_max_len 覆盖的上限
LAYA_SHA256_DIGESTS (无) 在解析 checkpoint 之前校验的 JSON 摘要:对所有 checkpoint 是 {artifact: digest},对每个 checkpoint 是 {model: {artifact: digest}}。见安全

比如,在 /laya 下发布 API 时,设置 LAYA_ROOT_PATH=/laya。代理必须在转发到容器之前剥掉这个 前缀;这项设置更新 FastAPI 生成的 URL,不改变内部的 /health 或 /v1/systemone 路由。

LAYA_PRELOAD 这里默认是 0,而不是包默认的 1,因为预加载会让首次启动下载全部三个 checkpoint。长时间运行的部署把它设为 1,这样第一个请求不用为构建买单。

LAYA_PORT 同时设置发布的宿主机端口和服务器绑定的端口,所以两者不会脱节。要挪动服务,只改 一处:

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

从文件读 bearer token

LAYA_API_KEY_FILE 在启动时读一次,移入 LAYA_API_KEY,然后在服务器 exec 之前删掉 _FILE 变量。优先用它,而不是把 key 放进环境:

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