关于 serve-model
serve-model 是指导在 MAX 上运行现有模型的技能,面向部署和排查服务的用户。它从最小命令开始,并依据模型架构与检查点信息调整参数。
主要功能
- 01生成自定义架构的启动命令
- 02选择设备、编码和上下文长度
- 03启动服务并检查就绪状态
- 04排查启动错误
适用场景
- 01在 MAX 上启动内置模型
- 02部署已有的自定义架构
- 03诊断 max serve 启动失败
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ modular/ skills --skill serve-model安装后在 Claude Code 中输入/serve-model确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/custom-arch.mdflags.mdtroubleshooting.mdscripts/suggest_serve_command.py详细介绍
使用 MAX 提供模型服务
max serve 会为模型启动兼容 OpenAI 的 HTTP 服务。它负责处理分词、批处理、KV 缓存和整个服务栈。你只需指定检查点;如果模型尚未内置于 MAX,还需指定自定义架构包。本指南将带你从“没有环境”到“服务能够响应请求”,并帮助你选择适合特定模型的标志,而不是靠猜测。
指导原则:从最简单的可行命令开始,只有模型或硬件要求时才添加标志。MAX 会自动检测大多数设置(数据类型、序列长度、设备默认值)。标志指定过多,是人们把原本正常运行的服务弄坏的最常见原因。
在以下情况下使用本指南:你想在 MAX 上运行、启动或托管模型:启用兼容 OpenAI 的端点、提供内置或自定义/移植架构的服务,或排查 max serve 启动失败的问题。
在以下情况下不要使用本指南:模型尚未在 MAX 中实现(没有可用的 arch.py、计算图和权重)。这是模型移植任务:使用 import-model 移植架构;如果模型可以提供服务但输出有误,则使用 debug-model。本指南用于运行现有模型,不用于编写模型。
参考资料
| 文件 | 何时阅读 |
|---|---|
| references/custom-arch.md | 提供自定义架构的服务:arch.py 到标志的映射、编码和设备,以及服务时的注意事项 |
| references/flags.md | 选择 --model、--devices、--quantization-encoding 和 --max-length 之外的任何服务标志 |
| references/troubleshooting.md | max serve 启动失败或出现难以理解的错误 |
阅读与你当前任务相关的参考资料,不必一开始就全部阅读。
快速开始(自定义架构):先执行此操作
如果已经安装 MAX,并且拥有可用的自定义架构包,那么只需调用四次即可完成整个任务。不要手动阅读 arch.py 和 config.json,再自行推断标志。随附的检查器会完成这些工作,并打印出可直接运行的命令及其推理过程:
# 1. Get the recommended command + notes (reads arch.py + config.json for you).
python <skill>/scripts/suggest_serve_command.py \
--custom-architectures /abs/path/to/my_arch --model <hf-repo-or-path>
# 2. Launch it (add `pixi run` if in a pixi project). On a REMOTE box, wrap with
# `setsid ... </dev/null` so it survives the SSH session:
setsid <the suggested command> </dev/null > /tmp/max-serve.log 2>&1 &
# 3. Wait for readiness in ONE call (fails fast on a crash; ~10 min budget for
# a cold compile, advancing `Still compiling` heartbeats are normal):
timeout 600 bash -c 'until grep -qE "Server ready|Uvicorn running" /tmp/max-serve.log; do
grep -qiE "Traceback|CRASHED|Error building|cannot be found|not found in registry" /tmp/max-serve.log && { echo SERVE_FAILED; tail -30 /tmp/max-serve.log; exit 1; }
sleep 3; done' && echo SERVE_READY
# 4. Confirm with one request (model field must equal --served-model-name):
curl -s http://localhost:8000/v1/chat/completions -H "Content-Type: application/json" \
-d '{"model":"my_arch","messages":[{"role":"user","content":"The capital of France is"}],"max_completion_tokens":32}'
阅读检查器的 # notes:。其中会指出容易踩坑的地方(例如与检查点不一致的 default_encoding、与内置架构重名的 name、仅适用于 GPU 的编码,以及 MoE)。如果命令能够正常运行且输出合理,任务就完成了。只有在注释或失败提示要求时,才继续查看下方的详细步骤。本文其余部分将解释检查器的原理,以及检查器无法满足需求时该怎么做。
1. 确认已安装 MAX
用户需要一个 nightly 构建中的 max 二进制文件。先检查;如果已安装,则不要重新安装(只有当项目包含 max[serve] 或 max-serve 额外依赖时,max serve 命令才可用):
max serve --help # already in a MAX env?
pixi run max serve --help # or inside a pixi project
如果 max serve 命令不可用,请设置环境。默认使用 pixi;关键是配置 conda 渠道
https://conda.modular.com/max-nightly/ 和 conda-forge。如果尚未安装 pixi,请按照 https://pixi.prefix.dev/latest/#installation 中的最新说明进行安装,然后:
# pixi (conda channels)
pixi init my-max-project \
-c https://conda.modular.com/max-nightly/ -c conda-forge && cd my-max-project
pixi add max-serve
如果已存在 pixi.toml,channels 行必须完全如下:
[workspace] # or [project] on older pixi
channels = ["https://conda.modular.com/max-nightly/", "conda-forge"]
有些用户更喜欢 uv,它会从 Modular 的 wheel 索引获取 MAX,而不是使用 conda。如果尚未安装 uv,请按照 https://docs.astral.sh/uv/getting-started/installation/ 中的最新说明进行安装,然后:
# uv (pip wheels)
uv init my-max-project && cd my-max-project
uv venv && source .venv/bin/activate
uv add "max[serve]" --index https://whl.modular.com/nightly/simple/ --prerelease allow
使用 pixi 设置后,请在命令前加上 pixi run(或进入 pixi shell)。使用 uv 后,请激活 venv(source .venv/bin/activate),然后直接调用 max。本技能后续内容中的命令均为裸 max serve ...;在 pixi 项目中且尚未进入 shell 时,请在前面加上 pixi run。
2. 这是内置模型还是自定义架构?
MAX 内置了许多架构。如果模型的架构已受支持,则完全不需要 --custom-architectures,只需使用 --model。
max list # every registered architecture + example repo IDs
将检查点的 config.json::architectures[0](例如 LlamaForCausalLM、Qwen2ForCausalLM)与列表进行比对。
- 在列表中:内置架构。跳至步骤 4,并省略
--custom-architectures。 - 不在列表中:需要自定义架构包(步骤 3)。如果用户还没有此类包,本技能无法为其生成;这属于 bring-up 任务(实现
arch.py、model.py、图和权重适配器)。请引导他们使用模型 bring-up 工作流,然后到此为止。
3. 指定自定义架构
自定义架构是一个 Python 包(包含 __init__.py 的目录),其中公开了一个顶层 ARCHITECTURES 列表,列表中包含 SupportedArchitecture 实例。通过 --custom-architectures 传入该包;MAX 会导入它,按 name 注册每个架构,并在每次请求时,将检查点的 config.json::architectures[0] 与已注册的 name 进行匹配。
请先阅读该包,再编写命令。架构包是大多数标志的准确信息来源,因此不要猜测。请打开两个文件:
arch.py:SupportedArchitecture(...)调用。其中的default_encoding是服务所用的编码;supported_encodings是--quantization-encoding必须属于的集合;name必须与检查点匹配;multi_gpu_supported表示是否可以进行分片;如果包中有chat_template.jinja,则需要使用--chat-template。config.json(检查点):architectures[0]必须与arch.py中的name相同;max_position_embeddings限定了--max-length的上限;torch_dtype/quantization_config应与default_encoding一致;MoE 字段(num_experts等)表明你可能需要使用--device-graph-capture。
references/custom-arch.md 是详细指南:其中包含 arch.py 到标志的逐字段映射、编码到设备的对照表,以及不明显的服务时注意事项(overlap-scheduler 与 logprobs、端口 8001 的指标冲突、trust-remote-code)。服务自定义架构时,请随时查阅。
将 --custom-architectures 指向包的目录(使用绝对路径对脚本和远程主机来说最稳妥)。IMPORT_PATH:MODULE_NAME 冒号格式也可用,但大多数工具使用目录路径:
max serve --model <hf-repo-or-path> --custom-architectures /abs/path/to/my_arch
请预先运行以下三项检查,而不要等到查看堆栈跟踪;它们几乎可以避免所有自定义架构服务失败:
SupportedArchitecture中的name=必须与config.json::architectures[0]完全相同。supported_encodings必须包含检查点实际采用的编码(bf16 检查点需要bfloat16,GPTQ 检查点需要gptq等)。weight_adapters必须包含检查点权重格式对应的条目(.safetensors对应WeightsFormat.safetensors,.gguf对应WeightsFormat.gguf)。
如果模型尚未是可正常工作的自定义架构包(尚未实现计算图、权重适配器和配置),那属于接入任务,而不是服务任务。本技能用于服务已有的包,不负责创建包。
4. 构建 serve 命令(默认优先)
从最简命令开始并运行。让 MAX 自动检测其余配置。
max serve --model <hf-repo-or-path> [--custom-architectures ...]
这已经会绑定到 0.0.0.0:8000,有 GPU 时使用 GPU 提供服务(否则使用 CPU),根据检查点推断 dtype,并根据 max_position_embeddings 设置 max_length。GPU 是默认选项,因此对于常见的单 GPU 情况,无需传入 --devices。对于许多在单 GPU 上运行的模型,这条最简命令就足够了。
只有在有明确理由时才添加标志。最常用的三个标志:
| 标志 | 适用场景 | 示例 |
|---|---|---|
--devices | 必须指定特定 GPU、跨 GPU 分片,或强制使用 CPU(GPU 已是默认选项)。 | --devices gpu:0 · --devices gpu:0,1,2,3 · --devices gpu:all · --devices cpu |
--quantization-encoding | 仓库包含多种格式,或自动检测选错格式。 | --quantization-encoding bfloat16 |
--max-length | 想使用比模型最大上下文更短的上下文(可节省 KV 内存),或需要限制长度以适配资源。 | --max-length 4096 |
其他所有设置(设备内存、批次大小、任务选择、滑动窗口、信任远程代码、多 GPU 并行、推测解码)请参阅
references/flags.md。添加任何不确定的标志之前,请先阅读该文档;
其中说明了每个标志的作用,以及何时不应设置。
按以下顺序决定:
- 优先使用默认值。尝试最简命令。对于内置配置,自动检测通常是正确的,而且 GPU 是默认设备。
- 对于自定义架构,阅读软件包。
arch.py中的default_encoding就是你的--quantization-encoding。该编码会限制可用设备:fp8、 fp4 和 gptq 只能使用 GPU;而 GPU 已是默认选项,因此无需为它们添加--devices(参见references/custom-arch.md)。将--max-length限制为config.json::max_position_embeddings。如果检查点包含自定义建模文件,则添加--trust-remote-code;如果软件包附带聊天模板,则添加--chat-template。这些不是猜测;你可以直接从软件包和配置中查到。 - 当某项选择会产生重大影响时,进一步检查。对于不常见的属性
(滑动窗口、部分 RoPE、MoE 路由),检查
config.json,并使用references/flags.md将检查结果对应到标志。 - 不确定时就询问。如果某项决定取决于你无法看到的信息(哪些
GPU 空闲、需要多长的上下文、使用 CPU 还是 GPU),请询问用户,而不是猜测。错误的
--devices或 dtype 会导致程序缓慢且难以理解地失败;快速问一句更省事。
5. 启动并确认运行正常
启动(在后台运行,并记录可跟踪的日志):
max serve --model <hf-repo-or-path> [flags] > /tmp/max-serve.log 2>&1 &
如果你通过 SSH 在远程机器上启动,单独使用 & 会在 SSH 会话关闭时终止进程,而且编译可能耗时超过连接时长。请彻底分离进程:
setsid max serve --model <hf-repo-or-path> [flags] </dev/null > /tmp/max-serve.log 2>&1 &
通过单次调用监视日志心跳来等待服务就绪;如果进程崩溃则快速失败,而不是一直等待到超时:
timeout 600 bash -c 'until grep -qE "Server ready|Uvicorn running" /tmp/max-serve.log; do
grep -qiE "Traceback|CRASHED|Error building|cannot be found|not found in registry" /tmp/max-serve.log && { echo SERVE_FAILED; tail -30 /tmp/max-serve.log; exit 1; }
sleep 3; done' && echo SERVE_READY
服务器就绪时会打印以下内容:
Server ready on http://0.0.0.0:8000 (Press CTRL+C to quit)
大模型首次启动时会进行编译。出现一段没有其他输出、但持续显示
Still compiling model (Ns elapsed) 心跳的间隔是正常的,并不代表进程卡住:已用时计数器是判断进程是否存活的信号。只要计数器持续递增,就继续等待;只有计数器停止变化(或者进程仍在运行,但日志的修改时间停止更新),才应认为服务卡住了。
确认服务正常后,发送一个实际请求:
curl -s http://localhost:8000/v1/health # 200 when ready
curl -s http://localhost:8000/v1/models # served model name
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "<hf-repo-or-path>",
"messages": [{"role": "user", "content": "The capital of France is"}],
"max_completion_tokens": 32
}'
请求中的 model 字段必须与传给 --model 的值一致(如果通过
--served-model-name 覆盖,则需与该参数的值一致)。请阅读响应:服务器状态显示正常,并不代表启动流程就完成了。检查文本是否连贯,而不是重复内容或乱码。如果服务成功运行,但输出有误,那属于兼容性/正确性问题,而非服务问题。
缓存权重和编译结果,以加快后续启动
模型首次启动时会下载权重并编译计算图,这是耗时的部分。这两项结果都会缓存,因此后续启动同一模型时会快得多。
-
权重通过
huggingface_hub下载到共享的 Hugging Face 缓存中(默认路径为~/.cache/huggingface;设置HF_HOME可更改路径)。 再次启动同一仓库的模型时会复用缓存权重,无需重新下载。 -
编译结果也会缓存。若要提前预热这两种缓存(例如在演示或部署之前),以便首次运行
max serve时跳过下载和Still compiling等待,请先运行max warm-cache:max warm-cache --model <hf-repo-or-path> [--custom-architectures /abs/path/to/my_arch]编译后的产物(MEF)与平台相关,因此请在相同硬件上预热缓存(或者传入
--target,例如cuda:sm_90,以便在不同主机上针对部署目标进行编译)。
故障排查
根据症状查阅 references/troubleshooting.md。其中介绍了一些看似晦涩、但只需一行即可修复的启动故障(编码不匹配、architectures[0] 名称不匹配、trust_remote_code、加载时内存不足、端口被占用、设备路由错误)。请先查看服务日志;真正的错误通常出现在最后一段 traceback 上方几行。