命令行与 SDK

一个包两种用法:终端里的 sp 命令,和 Python 里的同一份客户端。

sp 是平台的命令行工具,同时也是 Python SDK——一个包两种用法, 共用同一份客户端与类型。习惯 Slurm 的人可以按 squeue / scancel / sinfo 的对应关系直接上手。

安装

uv pip install -e cli/        # 或 pip install -e cli/
export SP_ENDPOINT=http://stonepair.internal
export SP_TOKEN=<你的 API Key>

API Key 在「AI 网关 › API 密钥」里生成。

别把 token 写进脚本

SP_TOKEN 是你的身份。提交到仓库里的 token 等同于把账号交出去—— 用环境变量或密钥管理工具注入,不要落在代码里。

提交一个训练任务

sp submit --template torch-distributed \
          --nodes 2 --gpus 8 \
          --entry train.py

提交后任务进入队列。--template 指定一个训练模板,模板决定镜像、启动方式 与默认规格;命令行上给的参数覆盖模板里的默认值。

日常几条

命令作用Slurm 里的对应
sp ls列出任务squeue
sp describe <job>任务详情与事件流水scontrol show job
sp logs <job>看日志,-f 跟随sacct + tail
sp cancel <job>取消任务scancel
sp queues队列配额与排队情况
sp capacity各集群的 GPU 余量sinfo

任务 id 支持前缀匹配,不必贴全:

sp describe a3f2          # 等价于 sp describe a3f2c891-...
sp logs a3f2 -f           # 跟随输出
sp logs a3f2 --replica 0  # 只看某个副本

在 Python 里用

同一个包,connect() 读的是上面那两个环境变量:

from sp import connect

c = connect()                        # 读 SP_ENDPOINT / SP_TOKEN
job = c.post("/training/jobs", {
    "template": "torch-distributed",
    "nodes": 2,
    "gpus_per_node": 8,
    "entry": "train.py",
})

for line in c.logs(job["id"], follow=True):
    print(line)

响应格式

平台所有接口统一用一层信封,code0 表示成功:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "a3f2c891-4d5e-4b7a-9c31-8e2f6d0a1b34",
    "status": "queued",
    "queue": "team-nlp",
    "gpus": 16
  }
}

出错时 code 非零、message 是给人看的一句话:

{ "code": 40301, "message": "项目配额不足:还需 8 卡", "data": null }
先跑通再上规模

第一次用先提一个单卡任务把链路走通(提交 → 排队 → 日志 → 取消), 再改成多机多卡。多机那一支要求集群装了 Volcano,没装时只是该选项不可用。

在本仓库里开发

make cli-install                       # 建 venv 并装上 sp
make cli-test                          # 单元测试,不需要服务端
make cli-smoke                         # 对真服务端跑一遍完整闭环

make cli-smoke 会走完提交 → 跑起来 → 看日志 → 取消 → 验集群已清理。 它验的是跨进程的东西:契约对不对得上、状态迁移是不是真发生了、 取消是不是真删了集群里的资源。