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