Install
openclaw skills install @huaweicloudskill/huawei-cloud-modelarts-vllm-ascend-model-deploy指导在华为云 ModelArts 推理平台通过 vLLM-Ascend 推理框架部署开源大语言模型(GLM/Qwen/DeepSeek/Llama 等)为昇腾 NPU 在线推理服务的完整流程。覆盖:确认模型后按 vllm-ascend 社区文档与用户确认部署形式(单节点/多节点/PD分离/PD共置 4 种形式,统一单部署单元承载),从 HuggingFace/ModelScope 下载模型权重并上传 OBS、从 Quay.io 拉取 vllm-ascend 镜像并推送 SWR、按确认的部署形式选用专用脚本模板(单节点/多节点/PD/PD共置 四套,脚本内不做部署形式运行时分支)生成启动/探针/角色识别脚本并上传 OBS、按 ModelArts 平台适配要点(端口 8080、OBS 挂载、bash 数组、探针命令检查、超节点亲和组、Mooncake KV 传输)通过新版在线服务部署(二选一: 方式A 调用 CreateInferService API(POST /v2/{project_id}/services)自动部署 / 方式B 在 ModelArts 控制台按一步步点击指导手动部署;不再创建 AI 应用——该模块已废弃)、通过 OpenAI 兼容 API 调用验证。Triggers include: "ModelArts 部署大模型/开源模型", "vllm-ascend", "昇腾 NPU 推理", "HuggingFace/ModelScope 模型上云", "OBS/SWR 镜像迁移", "大模型在线服务", "多机部署", "多副本部署", "PD 分离部署", "PD 共置部署", "超节点亲和组", "Mooncake KV 传输", "新版在线服务", "CreateInferService", "控制台手动部署在线服务"。当用户提到以上任一场景时都应使用本技能,即使没有明确说出'部署'二字。
openclaw skills install @huaweicloudskill/huawei-cloud-modelarts-vllm-ascend-model-deploy通过 vLLM-Ascend 推理框架结合 ModelArts 推理平台的在线服务部署能力,将 HuggingFace、ModelScope 等开源社区的大语言模型(GLM、Qwen、DeepSeek、Llama 等)快速部署到昇腾 NPU 环境,提供 OpenAI 兼容的 RESTful API。本 skill 覆盖全流程: 模型确认与部署形式决策(4 种形式: 单节点/多节点/PD 分离/PD 共置,统一单部署单元)→ 权重/镜像准备 → 启动与探针脚本生成 → 新版在线服务部署(API 自动 / 控制台手动)→ OpenAI 兼容调用验证,并内置 ModelArts 平台适配要点(端口 8080、OBS 挂载、超节点亲和组、PD 分离、Mooncake KV 传输)与安全编码规范(URL 白名单 + 用户输入校验)。
重要声明: 本部署方案基于 vLLM-Ascend 开源社区提供的模型与镜像,仅适用于功能验证、原型测试等场景。生产环境的高可用、安全合规、可观测性及运维管控要求,请勿直接将本方案用于业务生产。模型能力与性能取决于开源社区。
步骤 1 模型权重准备 — 确认部署模型 → 查模型文档 → 与用户确认部署形式(4 种形式 + 节点数 + 副本取舍)→ 确认权重就绪 → OBS
步骤 2 部署镜像准备 — 按模型文档+部署形式定版本/tag → 确认 SWR 就绪状态(已就绪: 记录地址 / 未就绪: 自行或代下载)→ 记录地址
步骤 3 脚本准备 — 按确认的部署形式选用专用模板,填充模型文档参数 → 生成 start_vllm.sh / health_check.sh → 产物自检关卡(可用性硬性 + 性能软性,对照华为云最佳实践 + vllm-ascend 文档) → OBS SDK 上传
步骤 4 新版在线部署 — 二选一: 方式A API 自动(create_infer_service.py 调 CreateInferService)/ 方式B 控制台手动(11 步点击指导)—— 直接以 SWR 镜像 + OBS 挂载部署,不再创建 AI 应用(该模块已在平台废弃)
步骤 4.4 验证部署(已并入步骤 4) — 查询服务状态/调用端点 → 确认 RUNNING
步骤 6 调用验证 — OpenAI 兼容 API 调用 /v1/chat/completions
安全编码规范(强制,所有工具调用必须遵守): 本 skill 涉及 curl/脚本/API 等多处工具调用,任何传给工具的参数在拼接进命令前必须校验,防止恶意输入被利用(对应安全扫描 TM1 工具参数滥用):
- URL 白名单校验(强制): 任何 curl/HTTP 请求的目标 URL,主机名必须在白名单内才允许执行——白名单:
docs.vllm.ai、quay.io、huggingface.co、modelscope.cn、*.myhuaweicloud.com(iam/obs/modelarts/swr 等华为云域名)、127.0.0.1/localhost(本地探活)。不在白名单的 URL 一律拒绝执行,改用 AskUserQuestion 请用户确认目标地址。模型文档/镜像地址等用户提供的 URL 必须校验 host 后使用,禁止直接拼进 curl/命令。- 用户输入校验(强制): 模型名、OBS 路径、SWR 地址、服务名、workspace-id 等用户提供的输入,拼接进命令/请求体前必须先做格式校验(正则/白名单枚举,如服务名仅小写字母/数字/连字符、OBS 路径以
obs://开头、SWR 地址形如swr.<region>.myhuaweicloud.com/<org>/<name>:<tag>),类型与格式不符的非法输入直接拒绝,用 AskUserQuestion 让用户重新提供,禁止带病执行。- 禁止未校验拼接: 禁止将用户输入直接拼进 shell 命令/JSON 请求体(如把 URL 拼进
curl <url>、把模型名拼进脚本参数)。脚本侧的参数校验参考scripts/create_infer_service.py/scripts/upload_code_to_obs.py的现有实现(非法参数sys.exit拒绝)。 关键原则(镜像与脚本的共同前提): 步骤 2(镜像)与步骤 3(脚本)都必须先根据用户确认的模型,在 vllm-ascend 模型适配文档(https://docs.vllm.ai/projects/ascend/zh-cn/latest/tutorials/models/)中定位该模型页面,从页面提取镜像版本/tag 要求、启动命令示例与支持的部署形式(单节点 / 多节点 / PD 分离),再据此拉镜像、写脚本。禁止脱离模型文档凭经验猜 tag、猜部署形式或套用通用命令。 产物生成前置校验(强制,违反=产物作废): 生成任何部署产物(start_vllm.sh/health_check.sh/probe.sh/DEPLOY_GUIDE.md/ 部署指导文本 / API 请求体)前,必须重新 Read/grep 本 SKILL.md 对应章节 +templates/下实际模板文件,以磁盘当前内容为准。所有确定性取值(健康检查失败次数、启动延迟、端口、探针脚本文件名、挂载路径、TP_SIZE推导规则、镜像 tag、环境变量清单)必须来自本 skill 文件或模型适配文档——禁止凭经验/记忆/常识填写(例如健康检查失败次数是 skill 规定的 300 而非 K8s 默认 3;探针脚本是health_check.sh而非旧的probe.sh)。若产物中的任何数值/文件名/取值与 skill 当前文件不一致,该产物无效,必须按 skill 实际内容重写。本 skill 文件可能被外部更新(SKILL.md/模板/references 的时间戳会变),每次生成前必须核对当前文件,不得假设内容与上次会话一致。 API 部署前置校验(强制): 调用 CreateInferService 创建服务前,必须逐项核对以下规则,违反=请求必然失败:- 请求体是顶层平铺结构(
name/type/group_configs[]/runtime_config直接放顶层)——禁止用service.deployment.roles[]包裹(旧骨架报 400name/type/group_configs/runtime_config缺失)group_configs[].secret_type: "agency"(OBS 挂载委托认证)——dew/obspool/obs报ModelArts.8162/8163;此字段易在修改请求体时被覆盖丢失(修正端口/其他字段后必须复查)runtime_config.service_invoke.port必须与启动脚本PORT一致(8080)——否则探针探测端口错位- PD 双角色
unit_configs[].envs必须显式设不同PORT(如 DecodePORT: "7101")+VLLM_ROLE- 健康检查参数:
failure_threshold=300/initial_delay_seconds=300/period_seconds=60(failure_threshold=30窗口不足,vLLM V1 首启 10~20 分钟触发 Unhealthy)runtime_config.service_limit必填三项:request_timeout=300(秒,平台默认 30s 会掐断慢速推理请求,报ModelArts.8909 request timeout: 30s——PD 分离首请求需 prefill+decode 协作、大模型首请求含权重加载/CUDAGraph 编译,>30s 必触发)、request_size_limit=20、rate_limit(如{"num": 200, "unit": "SECONDS"});group_configs[].weight(100)必填- token 获取: 用户提供的 token 可能复制截断(含
-/不以==结尾 →401 decrypt token fail);推荐 IAM API 获取 + Python 正则完整提取(re.search(r'(?i)^X-Subject-Token:\s*(\S+)', content, re.M),禁 shell 管道grep|sed|tr,长 token 会丢字符)- 所有环境(生产/dev)API 调用都必须带
X-Workspace-Id头(--workspace-id 参数)——生产环境也必须带,不是只有 dev 环境需要;不带则查不到对应工作空间的服务(list 返回其他工作空间或空),导致误判"无同名服务"而创建失败(8006/8118)。⚠️ list API 的X-Workspace-Id头不起过滤作用——list 必须用 URL 查询参数?workspace_id=<id>才能按工作空间过滤(只传头返回的是 default 工作空间的服务);create_infer_service.py的cmd_list已拼接查询参数,其他脚本/手动调用 list API 时须加?workspace_id=<id>- 不确定请求体结构时: 查询已部署成功的现有服务(
show返回version.instance_groups[].unit_configs[]即完整参考),对照构造,不凭空猜- 部署超时时间统一 300 分钟(强制): CreateInferService 请求体顶层必须显式设置
deploy_timeout_minutes: 300(单位分钟),控制台部署时"部署超时时间"填 300 分钟。禁止使用平台默认(20~60 分钟)——多节点/大模型(如 GLM-5.2 MoE)首次启动含模型加载 + CUDAGraph 编译,60 分钟仍不足以 RUNNING,会触发部署超时失败(status: FAILED,详情deploy_timeout_minutes: 60)。字段在请求体顶层(与name/type同级);构造请求体后复查该字段未被覆盖丢失。 部署形式须与用户确认(本技能新增决策点): 确认模型后,必须先从模型文档/社区明确该模型采用单节点部署、多节点部署还是 PD 分离部署(步骤 1.1),整理推荐形式与依据,与用户确认后再进入镜像与脚本准备。不同部署形式下,启动脚本结构(单机 TP / 多机 Ray 分布式 / PD 分离双角色)、健康检查策略(PD 区分 prefill/decode)、ModelArts 部署配置(节点数/实例数/网络)差异显著,先定形式才能针对性适配。 部署形式是计划期决策,不是运行时决策(强制): 部署形式经用户确认后即固定为方案输入,生成的启动/健康检查脚本是该形式的专用产物——脚本内不再通过DEPLOY_FORM环境变量做运行时分支。步骤 3 按确认的形式直接从templates/选用对应模板(单节点/多节点/PD/PD+多节点四套),填充模型文档参数后在本地产物目录保存为start_vllm.sh/health_check.sh上传。ModelArts 部署时无需也不应再传DEPLOY_FORM环境变量(PD 的VLLM_ROLE、多节点的NODE_RANK/MASTER_ADDR等是形式内部的实例属性,由部署单元注入,不受此限制)。 ⚠️ 官方文档不可达时的强制降级与纠错机制: 若docs.vllm.ai网络不可达,严禁改用论坛帖/博客/搜索摘要作为 tag 依据(这些是二手信息,版本常与模型文档不一致)。先排查是否为 TLS 证书问题,再走降级。正确做法按优先级:- 使用 curl 访问第三方服务时的安全约定: 企业/云上环境常经安全代理(如 netentsec)转发公网请求,代理对目标站点做 TLS 中间人(MITM)证书替换,返回自签名/未知 CA 证书,默认校验失败报
SSL certificate problem。执行前必须先校验目标 URL 主机名在白名单内(docs.vllm.ai / quay.io / huggingface.co / modelscope.cn / *.myhuaweicloud.com / 127.0.0.1),不在白名单的 URL 直接拒绝执行并请用户确认;白名单校验通过后方可执行,必须携带-k(或--insecure)跳过代理 MITM 证书。校验逻辑: 定义 ALLOWED 白名单 → 提取目标 host →grep -qw匹配白名单 → 不匹配则exit 1拒绝 → 匹配则放行执行。注意:-k仅跳过证书校验,-k后仍返回 000/超时才是真拦截;-k后能拿到 200/302 即说明只是证书问题。内部/本地探活(如127.0.0.1健康检查)不使用-k;- 先验证是否证书问题: 按上述白名单校验通过后,执行
curl -sk -o /dev/null -w "%{http_code}" --max-time 15探测目标(如 docs.vllm.ai 在白名单内),返回 200/302 → 加-k继续查文档,不降级;- 加
-k仍不可达(代理真拦截/网络不通): 请求用户提供官方文档链接或页面内容(用户通常可访问,或给出如https://docs.vllm.ai/projects/ascend/zh-cn/latest/tutorials/models/<Model>.html的直达 URL);- 向用户明确披露: "官方文档不可达,当前 tag 依据为 XX,存在不确定性,请协助确认"——不得在未披露的情况下按猜测推进;
- 收到官方文档确认后,无条件改用官方 tag,并同步修正启动脚本与已上传 OBS 的产物(覆盖上传)。 任何情况下,模型页面明确标注的
docker pull quay.io/ascend/vllm-ascend:<tag>就是最终依据;带芯片变体的 tag(如-a3/-310p)按目标芯片选择,不带后缀的通用 tag 默认对应 A2(910B)。
本 skill 的核心部署操作(镜像推送、OBS 上传、调用 CreateInferService)默认使用 Python 脚本(scripts/)与 curl,以支持完整 JSON 请求体与安全 token 传递。若用户环境已配置 KooCLI(hcloud)并希望用 CLI 方式执行同等操作,命令格式遵循华为云 CLI 标准(安装参考 references/cli-installation-guide.md)。
hcloud <Service> <Operation> --cli-region={region} [--key=value]
ModelArtsCreateInferService--cli-region 必带: 指定区域,如 --cli-region=cn-north-4,必须与资源池所在区域一致示例(创建在线服务,需先 hcloud configure 配置 AK/SK 或用 --cli-auth-token):
hcloud ModelArts CreateInferService --cli-region=cn-north-4 \
--project_id=<PROJECT_ID> --body='{"name":"...","type":"REAL_TIME",...}'
注意: KooCLI 为可选替代方式;
--cli-region是 CLI 命令的必带参数。请求体字段与 Python 脚本scripts/create_infer_service.py --raw-json完全一致(顶层平铺结构),token 敏感凭据仍按"安全编码规范"处理。若 hcloud 命令执行报参数错误,回退到本 skill 的 Python 脚本方式(见步骤 4.3)。
GLM5.3、Qwen、DeepSeek)而非精确模型 ID,必须先抓取 vllm-ascend 模型索引页检索全部相关模型页面,整理完整候选清单(权重版本/硬件要求/镜像 tag/部署形式/下载来源)展示给用户,由用户确认选择,禁止 skill 自行替用户决策使用哪个模型(见步骤 1.0)。精确模型 ID 或用户明确授权"按你推荐的选"时方可省略候选清单。DEPLOY_FORM 环境变量在脚本内做运行时分支。不要默认所有模型都单节点部署,也不要在文档未支持时强行套用多机/PD 参数。开始前逐项与用户确认,缺失则提示补齐:
| 项 | 说明 | 确认方式 |
|---|---|---|
| 华为云账号 | 已开通 ModelArts、OBS、SWR 服务并完成实名认证;提供 OBS AK/SK 与 Endpoint(或临时委托凭据)供 OBS SDK 上传 | 用户确认 |
| OBS 桶 | 存储模型权重、启动脚本、健康检查脚本;建议同区域 | 用户提供桶名与区域 |
| SWR 镜像仓库 | 存放 vllm-ascend 推理镜像 | 用户提供组织名 |
| 昇腾 NPU 资源池 | ModelArts 专属资源池;需确认芯片型号(910B 系列/910C(A3)/310P)与卡数,以及资源池是否支持多节点(多机)规格(决定部署形式上限) | 用户提供资源池名称/芯片型号/卡数/多机能力 |
| ModelArts 域名/环境 | 调用 ModelArts API 前必须确认环境域名: 生产环境 modelarts.<region>.myhuaweicloud.com 与开发(dev)环境 modelarts-dev.<region>.myhuaweicloud.com 的工作空间列表与资源池可见性不同(生产域名下工作空间列表只有 default,dev 域名下才能查到全部工作空间(如 test));后续步骤 4 所有 API 调用(查工作空间/查资源池/创建服务)必须用确认后的域名 | 用户确认(用户通常知道用的是 dev 还是生产) |
| 工作空间名 | 资源池/服务所属的 ModelArts 工作空间(如 default / test);必须先确认工作空间名,再通过 API 查其 workspace-id(GET /v1/{project_id}/workspaces),后续 API 调用带 X-Workspace-Id 头 | 用户确认工作空间名 + API 查询 workspace-id |
| 部署形式 + 节点数 | 4 种部署形式(single 单节点 / multinode 多节点 / pd PD 分离 / pd_colocate PD 共置)+ 用户可用节点数 ≥ 最小节点数(见步骤 1.1b;pd 分离资源翻倍),确认后固定为方案输入,脚本按形式专用生成,不做运行时分支 | 模型文档核对 + 用户确认 |
| 模型权重来源 | HuggingFace 或 ModelScope 上的模型 ID;需结合 vllm-ascend 适配文档确认权重格式(如 BF16/W8A8)与下载来源 | 用户提供模型名 + 适配文档核对 |
| 网络 | 本地可访问 Quay.io / HuggingFace / ModelScope(必要时配代理或镜像站);curl 访问第三方服务前先按"安全编码规范"校验目标 URL 主机在白名单内,再加 -k 跳过证书校验(企业代理 MITM 常见,见"关键原则") | 实际执行验证 |
| 工具 | OBS Python SDK(esdk-obs-python,上传部署产物必需)、obsutil(可选,上传权重)、SWR 登录凭据、docker | 本机环境 |
核心原则: 流程中所有需要用户确认、选择、提供信息的决策点,一律通过 AskUserQuestion 交互式组件完成(文本输入 / 枚举选择 / 流程走向)。禁止用纯文本输出"请提供 X"/"请确认 X"后静默结束回合等待用户回复。 用法要求:
- 枚举/选择类: 候选直接作为
options展示(如模型候选清单逐条列为 option),每个 option 带简短 description。- 文本输入类: 每个 question 至少 2 个 options——提供常见默认值/推荐值作为 option,或在 question 文本中写明所需信息格式(如"OBS 权重路径,格式 obs://bucket/prefix/model/<模型名>"),用户通过 Other/notes 补充。文本类信息一次最多 4 个 question(工具上限),超过则分批。
- 合并提问: 相互独立的确认项合并到同一次 AskUserQuestion(最多 4 个 question);前一步输出(如候选清单表格)后必须紧跟一次交互式询问,不得"输出清单后静默等待"。 各步骤交互式确认点速查(均须用 AskUserQuestion): 1.0 模型确认(模糊名列全候选;实验性模型二次确认)/ 1.1a 部署形式(4 选 1: single/multinode/pd/pd_colocate)/ 1.1b 可用节点数 + 最小节点数提示 / 1.1c 副本取舍(单副本多实例 vs 多副本单实例,PD 分离资源翻倍)/ 1.2 权重是否已下载 + OBS 权重路径 / 2.1 SWR 镜像就绪状态 + 地址 / 2.4 SWR 组织名 + docker login 命令 / 3.0 芯片型号·卡数 / 3.4 OBS AK/SK/Endpoint + code 目录 / 4.0 ModelArts 域名·工作空间·区域 / 4.1 部署方式 A/B / 4.3 IAM 凭据或 token 获取方式 / 4.2 末 是否 API 代为部署 / 6 调用 URL·token。
为什么下载前必须先确认模型? 用户提示词中的模型名可能是系列名(如"GLM"、"Qwen")而非精确模型 ID;同一系列在 vllm-ascend 适配文档中可能有多个模型页面与变体(参数量/量化版本/权重格式不同),直接按猜测下载极易下错。 ⚠️ 模糊模型名的强制确认流程(核心约束): 当用户输入的模型名不是精确模型 ID(如
GLM5.3/Qwen/DeepSeek,而非GLM-5.3-Flash-w8a8)时,必须先抓取 vllm-ascend 文档模型索引页(按上方"安全编码规范"白名单校验后执行(curl 访问前先校验 URL 主机名在白名单内,见关键原则第 0 条)),检索并列出全部相关模型候选,交由用户明确选择确认——禁止 skill 自行替用户决策使用哪个模型(禁止凭"最常用/最合适/参数最小"等主观理由选型)。只有两种情况可省略候选清单: ① 用户提示词已给出精确模型 ID 且文档有对应页面;② 用户明确授权"就按你推荐的选"。确认前不进入任何后续步骤。
Qwen2.5-7B-Instruct)→ 记录为唯一候选,进入第 3 步; 模糊模型名/系列名 → 记录为候选集,必须进入第 2 步检索全部相关模型页面(禁止只取第一个匹配)。glm/qwen/deepseek)大小写不敏感过滤索引页,找出所有匹配页面;对每个页面提取: 权重版本、硬件要求(节点数/芯片/卡数)、镜像 tag、部署形式、下载来源(HF/ModelScope);整理成完整候选清单(表格: 候选模型 | 权重版本 | 硬件要求 | 镜像 tag | 部署形式),必须包含全部匹配项。索引页不可达时按"关键原则"降级机制处理,不得凭记忆列候选。Transformers does not recognize this architecture);必要时换团队/内部新版镜像或换稳定版本模型,docker run 验证 transformers 版本(见 2.1 镜像类型识别)。继续部署(接受实验版本风险) / 放弃,换稳定版本模型;选择"继续部署"后方可进入 1.1,并将该确认记入方案(后续失败复盘时引用)。为什么必须先确定部署形式? 同一模型可由 vllm-ascend 社区以不同形式部署,不同部署形式直接影响后续每一步:镜像 tag、启动脚本结构(单机 TP / 多机 DP / PD 分离双实例 / PD 共置单引擎)、健康检查策略、ModelArts 部署配置(节点数/副本数/超节点亲和组/推理单元)。先定部署形式,脚本适配才有的放矢,避免"先写通用脚本、部署时发现形式不匹配返工"。 ⚠️ 部署形式收敛为 4 种(本 skill 统一约定):
single(单节点)/multinode(多节点)/pd(PD 分离)/pd_colocate(PD 共置)。统一单部署单元承载: 单节点/多节点/PD 共置 = 1 个推理单元(unit_configs1 元素);PD 分离 = 2 个推理单元(unit_configs2 元素: prefill + decode,同一部署单元内)。不再考虑多部署单元场景,不再使用 9 场景编号 S1~S9。副本数(单副本/多副本)由 1.1c 依据用户可用节点数 + 可靠性需求决策,不独立枚举。
四阶段交互式确认(1.1a~1.1d,每阶段均用 AskUserQuestion):
references/deployment-form-decision.md 第四节线索表),将推荐的部署形式 + 依据(模型页面链接/内容摘要)整理给用户,用 AskUserQuestion 将 4 种形式列为 options(single / multinode / pd(PD 分离)/ pd_colocate(PD 共置)),由用户点击确认。确认前不进入镜像/脚本准备。
start_vllm.single.shstart_vllm.multinode.sh--kv-transfer-config、Mooncake、双实例方案 → start_vllm.pd.sh(同一部署单元内 prefill + decode 两个推理单元,资源翻倍)start_vllm.pd_colocate.shunit_configs[].count = 该单元所需节点数 N,group_configs[].count = 1;group_configs[].count = floor(M / (N × 单元数))(PD 分离单元数=2,资源翻倍);DEPLOY_FORM(取值 single / multinode / pd / pd_colocate)+ NNODES(单副本内节点数)+ REPLICAS(副本数)+ PD 角色分配(若 pd)。DEPLOY_FORM 仅是方案记录项,不会作为环境变量注入 ModelArts 或写入脚本——脚本按确认的形式直接生成专用版本(见步骤 3.2)。PD 的 VLLM_ROLE、多节点的 master/slave 判定由 ModelArts 部署单元/rank table 注入,不受此限制。完整决策依据与计算规则: 4 形式对比表、ModelArts 层级概念(部署单元/推理单元/副本数/亲和组)、vllm-ascend 线索判断表、最小节点数计算、副本/实例取舍算法详见
references/deployment-form-decision.md——确认前必须按该文件核对。
为什么不直接下载? 模型权重文件由用户(或其环境)负责获取与放置到 OBS。本 Skill 不代为下载权重,只负责确认权重已就绪并获取其 OBS 路径,避免越权操作与数十 GB 的下载开销。
scripts/download_model.py 的下载命令示例,但下载动作由用户执行;告知放置格式后再次用 AskUserQuestion 确认下载进度/路径。obs://{bucket_name}/{path}/model/
{bucket_name} 为 OBS 桶名,{path} 为用户自定义目录前缀(如 llm/weights)。权重文件需直接位于该目录或其子目录下(目录结构即模型目录结构,含 config.json 等)。obs://my-bucket/llm/weights/model/Qwen2.5-7B-Instruct),确认路径存在后再继续。禁止纯文本"请提供 OBS 路径"等待。obs://{bucket_name}/{path}/model/<模型目录>。./obsutil ls obs://{bucket_name}/{path}/model/
config.json、权重分片(*.safetensors)等关键文件/home/ma-user/model)。code 目录,即 obs://{bucket}/{path}/code(除非用户另行提供 code 目录)。记录该目录为方案输入 CODE_OBS_PATH,供步骤 3.4 上传与步骤 4/5 部署时引用。为什么权重必须放 OBS 而不是本地/镜像? ModelArts 在线服务部署时从 OBS 只读挂载权重,服务实例销毁重建后权重仍在,且支持多实例共享;镜像只含推理框架,权重与镜像分离是标准做法。
为什么拉镜像前必须先查模型文档? 不同模型适配的 vllm-ascend 版本不同(如
v0.23.0、v0.18.0rc1),部分模型还有专用镜像或芯片变体 tag(如-a3-openeuler、-310p-openeuler,甚至DeepSeekV4-flash-0731模型专用 tag)。盲目拉latest会导致版本/芯片不匹配而启动失败。镜像版本/tag 必须以用户确认的模型页面要求为准。
https://docs.vllm.ai/projects/ascend/zh-cn/latest/tutorials/models/ 找到步骤 1.0 确认模型的对应页面(URL 形如 .../tutorials/models/<ModelName>.html)。用 curl 访问前先按"安全编码规范"校验 URL 主机名(docs.vllm.ai 在白名单内),再必须加 -k 跳过证书校验(企业代理 MITM,见"关键原则"第 0 条),如 curl -sk <url>;用户提供的其他文档链接同样先校验 host 再访问。
-k 后仍不可达(代理真拦截,000/超时): 不要退化为搜索摘要/论坛帖,按"关键原则"降级机制——用 AskUserQuestion 请用户提供官方文档链接或页面内容,并向用户披露不确定性。v0.23.0(A2)/v0.23.0-a3/v0.23.0-310p)、是否有专用镜像;页面未直接给出 tag 时按"版本 + 芯片型号"在 vllm-ascend 官方镜像仓库 tag 列表选取(版本配套原则见约束限制第 5 条);记录 tag 来源(模型页面 URL)便于事后核对。详细查阅方法见
references/vllm-ascend-model-doc-guide.md。
为什么先确认再拉推? 镜像从 Quay.io 拉取后推送 SWR 是一次性且体积大(数 GB)的操作。用户环境可能已通过其他项目/团队镜像仓完成过该镜像的下载与上传(同一 SWR 镜像可复用,无需重复拉推);反之,若本地网络无法访问 Quay.io,则只能复用已有 SWR 镜像或改用代理。先确认镜像是否已就绪,可避免重复拉推、节省带宽与时间,也避免在用户本地环境做无意义的操作。
quay.io/ascend/vllm-ascend:<tag>)上传到租户的 SWR 镜像仓?(options: 已就绪,提供地址 / 未就绪,自行拉推 / 未就绪,由 skill 代拉推)swr.<region>.myhuaweicloud.com/<组织>/<镜像名>:<tag>,用户经 Other/notes 填写):
swr.<region>.myhuaweicloud.com/<组织>/<镜像名>:<tag>
ATB_*/LCCL_*、SOC_VERSION=ascend910b1、WorkingDir 非 /vllm-workspace、自定义 Entrypoint),其启动方式可能与标准 vllm serve 不同,直接套用本 skill 的 start_vllm.sh 可能启动失败。处理: 让用户确认是否标准官方镜像(或仅升级 transformers 的定制)——是则正常推进;否则**披露"该镜像可能不是标准 vllm-ascend 镜像,本 skill 标准脚本可能不兼容"**并询问镜像预期启动方式,必要时改用镜像自带入口。无法确认时请用户在 ARM 节点 docker run --rm <镜像> bash -c "uname -m && which python && python -c 'import transformers; print(transformers.__version__)'" 快速验证(排查 exec format error 与 transformers 版本)。SWR_IMAGE_ADDRESS,向用户复述确认。后续步骤 4 部署新版在线服务时直接作为模型镜像来源,本步骤不再执行任何拉取/推送SWR_IMAGE_ADDRESS(同分支 A)本节省命令供分支 B-1(用户自行下载上传)参考;分支 B-2(由 skill 代下载上传)的自动化执行见 2.4。tag 一律以步骤 2.0 从模型文档确认的版本为准(可能是
v0.23.0、v0.18.0rc1-a3-openeuler、DeepSeekV4-flash-0731等),不要默认用latest。
# 1. 拉取(以模型文档确认的 tag 为准,示例为 0.23.0;模型专用镜像拉专用 tag)
docker pull quay.io/ascend/vllm-ascend:v0.23.0
# 2. 登录 SWR(使用 SWR 控制台"操作指南"的登录指令,形如)
# 密码经 stdin 注入(不进命令行 argv,不暴露于 ps/proc/history)
export SWR_PASSWORD="<登录密钥>"
docker login -u cn-north-4@<AK> --password-stdin swr.cn-north-4.myhuaweicloud.com
# 3. 打 tag: <region 域名>/<组织>/<镜像名>:<tag>
docker tag quay.io/ascend/vllm-ascend:v0.23.0 \
swr.cn-north-4.myhuaweicloud.com/<org>/vllm-ascend:v0.23.0
# 4. 推送
docker push swr.cn-north-4.myhuaweicloud.com/<org>/vllm-ascend:v0.23.0
docker image inspect <image> | grep -i vllm 核对镜像内 vllm-ascend 版本与文档一致swr.cn-north-4.myhuaweicloud.com/my-org/vllm-ascend:<tag>)提供给 skill 记录适用前提: 本地环境可访问 Quay.io 且已安装 docker;用户已开通 SWR 并在控制台获取过登录指令。
1. 用 AskUserQuestion 收集用户输入(两个文本项合并为同一次 ≤4 question,禁止纯文本等待): ① SWR 镜像仓名称(文本输入): 用户提供 SWR 组织名(如 my-org)与镜像名(可省略,缺省取源镜像名 vllm-ascend);② docker login 命令(文本输入): 用户在 SWR 控制台(组织管理 → 操作指南)复制的登录指令,形如 docker login -u cn-north-4@<AK> --password-stdin swr.cn-north-4.myhuaweicloud.com(密码经 SWR_PASSWORD 环境变量 + stdin 注入,禁止 -p <密码> 明文传 argv)——skill 从该命令解析 SWR 登录域名/region 与登录凭据(用户不便提供命令原文时改为提供 region + AK + 登录密钥)。
2. 执行拉取与推送(全程展示进度,强制): 运行 scripts/pull_push_image.sh,入参: 源镜像 quay.io/ascend/vllm-ascend:<tag>(2.0 确认)、--org <SWR组织名>、--name <SWR镜像名>(缺省 vllm-ascend)、--login "<docker login命令>"。脚本打印 [1/4]~[4/4] 步骤标记并透传 docker layer 进度行;执行时设置足够长超时(镜像数 GB,建议 ≥ 30 分钟),禁止中途打断,同步转述执行输出。大镜像拉取慢时可配置代理或国内镜像加速,但 tag 仍以模型文档为准。
3. 返回并记录结果: 脚本完成时打印完整镜像地址(形如 swr.cn-north-4.myhuaweicloud.com/my-org/vllm-ascend:v0.23.0),skill 记录为方案输入 SWR_IMAGE_ADDRESS 并向用户复述确认,供步骤 4 部署使用;安全提醒: 提醒用户执行 docker logout swr.<region>.myhuaweicloud.com 清理本地登录凭据。
为什么脚本必须与模型、部署形式和资源规格对应? 不同模型(架构、参数量、上下文长度、是否 MoE)的 vllm 启动参数不同;同一模型在不同部署形式(单节点 / 多节点 / PD 分离,步骤 1.1 已确定)、不同芯片型号(如 910B 与 310P)与不同卡数下,启动脚本的结构差异很大(单机 TP 一条命令 / 多机需 Ray 分布式与节点角色 / PD 分离需 Prefill+Decode 双角色实例)。必须查阅该模型在 vllm-ascend 的模型适配文档(
https://docs.vllm.ai/projects/ascend/.../tutorials/models/<ModelName>.html),按"模型 + 部署形式 + 芯片型号 + 卡数"四维匹配,不能套用通用模板。这是本步骤的核心:先查适配文档,再写脚本。
动手查文档前,先用 AskUserQuestion 交互式确认目标资源池的芯片型号与卡数(options 列出常见芯片型号 910B(A2)/910C(A3)/310P 及各档卡数,如"910B(A2) 单机 8 卡"等),并记录到方案中。芯片型号 → 产品形态 → 单卡显存速查表(910B3 64GB / 910B4 32GB / 910C(A3) 以官方为准 / 310P 24GB 量级)与不同芯片 × 模型规模的卡数配置详见 references/ascend-hardware-matrix.md——数值以 vllm-ascend 官方适配文档与昇腾官网规格为准;芯片型号信息缺失时先向用户询问,不要猜测。要点: 310P 是推理卡,只适合 7B 以下小模型;大模型直接报错。
https://docs.vllm.ai/projects/ascend/zh-cn/latest/tutorials/models/(模型页面 URL 形如 .../tutorials/models/<ModelName>.html;curl 访问前先按"安全编码规范"校验 URL 白名单)vllm serve / 旧版 python -m vllm.entrypoints.openai.api_server,两者等价)HCCL_IF_IP/GLOO_SOCKET_IFNAME/TP_SOCKET_IFNAME/HCCL_SOCKET_IFNAME、--data-parallel-size/--data-parallel-size-local/--data-parallel-start-rank/--data-parallel-address/--data-parallel-rpc-port、slave 追加 --headless);PD 分离找 Prefill-Decode 启动参数、VLLM_ROLE、KV Cache 传输(Mooncake)与负载均衡要求——以模型页面/社区文档为准ASCEND_RT_VISIBLE_DEVICES、PYTORCH_NPU_ALLOC_CONF=expandable_segments:True、HCCL_BUFFSIZE、OMP_PROC_BIND=false、OMP_NUM_THREADS、VLLM_USE_V1、TASK_QUEUE_ENABLE、LD_PRELOAD=libjemalloc 等,以模型页面为准--tensor-parallel-size(对应卡数)、--max-model-len、--dtype、量化方式(W8A8 等)、--kv-cache-dtype、模型特有参数(--trust-remote-code、MoE 的 --enable-expert-parallel 等)references/vllm-ascend-model-doc-guide.md 与 references/deployment-form-decision.md原则: 部署形式已在步骤 1.1 与用户确认并固定为方案输入(
DEPLOY_FORM)。脚本按形式直接生成专用版本,不在脚本内通过DEPLOY_FORM环境变量做运行时分支——部署形式是计划期决策,不是运行时决策。
templates/ 下四套启动模板,按步骤 1.1a 确认的 4 种部署形式选择):
DEPLOY_FORM=single) → templates/start_vllm.single.sh: 单机单卡或单机多卡(TP)直启,无跨节点逻辑;多副本由 ModelArts 部署副本数承载,模板无需修改DEPLOY_FORM=multinode) → templates/start_vllm.multinode.sh: 已内置跨节点分布式结构——各节点运行同一脚本,ModelArts 注入 GLOBAL_RANK_TABLE_FILE_PATH(rank table JSON 路径)与 POD_IP(当前节点 IP);脚本调用同目录 get_master_ip.py 读取 rank table 取 master IP,与 POD_IP 比较判定 master/slave 角色(slave 启动占位 http server 并追加 --headless);根据 POD_IP 反查网卡名绑定 HCCL_IF_IP/GLOO_SOCKET_IFNAME/TP_SOCKET_IFNAME/HCCL_SOCKET_IFNAME(多网卡必需);--data-parallel-size 由 rank table 全部 server 数(节点数)动态推导(脚本调用 get_master_ip.py --dp-size,不再硬编码默认值);ModelArts 需配置超节点亲和组实例数=N(副本内节点数)DEPLOY_FORM=pd) → templates/start_vllm.pd.sh: 已内置实例角色分支(Prefill / Decode 两个独立推理单元,同一部署单元内)——通过 VLLM_ROLE=prefill|decode(由 ModelArts 同一部署单元内 2 个推理单元分别注入)区分角色,各自设置端口、NPU 卡、KV Cache 传输配置;权重目录两个角色实例挂载到相同路径;PD 具体参数(如 --deployment-config、Mooncake KV 传输、负载均衡)以模型页面/社区 PD 方案为准,通过 PD_EXTRA_ARGS 追加;PD 分离资源翻倍(prefill/decode 各需一份节点)DEPLOY_FORM=pd_colocate) → templates/start_vllm.pd_colocate.sh: 对齐 ModelArts 官方 glm_5_2.sh 单引擎 DP 形态——所有节点运行同一个 vLLM 进程组(data-parallel),prefill/decode 分工由 vLLM 引擎内部完成,外部只有 master 一个 API 入口;无需 VLLM_ROLE、无需 Mooncake --kv-transfer-config;master/slave 角色经 get_master_ip.py 读 rank table 取 master IP 与 POD_IP 比较判定(slave 启动占位 http server 并追加 --headless);按 POD_IP 反查网卡绑定 HCCL_IF_IP/GLOO_SOCKET_IFNAME 等;--data-parallel-size 由 rank table 动态推导;用户按模型文档将额外参数(如 --enable-expert-parallel、量化参数)直接加入 MODEL_ARGS 数组;需随启动/健康检查脚本一并复制 get_master_ip.py 到产物目录;ModelArts 需配置超节点亲和组实例数=N./<模型名>-<部署方式>/ 下保存为 start_vllm.sh(模板文件名仅标识形式,产物统一命名为 start_vllm.sh 供 ModelArts 引用)。MODEL_NAME、TP_SIZE、MAX_MODEL_LEN 等,便于 ModelArts 部署时通过环境变量覆盖TP_SIZE 默认值必须是从模型适配文档提取的固定数字(如 2/4/8),禁止从 ASCEND_RT_VISIBLE_DEVICES 动态推导——ModelArts 注入 ASCEND_RT_VISIBLE_DEVICES 可能只给单卡(如 "0"),推导为 TP=1,大模型权重装不进单卡显存,KV cache 为负 → 启动崩溃 ValueError: No available memory for the cache blocks;模板已改为固定默认值,生成产物时按模型文档 --tensor-parallel-size 替换;自检 H12 强制校验 TP_SIZE 为固定数字且与 --tp-size 一致(FAIL 阻断上传)ASCEND_RT_VISIBLE_DEVICESPYTORCH_NPU_ALLOC_CONF、HCCL_BUFFSIZE、OMP_PROC_BIND 等)--enable-expert-parallel、--trust-remote-code 等)通过模板内置的 MODEL_ARGS bash 数组追加(每项一个元素,JSON 用单引号包裹)——禁止用字符串变量(如 EXTRA_ARGS)存 JSON 参数: ${EXTRA_ARGS} 展开时引号丢失,argparse 报 error: argument --speculative-config: Value '{"method": cannot be converted ...。EXTRA_ARGS 环境变量仍可用于追加无 JSON 的普通参数(模板内自动并入数组)bash 执行(关键): 因脚本使用 bash 数组,ModelArts 启动命令必须用 bash 执行——部署时(code 目录已文件存储挂载到 /home/ma-user/code/)启动命令为 bash /home/ma-user/code/start_vllm.sh;禁止用 sh 执行(sh/dash 不识别 (...) 数组,报 Syntax error: "(" unexpected)${MODEL_PATH}/config.json 是否存在,缺失时打印挂载目录内容并退出(见下方代码块)。为什么? 权重未正确挂载时,vllm/transformers 会把本地路径当作 HuggingFace repo id 处理,报晦涩错误 OSError: Repo id must be in the form 'repo_name' or 'namespace/repo_name': '<MODEL_PATH>',极难定位;提前检查可将根因(OBS 存储地址填错层级、挂载路径与 MODEL_PATH 不一致、OBS 认证凭据缺失导致挂载为空)直接打印出来get_master_ip.py)时,一律用 SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) 定位,禁止硬编码 /code/ 等绝对路径。为什么? 用户挂载脚本的路径可能不是 /code/(取决于其 OBS 文件存储挂载配置),硬编码会导致探针报 can't open file '/code/xxx.py': No such file or directory模板即权威,生成产物前必须 Read 实际模板文件: 完整可运行的启动脚本模板见
templates/start_vllm.single.sh(单节点)/start_vllm.multinode.sh(多节点)/start_vllm.pd.sh(PD 分离)/start_vllm.pd_colocate.sh(PD 共置),本 skill 不在 SKILL.md 内复制示例代码——生成产物前按"产物生成前置校验"重新 Read/grep 模板文件,以磁盘当前内容为准填充(bash 数组MODEL_ARGS、权重挂载自检、相对路径定位、DATA_PARALLEL_SIZE动态推导、Mooncake 半结构化参数等均已内置在模板中)。
为什么需要平台适配? vllm-ascend 官方模型适配文档给出的启动命令是为裸机/容器直跑设计的(本地路径、8000 端口、直接 CLI 参数),不能直接用于 ModelArts 在线服务部署。 适配检查清单(模板填充完成后逐项核对,详见
references/modelarts-console-guide.md第十节): 启动命令包成 bash 脚本(exec python -m vllm.entrypoints.openai.api_server);监听端口 8080(与探针一致);模型路径${MODEL_PATH:-/home/ma-user/model}(OBS 只读挂载);参数用 bash 数组MODEL_ARGS(JSON 单引号);DATA_PARALLEL_SIZE由 rank table 动态推导(脚本调用get_master_ip.py --dp-size,禁硬编码);健康检查所有节点探 master /health(单引擎形态三层探针);探针配置 启动延迟 600s/超时 60s/周期 30s/失败次数 300;启动命令bash /home/ma-user/code/start_vllm.sh(禁 sh);脚本内文件引用$(dirname "$0")相对定位(禁硬编码/code/);权重自检 config.json;多副本由部署副本数承载;超节点亲和组=N;PD 分离在单部署单元内 2 个推理单元注入VLLM_ROLE+ 不同PORT;Mooncake 经MOONCAKE_*环境变量 →PD_JSON_ARGS自动拼装--kv-transfer-config。
新版在线服务健康检查推荐执行命令检查方式(官网约定: 启动探针 bash /code/health_check.sh startup、就绪探针 bash /code/health_check.sh readiness、存活探针 bash /code/health_check.sh liveness)。与启动脚本一致,探针脚本不通过 DEPLOY_FORM 环境变量做运行时分支——以"产物目录是否存在 get_master_ip.py"自然区分单/多节点(多节点/PD 共置场景生成时复制该脚本,单节点/PD 分离不复制)。
各部署形式探针行为: 单节点(single)startup/liveness 查 vllm 进程、readiness 探本地 /health;多节点(multinode)与 PD 共置(pd_colocate,同单引擎 DP 形态)startup/liveness 查 vllm 进程,readiness 调用 get_master_ip.py 取 master IP,所有节点都探 master 的 /health(对外统一入口);PD 分离(pd)各角色按注入的 PORT 探 /health。
通用要点: 端口与启动脚本一致(默认 8080,PD 按角色 PORT);脚本内引用同目录文件必须用 $(dirname "$0") 相对定位,禁硬编码 /code/(否则报 can't open file '/code/xxx.py');多节点时 get_master_ip.py 需随脚本一并复制上传(见 3.4);三层探针语义(K8s 标准): startup 防启动误杀、liveness 失败重启容器、readiness 失败移出流量端点。模板即权威: 完整可运行脚本见 templates/health_check.sh,生成产物前按"产物生成前置校验"重新 Read/grep 模板文件。
将适配生成的全部部署产物上传到 OBS code 目录,包括: 启动脚本(start_vllm.sh)、探针脚本(health_check.sh)、角色识别脚本(多节点场景的 get_master_ip.py 等)以及 code 目录内被引用的其他文件。多节点与 PD 分离的多个角色实例共享同一 code 目录(多节点各节点运行同一脚本;PD 的 Prefill/Decode 实例通过 VLLM_ROLE 区分角色)。
本地产物目录命名规范(强制): 适配产物在当前工作目录下以
<模型名>-<部署方式>命名一个目录(如Qwen3-8B-pd),不再使用通用的code。<模型名>取用户确认的模型 ID;<部署方式>用小写后缀标识,与DEPLOY_FORM对应: 单节点=single(Qwen3-8B-single,单机多卡可写作tp{N})、多节点=mn(Qwen3-397B-mn)、PD 分离=pd(Qwen3-8B-pd)、PD 共置=pd_co(DeepSeek-V3-pd_co)。其他部署方式可自定义描述性小写后缀;同一模型多种部署方式并存时各自独立目录,互不覆盖。
start_vllm.sh、health_check.sh 放入当前工作目录下的 ./<模型名>-<部署方式> 目录(如 ./Qwen3-8B-pd、./DeepSeek-V3-pd_co);多节点(multinode)与 PD 共置(pd_colocate)部署还需从 scripts/ 复制 get_master_ip.py 到该目录;执行 chmod +x 赋予执行权限。⚠️ LF 行尾强制(必做,违反=bash 无法执行): 产物与模板必须以 LF 行尾保存/上传——Windows 编辑/复制会带 CRLF,bash 报 $'\r': command not found / syntax error near unexpected token '$'{\r''(startup 探针失败转 FAILED)。上传前必须校验: python -c "d=open('<file>','rb').read(); assert b'\r\n' not in d, 'CRLF found'",检测到 CRLF 先转 LF(d.replace(b'\r\n', b'\n'))再上传。
1.5. ⚠️ 产物自检关卡(强制,FAIL 不得上传): 产物生成后、上传前,必须按 references/artifact-check.md 自检清单,运行 scripts/check_artifacts.py 静态校验产物的可用性(硬性)与性能最优(软性)——依据已确认的模型/资源规格/部署形式,对照**华为云官方最佳实践(modelarts_10_3121)**与 vllm-ascend 模型适配文档:
python scripts/check_artifacts.py --artifact-dir ./<模型名>-<部署方式> \
--deploy-form <single|multinode|pd|pd_colocate> \
--doc-params '<从模型文档提取的推荐参数 JSON>' \
--model-doc-url <模型文档 URL> \
--tp-size <卡数> --dp-size <节点数>
FULL_DECODE_ONLY 图模式、缺 enable_cpu_binding、缺 MTP 等),由用户决定是否优化后重新生成;--doc-params 来源: 步骤 3.1 从 vllm-ascend 模型页面提取的启动命令参数(如 --speculative-config/--compilation-config/--additional-config/--quantization 等),未提供时脚本提示但不 FAIL;skill 流程要求必须提供(自检对照依赖它)。obs://<bucket>/<prefix>/code(文本输入,question 中写明格式,用户经 Other/notes 填写);obs://<bucket>/<prefix>/model/<模型名>,在其同级创建 code 目录 obs://<bucket>/<prefix>/code(与 ModelArts 官方最佳实践目录结构一致:model/ 与 code/ 同级)。注意: OBS 目标目录固定为 code,与本地 ./<模型名>-<部署方式> 目录名无关(本地产物目录名仅用于本地区分,上传时以 --code-dir 参数指定)。scripts/upload_code_to_obs.py,命令如下:
export OBS_AK="<AK>"
export OBS_SK="<SK>"
export OBS_ENDPOINT="https://obs.<region>.myhuaweicloud.com"
# 方式 A: 用户提供 code 目录(--code-dir 为本地 ./Qwen3-8B-pd)
python scripts/upload_code_to_obs.py --code-dir ./Qwen3-8B-pd \
--code-obs-path obs://<bucket>/<prefix>/code
# 方式 B: 由模型目录推导同级 code 目录
python scripts/upload_code_to_obs.py --code-dir ./Qwen3-8B-pd \
--model-obs-path obs://<bucket>/<prefix>/model/Qwen3-8B
esdk-obs-python)递归上传整个本地产物目录(启动/健康检查/角色识别脚本等全部产物),打印每个上传对象与最终 code 目录地址./obsutil cp ./Qwen3-8B-pd/ obs://<bucket>/<prefix>/code/ -f -r,但默认使用 OBS SDKCODE_OBS_PATH(如 obs://<bucket>/<prefix>/code),向用户复述确认。步骤 4 部署新版在线服务时,启动脚本路径、探针命令、角色识别脚本引用均基于该目录。为什么用新版部署? ModelArts 平台的"创建 AI 应用 + 部署在线服务"两步式流程(旧版)已废弃下线。新版在线服务不再创建 AI 应用,直接在部署配置中指定 SWR 镜像 + OBS 权重挂载 + 探针命令 + 副本/角色结构(请求体结构
service.deployment.roles[],对应部署副本与推理单元)。
进入部署前,确认以下方案输入已齐备(均由前序步骤产出): SWR_IMAGE_ADDRESS(推理镜像地址,步骤 2)/ CODE_OBS_PATH(code 目录,含 start_vllm.sh/health_check.sh/get_master_ip.py,步骤 3.4)/ MODEL_PATH(权重 OBS 目录,只读挂载到容器 /home/ma-user/model,步骤 1.3)/ DEPLOY_FORM + NNODES + REPLICAS(single/multinode/pd/pd_colocate + 副本内节点数 + 副本数,步骤 1.1)/ 资源池信息(名称、芯片型号、单副本卡数、是否支持多机,步骤 3.0)/ MA_ENDPOINT(ModelArts 域名,生产 modelarts.<region>.myhuaweicloud.com 或 dev modelarts-dev.<region>...,须与资源池环境一致)/ WORKSPACE_NAME + WORKSPACE_ID(API 调用带 X-Workspace-Id 头,4.3 步骤 0 查 ID)。
⚠️ 调用 ModelArts API 前必须先确认环境信息(强制): 必须先通过 AskUserQuestion 交互式确认 ModelArts 域名(生产 / dev)、工作空间名与区域,再调用任何 ModelArts API(3 项合并为同一次 AskUserQuestion)。域名不同 → 工作空间列表/资源池可见性不同 → 必须用正确域名 + 正确
X-Workspace-Id。禁止不确认环境就凭默认域名(生产)直接调 API,也禁止纯文本"请确认环境"等待。
用 AskUserQuestion 交互式确认部署方式(options: 方式 A — API 自动部署 / 方式 B — 控制台手动部署,附适用场景说明),两种方式等价,按用户偏好选择:
| 方式 | 适用场景 | 特点 |
|---|---|---|
| 方式 A — API 自动部署 | 用户愿意提供 IAM Token,希望 skill 代调 API 完成部署 | 一条命令完成,需 --endpoint/--project-id/token(环境变量 IAM_TOKEN 或 --token-file) |
| 方式 B — 控制台手动部署 | 用户不便提供 Token,或希望保留人工确认每个配置项 | skill 将完整操作步骤直接打印在对话中(含该模型的具体取值),用户照此在控制台点击操作 |
方式 B 输出要求(强制): 用户选择方式 B 后,skill 必须将 4.2 的完整操作步骤逐条打印输出到对话中,并用 4.0 的方案输入替换所有占位符,生成自包含、可直接照做的分步指导。禁止只给文件路径或"详见 references/xxx"让用户自行查阅。部署完成后回到 4.4 验证服务就绪与步骤 6 调用验证。
方式 B 不索要 API 环境信息(强制): 用户选择方式 B 后,不得向用户索要 ModelArts 域名(生产/dev)、工作空间名、资源池名称、project-id、IAM Token 等 API 部署(方式 A)才需要的参数——控制台部署时这些都在控制台页面上由用户直接选择。打印指导前只需确认方式 B 自身需要的输入: 服务名(可自动生成或让用户填)、部署形式/资源规格(步骤 1.1/3.0 已确认)。唯一例外: 打印完整指导后,按本小节末尾的强制要求主动询问一次"是否需要 API 代为部署(方式 A)"——那是给出选项,不是索要参数。 本小节是打印输出模板,不是让用户查阅的文档。 用户选择方式 B 后,skill 按
references/modelarts-console-guide.md第一节的 11 步结构完整打印到对话中,并把所有占位符({CODE_OBS_PATH}/{MODEL_PATH}/SWR_IMAGE_ADDRESS/服务名/场景取值等)替换为 4.0 方案输入的实际值,输出一份该模型专属的分步指导。控制台路径以实际版本为准(公有云新版入口: 左侧菜单 模型推理 > 在线推理;部分版本为 模型部署 > 在线服务)。 打印格式(强制): 每步用**第 N 步 — <标题>**开头(1 进入部署页面 / 2 基础信息 / 3 资源配置 / 4 模型配置与文件存储挂载 / 5 单元配置 / 6 部署管理配置 / 7 故障恢复 / 8 健康检查 / 9 运行环境配置 / 10 亲和调度 / 11 确认部署),下方列出该步要做的具体动作与已填好的具体值(不是占位符、不是"按场景选择"式描述);4 种部署形式差异(见 4.5 与 reference 速查表)在打印时直接展开为该形式对应的确定值。整个输出必须自包含——用户无需打开任何其他文件。关键取值速查: 服务名小写字母/数字/下划线;权重挂载/home/ma-user/model;code 挂载CODE_OBS_PATH → /home/ma-user/code/;镜像SWR_IMAGE_ADDRESS(tag 以模型文档为准,勿用 latest);容器端口 8080;探针命令bash /home/ma-user/code/health_check.sh startup|readiness|liveness;启动延迟 600s、失败次数 300、超时 60s、周期 30s;启动命令bash /home/ma-user/code/start_vllm.sh(禁 sh);PD 单元名小写prefill/decode;multinode/pd_colocate 亲和调度强亲和指向同一超节点(亲和组实例数=N);pd(PD 分离)单部署单元内 2 个推理单元注入VLLM_ROLE=prefill|decode,且模型文档要求时提供MOONCAKE_MASTER_ADDR。 第 9 步环境变量唯一来源(强制): 只列 4.5 表格该场景行第 4 列"需处理"单元格要求的项——该列写"无需注入"(S1~S5)则直接写"无需填写任何环境变量";禁止自行展开脚本默认值参数(TP_SIZE/MODEL_PATH/PORT/昇腾环境变量/MODEL_NAME等一律不列,脚本已有默认或自动推导)。部署形式已固定在脚本中,无需也不应再传DEPLOY_FORM环境变量。 文件存储挂载必须完整打印(强制): 第 4 步打印时必须包含"文件存储挂载"子项——code 目录(CODE_OBS_PATH实际值)挂载到/home/ma-user/code/,与权重挂载(/home/ma-user/model)并列展示,不得遗漏。缺失会导致启动/探针脚本无法访问(报can't open file)。 输出自包含(强制): 各步打印时把占位符全部替换为该模型的确定值;references/modelarts-console-guide.md与references/deployment-form-decision.md仅供 skill 填充取值时参考,不推给用户。 控制台指导展示后主动询问 API 部署(强制): 输出完整 11 步控制台指导后,必须立即用 AskUserQuestion 交互式询问: 是否由 skill 直接通过 API 代为部署(方式 A)?(options: 代为部署,提供 IAM Token / 自己在控制台操作)。若用户同意,按 4.3 方式 A 执行;若用户选择控制台操作,则结束交付。不得默认用户自己操作控制台,也不得默认替用户部署——必须询问;禁止输出指导后不加询问静默等待。
方式 A 前置: 需
--endpoint(ModelArts 服务端点,与资源池同区域)、--project-id、token(请求头Authorization: Bearer <token>,有效期 24h)、--workspace-id(可选,dev 环境需要X-Workspace-Id头)。环境信息(域名/区域/工作空间)已在"交互式确认规范"或 4.0 用 AskUserQuestion 确认;IAM 凭据用 AskUserQuestion 收集(见下方 token 获取与提取)。project-id无需单独向用户索要——获取 token 后用GET https://iam.<region>.myhuaweicloud.com/v3/auth/projects(带X-Auth-Token头)自动查询,按name匹配区域(如cn-north-7)取id即可(见步骤 0 第 ⑥ 步)。 ⚠️ token 安全传递(强制,安全编码规范): IAM Token 是敏感凭据,禁止作为命令行参数传递(ps//proc/<pid>/cmdline/Shell 历史均会明文暴露)。脚本已移除--token参数,按优先级提供: ① 环境变量IAM_TOKEN(推荐,不进进程 argv;Windows 上一律用此方式——NTFS 权限映射 0o666,chmod 600不可靠,--token-file会被拒绝) ②--token-file <文件>(仅 Linux 可靠,权限须 600,脚本拒绝 0o644 等) ③ 交互式输入(不回显,不可管道/脚本化)。 ⚠️ Agent Bash 工具独立 shell: Agent Bash 工具每次调用是独立 shell,export IAM_TOKEN=...不跨调用持久化——必须IAM_TOKEN=<token> python scripts/create_infer_service.py ...在同一条命令内完成(token 可由python -c "...读 token 文件..."内联读取后赋给环境变量再执行)。⚠️ 超长 token(含 base64 编码的 PKI token 可达 8KB+): bash heredoc/内联传递会因引号/特殊字符冲突报unexpected EOF——禁止用 bash heredoc/cat <<EOF传 token;改用 Write 工具将含 token 的完整 Python 脚本写入.py文件(token 作为 Python 字符串常量),再用python <脚本>.py执行(脚本内requests直接引用 token 变量,不经 shell argv)。 ⚠️ 步骤 0: 调用任何 ModelArts API 前必须先确认环境信息(强制): 禁止凭默认域名(生产modelarts.<region>.myhuaweicloud.com)直接调用。① 用 AskUserQuestion 交互式确认域名(生产modelarts.<region>.myhuaweicloud.com/ 开发modelarts-dev.<region>.myhuaweicloud.com——生产域名下工作空间列表只返回 default,dev 域名才能查到全部工作空间);② 用 AskUserQuestion 确认工作空间名(options + Other);③ 用确认后的域名查 workspace-id(GET /v1/{project_id}/workspaces,带Authorization: Bearer <token>,无需 X-Workspace-Id 头),按工作空间名匹配出id记为WORKSPACE_ID(查不到 → 换 dev 域名再查);④ 查资源池列表用GET /v2/{project_id}/pools(v1 路径/v1/{project_id}/pools报 404APIGW.0101)——响应items[]中取metadata.name为资源池 ID(pool_id),spec.resources[].count为节点数,必须带X-Workspace-Id头;查节点卡数用GET /v2/{project_id}/pools/{pool_id}/nodes(响应items[].status.resources["huawei.com/ascend-1980"]=总卡数、availableResources=可用卡数);⑤ 后续所有 API 调用使用: 确认后的域名 + 头X-Workspace-Id: {WORKSPACE_ID}+Authorization: Bearer <token>。⑥ project-id 自动查询(无需向用户索要): 获取 token 后调GET https://iam.<region>.myhuaweicloud.com/v3/auth/projects(带X-Auth-Token头),响应projects[]中按name匹配目标区域(如cn-north-7)取id即为project_id。 ⚠️ 请求体结构: 新版 CreateInferService 请求体是顶层平铺结构——不是{"service": {"deployment": {"roles": []}}}包裹结构(旧骨架报 400name/type/group_configs/runtime_config缺失)。完整请求体 JSON 示例与字段说明见references/modelarts-console-guide.md第三节(顶层平铺、secret_type: "agency"、service_invoke.port=8080、deploy_timeout_minutes=300(部署超时统一 300 分钟,见 API 部署前置校验第 10 条)、PD 双角色不同PORT、unit_configs[].name仅小写字母/数字/连字符(大写Prefill/Decode报 400)、flavor为推理实例规格(如modelarts.bm.arm.192u.1536g.npu.8d910b,非资源池节点规格modelarts.bm.npu.arm.ssd——节点规格是 ECS 物理机 flavor,报400 ModelArts.6404 Flavor not found;推理 flavor 格式为modelarts.bm.arm.<cpu>u.<mem>g.npu.<n>d910b,从节点status.resources的 CPU/内存/卡数推导)、failure_threshold=300/initial_delay_seconds=300/period_seconds=60、group_configs[].weight(100)与service_limit三项必填(request_timeout=300/request_size_limit=20/rate_limit,见 API 部署前置校验第 6 条;request_timeout缺失时平台默认 30s,慢速/PD 首请求报ModelArts.8909 request timeout)、S4 多节点用unit_configs[].count=N 承载跨节点数(单副本资源实例数为多,group_configs[].count=1)、获取正确结构的最可靠方法=查询已部署成功的现有服务show反推)。构造请求体前对照 reference,字段名以 API Explorer 为准。
基础命令(推荐 --raw-json 整体传入,字段零误差):
# 创建在线服务(单部署单元;PD 分离传两个 --role: prefill + decode,其余形式一个 --role)
# token 安全提供: 环境变量 IAM_TOKEN(推荐,不进进程 argv),或 --token-file <文件>(权限 600)
IAM_TOKEN=<IAM_TOKEN> python scripts/create_infer_service.py create \
--endpoint https://modelarts.cn-north-4.myhuaweicloud.com \
--project-id <PROJECT_ID> \
--service-name qwen3-8b \
--replicas 1 \
--raw-json '{"name": "...", "type": "REAL_TIME", ...}' # 完整平铺请求体见 reference
⚠️ 服务名占用: 创建服务返回
400 ModelArts.8006 "The service name xxx already exists"→ 服务名已被占用(同地域唯一,可能在其他 workspace 或由本 skill 前序操作创建)。处理顺序(强制): ① 先确认占用者是"旧服务占资源"还是"仅同名无资源": 查资源池可用卡数(见 8118 处理);② 若资源池可用卡数为 0 → 先停止旧服务释放资源(见下方 8118 处理),等待STOPPED后再创建;禁止直接换新服务名重试——换名后若资源仍被旧服务占用,仍会报8118 Insufficient NPU resources(Requested 16 > Available 0),白白多一次失败;③ 若资源池卡数充足且确需复用旧服务名,才考虑换新服务名(小写字母/数字/连字符,如原名加-2)重新创建,或用 AskUserQuestion 交互式确认是否管理/复用旧服务。关键: list 查不到同名服务 ≠ 服务不存在——list(GetServices)可能不返回 FAILED/DELETING/STOPPING 等非运行态服务(且 dev 环境必须带--workspace-id才查得到对应工作空间服务),但该服务仍占用资源池卡数;判断服务是否存在以资源池可用卡数与 create 返回的 8006/8118 为准。 ⚠️ 失败/旧服务资源清理(强制,部署失败重试前必查): 创建新服务返回400 ModelArts.8118 Insufficient NPU resources(Requested 卡数 > Available 0 卡)说明失败的旧服务仍占用资源池全部卡数。处理: ① 查旧服务状态GET /v2/{project_id}/services/{sid}(DEPLOYING/FAILED/STOPPING 均可能占资源);② 停止旧服务释放资源POST /v2/{project_id}/services/{sid}/stop(FAILED 返回ModelArts.6850 ... can not STOP时实例已终止,可直接创建新服务);③ 等待旧服务STOPPED后再创建;④ dev 环境 DELETE 可能 404(method DELETE not found),用 stop 替代。优先用 stop 而非反复尝试不同 DELETE 路径。 code 目录文件存储挂载(关键):unit_configs[].files[]内配置 code 目录挂载(files[].address=CODE_OBS_PATH→files[].mount_path=/home/ma-user/code),启动命令与探针命令一律用容器内路径bash /home/ma-user/code/...。 envs 只需注入少数项:TP_SIZE无需写入 envs(脚本按资源池实例规格自动推导);MODEL_PATH/昇腾环境变量等模板已有默认值;pd(PD 分离)必须在同一部署单元内 2 个推理单元分别加VLLM_ROLE=prefill|decode与PORT(双角色不同);MODEL_NAME非必填(脚本默认值model,仅在需自定义 served-model-name 时注入);pd 且模型文档要求 Mooncake 时加MOONCAKE_MASTER_ADDR。 ⚠️ token 获取与提取(强制): ① 获取 token 必须用 Python requests 调用 IAM API:resp = requests.post('https://iam.<region>.myhuaweicloud.com/v3/auth/tokens', json=<IAM请求体>, verify=False, timeout=30)(requests 直接传 dict/JSON,凭据正确即返回 201),响应头resp.headers['X-Subject-Token']取 token;禁止用 curl-d字符串拼接 JSON body 获取 token(Windows bash 下'"$VAR"'引号拼接致密码传递错误,凭据正确也返回 401);② token 必须用 project scope 获取("scope": {"project": {"name": "<region>"}},与资源池同区域);禁止 domain scope(报400 ModelArts.6400 ... getProject() is null);③ IAM 凭据三要素索要顺序必须为「账号名 → IAM 用户名 → 密码」(强制): 用 AskUserQuestion 收集时,按"账号名(domain.name)、IAM 用户名(user.name)、密码(password)"的顺序展示与收集——账号名(主账号)是用户最易识别的第一要素,放第一位;用户名(IAM 子用户)次之;密码最后。字段对应关系: 账号名=主账号(domain.name)、用户名=IAM 子用户(user.name)、密码=登录密码;顺序错配会 401 且有账号锁定风险——先询问"以哪种方式提供 token"(IAM 用户名/密码 / 直接提供 Token),收集后按"账号名(domain.name)、IAM 用户名(user.name)、密码(password)"顺序向用户复述字段对应关系再取 token;④ 提取 token 必须用 Python 正则完整提取:re.search(r'(?i)^X-Subject-Token:\s*(\S+)', content, re.M)——禁止用grep | sed | tr管道(长 token 丢字符导致 401);⑤ 校验 token 可见项目(可选):GET https://iam.<region>.myhuaweicloud.com/v3/auth/projects(带X-Auth-Token);⑥ 用户直接提供 token 时,若含-/_或非==结尾,先怀疑复制截断,用 AskUserQuestion 请用户选择重新提供 / 改用 IAM 用户名密码。⑦ 超长 PKI Token 禁止通过 AskUserQuestion 传递(强制): IAM Token 为 PKI 格式(含 base64 编码的证书链+签名,可达 8KB+),AskUserQuestion 的 answer/notes 字段有长度限制,超长 token 会被截断,末尾缺失签名块导致 API 报401 decrypt token fail——反复重试无效,且用户复制时可能再截断。正确方式: ① 优先请用户提供 IAM 用户名/密码,skill 用 Python requests 调 IAM API 获取 token;② 或请用户将 token 保存为本地文件并提供文件路径,skill 读取后设置os.environ['IAM_TOKEN'](环境变量方式,不进进程 argv,Windows 推荐)调用脚本;③ 禁止把超长 token 作为 Python 字符串常量内嵌脚本(引号/转义易错,且偏离 skill 的 token 安全传递规范)。⑧ IAM 凭据三要素错配排查(强制): 凭据正确但 401The username or password is wrong时,禁止反复猜测用户名/密码组合(多次错误有账号锁定风险)——让用户提供 postman/已调通的完整请求体,逐字段核对user.name/domain.name/password,特别是 domain.name(账号名)易因手工抄录/解析漏字符而错配(如ei_pangu_x60079363_01误写ei_pangu_x6007963_01)。
方式 A(API 自动): IAM_TOKEN=<IAM_TOKEN> python scripts/create_infer_service.py list --endpoint ... --project-id ... --workspace-id <WORKSPACE_ID>(拿 service_id,所有环境(生产/dev)必须带 workspace-id,不带则查到其他工作空间服务或空,误判无同名服务);... show --endpoint ... --project-id ... --workspace-id <WORKSPACE_ID> --service-id <SERVICE_ID>(拿部署状态与调用端点)。⚠️ list API 响应字段是 data[](非 services[]/items[]): create_infer_service.py 已按 data 字段解析;若用其他脚本调 list API,必须取 resp.json()["data"],取错字段会显示空列表误判无服务。⚠️ list 查不到 ≠ 服务不存在: GetServices(list) 可能不返回 FAILED/DELETING/STOPPING 等非运行态服务,但该服务仍占用资源池卡数(见 4.3"失败/旧服务资源清理");判断是否有同名/旧服务,以资源池可用卡数与 create 返回的 8006/8118 为准,不要因 list 为空就认定可安全创建。
方式 B(控制台手动): 在线服务列表页查看状态,单击服务名进入详情页获取 "公网调用 URL"(access_address)。
⚠️ dev 环境调用端点(predict_url): dev 环境服务
RUNNING后show详情返回access_address: null,调用端点位于predict_url[]字段(如"predict_url": [{"type": "PUBLIC", "urls": ["100.93.1.22"]}, ...])。调用 URL 格式:http://{PUBLIC_IP}/v2/infer/{service_id}/v1/chat/completions(OpenAI 兼容)。注意: ① 协议必须是 http(用 https 报400 ModelArts.8910 Request protocol: HTTPS does not match...);② 路径必须带/v2/infer/{service_id}前缀(裸 IP +/v1/chat/completions报404 ModelArts.2836 Path not found)。
通用要点: 等待状态变为 RUNNING(部署中 DEPLOYING,失败 FAILED);若 access_address 为 None,改用 predict_url[].urls[] 中 type=PUBLIC 的地址按上述格式拼接;若反复重启,优先检查探针 startup 延迟与失败次数配置(见常见问题排查"服务反复重启");code 目录(CODE_OBS_PATH)通过文件存储挂载到容器内 /home/ma-user/code/,启动/探针命令一律用容器内路径(bash /home/ma-user/code/start_vllm.sh、bash /home/ma-user/code/health_check.sh startup),脚本内引用同目录文件用 $(dirname "$0") 相对定位。
下表同时适用于方式 A(API group_configs[]/unit_configs[] 字段)与方式 B(控制台单元配置/环境变量);完整映射表、环境变量分类速查(①脚本自动推导 TP_SIZE/DATA_PARALLEL_SIZE ②容器内固定 MODEL_PATH/PORT ③平台注入 VLLM_ROLE(仅 pd 分离)④模型文档要求 MAX_MODEL_LEN/DTYPE/MODEL_NAME ⑤社区方案 MOONCAKE_MASTER_ADDR)与控制台速查表见 references/modelarts-console-guide.md 第一节(4 形式控制台配置速查)与第六节(4 形式 → 请求体映射)。要点速览:
| 部署形式 | 推理单元 | 副本数 | 需在部署单元/模型配置中处理的项 | 探针 |
|---|---|---|---|---|
| single 单节点 | 1 个 role-1 | 1(默认)/ M(可靠性) | 无需注入(TP_SIZE 脚本按卡数推导;MODEL_NAME 非必填,脚本默认值 model) | health_check.sh 探本地 /health |
| multinode 多节点 | 1 个 role-1 | 1(默认)/ M | 请求体 unit_configs[].count=副本内节点数 N(单副本资源实例数为多,group_configs[].count=1);ModelArts 注入 GLOBAL_RANK_TABLE_FILE_PATH(rank table JSON 路径)与 POD_IP(当前节点 IP)——脚本经 get_master_ip.py 读取 rank table 取 master IP 与 --dp-size 推导 DATA_PARALLEL_SIZE,与 POD_IP 比较判定 master/slave 角色(slave 追加 --headless)+ 超节点亲和组=N | 所有节点探 master /health |
| pd PD 分离 | 2 个: prefill + decode(同一部署单元内) | 1(默认)/ M(可靠性,资源翻倍) | 同一部署单元内 2 个推理单元分别注入 VLLM_ROLE=prefill 与 VLLM_ROLE=decode + 双角色不同 PORT(如 8080/8081)+ 各 unit_configs[].count=该角色节点数 | 各角色按注入 PORT 探 /health |
| pd_colocate PD 共置 | 1 个 role-1 | 1(默认)/ M | 无需注入任何角色/端口环境变量——对齐官方 glm_5_2.sh 单引擎 DP 形态,PD 分工由 vLLM 引擎内部完成;仅需 unit_configs[].count=N + 超节点亲和组=N | 所有节点探 master /health |
结论: 需要用户/部署配置处理的只有 —— pd(PD 分离)在单部署单元内 2 个推理单元注入
VLLM_ROLE与双角色不同PORT;模型文档要求不同于默认值时覆盖MAX_MODEL_LEN/DTYPE/TENSOR_PARALLEL_SIZE。multinode 与 pd_colocate 对齐官方单引擎 DP 形态,无需注入任何角色变量(master/slave 由get_master_ip.py自动判定;DATA_PARALLEL_SIZE由get_master_ip.py --dp-size动态推导);TP_SIZE已由脚本按资源规格自动推导;健康检查失败次数已自动设 300(见步骤 4.2 第 8 步);其余全部有默认值或容器内固定,无需用户输入**。 详细字段映射与 PD 多角色配置见references/modelarts-console-guide.md(新版 API 字段详解)与references/mooncake-pd-deploy-guide.md。
| 操作 | 命令 | 说明 |
|---|---|---|
| 扩缩容 | IAM_TOKEN=<IAM_TOKEN> python scripts/create_infer_service.py scale --service-id <ID> --deployment-id <DID> --replicas 2 | 调整部署副本数(token 用环境变量或 --token-file,禁止命令行明文) |
| 删除服务 | IAM_TOKEN=<IAM_TOKEN> python scripts/create_infer_service.py delete --service-id <ID> | 清理(测试完毕/失败重建前) |
| 更新配置 | 新版 API(UpdateService/重新部署) | 按需参考官方 API |
服务就绪后,通过 OpenAI 兼容 API 验证(脚本: scripts/test_inference.py)。调用端点自动从 4.4 获取(dev 环境为 http://{PUBLIC_IP}/v2/infer/{service_id}/v1/chat/completions);若服务配置了推理请求认证,用 AskUserQuestion 交互式收集推理 token(文本输入,question 中写明格式):
python scripts/test_inference.py --url https://<modelarts-inference-endpoint>/v1/chat/completions \
--token <token> --model <MODEL_NAME> --prompt "你好,请介绍一下你自己"
# 可选参数: --max-tokens 256 --temperature 0.7
验证要点: 返回
choices[0].message.content有正常文本 → 部署成功;本地联调可用http://127.0.0.1:8080/v1/chat/completions先验证脚本与参数,再上云。完整调用逻辑见references/verification-method.md(OpenAI 兼容调用示例、认证处理、验证失败定位)。
各步骤输出: ① 交互式确认 — AskUserQuestion options(模型候选/部署形式/部署方式等);② 部署产物 — ./<模型名>-<部署方式>/ 下 start_vllm.sh/health_check.sh(多节点含 get_master_ip.py),上传至 CODE_OBS_PATH;③ 控制台指导 — 11 步分步打印(占位符替换为该模型确定值);④ API 部署 — 服务 id/status 与调用端点 URL;⑤ 调用验证 — choices[0].message.content 返回文本。
完整排查表见
references/troubleshooting.md(按现象定位根因与排查动作)。高频问题速览:
现象 根因 快速处理 服务反复重启(最常见) 健康检查启动延迟过短,vLLM V1 首启 5~10 分钟被杀重启 启动延迟 600s + 失败次数 300(部署配置已自动设 300);探针路径/端口与脚本一致 ValueError: No available memory for the cache blocksTP_SIZE从ASCEND_RT_VISIBLE_DEVICES动态推导,ModelArts 注入单卡 → TP=1,大模型权重装不进单卡显存,KV cache 为负脚本 TP_SIZE改为模型文档推荐的固定值(如 2/4/8);自检 H12 强制校验启动即退出 exec format error镜像架构非 arm64 / 非标准镜像(MindIE/ATB) docker inspect查 Architecture;镜像类型识别见 2.1Transformers does not recognize this architecture镜像内 transformers 过旧,不识别实验性模型新架构 核对模型文档版本 vs 镜像 tag;换新版镜像或稳定模型 Syntax error: "(" unexpected脚本被 sh执行启动命令用 bash /home/ma-user/code/start_vllm.shRepo id must be in the form...模型权重未挂载(MODEL_PATH 下无 config.json) 核对 OBS 存储地址层级/挂载路径/认证凭据;脚本内置 config.json 自检 400 ModelArts.8118 Insufficient NPU resources失败的旧服务仍占用资源池全部卡数 ① 先查资源池节点可用卡数( GET /v2/{project_id}/pools/{pool_id}/nodes的availableResources);②POST .../services/{sid}/stop停止旧服务,等待 STOPPED 再创建;若 list 查不到旧服务(非运行态不返回)仍按 8118 处理400 ModelArts.8006 service name exists服务名已被占用(同地域唯一,含本 skill 前序创建的旧服务) 先停旧服务释放资源再创建(见 4.3),勿直接换名重试(换名后仍 8118) 400 ModelArts.8006 + 8118 同现旧服务占同名+占资源,list 查不到(非运行态) 资源池可用卡数为 0 → 停旧服务优先于换名;判断服务存在以资源池卡数+8006/8118 为准 400 name/type/group_configs/runtime_config 缺失请求体用了旧骨架 service.deployment.roles[]用 4.3 顶层平铺结构; show反推正确结构401/403 decrypt token failIAM Token 失效(24h)或复制截断 重新获取 token;IAM API + Python 正则完整提取(禁 shell 管道) 400 ModelArts.6404 Flavor not foundunit_configs[].flavor误填资源池节点规格(如modelarts.bm.npu.arm.ssd)改填推理实例规格(如 modelarts.bm.arm.192u.1536g.npu.8d910b);从节点status.resources的 CPU/内存/卡数推导查工作空间/资源池列表为空 域名用错(生产 vs dev)/权限不足 确认环境域名; modelarts-dev.<region>才能查到全部工作空间list 返回其他工作空间的服务 list API 的 X-Workspace-Id头不起过滤作用,需 URL 查询参数list URL 拼接 ?workspace_id=<id>查询参数(create_infer_service.py已修复)
references/deployment-form-decision.md — 部署形式决策矩阵(4 形式全覆盖): 4 形式对比、ModelArts 关键概念(部署单元/推理单元/副本数/超节点亲和组)、四阶段决策流程(1.1a~1.1d)、模型规模×硬件速查、副本/实例取舍算法、形式×步骤影响矩阵references/modelarts-console-guide.md — 新版在线服务部署详解: 控制台 11 步分步操作 + 4 形式控制台速查表;CreateInferService 顶层平铺请求体 JSON 示例 + 字段说明、4 形式 → group_configs/unit_configs 映射矩阵、探针配置、生命周期 APIreferences/vllm-ascend-model-doc-guide.md — vllm-ascend 模型适配文档查阅指南:URL 结构、模型页面章节、镜像 tag 提取、部署形式线索、常见环境变量速查references/ascend-hardware-matrix.md — 昇腾芯片型号(A2/A3/310P)速查:产品形态、显存、不同芯片 × 模型规模的卡数配置references/mooncake-pd-deploy-guide.md — Mooncake PD 分离部署指南(pd 分离专用):Mooncake KV 传输、XpYd 代理、--kv-transfer-config/--deployment-config、pd_colocate 模板改造、单部署单元双推理单元 PD 部署references/iam-policies.md — IAM 最小权限策略(OBS/SWR/ModelArts/IAM 各操作所需 Action 与 IAM API token 获取请求体示例)references/verification-method.md — 部署验证方法(方式 A/B 验证步骤、OpenAI 兼容调用检查、常见验证失败定位)references/acceptance-criteria.md — 验收标准(部署成功判定、产物核对清单)references/artifact-check.md — 部署产物自检清单(上传 OBS 前强制关卡): 可用性硬性(H01references/troubleshooting.md — 常见问题排查全表(现象 → 根因 → 排查动作)references/cli-installation-guide.md — KooCLI(hcloud)安装指南: 下载地址、跨平台安装步骤、AK/SK 配置、常见安装问题scripts/create_infer_service.py — 新版推理 API 部署脚本(create/list/show/delete/scale;--raw-json 整体传平铺请求体;token 禁命令行传参,经 IAM_TOKEN/--token-file(600)/交互式提供)scripts/check_artifacts.py — 部署产物自检脚本(步骤 3.4 强制关卡): 可用性硬性 H01references/artifact-check.md)scripts/upload_code_to_obs.py — 用 OBS Python SDK(esdk-obs-python)上传部署产物到 OBS code 目录(支持 --code-obs-path 或 --model-obs-path 推导)scripts/pull_push_image.sh — Quay.io 拉取 + SWR 推送辅助脚本(--login 传登录命令(仅支持 --password-stdin,密码经 SWR_PASSWORD 环境变量注入)scripts/get_master_ip.py — 多节点/PD 共置场景角色识别脚本(从 ModelArts 注入的 GLOBAL_RANK_TABLE_FILE_PATH 全局 rank table 取 master IP、dp_rank 与 --dp-size 数据并行总数;多节点/pd_colocate 需随脚本一并复制上传)scripts/test_inference.py — OpenAI 兼容 API 调用验证脚本;scripts/download_model.py — 权重下载命令示例(供用户参考);scripts/obs_upload.sh — obsutil 上传权重辅助脚本templates/start_vllm.single.sh — 单节点启动模板(单机单卡/多卡 TP;内置权重挂载自检;不含 DEPLOY_FORM 运行时分支);templates/start_vllm.multinode.sh — 多节点启动模板(master/slave 角色判定经 get_master_ip.py 读 rank table、POD_IP 比较;HCCL_IF_IP/GLOO_SOCKET_IFNAME 多网卡绑定;--data-parallel-* 参数;DATA_PARALLEL_SIZE 经 get_master_ip.py --dp-size 动态推导;slave 追加 --headless);templates/start_vllm.pd.sh — PD 分离启动模板(Prefill/Decode 双角色,VLLM_ROLE 注入、各自端口);templates/start_vllm.pd_colocate.sh — PD 共置启动模板(对齐官方 glm_5_2.sh 单引擎 DP 形态,无需 VLLM_ROLE/Mooncake;master/slave 经 get_master_ip.py 读 rank table 判定;--data-parallel-* 参数 + slave --headless;单一 PORT);templates/health_check.sh — 统一健康检查模板(startup/liveness/readiness 三类探针,按是否存在 get_master_ip.py 区分单/多节点)