导言
目标读者
本书《TensorStack AI 计算平台 - 用户使用手册》 的目标读者是 “TensorStack AI 计算平台” 的使用者,包括:
- AI 研究人员
- 建模工程师
- 数据处理工程师
- 机器学习工程师
- AI 应用开发工程师等
系统管理员、运维人员需要参考另外的《TensorStack AI 计算平台 - 管理员手册》系列。
如何使用
概述 介绍了产品的基本功能和使用模式。
用户首次使用可以跟从快速开始的内容,快速完成基本的体验。
然后,用户可以阅读 AI 开发和应用章节,以学习 AI 开发相关的概念。
其他章节内容如下:
- 账户和安全 讨论用户账户和系统安全问题。
- 计算资源 讨论如何使用集群计算资源。
- 存储 章节对平台的存储方面的支持进行了说明。
- 辅助 章节描述平台提供的一些重要辅助功能,例如如何处理敏感秘密信息,打包容器镜像等。
- 命令行工具和 SDK 讨论 TensorStack 平台的提供的命令行工具和 Python SDK 。
- 操作示例 章节提供了一些具体的操作指南。
- 参考 章节对 API 提供了完整的描述。
- 示例 章节提供了一些具体的应用示例,特别是对 LLM 领域的场景提供了全面的支持演示。
- 集成 章节讨论了一些优秀的第三方工具在 TensorStack 平台上的集成及使用。
- 附录1:背景 介绍了产品的技术架构和设计思路等。
“TensorStack AI 计算平台” 是一个功能强大且灵活的产品,支持在大规模(10^3 节点)集群上进行各种 AI 场景的计算。用户在一定的时间的学习、使用、探索、积累之后,就能对其功能有深入的理解,并在上面完成各种优秀的工作。
本手册使用的例子一般存放在下列 repos:
反馈
非常欢迎各种反馈,可在 Github Issues 页面 创建 issue。
版权声明
© 2023-2024 TensorStack.
本书/网站的内容版权由 TensorStack 所有,欢迎使用。
概述
产品介绍
“TensorStack AI 计算平台” 是面向 AI 集群的系统软件,针对 AI 集群的硬件架构和 AI 领域的计算任务的特性和需求,提供稳定、可扩展的 AI 技术平台能力,服务 AI 技术研发和规模化落地。
AI 集群的拥有者可以使用这套软件,构建自己的 “AI 私有云” 或 “AI 混合云” 基础设施服务。
通过先进的架构和丰富的 API + 系统服务,“TensorStack AI 计算平台” 合理地隐藏了分布式并行、异构计算、加速计算等技术的复杂细节,提高了抽象层次,并为 AI 领域的各种计算提供了针对性的支持,极大地提升了 AI 技术研究、开发、应用的工作效率。
基本流程
用户使用 “TensorStack AI 计算平台” 的基本交互流程:
- 管理员 - 创建 - 项目(Project)并设定项目管理员。
- 用户以项目管理员或者普通成员的方式使用项目。
- 用户可以同时使用多个项目。
- 管理员 - 创建 - 用户帐户。
- 用户 - 使用其帐户 - 登录系统。
- 用户 - 在项目中 - 完成工作(创建各种计算任务)。
使用功能
用户主要通过创建各种类型 CRD 的实例(instance)使用产品的功能。例如:
- 创建一个
Notebook
CRD 的实例,以使用 Jupyter Notebook; - 为了使用 DeepSpeed 进行大规模并行的 LLM 预训练,创建一个
DeepSpeedJob
CRD 的实例; - 为了部署一个模型推理服务,并支持服务规模的自动伸缩,创建一个
MLService
CRD 的实例;
CLI
CRD 实例(instance)的创建总是可以通过命令行实现,例如使用 kubectl
可以方便的创建一个 Notebook:
# create a notebook
kubectle create -f notebook-tutorial.yaml
notebook-tutorial.yaml
# notebook-tutorial.yaml
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
requests:
cpu: '8'
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
UI
对于很多 CRD,TensorStack 的 Web 控制台(console)提供了通过表单(form)创建其实例的方式。
例如,可使用如下表单创建 Notebook 实例:
下一步
快速入门
欢迎使用“TensorStack AI 平台”!
本节将带领你快速体验 “TensorStack AI 平台” 的基本功能,并完成一个简单的 AI 项目,涵盖模型的构建、训练、部署等。
使用 TensorStack AI 平台之前,你需要:
下一步
训练你的第一个模型
本教程带领你使用 Notebook,来构建和训练一个 AI 模型。
创建 Notebook
在 TensorStack AI 平台首页,点击模型构建进入构建控制台(Build Console)。
构建控制台(Build Console)的总览页面展示了多种资源,你可以点击右上角的按钮切换 Project,也可以点击事件和配额标签页以查看当前 Project 最近发生的事件以及计算资源(CPU、内存、GPU 等)配额。
创建 PVC
在创建 Notebook 之前,首先需要创建一个用于存储文件的 PVC(持久卷)。在左侧的导航菜单中点击存储 > 持久卷进入 PVC 管理页面,然后点击右上角的创建 PVC。
在 PVC 创建页面,如下填写各个参数:
- Name 填写
mnist
。 - Size 填写
1Gi
。
其他参数保持默认即可。完成之后,点击创建。
在跳转回到 PVC 管理页面之后,可点击右上角的刷新图标来手动刷新 PVC 状态。下图展示 PVC mnist
已经创建完成。
创建 Notebook
在左侧的导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击右上角的创建 Notebook。
在 Notebook 创建页面,如下填写各个参数:
- 名称填写
mnist
。 - 镜像类型选择
Jupyter
,镜像选择t9kpublic/torch-2.1.0-notebook:1.77.1
。 - 存储卷选择
mnist
。 - 调度器选择默认调度器,模板选择 large。
完成之后,点击创建。
在跳转回到 Notebook 管理页面之后,等待刚才创建的 Notebook 准备就绪。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。点击右上角的刷新图标来手动刷新 Notebook 状态,待 Notebook 开始运行之后,点击右侧的打开进入其前端页面。
现在 Notebook 已经可以使用了,你可以在这里进行模型的开发与测试。
使用 Notebook 训练模型
在 Notebook 的前端页面,点击左上角的 +,然后点击 Notebook 下的 Python3 以新建一个 .ipynb
文件。
复制下面的训练脚本到该 .ipynb
文件的代码框中。该脚本基于 PyTorch 框架,建立一个简单的卷积神经网络模型,并使用 MNIST 数据集的手写数字图像进行训练和测试。
torch_mnist.py
import os
import shutil
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.conv3 = nn.Conv2d(64, 64, 3, 1)
self.pool = nn.MaxPool2d(2, 2)
self.dense1 = nn.Linear(576, 64)
self.dense2 = nn.Linear(64, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.dense1(x))
output = F.softmax(self.dense2(x), dim=1)
return output
def train():
global global_step
for epoch in range(1, epochs + 1):
model.train()
for step, (data, target) in enumerate(train_loader, 1):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if step % 500 == 0:
train_loss = loss.item()
print('epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
writer.add_scalar('train/loss', train_loss, global_step)
scheduler.step()
global_step = epoch * steps_per_epoch
test(val=True, epoch=epoch)
def test(val=False, epoch=None):
label = 'val' if val else 'test'
model.eval()
running_loss = 0.0
correct = 0
with torch.no_grad():
loader = val_loader if val else test_loader
for data, target in loader:
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target)
running_loss += loss.item()
prediction = output.max(1)[1]
correct += (prediction == target).sum().item()
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
print(msg)
writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
global_step)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
kwargs = {
'num_workers': 1,
'pin_memory': True
} if torch.cuda.is_available() else {}
torch.manual_seed(1)
model = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)
dataset_path = './data'
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5), (0.5))])
train_dataset = datasets.MNIST(root=dataset_path,
train=True,
download=True,
transform=transform)
train_dataset, val_dataset = torch.utils.data.random_split(
train_dataset, [48000, 12000])
test_dataset = datasets.MNIST(root=dataset_path,
train=False,
download=True,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=32,
shuffle=True,
**kwargs)
val_loader = torch.utils.data.DataLoader(val_dataset,
batch_size=400,
shuffle=False,
**kwargs)
test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=1000,
shuffle=False,
**kwargs)
log_dir = './log'
if os.path.exists(log_dir):
shutil.rmtree(log_dir, ignore_errors=True)
writer = SummaryWriter(log_dir)
global_step = 0
epochs = 10
steps_per_epoch = len(train_loader)
train()
test()
torch.save(model.state_dict(), 'model_state_dict.pt')
点击上方的运行按钮,可以看到训练开始进行:
训练结束后,点击左上角的新建文件夹按钮,为新文件夹命名 first-model,并将当前教程产生的所有文件拖拽移动到其中。
下一步
- 针对同样的模型,使用 Job 进行并行训练
- 全面了解模型构建
进行并行训练
本教程带领你使用 PyTorchTrainingJob,将教程训练你的第一个模型中的模型训练改进为使用 GPU 加速的数据并行训练。
在 Notebook 中准备并行训练
回到 Notebook mnist
,在 HOME 目录(即左侧边栏文件浏览器显示的根目录 /
)下,点击左上角的 +,然后点击 Other 下的 Python File 以新建一个 Python 脚本文件。
向该文件复制以下代码,并将其命名为 torch_mnist_trainingjob.py
。该脚本在上一篇教程的脚本的基础上进行了修改以支持数据并行训练。
torch_mnist_trainingjob.py
import argparse
import logging
import os
import shutil
import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parallel import DistributedDataParallel as DDP
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms
parser = argparse.ArgumentParser(
description='DDP training of PyTorch model for MNIST.')
parser.add_argument(
'--backend',
type=str,
help='Distributed backend',
choices=[dist.Backend.GLOO, dist.Backend.NCCL, dist.Backend.MPI],
default=dist.Backend.GLOO)
parser.add_argument('--log_dir',
type=str,
help='Path of the TensorBoard log directory.')
parser.add_argument('--save_path',
type=str,
help='Path of the saved model.')
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.conv3 = nn.Conv2d(64, 64, 3, 1)
self.pool = nn.MaxPool2d(2, 2)
self.dense1 = nn.Linear(576, 64)
self.dense2 = nn.Linear(64, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.dense1(x))
output = F.softmax(self.dense2(x), dim=1)
return output
def train():
global global_step
for epoch in range(1, epochs + 1):
model.train()
for step, (data, target) in enumerate(train_loader, 1):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if step % (500 // world_size) == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
if args.log_dir and rank == 0:
writer.add_scalar('train/loss', train_loss, global_step)
scheduler.step()
global_step = epoch * steps_per_epoch
test(val=True, epoch=epoch)
def test(val=False, epoch=None):
label = 'val' if val else 'test'
model.eval()
running_loss = 0.0
correct = 0
with torch.no_grad():
loader = val_loader if val else test_loader
for data, target in loader:
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target)
running_loss += loss.item()
prediction = output.max(1)[1]
correct += (prediction == target).sum().item()
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
logging.info(msg)
if args.log_dir and rank == 0:
writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
global_step)
if __name__ == '__main__':
args = parser.parse_args()
logging.info('Using distributed PyTorch with %s backend', args.backend)
dist.init_process_group(backend=args.backend)
rank = dist.get_rank()
world_size = dist.get_world_size()
local_rank = int(os.environ['LOCAL_RANK'])
use_cuda = not args.no_cuda and torch.cuda.is_available()
if use_cuda:
logging.info('Using CUDA')
device = torch.device('cuda:{}'.format(local_rank) if use_cuda else 'cpu')
kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
torch.manual_seed(1)
dataset_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'data')
# rank 0 downloads datasets in advance
if rank == 0:
datasets.MNIST(root=dataset_path, train=True, download=True)
model = Net().to(device)
model = DDP(model)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001 * world_size)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5), (0.5))])
train_dataset = datasets.MNIST(root=dataset_path,
train=True,
download=False,
transform=transform)
train_dataset, val_dataset = torch.utils.data.random_split(
train_dataset, [48000, 12000])
test_dataset = datasets.MNIST(root=dataset_path,
train=False,
download=False,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=32 * world_size,
shuffle=True,
**kwargs)
val_loader = torch.utils.data.DataLoader(val_dataset,
batch_size=400,
shuffle=False,
**kwargs)
test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=1000,
shuffle=False,
**kwargs)
if args.log_dir and rank == 0:
if os.path.exists(args.log_dir):
shutil.rmtree(args.log_dir, ignore_errors=True)
writer = SummaryWriter(args.log_dir)
global_step = 0
epochs = 10
steps_per_epoch = len(train_loader)
train()
test()
if rank == 0:
torch.save(model.state_dict(), args.save_path)
创建 Job 进行并行训练
回到模型构建控制台,在左侧的导航菜单中点击构建 > Job 进入 Job 管理页面,然后点击右上角的创建 Job > PyTorch。
为了简化操作,在 Job 创建页面,点击预览 YAML,然后直接复制下面的 YAML 配置文件并粘贴到编辑框中,然后点击创建。
job.yaml
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: mnist # Job 名称
spec:
tensorboardSpec: # TensorBoard 服务器规约
resources:
limits:
cpu: 1
memory: 1Gi
trainingLogFilesets:
- t9k://pvc/mnist/log # 日志文件路径
image: tensorflow/tensorflow:2.14.0
# TensorBoard 服务器使用的镜像
torchrunConfig:
enabled: true # torchrun 启动
maxRestarts: 3
procPerNode: "4" # 每个副本启动的进程数
rdzvBackend: c10d
extraOptions: []
replicaSpecs:
- type: node
replicas: 1 # 副本数
restartPolicy: ExitCode
template:
spec:
securityContext:
runAsUser: 1000
containers:
- name: pytorch
image: t9kpublic/pytorch-1.13.0:sdk-0.5.2
# 容器的镜像
workingDir: /t9k/mnt # 工作路径
args: # `python`命令的参数
- torch_mnist_trainingjob.py
- "--log_dir"
- "log"
- "--save_path"
- "./model_state_dict.pt"
- "--backend"
- "nccl"
resources: # 计算资源
limits: # 限制量
cpu: 8 # CPU
memory: 16Gi # 内存
nvidia.com/gpu: 4 # GPU
requests: # 请求量
cpu: 4
memory: 8Gi
nvidia.com/gpu: 4
volumeMounts:
- name: data
mountPath: /t9k/mnt # 挂载路径
- name: dshm
mountPath: /dev/shm # 挂载共享内存
volumes:
- name: data
persistentVolumeClaim:
claimName: mnist # 要挂载的 PVC
- name: dshm
emptyDir:
medium: Memory
在跳转回到 Job 管理页面之后,等待刚才创建的 Job 就绪。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。点击右上角的刷新图标来手动刷新 Job 状态,待 Job 开始运行之后,点击其名称进入详情页面。
可以看到,Job 及其创建的 4 个 Worker(工作器)正在运行。
切换到副本标签页,点击副本的日志会显示其命令行输出,可以看到并行训练的当前进度。
torch_mnist_trainingjob.py
训练脚本在训练过程中添加了 TensorBoard 回调并将日志保存在了 log
目录下,Job 相应地启动了一个 TensorBoard 服务器用于可视化展示这些数据。点击 TensorBoard 右侧的 Running 进入其前端页面。
一段时间之后,Job 的状态变为 Done,表示训练已经成功完成。回到 Notebook mnist,将当前教程产生的所有文件移动到名为 parallel-training
的新文件夹下。
下一步
部署模型
本教程带领你使用 SimpleMLService,部署模型为推理服务。
在教程训练你的第一个模型和进行并行训练中,训练完成的模型都被保存为文件 model_state_dict.pt
,这两个模型文件所对应的模型是相同的。本教程将部署这个模型为推理服务。
准备模型文件
这里我们使用 TorchServe 部署 PyTorch 模型。回到 Notebook mnist
,在 HOME 目录(即左侧边栏文件浏览器显示的根目录 /
)下新建以下文件:
model.py
import torch
from torch import nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.conv3 = nn.Conv2d(64, 64, 3, 1)
self.pool = nn.MaxPool2d(2, 2)
self.dense1 = nn.Linear(576, 64)
self.dense2 = nn.Linear(64, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.dense1(x))
output = F.log_softmax(self.dense2(x), dim=1)
return output
handler.py
from torchvision import transforms
from ts.torch_handler.image_classifier import ImageClassifier
from torch.profiler import ProfilerActivity
class MNISTDigitClassifier(ImageClassifier):
image_processing = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5), (0.5))])
def __init__(self):
super().__init__()
self.profiler_args = {
"activities": [ProfilerActivity.CPU],
"record_shapes": True,
}
# def postprocess(self, data):
# return data.argmax(1).tolist()
点击左上角的 +,然后点击 Other 下的 Terminal 以新建一个终端。
执行以下命令以打包一个 torch 的模型包(model archive):
# 使用 Notebook 中训练的模型
torch-model-archiver --model-name mnist \
--version 1.0 \
--model-file model.py \
--handler handler.py \
--serialized-file first-model/model_state_dict.pt
# 如果使用 Job 中训练的模型,切换参数
# --serialized-file parallel-training/model_state_dict.pt
部署推理服务
在 TensorStack AI 平台首页,点击Deploy进入模型部署控制台。
模型部署控制台的总览页面展示了当前部署服务的数量以及资源使用情况。在左侧的导航菜单中点击部署 > SimpleMLService,点击右上角的 + 弹出创建对话框,然后复制下面的 YAML 配置文件并粘贴到编辑框中,最后点击创建。
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: mnist
spec:
replicas: 1
storage:
pvc:
containerPath: /var/lib/t9k/models
name: mnist
subPath: .
pytorch:
image: pytorch/torchserve:0.9.0-cpu
modelsFlag: "mnist=mnist.mar"
resources:
requests:
cpu: 1
memory: 1Gi
在跳转回到 SimpleMLService 管理页面之后,等待刚才创建的 SimpleMLService 准备就绪。
- 第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。
- 点击右上角的刷新按钮以手动刷新 SimpleMLService 状态。
使用推理服务
查看推理服务地址
待 SimpleMLService 就绪之后,点击其名称进入详情页面。
页面中展示的 DNS 即为推理服务地址,注意该地址只能从集群内部访问。
访问推理服务
回到 Notebook mnist
,在终端中执行以下命令以下载测试数据,并向推理服务发送请求。注意变量 URL
的值需要修改为实际部署的推理服务的地址。
# 下载测试图像文件
wget https://t9k.github.io/user-manuals/assets/get-started/deployment/{0,1,2}.png
# 注意:此 URL 只适合在集群内当前项目(Project)内部(例如当前项目的 Notebook 中)访问使用
URL="http://mnist.demo.svc.cluster.local/v1/models/mnist:predict"
curl -T 0.png $URL # 或使用 `1.png`, `2.png`
响应体应是一个类似于下面的 JSON,其预测了图片最有可能是的 5 个数字以及相应的概率:
{
"0": 1.0,
"2": 1.7797361302828807e-16,
"9": 6.094195260341553e-19,
"6": 1.5410183526346253e-19,
"5": 7.889719768364669e-20
}
清理
体验结束后,可将当前教程产生的所有文件移动到名为 deployment
的新文件夹下。
也可以将部署的推理服务删除:
# optional, delete service if desired.
kubectl delete SimpleMLService mnist
下一步
- 了解模型部署
- 进一步学习如何部署简单推理服务
- 进一步学习如何部署用于生产环境的模型推理服务
AI 开发和应用
TensorStack AI 平台提供了一套完整、全面的工具和服务,对 AI 模型的构建、训练和部署提供全流程的支持,从而助力研究人员轻松、高效地实现 AI 项目,加速 AI 模型的研究、开发和应用。
下图展示了在平台上开发一个深度学习模型的完整流程,以及各个模块发挥的功能:
下一步
模型构建
一次完整的模型构建实验由许多步骤组成,包括准备实验数据、开发机器学习算法、选择训练超参数和执行训练等等。
TensorStack AI 平台的模型构建模块可以帮助你在分布式集群中快速方便地完成上述工作。模型构建模块的功能包括:
- Notebook:在线机器学习开发工具,你可以使用此模块直接在平台上开发机器学习脚本。
- TensorBoard:机器学习可视化工具,实现训练过程可视化、模型可视化。
- Job:一类任务型资源,其中包括 TensorFlowTrainingJob、MPIJob 等多种资源,使用各种机器学习框架、通信协议来进行分布式计算。其中 TensorFlowTrainingJob 和 PyTorchTrainingJob 集成了 TensorBoard 的创建功能,可以监控训练进程和查看训练结果。
- AutoTune:超参数调优实验,在给定的搜索空间中查找最优的超参数组合以及机器学习网络结构。AutoTune 在进行超参数调优的过程中需要使用 TrainingJob(根据训练框架选用 TensorFlowTrainingJob、PyTorchTrainingJob 或 XGBoostTrainingJob)对超参数的效果进行验证。
架构
如上图所示:
- TensorStack CLI 是 TensorStack AI 平台所使用的命令行工具,可以用于操作几乎所有 TensorStack AI 平台的模块,包括模型构建。
- Kubernetes API Server 是 Kubernetes 的重要组成部分,负责对外提供接口,接受对集群的操作请求。在此框架中,Kubernetes API Server 需要向模型构建模块提供集群中的资源信息,同时接收资源的创建、删除等请求。
- 红框中的内容为模型构建模块的组成部分:
- 控制台(Console):模块的交互界面,你可以通过此界面使用模块的全部功能。
- 服务器(Server):模块功能的提供者,为你提供查看、创建、修改和删除资源的接口。
- 控制器(Controller):资源控制器,用于处理资源的创建和修改请求。
下一步
- 学习使用 Notebook
- 学习使用 TensorBoard
- 学习使用 T9k Job
- 学习使用 AutoTune
Notebook
JupyterLab 是一款非常流行的机器学习开发工具,它通过友好易用的 Web 界面提供交互式计算环境,支持多种编程语言和执行环境,在机器学习、AI、数据处理、数值模拟、统计建模、数据可视化等领域被广泛使用。
用户可以使用 Notebook CRD 在集群中快速部署一个 JupyterLab 服务,同时本产品还提供 GPU 支持、SSH 访问支持等功能。
创建 Notebook
下面是一个基本的 Notebook 配置示例:
# notebook-tutorial.yaml
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
requests:
cpu: '8'
memory: 16Gi
nvidia.com/gpu: 1
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
在该例中,spec.template.spec
字段定义所要创建的 Pod 的规约:
- 指示 Pod 运行一个
notebook
容器 (spec.template.containers
),该容器运行的镜像是t9kpublic/torch-2.1.0-notebook:1.77.1
,这是一个 Notebook 镜像; - 通过
spec.template.spec.volumes
,spec.template.containers[].volumeMounts
指示挂载网络文件系统 PVCtutorial
到/t9k/mnt
; - 通过
spec.template.spec.containers[].resources
指定使用的 CPU、memory、GPU 资源 。
使用 GPU
Notebook 支持通过申请使用 GPU 资源,例如:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
command: []
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
在该例中:
- 申请使用 16 个 CPU、32Gi 内存以及一个 NVIDIA GPU;系统会自动将 Notebook 调度到集群中某个能提供这些资源的节点上。
SSH 访问
Notebook 提供运行 SSH Server 的支持。下面的 Notebook 示例运行一个支持 SSH 连接的 JupyterLab 镜像:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
ssh:
authorized_keys:
- example-user
enabled: true
serviceType: ClusterIP
在该例中,用户:
- 设置
spec.ssh.enabled
字段的值为true
,T9k 系统将会自动创建一个处理 SSH 请求的Service
; - 通过
spec.ssh.serviceType
字段指定服务类型为ClusterIP
; - 设置自动挂载存放在
Secret/example-user
中的用户 SSH key;
使用此 SSH 服务需要通过 t9k-pf 工具进行端口转发。
资源回收
T9k 系统提供空闲 Notebook 资源回收的支持。系统在检测到 Notebook 处于空闲状态并超过一定时长时,就会自动删除工作负载以释放计算资源。目前,资源回收仅针对 Jupyter 类型的 Notebook,其他类型(例如 RStudio)的 Notebook 不会被回收。
管理员可设置回收策略,使得:
- Notebook 没有活跃运行超过 1h (管理员可修改此时长)后,标记该 Notebook 为
Idle
。 - Notebook 进入
Idle
状态超过 24h (管理员可修改此时长)后,删除该 Notebook 底层工作负载。
如果需要再次使用该 Notebook,你可以在模型构建控制台中手动点击恢复按钮。
Notebook 镜像
T9k 提供了一些预先构建的镜像,与 JupyterLab 原生镜像相比内置了更丰富的工具包,请参阅 Notebook 标准镜像列表。
在这些镜像中:
- 默认启动一个 JupyterLab 服务。
- 预装了 Python3 以及
tensorflow
、pytorch
、keras
、pandas
、scikit-learn
等常用 Python 包。 - 身份是一个名为
t9kuser
的非root
用户(用户 ID 为 1000,组 ID 为 1000),$HOME
目录为/t9k/mnt
。 - 预装了
tensorboard
插件,你可以在网页中创建 TensorBoard 以可视化数据。
用户也可以自行构建镜像,并上载到镜像 registry 中供使用。
下一步
用户可尝试如下功能:
参考
- T9k 提供的 Notebook 标准镜像列表
- JupyterLab 文档
TensorBoard
TensorBoard 是 TensorFlow 提供的一种可视化机器学习过程和结果的工具,功能强大且广泛应用于多种框架。
你可以使用本产品在集群中一键部署 TensorBoard,可视化训练模型。
创建 TensorBoard
下面是一个基本的 TensorBoard 配置示例:
# tensorboard-example.yaml
apiVersion: tensorstack.dev/v1beta1
kind: TensorBoard
metadata:
name: pytorchtrainingjob-tensorboard
namespace: t9k-example
spec:
image: docker.mirrors.ustc.edu.cn/tensorflow/serving:2.6.0-gpu
trainingLogFilesets:
- t9k://pvc/pytorchtrainingjob-tensorboard-pvc/log
在该例中,TensorBoard 使用 docker.mirrors.ustc.edu.cn/tensorflow/serving:2.6.0-gpu
镜像,对名为 pytorchtrainingjob-tensorboard-pvc
的 PVC 中 /log
路径下的模型数据进行可视化。
FileSet
FileSet 是一种特殊的资源定位符(URI),是一种用于定位多种存储技术中的资源的字符串。
FileSet 的格式为 t9k://storage-type/storage-identity/path
,由下列四部分构成:
- 协议:
t9k://
。 - 存储器类型:当前 FileSet 支持 PVC(在 FileSet 中写作
pvc
) 和 MinIO(在 FileSet 中写作minio
) 两种存储器。 - 存储器定位方式:FileSet 使用 PVC 的名称来定位 PVC 存储器,使用记录了 MinIO 地址、用户名和密码的 Secret 来定位 MinIO 存储器。
- 数据在存储器中的路径:模型在存储器中的准确位置。
下面是两个 FileSet 示例:
t9k://pvc/pytorchtrainingjob-tensorboard-pvc/log/model
表示:所指向的资源被存储在名为pytorchtrainingjob-tensorboard-pvc
的 PVC 中的log/model
路径下。t9k://minio/secret-name/bucket1/log/model
表示:所指向的资源被存储在一个 MinIO 中名为bucket1
的 Bucket 中的log/model
路径下,该 MinIO 的地址、用户名和密码被存储在名为secret-name
的 Secret 中。
TrainingJob 自动创建 TensorBoard
我们在 TensorFlowTrainingJob 和 PyTorchTrainingJob 中集成了 TensorBoard 的创建,你可以在创建 TrainingJob 后直接进入 TensorBoard 监控训练进程和查看训练结果。
资源回收
TensorBoard 提供空闲资源回收的支持,在检测到 TensorBoard 处于空闲状态并超过一定时长时,删除工作负载以释放计算资源。默认情况下(管理员可修改配置):
- TensorBoard 无人使用超过 1h 后,标记该 TensorBoard 为
Idle
。 - TensorBoard 进入
Idle
状态超过 24h 后,删除该 TensorBoard 底层工作负载。
如果需要再次使用该 TensorBoard,你可以在模型构建控制台中手动点击恢复按钮。
AutoTune
为了降低 AI 开发门槛和逐渐实现机器学习自动化,TensorStack AI 平台提供了自动化机器学习 (AutoML)工具 AutoTune。AutoTune 具有以下特点:
- 内置最新的自动机器学习算法,为用户自动地进行特征工程、神经网络架构搜索、超参调优和模型压缩。
- 提供可视化展示平台,实时跟踪超参数训练过程,以交互式图形和表格的形式刻画多个不同维度的信息,用户可以借此更好地比较、分析、决策出最优参数。
- 持海量实验数据的存储,让用户轻松地实现任意实验结果之间的比较。
- 融合领先的 AI 最佳实践,提供自动化、准确性和协作水平,提高企业 AI 生产效率。
基本结构
在上述结构图中:
- AutoTune Controller 是 AutoTuneExperiment 的控制器,可以看做是 AutoTune 实验的入口。用户在集群中创建 AutoTuneExperiment 资源后,由控制器创建 AutoTune Server 和 Web 来执行 AutoTune 实验。
- AutoTune Server 是执行实验的主体,其中包括:
- Optimizer:超参数调优器,在限定的搜索空间内用特定的调优算法选择合适的超参数组合。
- Training Manager:训练任务管理器,使用 Optimizer 产生的超参数,创建 TrainingJob 进行训练,并将训练结果反馈给 Optimizer 用于下一次超参数选择。AutoTune 可以同时创建多组 TrainingJob 来测试不同的超参数组合以加快训练效率。目前 AutoTune 支持使用 TensorFlowTrainingJob、PyTorchTrainingJob 和 XGBoostTrainingJob 进行训练。
- AutoTune Web 是 AutoTune 的可视化界面,你可以通过此界面实时查看实验状态,对比各组超参数对实验产生的影响。
AutoTuneExperiment
你可以通过创建 AutoTuneExperiment 来实现自动优化模型超参数。
创建 AutoTuneExperiment
下面是一个基本的 AutoTuneExperiment 示例:
apiVersion: tensorstack.dev/v1beta1
kind: AutoTuneExperiment
metadata:
name: experiment-sample
spec:
maxExecSeconds: 7200
maxTrialNum: 50
trialConcurrency: 3
searchSpace: |-
{
"batch_size": {"_type": "choice", "_value": [512, 1024, 2048, 4096, 8092]},
"learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}
}
trainingConfig:
type: tensorflow
tasks:
- type: worker
replicas: 1
template:
spec:
securityContext:
runAsUser: 1000
containers:
- command:
- python3
- dist_mnist.py
workingDir: /mnt/mnist-distributed
imagePullPolicy: IfNotPresent
image: t9kpublic/tensorflow-1.15.2:tuner-2.23
name: tensorflow
tuner:
builtinTunerName: TPE
classArgs: |-
{
"optimize_mode": "minimize",
"constant_liar_type": "min"
}
在该例中:
- 使用 TensorFlowTrainingJob 进行训练(由
trainingConfig
字段指定,详细配置方法请参阅训练框架支持)。 - 使用 TPE 算法进行超参数调优,算法的参数为
{"optimize_mode": "minimize", "constant_liar_type": "min"}
(由tuner
字段指定,更多参数请参阅超参数调优算法)。 - 超参数的搜索空间为
{"batch_size": {"_type": "choice", "_value": [512, 1024, 2048, 4096, 8092]},"learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}}
(由searchSpace
字段指定,搜索空间的格式及含义请参阅搜索空间)。 - 可以同时测试 3 组超参数,最大测试次数为 50(分别由
trialConcurrency
和maxTrialNum
字段指定),实验的最大执行时间为 2 小时(7200 秒,由maxExecSeconds
字段指定),如果时间超出,实验进入TIMEOUT
状态。
AIStore 的使用
AutoTuneExperiment 支持将实验数据存储在 AIStore 中,通过设置 spec.aistore
字段以使用 AIStore 数据库,其中:
spec.aistore.folder
声明实验数据存储在哪个 AIStore 文件夹中,内容应填写文件夹的 ID。spec.aistore.secret
引用一个 K8s Secret,其中应记录 API Key,用于上传数据时进行身份验证。
下面是一个存储 APIKey 的 Secret 示例:
apiVersion: v1
data:
apikey: ZDQyMjJjZjUtMmI0Ni00Mjk2LWFiMzYtYWI4NmVhZGUwZjQx
kind: Secret
metadata:
name: aistore-secret
type: Opaque
搜索空间
搜索空间是实验过程中超参数的设置范围,AutoTuneExperiment 会在此范围中选择超参数进行训练,最后找出最优的超参数组合。
搜索空间是一个 JSON 结构,具体格式请参阅搜索空间。
训练框架支持
AutoTuneExperiment 支持对多种训练框架进行超参数的调优,包括 TensorFlow、PyTorch 和 XGBoost。
AutoTuneExperiment 通过设置 spec.trainingConfig
字段实现对上述框架的支持。其中:
spec.trainingConfig.type
可设置为tensorflow
、pytorch
和xgboost
,分别表示使用 TensorFlow、PyTorch 和 XGBoost 框架进行训练。spec.trainingConfig.tasks
字段的设置请根据所使用的框架种类分别参阅 TensorFlowTrainingJob、PyTorchTrainingJob 和 XGBoostTrainingJob。
超参数调优算法
AutoTuneExperiment 在调参过程中需要使用超参数调优算法对超参数进行选择,对于不同的训练框架和不同的超参数种类,超参数调优算法的效率和效果也是不一样的。
算法根据功能和定义分为两类:
- Tuner 算法:超参数调优算法,用于选取合适的超参数组合。
- Assessor 算法:训练评估算法,用于判断当前训练是否符合预期,如果不符合则终止训练。
算法的详细介绍以及参数配置请参阅超参数调优算法。
实验状态
AutoTuneExperiment 的生命周期包括以下五个阶段:
PENDING
:AutoTune 的相关组件(包括 AutoTune Server 和 AutoTune Web)已经创建成功,等待控制器启动 AutoTuneExperiment。RUNNING
:AutoTuneExperiment 运行中。TIMEOUT
:如果达到最大执行时间(由spec.maxExecSeconds
字段指定)后,实验仍未完成(实际训练次数小于maxTrialNum
字段指定的训练次数),则实验超时,不再创建新的训练。DONE
:AutoTuneExperiment 在最大执行时间内完成了maxTrialNum
字段指定的训练次数(无论成功或失败),则实验完成。ERROR
:AutoTuneExperiment 初始化阶段或运行阶段出现错误。
下一步
搜索空间
搜索空间用于定义超参数的范围,AutoTune 会在这一范围内对超参数进行组合并测试,最后得到效果最好的一组训练。
格式
{
"parameter1": {"_type": "choice", "_value":[1, 2, 3, 4]},
"parameter2": {"_type": "randint", "_value":[1, 10]},
...
}
在上述结构中:
- 每一个条目都记录了一个超参数的名称和搜索方式:
- 每一个条目的键值(例如
parameter1
和parameter2
)表示超参数的名称。 _type
是超参数搜索方法。_value
表示搜索方法所使用的参数。
- 每一个条目的键值(例如
choice
和randint
表示超参数的搜索方法,其具体含义请参阅搜索方法。
搜索方法
_type | _value 格式 | 详细描述 |
---|---|---|
choice | 数组(数字或字符串) | 每次训练选取数组 _value 中一个值作为超参数。例:{"learning_rate":{"_type": "choice", "_value": [0.01, 0.02, 0.1, 0.2]}} ,进行超参数调优时,每一组训练会从四个值中选取一个。 |
randint | [lower, upper] | 每次训练选取 lower 和 upper 之间中的一个随机整数(不包括 upper )作为超参数。例:{"learning_rate":{"_type": "randint", "_value": [1, 10]}} ,进行超参数调优时,每一组训练可能取到的值有 [1, 2, 3, 4, 5, 6, 7, 8, 9] 。 |
uniform | [low, high] | 每次训练从 lower 到 upper 区间内均匀采样作为超参数。 |
quniform | [low, high, q] | 取值方法为 clip(round(uniform(low, high) / q) * q, low, high) ,此公式含义为:从 low 到 high 区间内均匀采样,然后将取值除以 q ,并四舍五入为整数,然后将超出 [low, high] 区间的值舍弃,加上 low 和 upper 两个值,构成选值区间。例:_value 为 [0, 10, 2.5] ,表示超参数的选值范围时 [0, 2.5, 5, 7.5, 10] ;_value 为 [2, 10, 5] ,表示超参数的选值范围时 [2, 5, 10] 。 |
loguniform | [low, high] | 取值方法为 exp(uniform(log(low), log(high))) ,此公式含义为:从 log(low) 到 log(high) 区间内均匀采样得到样本 x ,然后计算 exp(x) 得到超参数。 |
qloguniform | [low, high, q] | 取值方法为 clip(round(loguniform(low, high) / q) * q, low, high) (其中 loguniform(low, high) 表示 exp(uniform(log(low), log(high))) ),此公式含义参考 quniform 和 loguniform 条目。 |
normal | [mu, sigma] | 超参数的取值满足正态分布 N(mu, sigma^2) 。 |
qnormal | [mu, sigma, q] | 取值方法为 round(normal(mu, sigma) / q) * q ,此公式含义参考 quniform 条目。 |
lognormal | [mu, sigma] | 取值方法为 exp(normal(mu, sigma)) ,此公式含义参考 loguniform 条目。 |
qlognoraml | [mu, sigma, q] | 取值方法为 round(exp(normal(mu, sigma)) / q) * q ,此公式含义参考 quniform 和 loguniform 条目。 |
超参数调优算法
AutoTuneExperiment 在调参过程中需要使用超参数调优算法对超参数进行选择,对于不同的训练框架和不同的超参数种类,超参数调优算法的效率和效果也是不一样的。
算法根据功能和定义分为两类:
- Tuner 算法:超参数调优算法,用于选取合适的超参数组合。
- Assessor 算法:训练评估算法,用于判断当前超参数的训练中间结果是否符合预期,如果不符合则终止训练。
Tuner 算法
HyperOpt 类算法
HyperOpt 是一个用于超参数调优的 Python 库,其中主要包含三种超参数调优算法:Random
、Anneal
和 TPE
。三种算法之间的区别以及算法的使用方法请参阅 HyperOpt 文档。
算法支持使用的搜索方法有:choice
、randint
、loguniform
和 qloguniform
。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "Anneal",
"classArgs": {
"optimize_mode": "minimize",
"constant_liar_type": "min"
}
}
}
Evolution
进化算法(Evolution)是受生物进化启发得到的一种优化算法。进化算法的详细介绍请参阅 Evolutionary algorithm WIKI 文档。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "Evolution",
"classArgs": {
"optimize_mode": "minimize",
"population_size": 32
}
}
}
Batch
Batch 是一种最简单的选参算法,此算法只支持一种超参数的优化(搜索空间中只能有一个条目)且仅支持 choice
搜索方法。
下面是 AutoTuneExperiment 使用此算法的一个示例(Batch 算法不需要填写参数):
{
"searchSpace": {
"learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}
},
"tuner": {
"builtinTunerName": "Batch"
}
}
上述示例中,搜索空间中只有一个超参数,且 _type
为 choice
;Batch 算法不需要传入参数,所以没有填写 tuner.classArgs
字段。
GridSearch
一种基本的选参算法,根据搜索空间中的参数和范围,枚举所有可能的超参数组合,一一测试。
算法支持使用的搜索方法有:choice
、randint
和 quniform
。
下面是 AutoTuneExperiment 使用此算法的一个示例(GridSearch 算法不需要填写参数):
{
"tuner": {
"builtinTunerName": "GridSearch"
}
}
MetisTuner
Metis 算法的详细介绍请参阅论文 Metis: Robustly Optimizing Tail Latencies of Cloud Systems。
算法支持使用的搜索方法有:choice
、randint
、uniform
和 quniform
。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "MetisTuner",
"classArgs": {
"optimize_mode": "maximize",
"no_resampling": true,
"no_candidates": false,
"selection_num_starting_points": 600,
"cold_start_num": 10,
"exploration_probability": 0.9
}
}
}
GPTuner
GPT 是一种能够极大减少超参数优化步骤的贝叶斯优化算法。算法的详细介绍请参阅 NNI GPTuner 文档。
算法支持使用的搜索方法有:randint
、uniform
、quniform
、loguniform
、qloguniform
和数字形式的 choice
。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "GPTuner",
"classArgs": {
"optimize_mode": "maximize",
"utility": "ei",
"kappa": 5,
"xi": 0,
"nu": 2.5,
"alpha": 1e-6,
"cold_start_num": 10,
"selection_num_warm_up": 100000,
"selection_num_starting_points": 250
}
}
}
PPOTuner
PPO 算法继承了 OpenAI 中 ppo2 的主要逻辑,并适应 NAS 场景。
算法支持使用的搜索方法有:layer_choice
和 input_choice
。下面是一个搜索空间设置的示例:
{
"first_conv": {"_type": "layer_choice", "_value": ["conv5x5", "conv3x3"]},
"mid_conv": {"_type": "layer_choice", "_value": ["0", "1"]},
"skip": {
"_type": "input_choice",
"_value": {"candidates": ["", ""], "n_chosen": 1}
}
}
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "PPOTuner",
"classArgs": {
"optimize_mode": "maximize",
"trials_per_update": 20,
"epochs_per_update": 4,
"minibatch_size": 4,
"ent_coef": 0.0,
"lr": 3e-4,
"vf_coef": 0.5,
"max_grad_norm": 0.5,
"gamma": 0.99,
"lam": 0.95,
"cliprange": 0.2
}
}
}
PBTTuner
PBT 算法得自 Population Based Training of Neural Networks。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"tuner": {
"builtinTunerName": "PBTTuner",
"classArgs": {
"optimize_mode": "maximize",
"population_size": 10,
"factor": 0.2,
"resample_probability": 0.25,
"fraction": 0.2
}
}
}
Assessor 算法
Medianstop
Medianstop 算法的逻辑是:如果在某一步 S
,当前运行的实验的最佳观测值比所有已经完成的训练的第 S 步前的观测值的中位数差,则停止此次训练。此策略出自论文 Google Vizier: A Service for Black-Box Optimization 。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"assessor": {
"builtinAssessorName": "Medianstop",
"classArgs": {
"optimize_mode": "maximize",
"start_step": 0
}
}
}
在上述示例中,start_step
表示从第几步开始上传观测值(过早上传观测值,可能会错误的停止一些刚开始表现较差的训练)。
Curvefitting
Curvefitting 算法使用学习曲线拟合算法来预测未来的学习曲线性能。其逻辑是:如果在某一步,当前训练的预测结果是收敛的并且比历史上的最佳结果差,则停止此次训练。Curvefitting 算法的详细介绍请参阅 NNI Curvefitting 文档。
下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs
字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):
{
"assessor": {
"builtinAssessorName": "Curvefitting",
"classArgs": {
"optimize_mode": "minimize",
"epoch_num": 20,
"start_step": 6,
"threshold": 0.95,
"gap": 1
}
}
}
模型部署
TensorStack AI 平台的模型部署模块可以帮助你快速地将训练完成的 AI 模型部署为推理服务。
针对不同的应用场景,有以下两种 TensorStack API可供使用:
- MLService 是完善的模型推理服务,可用于生产环境,具有以下特性:
- 基于 Serverless 架构,服务容量(serving capacity)可根据负载自动伸缩;
- 自动暴露服务到集群外部,快速上线。
- SimpleMLService 是精简的模型推理服务,可用于快速测试、固定容量部署等场景。具有以下特性:
- 服务副本数目(replica)固定;
- 集群外部访问需要额外配置 Ingress 等资源。
同时,TensorStack AI 平台对模型部署提供自动化的运维支持,包括性能和资源的监控告警以及故障检测,以保障推理服务长期可靠运行。
架构
模型部署模块的架构如下图:
根据用户提供的模型存储位置和 AI 框架等设置,模型部署模块的控制器(controller)协调模型下载并启动模型推理服务。
下一步
- 了解 SimpleMLService
- 了解 MLService
SimpleMLService
SimpleMLService 用于在 TensorStack AI 平台上简单、快捷地部署 AI 模型推理服务,可用于小规模模型部署,快速测试等场景。
SimpleMLService 具有以下特性:
- 直接支持 TensorFlow、PyTorch 框架,并允许用户自定义框架,具有良好的可扩展性。
- 支持 PVC、S3 模型存储方式。
- 直接支持从集群内部访问推理服务;集群外访问需要用户进行额外配置。
- 服务容量固定,不支持自动伸缩。
创建 SimpleMLService
下面是一个基本的 SimpleMLService 示例:
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: mnist
spec:
replicas: 1
storage:
s3:
secretName: s3-secret
uri: s3://models/mnist/
containerPath: /var/lib/t9k/model
tensorflow:
image: t9kpublic/tensorflow-serving:2.6.0
resources:
requests:
cpu: 1
memory: 1Gi
本示例的 spec 字段的子字段释义如下:
replicas
: 定义运行推理服务的副本数量是 1。storage.s3
: 设定使用 S3 存储模型,子字段的释义如下:secretName
: Secrets3-secret
中存储 S3 配置信息,其详情参见:创建-s3-secret。uri
: 模型在 S3 中的存储路径是s3://models/mnist/
。containerPath
: 模型被加载后,在容器中存储模型的文件系统路径是/var/lib/t9k/model
。
tensorflow
: 设定使用tensorflow
推理框架,子字段释义如下:image
: 指定推理服务容器镜像t9kpublic/tensorflow-serving:2.6.0
。resources
: 这顶一个副本 Pod 使用的资源量。
直接支持的 AI 框架
SimpleMLService 目前直接支持 TensorFlow、PyTorch 两种框架。
TensorFlow
可以通过设置 spec.tensorflow
字段来部署 TensorFlow 框架,参考示例:创建 SimpleMLService。
当使用 TensorFlow 时,控制器会在容器中设置下列启动命令:
/usr/bin/tensorflow_model_server \
--port=9090 \
--rest_api_port=8080 \
--model_name=<SimpleMLService name> \
--model_base_path=<model-dir-in-container>
PyTorch
可以通过设置 spec.pytorch
字段来部署 PyTorch 框架,示例如下:
spec:
pytroch:
image: <pytorch-image>
modelsFlag: "resnet-18=resnet-18.mar"
resources:
requests:
cpu: 1
memory: 1Gi
当使用 PyTorch 时,控制器会在容器中设置下列启动命令:
torchserve \
--start \
--model-store=<mode-dir> \
--models <spec.pytorch.modelsFlag>
自定义框架
如果需要使用 PyTorch, TensorFlow 之外的框架,可以通过设置 spec.custom
字段来自定义框架。
用户可在 spec.custom.spec
字段中定义一个完整的 PodSpec,并需要满足下列要求:
- 至少设置一个
containers
成员。 - 启动推理服务运行命令时,指定正确的模型路径。
- 未设置 spec.service 时,推理服务的服务端口应该使用 8080。
示例如下:
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: pvc-custom
spec:
replicas: 1
storage:
s3:
secretName: s3-secret
uri: s3://models/mnist/
containerPath: /custom/path
custom:
spec:
containers:
- name: user-container
args:
- --port=9000
- --rest_api_port=8080
- --model_name=mnist
- --model_base_path=/custom/path
command:
- /usr/bin/tensorflow_model_server
image: "t9kpublic/tensorflow-serving:2.6.0"
副本数量
副本数量通过字段 spec.replicas
设置,用于定义 SimpleMLService 的 Pod 数量,默认值是 1。
暴露服务
通过设置 spec.service
字段来选择将服务的哪个端口暴露出来。未设置时,默认将 Pod 的 8080 端口映射到 Service 的 80 端口。
下面是一个示例:
spec:
service:
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
type: ClusterIP
在该例中:
- 将 Pod 的 8080 端口映射到 Service 的 80 端口,协议是 TCP。
- Service 的 Type 是 ClusterIP。
调度器
SimpleMLService 支持使用两种调度器:
通过 spec.scheduler
字段可以设置欲使用的调度器:
- 不设置
spec.scheduler
字段,默认使用 Kubernetes 调度器。 - 设置
spec.scheduler.t9kScheduler
字段,使用 T9k Scheduler 调度器。
在下面的示例中,SimpleMLService 使用 T9k Scheduler 调度器,并申请使用 队列 default
中的资源。
spec:
scheduler:
t9kScheduler:
queue: default
模型存储
SimpleMLService 支持使用 S3 或 PVC 中存储的模型。
S3
如需使用 S3 服务中存储的模型:
- 创建存储 S3 服务信息的 Secret
- 设置 SimpleMLService 的
spec.storage.s3
字段
创建 S3 Secret
存储 S3 信息的 Secret 需要满足下列条件:
- 设置 label
tensorstack.dev/resource: s3
。 - 设置
data[.s3cfg]
字段,内容是 Base64 编码的 s3cmd config。
YAML 示例如下:
apiVersion: v1
kind: Secret
metadata:
name: s3-sample
labels:
tensorstack.dev/resource: s3
type: Opaque
data:
.s3cfg: aG9zdF9iYXNlID0gZXhhbXBsZS5zMwpob3N0X2J1Y2tldCA9IGV4YW1wbGUuczMKYnVja2V0X2xvY2F0aW9uID0gdXMtZWFzdC0xCnVzZV9odHRwcyA9IEZhbHNlCmFjY2Vzc19rZXkgPSB1c2VyCnNlY3JldF9rZXkgPSBwYXNzd29yZApzaWduYXR1cmVfdjIgPSBGYWxzZQo=
其中 data[.s3cfg]
字段 Base64 解码后如下:
host_base = example.s3
host_bucket = example.s3
bucket_location = us-east-1
use_https = False
access_key = user
secret_key = password
signature_v2 = False
设置 spec.storage.s3
设置 SimpleMLService 的 spec.storage.s3
字段来使用存储在 S3 中的模型数据。spec.storage.s3
字段包含下列子字段:
secretName
: 前述步骤创建的 S3 配置信息的 Secret 名称。uri
: 模型在 S3 中的存储标识。containerPath
: 模型在容器中的存储路径。
示例如下:
spec:
storage:
s3:
secretName: s3-secret
uri: s3://models/mnist/
containerPath: /var/lib/t9k/model
PVC
通过配置 spec.storage.pvc
字段可以使用存储在 PVC 中的模型数据。spec.storage.pvc
字段包含下列子字段:
name
: 存储模型数据的 PVC 的名称。subPath
: 模型在 PVC 中的路径,不可以是绝对路径(即开头不能是/
)。containerPath
: 模型在容器中的存储路径。
示例如下:
spec:
storage:
pvc:
name: demo
subPath: path/mnist
containerPath: /var/lib/custom
服务状态
SimpleMLService 的状态记录在 status
字段中。
status.address
字段记录了推理服务在集群内的访问地址,子字段如下:
url
: 推理服务在集群内的访问地址ports
: 推理服务可供访问的服务端口
status.conditions
字段表明了当前 SimpleMLService 的状态,包括下列 2 种类型:
ModelDownloaded
: 模型是否成功地被下载到本地。Ready
: 推理服务是否就绪。
在下面的示例中:
- 访问推理服务的地址是
sample.demo.svc.cluster.local
- 模型已经下载到容器本地
- 推理服务处于就绪状态
status:
address:
url: sample.demo.svc.cluster.local
ports:
- port: 80
protocol: TCP
conditions:
- lastTransitionTime: "2023-12-27T06:52:39Z"
status: "True"
type: ModelDownloaded
- lastTransitionTime: "2023-12-27T06:52:41Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Ready
下一步
- 了解如何部署一个简单推理服务
- API 参考:SimpleMLService
MLService
MLService 用于在 TensorStack AI 平台上部署 AI 推理服务,其功能全面,可用于生产环境。
概述
MLService
是推理服务的核心 API,由 releases
和 transformer
两部分构成:
spec.releases
定义一个或多个releases
,以提供多版本模型推理服务的支持。- 可选的
transformer
定义前处理(pre-processing)和后处理(post-processing)计算。
MLService
的主要特性包括:
- 支持定义多个版本(
release
)的推理服务,每个release
包含一个predictor
,其定义了:- 模型存储(
storage
) - 模型规约(
model
),包括modelUri
,parameters
,runtime
(引用MLServiceRuntime
定义运行推理服务Pod
的模版) - 计算资源(
resources
) - 其他部署参数(
minReplicas, maxRelicas, logger ...
)
- 模型存储(
- 每个
release
服务的容量可独立自动伸缩,可通过minReplicas
、maxReplicas
设置容量的上下限。 - 支持金丝雀(canary release)发布模式。
- 用户可定制
transformer
组件,以在调用推理服务时进行前处理(pre-processing),以及获得推理结果后进行后处理(post-processing)。 transformer
的容量也可独立自动伸缩,可通过minReplicas
、maxReplicas
设置容量的上下限。
示例
下面是一个基本的 MLService 示例:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: torch-mnist
spec:
default: version1
releases:
- name: version1
predictor:
minReplicas: 1
maxReplicas: 3
model:
parameters:
"MODEL_PATH": "mnist=model.mar"
runtime: torchserve
modelUri: pvc://tutorial/tutorial-examples/deployment/pvc/mlservice-torch/
MLServiceRuntime
在示例中,我们使用了 MLServiceRuntime torchserve
。
MLServiceRuntime 定义了推理服务的模版,包含了推理服务的关键信息,例如镜像、启动命令、资源需求等,能够方便地帮助用户快速部署多种模型推理服务程序。
一个 MLServiceRuntime 可以被多个 MLService 使用。
定义
一个基本的 MLServiceRuntime 的示例:
apiVersion: tensorstack.dev/v1beta1
kind: MLServiceRuntime
metadata:
name: torchserve
spec:
enabled: true
template:
spec:
containers:
- name: user-container
image: torchserve:0.9.0-cpu
args:
- torchserve
- --start
- --model-store=/var/lib/t9k/model
- --models {{if .MODEL_PATH}}{{.MODEL_PATH}}{{else}}all{{end}}
resources:
limits:
cpu: "200m"
memory: 200Mi
ports:
- containerPort: 8080
protocol: TCP
该 MLServiceRuntime 在 spec.template
中定义了推理服务的副本(Pod)的模版,以指定容器镜像 torchserve:0.9.0-cpu
、启动命令 torchserve
及其他命令行参数等。
使用
用户可以在 MLService 的 predictor
定义中指定要使用的 MLServiceRuntime 名称,例如:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: demo
spec:
default: version1
releases:
- name: version1
predictor:
model:
runtime: torchserve
modelUri: "<your-model-registry/your-model-path>"
用户在 release version1
的 .predictor.model.runtime
中指定了 torchserve
,系统在创建推理服务器副本(Pod)时,将会使用名称为 torchserve
的 MLServiceRuntime。
进一步的配置
除了直接使用 MLServiceRuntime 定义好的 Pod 模版,MLService 还支持对其进行进一步的配置和修改。
Parameters
MLService 支持在 predictor
的 .model.parameters
设置参数,该字段是一个 map 类型,key 为参数名,value 为参数值。
在之前的 MLServiceRuntime 示例 中包含了 --models {{if .MODEL_PATH}}{{.MODEL_PATH}}{{else}}all{{end}}
的内容。这里使用了 golang template 的语法,含义为:
- 如果使用此 MLServiceRuntime 的 MLService 指定了
MODEL_PATH
,这一行会被设置为--model <用户指定的 MODEL_PATH>
- 如果没有指定
MODEL_PATH
,这一行会被设置为--model all
如下所示,在 MLService 中设置 MODEL_PATH
:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: demo
spec:
default: version1
releases:
- name: version1
predictor:
model:
parameters:
"MODEL_PATH": "mnist=model.mar"
runtime: torchserve
modelUri: "<your-model-registry/your-model-path>"
由上述 MLService 最终产生的副本(Pod)的 args
中会包含 --model mnist=model.mar
,指定了使用模型的名称和文件。
StrategicMergePatch
MLServiceRuntime 定义了 Pod 模版,但不一定能适用于所有场景。MLService 支持用户在 MLServiceRuntime 的基础上,进行进一步的叠加修改,例如:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: demo
spec:
default: version1
releases:
- name: version1
predictor:
model:
parameters:
"MODEL_PATH": "mnist=model.mar"
runtime: torchserve
modelUri: "<your-model-registry/your-model-path>"
template:
spec:
containers:
- name: user-container
image: self-torchserve:latest
将上面 MLService 中 predictor version1
的 template.spec
和之前的 Runtime 定义示例 相比,
可以发现他们都定义了一个名为 user-container
的 container,但是 image
不同。
于是最终生成的 Pod 中,MLService 中定义的 image
会覆盖 MLServiceRuntime 中的 image
,但是 MLServiceRuntime 中 args
等其余设置都会被保留。
上述的 StrategicMergePatch 给用户提供了完整的个性化改动方案。除此以外,针对改动频率更高的资源要求(resources),MLService 提供了更方便的个性化改动方案。用户可以直接通过 Predictor 中的 resources
覆盖 Runtime 的资源要求,例如:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: demo
spec:
default: version1
releases:
- name: version1
predictor:
model:
modelFormat:
name: pytorch
modelUri: "<your-model-registry/your-model-path>"
resources:
limits:
cpu: 500m
memory: 1Gi
模型存储
MLService 支持 S3 和 PVC 两种存储模型的方式,用户需要根据模型存储的类型填写 MLService 的配置。
PVC
在MLService中使用 PVC 存储模式需要在 spec.releases[*].predictor.model.modelUri
中设置包含前缀 pvc://
的模型路径。
例如,下面的示例指定模型存储在 PVC tutorial
的 models/example/
路径下:
...
releases:
- name: test1
predictor:
model:
modelUri: "pvc://tutorial/models/example"
...
S3
S3 是一种对象存储服务和协议,具有良好的可扩展性、数据可用性和安全性等优点,其协议被多种商业和开源产品支持,并且被广泛部署。
可在 MLService 中通过 spec.releases[*].predictor.model.modelUri
和
spec.releases[*].predictor.storage.s3Storage.secretName
设定 S3 的配置参数,其中:
modelUri
必需包含前缀s3://
。secretName
指向的Secret 存储的 S3 配置格式应当是 s3cmd 配置文件格式。
例如,下面的示例指定模型在 S3 中的存储 Uri
前缀为 s3://models/example/
,S3 的配置信息存储在 Secret s3-model
中:
...
releases:
- name: test1
predictor:
model:
modelUri: "s3://models/example/"
storage:
s3Storage:
secretName: s3-model
...
更多配置
发布策略
多版本支持
一个 MLService 可以同时部署多个版本(release)的推理服务,以使用不同的模型文件,或者其他配置等。
在下面的示例中,MLService 同时部署了 nov-02
(设置为默认)、nov-05
和 nov-11
三个版本的服务,这三个版本都使用同一个 MLServiceRuntime,但是使用的模型不同(不同的 modelUri
):
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: multi-releases
spec:
default: nov-02
releases:
- name: nov-02
predictor:
model:
runtime: torchserve
modelUri: pvc://tutorial/model-11-02
- name: nov-05
predictor:
model:
runtime: torchserve
modelUri: pvc://tutorial/model-11-05
- name: nov-11
predictor:
model:
runtime: torchserve
modelUri: pvc://tutorial/model-11-11
金丝雀发布
MLService 支持金丝雀(canary release)发布策略。用户可以通过 spec.canary
字段设置金丝雀发布对应的模型版本(release
),spec.canaryTrafficPercent
字段设置金丝雀发布的路由权重。spec.default
是必需字段,用于设置默认发布。
例如上一节中我们部署了 3 个版本的模型,我们想主要(80%
流量)使用 nov-02
这个版本,并且将刚刚训练好的 nov-11
作为金丝雀版本:
- 默认发布:
nov-02
,路由权重为 80%。 - 金丝雀发布:
nov-11
,路由权重为 20%。
...
spec:
default: nov-02
canary: nov-11
canaryTrafficPercent: 20
...
日志收集
MLService 支持对预测请求进行日志收集,详情见2.2.2.1日志收集
前处理及后处理
MLService 支持部署含有 transformer
模块的前处理(pre-processing)及后处理(post-processing)的推理服务:
- 预处理:用户发向推理服务的原始数据,先经过 transformer 预处理,然后再被发送到推理服务。
- 后处理:推理服务返回的预测结果,先经过 transformer 后处理,然后再返回给用户。
用户可以使用 Tensorstack SDK 编写 transformer 代码,制作镜像,并基于该镜像创建含有 transformer 的推理服务。详细示例请参阅制作并部署含有 Transformer 的模型推理服务。
下文展示了一个使用 transformer 的推理服务:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: pic-mnist
spec:
default: origin
transformer:
minReplicas: 1
minReplicas: 5
template:
spec:
containers:
- name: user-container
image: t9kpublic/transformer-example:0.1.0
resources:
limits:
cpu: "500m"
memory: 500Mi
容量伸缩
MLService 支持自动伸缩服务容量:即根据服务负载的变化,自动调节推理服务的部署规模(副本数量)。具体原理可以查看 Knative Autoscaling。
用户可以通过设置 spec.releases[*].predictor.minReplicas
字段和 spec.releases[*].predictor.maxReplicas
字段来指定 Predictor 工作负载数量的下限和上限。
同样的,如果用户启用了 Transformer,可以通过 spec.transformer.minReplicas
字段和 spec.transformer.maxReplicas
字段来指定 Transformer 工作负载数量的下限和上限。
以下是一些特殊情况:
minReplicas
不填时,工作负载数量的默认最小值为 1。minReplicas
等于 0 时,当没有流量请求时,MLService 会缩容到 0,不再占用系统资源。maxReplicas
不填或设为 0 时,工作负载数量没有上限。
除了负载数量的限制,用户还可以在具体的 Runtime 或者组件(Predictor 或者 Transformer)的 Pod 定义中设置 Knative Autoscaling 相关的 Annotation,例如:
...
spec:
releases:
- name: version1
minReplicas: 1
maxReplicas: 3
predictor:
template:
metadata:
annotations:
autoscaling.knative.dev/metric: "rps"
autoscaling.knative.dev/target: "100"
...
在上面的示例中,我们设置了工作负载数量的范围为 [1,3]
,自动伸缩指标(metric)为 rps
,自动伸缩目标(target)为 100
。这意味着当每个工作负载每秒处理的请求数量(requests-per-second)达到 100 时,负载会开始扩容,且扩容最大数量为 3,最小数量为 1。
调度器
MLService 支持使用两种调度器:Kubernetes 默认调度器(默认)和 T9k Scheduler。MLService 通过 spec.scheduler
字段设置调度器:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,使用了 T9k Scheduler 调度器,且工作负载处于队列 default
中。
...
spec:
scheduler:
t9kScheduler:
queue: default
...
服务状态
通过 MLService 的状态字段可以获取如下信息:
- 推理服务的全局状态及服务地址:
status.ready
表明推理服务是否准备就绪,status.address.url
表明全局推理服务地址。 - 每个部署的模型的状态及服务地址:
status.releases[*].ready
表明该版本推理服务是否准备就绪,status.releases[*].url
表明该版本的推理服务地址。 - Transformer 的状态及服务地址:
status.ready
表明 Transformer 服务是否准备就绪,status.transformer.url
表明 Transformer 服务地址。 - 推理服务没有就绪的原因:
status.conditions
以及status.releases[*].message
等字段中会记录相关报错信息。
以多版本支持的示例的状态为例,其 MLService 状态字段如下。从状态字段可以看出,该推理服务处于就绪状态,外部访问地址为 http://multi-releases.<project>.<domain>
,某个 release 的访问地址为 http://multi-releases-predict-<release>.<project>.<domain>
status:
address:
url: http://multi-releases.<project>.<domain>
canaryRelease: nov-02
conditions:
- lastTransitionTime: "2023-11-27T10:44:27Z"
status: "False"
type: Paused
- lastTransitionTime: "2023-11-27T10:50:04Z"
status: "True"
type: Ready
defaultRelease: nov-05
releases:
- name: nov-02
ready: true
readyReplicas: 1
totalReplicas: 1
trafficPercent: 80
url: http://multi-releases-predict-nov-02.<project>.<domain>
- name: nov-05
ready: true
readyReplicas: 1
totalReplicas: 1
trafficPercent: 20
url: http://multi-releases-predict-nov-05.<project>.<domain>
- name: nov-11
ready: true
readyReplicas: 1
totalReplicas: 1
trafficPercent: 0
url: http://multi-releases-predict-nov-11.<project>.<domain>
如果推理服务没有就绪,你可以通过查看 status.conditions
中 type 为 Ready
的 reason 以及 message 来查看具体信息,同时 Event 中也会有相关的错误信息。
访问推理服务
MLService 部署成功后,通过状态字段 status.address.url
可以查询到全局推理服务的 Base URL,再加上部署模型对应的路径即可得到访问推理服务的地址。
以示例中的服务为例,推理服务地址的状态字段如下:
...
status:
address:
url: http://torch-mnist.<project>.<domain>
...
由于服务使用的是 TorchServe 框架,按照其 API 规范,用户可以通过下述命令查看服务状态:
$ curl http://torch-mnist.<project-name>.<domain-name>/v1/models/mnist
{
"model_version_status": <model-status>
}
并调用推理服务:
# 数据在 https://github.com/t9k/tutorial-examples/blob/v20240206/deployment/pvc/mlservice-torch/test_data/0.png
$ curl -T test_data/0.png http://torch-mnist.<project-name>.<domain-name>/v1/models/mnist:predict
{
"predictions": <predict-result>
}
下一步
- 了解如何部署一个模型推理服务
- 了解如何部署一个包含 Transformer 的推理服务
- 应用示例:使用 vLLM 部署 LLM 推理服务
- 应用示例:部署对话式搜索引擎
参考
- API 参考:MLService
- API 参考:MLServiceRuntime
- Knative Autoscaling
日志收集
MLService 支持对 predictor 和 transformer 服务进行日志收集,包括接收到的 request 和返回的 response 消息。开启日志收集后,系统会为 MLService 添加日志发送能力,其根据配置的接收 URL,将日志发送到 URL 指定的服务。
设置 MLService
用户可以为每个 predictor 和 transformer 设置日志收集功能:
- predictor: MLService 的
spec.releases[*].predictor.logger
字段来启用 predictor 的日志收集功能。 - transformer:通过设置 MLService 的
spec.transformer.logger
字段启用 transformer 的日志收集功能。
用户可以通过日志收集的下列字段,来设置日志收集配置:
urls
:url 数组,系统会将收集到的日志发送到 url 对应的服务。mode
:表示对哪些内容进行收集记录。可选值是 all, response, request,默认值是 all。- all:requests 和 response 都会被收集记录。
- response:只记录收集 response。
- request:只记录收集 requests。
接收日志
日志数据通过 HTTP 协议被发送(HTTP POST)到用户提供的 URL。
日志数据格式是 CloudEvent,如下例所示:
Context Attributes,
specversion: 1.0
type: tensorstack.dev.mlservice.response
source: torch-mnist-logger-predict-origin
id: 0009174a-24a8-4603-b098-09c8799950e9
time: 2021-04-10T00:23:26.080736102Z
datacontenttype: application/json
Extensions,
component: predict
inferenceurl: /v1/models/mnist
mlservicename: torch-mnist-logger
namespace: example
traceparent: 00-6d69e2d3917689ee301610780af06de8-be01c3cfdf8e446e-00
Data,
{
"0": 1.0,
"2": 1.3369853835154544e-10,
"6": 7.10219507987428e-14,
"5": 5.859705488843112e-14,
"9": 3.2580891499658536e-15
}
在上述示例中:
type
:表明当前 CloudEvent 数据记录 response 内容。source
:release 名称是 origin(source 命名规则是<mlservice-name>-<component>-<release-name>
)component
:组件是 predictinferenceurl
:URL path 是/v1/models/mnist
mlservicename
:MLService 的名称是 torch-mnist-loggernamespace
:MLService 所在的 namespace 是 exampleData
:MLService 向用户返回的 response 内容是 {“0”: 1.0,“2”: 1.3369…}
在 HTTP Request 中:
- CloudEvent 的 Data 内容存在 Request Body 中
- CloudEvent 的其他内容存在 Request Header 中
可使用 CloudEvent 库来实现接收日志数据的 HTTP Server,具体实现可参考 CloudEvent Sample。
示例
部署日志接收服务
我们在集群内部署 event-display 服务来接受日志,注意:
- event-display 仅简单地将接收到的 CloudEvents 打印出来;
- event-display 作为演示的目的。
event-display.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: event-display
spec:
replicas: 1
selector:
matchLabels:
app: event-display
template:
metadata:
labels:
app: event-display
spec:
containers:
- name: event-display
image: t9kpublic/knative_event_display:1.0.0
resources:
limits:
cpu: 100m
memory: 100Mi
---
kind: Service
apiVersion: v1
metadata:
name: event-display
spec:
selector:
app: event-display
ports:
- protocol: TCP
port: 80
targetPort: 8080
部署命令
kubectl create -f event-display.yaml
部署 MLService
请按照使用方法准备环境,基于部署用于生产环境的模型推理服务示例来部署 MLService logger-example。
首先将 mlservice.yaml 修改为下列内容,注意:
- event-display 和 MLService 需要部署在同一个 namespace/project 中。
- 这个 MLService 仅对 predictor 设置了 logger 服务。
mlservice.yaml
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: logger-example
spec:
default: origin
releases:
- name: origin
predictor:
logger:
mode: all
resources:
limits:
cpu: "1"
memory: 2Gi
requests:
cpu: "0.5"
memory: 1Gi
urls:
- http://event-display
minReplicas: 1
model:
parameters:
"MODEL_PATH": "mnist=model.mar"
runtime: t9k-torchserve
modelUri: pvc://tutorial/tutorial-examples/deployment/mlservice/torch-pvc/
containersResources:
- name: user-container
resources:
limits:
cpu: "500m"
memory: 1Gi
然后按照 README 文档的操作步骤进行操作。
查看日志
查看 event-display 容器的日志,可看到日志中打印的 CloudEvent 记录了预测请求的详细信息:
terminal.log
$ k get pod -l app=event-display
NAME READY STATUS RESTARTS AGE
event-display-7d8d9f97db-lpgg2 1/1 Running 0 14m
$ k logs event-display-7d8d9f97db-lpgg2
Context Attributes,
specversion: 1.0
type: tensorstack.dev.mlservice.request
source: logger-example-predict-origin
id: ff726d6b-7fd8-471e-9ddc-de03b201d882
time: 2024-02-29T08:07:00.849119273Z
Extensions,
component: predict
inferenceurl: /v1/models/mnist:predict
mlservicename: logger-example
namespace: demo
Data,
PNG
IHDWfHIDATxc`X`ˬUvo>C0$ůشi˿_{ ZATI̶_Q%̓*y_:=U9;4ɺpJ^{oG8NIx$!K.w;@@4^0
G$Qp֛q?{4g^B
<`Rr330
ztB?IENDB`
☁️ cloudevents.Event
Context Attributes,
specversion: 1.0
type: tensorstack.dev.mlservice.response
source: logger-example-predict-origin
id: ff726d6b-7fd8-471e-9ddc-de03b201d882
time: 2024-02-29T08:07:01.468872477Z
Extensions,
component: predict
inferenceurl: /v1/models/mnist:predict
mlservicename: logger-example
namespace: demo
Data,
{
"0": 1.0,
"2": 1.3369905182969433e-10,
"6": 7.102208632401436e-14,
"5": 5.859716330864836e-14,
"9": 3.2580891499658536e-15
}
参考
- API 参考:MLService
- CloudEvents
- event display 源码
模型存储
Job
TensorStack 定义了一系列 CRD(称为 Job)以支持批处理(Batch Processing)计算任务,特别是 AI 领域的大规模分布式并行训练类型性质的计算。
Job 类型
为了支持不同框架的计算任务,TensorStack 提供了一系列 Job:
- TrainingJob:一类使用分布式计算框架进行机器学习的 T9k Job。
- PyTorchTrainingJob:服务于 PyTorch 分布式训练框架的 T9k Job。
- TensorFlowTrainingJob:服务于 TensorFlow 分布式训练框架的 T9k Job。
- XGBoostTrainingJob:服务于 XGBoost 分布式计算框架的 T9k Job。
- ColossalAIJob:服务于 ColossalAI 分布式训练框架的 T9k Job。
- DeepSpeedJob:服务于 DeepSpeed 分布式训练框架的 T9k Job。
- MPIJob:MPIJob 使用户能够方便地在集群环境中使用 OpenMPI 进行并行计算。
- BeamJob:用于在集群中通过 Apache Beam Python SDK 运行分布式计算任务,并支持多种底层计算引擎(例如 Apache Spark, Apache Flink)。
- GenericJob:一个通用的 T9k Job 资源,支持各种并行计算场景及 T9k 高级调度策略。
- GenericJob 十分灵活,用户可以使用 GenericJob 实现 MPIJob、PyTorchTrainingJob 等特定功能的 T9k Job;但其自动化程度低,需要手工设置很多参数。
- GenericJob 的目的是提供一个总是可行的 “通用” 机制,以支持一些其他特定功能 T9k Jobs 还未支持的新的计算场景。
运行模式
T9k Job 支持多种运行模式(spec.runMode
):
- 立即(Immediate)模式:默认、基本模式。Job 被分配资源后,将会立即开始运行。
- 调试(Debug)模式:帮助用户创建 Job 环境,但不立即执行,用户可以在训练环境中手动启动 Job 或者运行调试代码。
- 暂停(Pause)模式:暂停执行 Job;在一些场合下(如集群资源不足),用户可随时暂停 Job,待条件允许再继续执行 Job。
- 弹性(Elastic)伸缩模式:可以动态调整 Job 规模。
以下是各类型 Job 支持的模式列表:
Job 类型 | 立即模式 | 调试模式 | 暂停模式 | 弹性伸缩模式 |
---|---|---|---|---|
GenricJob | * | * | * | |
PyTorchTrainingJob | * | * | * | * |
TensorFlowTrainingJob | * | * | * | |
XGBoostTrainingJob | * | * | * | |
MPIJob | * | * | * | |
ColossalAIJob | * | * | * | |
DeepSpeedJob | * | * | * | * |
BeamJob | * |
各种模式的具体使用方式,请参考对应 Job 类型的文档。
GenericJob
GenericJob 是最基本的 T9k Job 资源,支持使用 T9k 高级调度策略。GenericJob 的使用十分灵活,一个熟练的使用者可以通过 GenericJob 实现 MPIJob、PyTorchTrainingJob 等特定功能的 T9k Job。
创建 GenericJob
下面是一个基本的 GenericJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
name: generic-example
spec:
successRules:
- { "worker": [0] }
failureRules:
- { "worker": [0] }
- { "worker": [1] }
replicaSpecs:
- type: worker
replicas: 4
template:
spec:
containers:
- command:
- sleep
- '365'
image: nginx:latest
name: sleep
在该例中:
- 创建 4 个副本(由
spec.replicaSpecs[0].replicas
字段指定),这些副本的角色为worker
(由spec.replicaSpecs[0].type
字段指定)。每个副本执行命令sleep 365
(由spec.replicaSpecs[0].template
字段指定)。 - GenericJob 的成功条件为序号为 0 且角色为
worker
的副本执行完成(由spec.successRules
字段指定)。 - GenericJob 的失败条件有两个,任意一个条件达成都会导致 GenericJob 失败(由
spec.failureRules
字段指定):- 序号为 0 且角色为
worker
的副本执行失败。 - 序号为 1 且角色为
worker
的副本执行失败。
- 序号为 0 且角色为
成功和失败
GenericJob 的成功和失败条件是通过 spec.successRules
和 spec.failureRules
字段指定的,其规则如下:
spec.successRules
数组包含 GenericJob 的所有成功条件,其中:- 任意一个条件达成则 GenericJob 成功。
- 每个条件是一个由若干副本组成的集合,如果这些副本都执行完成,则该条件达成。
spec.failureRules
数组包含 GenericJob 的所有失败条件,其中- 任意一个条件达成则 GenericJob 失败。
- 每个条件是一个由若干副本组成的集合,如果这些副本都失败或者重启次数耗尽,则该条件达成。
在下面的示例中,记录了 3 种 GenericJob 成功的判定条件:
- 角色为
master
且序号为 0 的副本执行完成。 - 角色为
worker
且序号为 0、1、2 的三个副本全部执行完成。 - 角色为
master
且序号为 2 和角色为worker
且序号为 0、1 的三个副本全部执行完成。
和 1 种 GenericJob 失败的判定:
- 角色为
master
且序号为 0 的副本执行失败。
...
spec:
successRules:
- {"master": [0]}
- {"worker": [0, 1, 2]}
- {"master": [2], "worker": [0, 1]}
failureRules:
- {"master": [0]}
暴露副本的服务
在分布式计算中,有时需要不同的副本之间进行通信和数据交换。使用者可以通过设置 spec.service
字段来暴露副本的端口。
在下面的示例中,GenericJob 暴露出每一个副本的服务:端口为 2222
,域名的格式为 [job-name]-[type]-[rank]
,例如下例中角色为 worker
且序号为 0 的副本的域名为 generic-example-worker-0
。
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
name: generic-example
spec:
service:
ports:
- name: http
port: 2222
replicaSpecs:
- type: worker
replicas: 1
...
变量替换
在副本的配置信息中有时需要传入副本自身或其他副本的信息,包括序号、角色和副本的服务地址等。GenericJob 通过变量替换的方式提供这些信息,主要有以下 5 种变量:
$(type)
:当前副本的角色。$(rank)
:当前副本在同类副本中的序号。$(replicas[_type_])
:扮演此角色的副本的数量。$(service._type_[_rank_].host)
:各个副本的域名(当且仅当副本的服务被暴露出来,此变量可用)。$(service.port[_port-name_])
:spec.service.ports
字段中定义的服务端口号(当且仅当副本的服务被暴露出来,此变量可用)。
上述变量中 _type_
、_rank_
和 _port-name_
需填入具体的角色、序号和端口名称(由 spec.service.ports[*].name
字段指定)。
变量替换可以被使用在下列字段中:
spec.replicaSpecs[*].template.command
spec.replicaSpecs[*].template.args
spec.replicaSpecs[*].template.env
以下是用 GenericJob 实现的 TensorFlow 分布式框架使用示例,其中 TF_CONFIG
环境变量需要填写所有副本的地址和当前副本的序号等信息,我们使用变量替换的方式添加:
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
name: generic-example
spec:
replicaSpecs:
- type: worker
replicas: 4
template:
spec:
containers:
- command:
- python
- /mnt/training.py
image: tensorflow/tensorflow:2.11.0
name: tensorflow
env:
- name: TF_CONFIG
value: '{"task":{"type":"$(type)","index":$(rank)},"cluster":{"worker":["$(service.worker[0].host):$(service.port[http])","$(service.worker[1].host):$(service.port[http])","$(service.worker[2].host):$(service.port[http])","$(service.worker[3].host):$(service.port[http])"]}}'
重启机制
GenericJob 为副本提供以下重启机制:
Never
:不重启OnFailure
:错误即重启Always
:总是重启(谨慎使用此策略,此策略可能导致 GenericJob 无法停止)
GenericJob 重启机制通过 spec.replicaSpecs[*].restartPolicy
字段指定:
spec.replicaSpecs[*].restartPolicy.policy
表示当前副本所使用的重启策略,可以设置为Never
、OnFailure
或Always
。spec.replicaSpecs[*].restartPolicy.limit
表示当前副本的最大重启次数。
不同的角色可以使用不同的重启策略,比如 master
使用 Always
,worker
使用 OnFailure
。
清除策略
在 GenericJob 成功或失败后,控制器清理所创建的 Kubernetes 资源,使 GenericJob 不再浪费集群资源(内存、CPU 等)。GenericJob 提供三种策略,通过 spec.cleanUpPolicy
字段指定:
All
:清除全部副本None
:不清除副本Unfinished
:清除未结束(处于Pending
、Running
或Unknown
阶段)的副本
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 GenericJob。
调度器
目前 GenericJob 支持两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,GenericJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
调试模式
GenericJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为sleep inf
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
sleep inf
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
GenericJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 GenericJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
GenericJob 状态
GenericJob 的状态和阶段
status.conditions
字段用于描述当前 GenericJob 的状态,包括以下 6 种类型:
Initialized
:GenericJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:GenericJob 成功。Failed
:GenericJob 失败。Paused
:GenericJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 GenericJob 所处的阶段,GenericJob 的整个生命周期主要有以下7个阶段:
Pending
:GenericJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:GenericJob 进入暂停模式。Resuming
:GenericJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:GenericJob 成功。Failed
:GenericJob 失败。Unknown
:控制器无法获得 GenericJob 的阶段。
在下面的示例中,GenericJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;GenericJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;但是 GenericJob 的训练结果是失败的,所以类型为 Failed
的 condition
被设置为 True
(原因是 The job is failed with rule: { "worker": [0] }
)。当前 GenericJob 运行阶段为 Failed
。
...
status:
conditions:
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "The job has been initialized successfully."
reason: "-"
type: Initializing
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "All pods are running normally."
reason: "-"
type: Running
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "False"
message: "All pods are running normally."
reason: "-"
type: ReplicaFailure
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "False"
message: 'The job is failed with rule: { "worker": [0] }'
reason: "Failed"
type: Completed
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "True"
message: 'The job is failed with rule: { "worker": [0] }'
reason: "Failed"
type: Failed
phase: Failed
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和);
- 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了
Creating
和Deleted
分别表示正在创建和已删除; - 副本在集群中对应的 Pod 的索引信息。
在下面的示例中,GenericJob 创建了 2 个角色为 worker
的副本,这 2 个副本的重启次数之和为 3,当前均处于 Running
阶段,分别运行在 generic-example-worker-0
和 generic-example-worker-1
这 2 个 Pod 上。
...
status:
tasks:
- type: worker
restartCount: 3
status:
- phase: Running
name: generic-example-worker-0
uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
containers: []
- phase: Running
name: generic-example-worker-1
uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
containers: []
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面示例中,GenericJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
PyTorchTrainingJob
PyTorchTrainingJob 是服务于 PyTorch 分布式训练框架的 T9k Job。
你可以较为方便地使用 PyTorchTrainingJob 为 PyTorch 训练脚本提供训练环境,并监控训练进程。
创建 PyTorchTrainingJob
下面是一个基本的 PyTorchTrainingJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: pytorch-example
spec:
replicaSpecs:
- replicas: 4
restartPolicy: OnFailure
template:
spec:
containers:
- command:
- python
- dist_mnist.py
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
type: worker
在该例中:
- 创建 4 个副本(由
spec.replicaSpecs[*].replicas
字段指定),副本的角色为worker
(由spec.replicaSpecs[*].type
字段指定)。 - 每个副本使用
pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
镜像,执行命令python dist_mnist.py
(由template
字段指定,此处的填写方式参考 PodTemplate)。 - 当副本失败后,会自动重启(由
spec.replicaSpecs[*].restartPolicy
字段指定)。
使用 torchrun 启动训练
前面的示例中所使用的训练方法比较原始,即直接用 python
启动训练脚本,执行训练。
PyTorch 在后续提供了 torch.distributed.launch
包和 torchrun
工具来更好地启动和管理训练,具体优点包括:支持一机多进程、高容错、弹性伸缩训练规模等。PyTorchTrainingJob 也支持使用 torchrun
启动训练来继承这些优点。
spec:
torchrunConfig:
enabled: true
maxRestarts: 10
procPerNode: "1"
rdzvBackend: c10d
extraOptions: []
在 PyTorchTrainingJob 的定义中加入上述片段,来使用 torchrun
启动训练,其中:
enabled
:是否启用torchrun
。maxRestarts
:训练进程的最多重启次数。procPerNode
:一个副本中启动多少个训练进程。除了可以指定一个数字字符串之外,还可以设置为gpu
,表示启动等同于副本所使用的 GPU 数量的训练进程。rdzvBackend
:torchrun
所使用的汇合通信方式,可以设置为c10d
、etcd
或etcd-v2
,但是只有c10d
是torch
内置的。如果用户希望使用etcd
需要自行搭建etcd
服务器。extraOptions
:torchrun
的其他参数,上面的参数是torchrun
比较常用的设置,用户也可以通过extraOptions
字段提供更多torchrun
的其他设置。
弹性训练
使用 torchrun 启动的 PyTorchTrainingJob 支持弹性伸缩训练规模,通过 spec.elastic
设置伸缩范围和当前期望训练规模。
在下面的示例中,PyTorchTrainingJob 启用弹性训练功能,训练规模的伸缩范围是 [4,10],当前期望训练规模为 7。
spec:
elastic:
enabled: true
minReplicas: 4
maxReplicas: 10
expectedReplicas: 7
注:期望训练规模(spec.elastic.expectedReplicas
)并不代表实际训练规模,当集群资源数量不足时,控制器可能无法创建足够的副本。
最佳实践
...
spec:
torchrunConfig:
enabled: false
minNodes: 1
maxRestarts: 10
procPerNode: "1"
rdzvBackend: c10d
extraOptions: []
replicaSpecs:
- replicas: 4
restartPolicy: OnFailure
template:
spec:
containers:
- command:
- python
args:
- dist_mnist.py
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
type: worker
...
在上面的示例中:spec.replicaSpecs[*].template.spec.containers[0].command
只填写 python
,其他参数填写在 spec.replicaSpecs[*].template.spec.containers[0].args
中。这样可以实现以下效果:
- 当
spec.torchrunConfig.enabled
设置为false
时,控制器会为训练副本设置正确的环境变量,并通过python dist_mnist.py
命令启动训练脚本。 - 当
spec.torchrunConfig.enabled
设置为true
时,控制器会忽略python
命令,而是改用torchrun
命令,其格式为:torchrun <torchrun_args> dist_mnist.py
。
这样做的优点就是,在切换 torchrun
模式时,不需要对其他字段进行改动。
另外,如果用户使用 Python Module 作为训练脚本,可以参考以下配置:
...
spec:
torchrunConfig:
enabled: false
...
replicaSpecs:
- replicas: 4
restartPolicy: OnFailure
template:
spec:
containers:
- command:
- python
args:
- -m
- training.module
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
type: worker
...
在上面的示例中,当 spec.torchrunConfig.enabled
设置为 true
时,-m
参数同样可以被 torchrun
使用。
成功和失败
在 PyTorch 分布式训练框架中,需要设置 MASTER_ADDR
和 MASTER_PORT
,PyTorchTrainingJob 会将第一个训练副本作为 master(主节点)。当分布式训练的主节点成功结束,PyTorch 分布式训练成功;反之,当分布式训练的主节点执行失败,PyTorch 分布式训练失败。
但是 master 的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,PyTorchTrainingJob 支持副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit
字段指定),当副本重启次数达到上限后,如果主节点再次失败,则训练失败。此外,PyTorchTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds
字段指定),当超过这个执行时间后,训练失败。
如果 PyTorchTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则训练成功。
重启机制
PyTorchTrainingJob 的 spec.replicaSpec[*].template
字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能满足 PyTorchTrainingJob 的需求,所以 PyTorchTrainingJob 会给副本的重启策略都设置为 Never,并由控制器根据 spec.replicaSpec[*].restartPolicy
字段处理副本的重启。
可选的重启策略有以下四种:
Never
:不重启OnFailure
:失败后重启Always
:总是重启ExitCode
:特殊退出码重启
使用 Never
重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。
ExitCode
是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:
- 130(128+2):使用
Control+C
终止容器运行。 - 137(128+9):容器接收到
SIGKILL
信号。 - 143(128+15):容器接收到
SIGTERM
信号。 - 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。
重启次数限制
如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),PyTorchTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit
字段(默认为 3)来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。
清除策略
在训练结束后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,PyTorchTrainingJob 提供清除策略,在训练结束后删除这些副本。
PyTorchTrainingJob 提供以下三种策略:
None
:不删除副本。All
:删除所有副本。Unfinished
:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议用户在调试完毕后手动删除这些副本或删除整个 PyTorchTrainingJob。
调度器
目前 PyTorchTrainingJob 支持使用以下两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,PyTorchTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
TensorBoard 的使用
PyTorchTrainingJob 支持使用 TensorBoard 对训练过程和结果进行实时可视化(由 spec.tensorboardSpec
字段设置)。
在下面的示例中,PyTorchTrainingJob 使用 t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
镜像创建一个 TensorBoard,可视化名为 torch-tensorboard-pvc
的 PVC 中 /log
路径下的模型数据。
...
spec:
tensorboardSpec:
image: t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
trainingLogFilesets:
- t9k://pvc/torch-tensorboard-pvc/log
调试模式
PyTorchTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为sleep inf
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
sleep inf
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
PyTorchTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 PyTorchTrainingJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
PyTorchTrainingJob 状态
PyTorchTrainingJob 的状态和阶段
status.conditions
字段用于描述当前 PyTorchTrainingJob 的状态,包括以下 6 种类型:
Initialized
:PyTorchTrainingJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:PyTorchTrainingJob 成功。Failed
:PyTorchTrainingJob 失败。Paused
:PyTorchTrainingJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 PyTorchTrainingJob 所处的阶段,PyTorchTrainingJob 的整个生命周期主要有以下7个阶段:
Pending
:PyTorchTrainingJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:PyTorchTrainingJob 进入暂停模式。Resuming
:PyTorchTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:PyTorchTrainingJob 成功。Failed
:PyTorchTrainingJob 失败。Unknown
:控制器无法获得 PyTorchTrainingJob 的阶段。
在下面的示例中,PyTorchTrainingJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;PyTorchTrainingJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;PyTorchTrainingJob 的训练成功结束,所以类型为 Completed
的 condition
被设置为 True
(原因是 The job has finished successfully.
)。当前 PyTorchTrainingJob 运行阶段为 Succeeded
。
...
status:
conditions:
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: The job has been initialized successfully.
reason: '-'
status: "True"
type: Initialized
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Running
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Failed
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "True"
type: Completed
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: All pods are running normally.
reason: '-'
status: "False"
type: ReplicaFailure
phase: Succeeded
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和);
- 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了
Creating
和Deleted
分别表示正在创建和已删除; - 副本在集群中对应的 Pod 的索引信息。
在下面的示例中,PyTorchTrainingJob 创建了 1 个角色为 worker
的副本,当前均处于 Succeeded
阶段,运行在 torch-mnist-trainingjob-5b373-worker-0
这个 Pod 上。
...
status:
tasks:
- replicas:
- containers:
- exitCode: 0
name: pytorch
state: Terminated
name: torch-mnist-trainingjob-5b373-worker-0
phase: Succeeded
uid: d39f91d6-9c48-4c57-bb71-4131226395b6
type: worker
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面示例中,PyTorchTrainingJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
TensorBoard 状态
status.tensorboard
字段用来记录 TensorBoard 的状态。
在下面的示例中,PyTorchTrainingJob 创建了名为 torch-mnist-trainingjob-5b373
的 TensorBoard,TensorBoard 目前运行正常。
status:
tensorboard:
action: NOP
dependent:
apiVersion: tensorstack.dev/v1beta1
kind: TensorBoard
name: torch-mnist-trainingjob-5b373
namespace: demo
uid: b09378f3-2164-4f14-a425-a1340fa32d7d
note: TensorBoard [torch-mnist-trainingjob-5b373] is ready
ready: true
reason: DependentReady
type: Normal
下一步
TensorFlowTrainingJob
TensorFlowTrainingJob 是服务于 TensorFlow 分布式训练框架的 T9k Job。
你可以较为方便地使用 TensorFlowTrainingJob 为 TensorFlow 训练脚本提供训练环境,并监控训练进程。
创建 TensorFlowTrainingJob
下面是一个基本的 TensorFlowTrainingJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
name: tensorflow-example
spec:
replicaSpecs:
- replicas: 4
restartPolicy: OnFailure
template:
spec:
containers:
- command:
- python
- dist_mnist.py
image: tensorflow/tensorflow:2.11.0
name: tensorflow
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
type: worker
在该例中:
- 创建 4 个副本(由
spec.replicaSpecs[*].replicas
字段指定),副本的角色为worker
(由spec.replicaSpecs[*].type
字段指定)。 - 每个副本使用
tensorflow/tensorflow:2.11.0
镜像,执行命令python dist_mnist.py
(由spec.replicaSpecs<a target="_blank" rel="noopener noreferrer" href="https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates">*].template
字段指定,此处的填写方式参考 [PodTemplate)。 - 当副本失败后,会自动重启(由
spec.replicaSpecs[*].restartPolicy
字段指定)。
副本的角色
在 TensorFlow 分布式训练框架中,副本有 4 种类型:Chief、Worker、PS 和 Evaluator。
在 TensorFlowTrainingJob 中,副本的类型由 spec.replicaSpecs[*].type
字段指定,分别是 chief
、worker
、ps
和 evaluator
。
成功和失败
在 TensorFlow 分布式训练框架中,Chief 是主节点。如果没有指定 Chief,则会选择第一个 Worker 作为主节点。当分布式训练的主节点执行完成时,TensorFlow 分布式训练成功;反之,当分布式训练的主节点执行失败时,TensorFlow 分布式训练失败。
在 TensorFlowTrainingJob 中,如果没有 Chief 副本,则选取序号为 0 的 Worker 节点作为主节点。主节点的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,TensorFlowTrainingJob 允许副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit
字段指定),当副本重启次数达到上限后,如果主节点再次失败,则 TensorFlowTrainingJob 失败。此外,TensorFlowTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds
字段指定),当超过这个执行时间后,TensorFlowTrainingJob 失败。
如果 TensorFlowTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则 TensorFlowTrainingJob 成功。
重启机制
TensorFlowTrainingJob 的 spec.replicaSpec[*].template
字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能完全满足 TensorFlowTrainingJob 的需求,所以 TensorFlowTrainingJob 使用 spec.replicaSpec[*].restartPolicy
字段覆盖 spec.replicaSpec[*].template
中指定的重启策略。
可选的重启策略有以下四种:
Never
:不重启OnFailure
:失败后重启Always
:总是重启ExitCode
:特殊退出码重启
使用 Never
重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。
ExitCode
是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:
- 130(128+2):使用
Control+C
终止容器运行。 - 137(128+9):容器接收到
SIGKILL
信号。 - 143(128+15):容器接收到
SIGTERM
信号。 - 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。
重启次数限制
如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),TensorFlowTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit
字段来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。
清除策略
在训练结束后,可能有些副本仍处于运行状态,比如 TensorFlow 训练框架中的 PS 经常在训练完成后仍然保持运行。这些运行的副本仍然会占用集群资源,TensorFlowTrainingJob 提供清除策略,在训练结束后删除这些副本。
TensorFlowTrainingJob 提供以下三种策略:
None
:不删除副本。All
:删除所有副本。Unfinished
:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 TensorFlowTrainingJob。
调度器
目前 TensorFlowTrainingJob 支持使用以下两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,TensorFlowTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
TensorBoard 的使用
TensorFlowTrainingJob 支持使用 TensorBoard 对训练过程和结果进行实时可视化(由 spec.tensorboardSpec
字段设置)。
在下面的示例中,TensorFlowTrainingJob 使用 t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
镜像创建一个 TensorBoard,可视化名为 tensorflow-tensorboard-pvc
的 PVC 中 /log
路径下的模型数据。
...
spec:
tensorboardSpec:
image: t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
trainingLogFilesets:
- t9k://pvc/tensorflow-tensorboard-pvc/log
...
调试模式
TensorFlowTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为sleep inf
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
sleep inf
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
TensorFlowTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 TensorFlowTrainingJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
TensorFlowTrainingJob 状态
TensorFlowTrainingJob 的状态和阶段
status.conditions
字段用于描述当前 TensorFlowTrainingJob 的状态,包括以下 6 种类型:
Initialized
:TensorFlowTrainingJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:TensorFlowTrainingJob 成功。Failed
:TensorFlowTrainingJob 失败。Paused
:TensorFlowTrainingJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 TensorFlowTrainingJob 所处的阶段,TensorFlowTrainingJob 的整个生命周期主要有以下7个阶段:
Pending
:TensorFlowTrainingJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:TensorFlowTrainingJob 进入暂停模式。Resuming
:TensorFlowTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:TensorFlowTrainingJob 成功。Failed
:TensorFlowTrainingJob 失败。Unknown
:控制器无法获得 TensorFlowTrainingJob 的阶段。
在下面的示例中,TensorFlowTrainingJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;TensorFlowTrainingJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;TensorFlowTrainingJob 的训练成功结束,所以类型为 Completed
的 condition
被设置为 True
(原因是 The job has finished successfully.
)。当前 TensorFlowTrainingJob 运行阶段为 Succeeded
。
...
status:
conditions:
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: The job has been initialized successfully.
reason: '-'
status: "True"
type: Initialized
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Running
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Failed
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "True"
type: Completed
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: All pods are running normally.
reason: '-'
status: "False"
type: ReplicaFailure
phase: Succeeded
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和);
- 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了
Creating
和Deleted
分别表示正在创建和已删除; - 副本在集群中对应的 Pod 的索引信息。
在下面的示例中,TensorFlowTrainingJob 创建了 1 个角色为 worker
的副本,当前均处于 Succeeded
阶段,运行在 mnist-trainingjob-5b373-worker-0
这个 Pod 上。
...
status:
tasks:
- replicas:
- containers:
- exitCode: 0
name: pytorch
state: Terminated
name: mnist-trainingjob-5b373-worker-0
phase: Succeeded
uid: d39f91d6-9c48-4c57-bb71-4131226395b6
type: worker
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面示例中,TensorFlowTrainingJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
TensorBoard 状态
status.tensorboard
字段用来记录 TensorBoard 的状态。
在下面的示例中,TensorFlowTrainingJob 创建了名为 mnist-trainingjob-5b373
的 TensorBoard,TensorBoard 目前运行正常。
status:
tensorboard:
action: NOP
dependent:
apiVersion: tensorstack.dev/v1beta1
kind: TensorBoard
name: mnist-trainingjob-5b373
namespace: demo
uid: b09378f3-2164-4f14-a425-a1340fa32d7d
note: TensorBoard [mnist-trainingjob-5b373] is ready
ready: true
reason: DependentReady
type: Normal
下一步
DeepSpeedJob
DeepSpeedJob 是服务于 DeepSpeed 分布式训练框架的 T9k Job。
你可以较为方便地使用 DeepSpeedJob 为 DeepSpeed 训练脚本提供训练环境,并监控训练进程。
创建 DeepSpeedJob
下面是一个基本的 DeepSpeedJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepspeedJob
metadata:
name: deepspeed-example
spec:
config:
slotPerWorker: 1
run:
python: /t9k/mnt/train.py
worker:
replicas: 4
template:
spec:
restartPolicy: OnFailure
containers:
- image: deepspeed/deepspeed:v072_torch112_cu117
imagePullPolicy: IfNotPresent
name: worker
resources:
limits:
cpu: 4
memory: 4Gi
requests:
cpu: 2
memory: 2Gi
volumeMounts:
- mountPath: /t9k/mnt
name: code
volumes:
- name: code
persistentVolumeClaim:
claimName: deepspeed
在该例中:
- 创建 4 个训练副本,这些副本会启动
sshd
服务。 - 第一个副本会启动
deepspeed
程序,该程序会通过pdsh
(或其他方式)访问 4 个副本,并在每个副本上运行/t9k/mnt/train.py
脚本。
训练配置
DeepSpeedJob 在 spec.config
中配置如何执行训练。有以下参数可以设置:
run
:如何启动训练,以下三个参数只能填写一个,否则报错:python
:使用 Python 脚本进行训练。指定 Python 文件以及启动参数。module
:使用 Python module 进行训练。指定 Python module 以及启动参数。exec
:使用可执行文件/命令进行训练。指定可执行文件以及启动参数。
slotsPerWorker
:每一个副本上设置多少个“插槽”。“插槽”是继承自 MPI 中的概念,表示一个副本上可以运行多少个训练进程。一般来说该值被设为每个副本分配的 GPU 数量。例如当创建了一个replica
为 4 的任务,并且给每个副本分配了 2 个nvidia.com/gpu
,则应该将slotsPerWorker
设为 2,这样最后一共会运行4 * 2 = 8
个训练进程。localRank
:是否传递LOCAL_RANK
环境变量,默认为true
。autotune
:启用超参数调优,可以设置为none
、run
、tune
,默认为none
。none
为不启动超参数调优;tune
只查找最合适的超参数组合,但是不执行训练;run
查找最合适的超参数组合,并用该超参数执行训练。otherArgs
:设置其他 DeepSpeed 参数,详见下文。
otherArgs
DeepSpeedJob 希望提供用户足够的灵活性,所以支持用户通过 otherArgs
字段设置传入 DeepSpeed 的参数。config 中的配置实际上也是通过 DeepSpeed 参数实现的,以下列出除了在配置文件中指定的参数之外的其他可用参数:
--launcher
: 多节点训练使用的启动器后端,目前的选项包括 PDSH、OpenMPI、MVAPICH、SLURM、MPICH。(默认:pdsh
)。目前 DeepSpeedJob 只支持pdsh
。--no_ssh_check
:多节点训练时不执行 ssh 检查。--save_pid
: 在/tmp/<main-pid>.ds
处保存包含启动器进程 ID(pid),其中<main-pid>
是第一个调用 DeepSpeed 的进程的 pid。PDSH 模式下不支持。--enable_each_rank_log
: 将每个 Rank 的 stdout 和 stderr 重定向到不同的日志文件。PDSH 模式下不支持。--bind_cores_to_rank
:将每个 Rank 绑定到主机的不同核心。PDSH 模式下不支持。--bind_core_list
:要绑定的核心列表,以逗号分隔。例如1,3-5,7 => [1,3,4,5,7]
。 未指定时,系统上的所有核心都将被绑定。PDSH 模式下不支持。
训练的成功和失败判定
DeepSpeedJob 分布式训练框架中,第一个训练副本(下文记为 worker-0
)是分布式任务的主节点。当 worker-0
成功结束,则 DeepSpeedJob 训练成功;反之,当 worker-0
执行失败,DeepSpeedJob 训练失败。
如果一次训练执行时间过长,用户可能需要考虑代码是否需要优化、是否需要分配更多资源等问题。DeepSpeedJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds
字段指定),当超过这个执行时间后,训练失败。
清除策略
在训练完毕后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,DeepSpeedJob 提供清除策略,可以在训练结束后删除这些训练副本。
DeepSpeedJob 提供以下三种策略:
None
:不删除副本。All
:删除所有副本。Unfinished
:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 DeepSpeedJob。
调度策略
目前 DeepSpeedJob 支持两种调度策略:
- Kubernetes 的默认调度器
- T9k Scheduler
调度策略通过 CRD 的 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度策略。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,MPIJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
调试模式
DeepSpeedJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为/usr/sbin/sshd -D
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
sleep inf
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
/usr/sbin/sshd -D
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["sleep", "inf"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
DeepSpeedJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 DeepSpeedJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
DeepSpeedJob 状态
DeepSpeedJob 的状态和阶段
status.conditions
字段用于描述当前 DeepSpeedJob 的状态,包括以下 5 种类型:
Initialized
:DeepSpeedJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:DeepSpeedJob 成功。Failed
:DeepSpeedJob 失败。
status.phase
字段用于描述当前 DeepSpeedJob 所处的阶段,DeepSpeedJob 的整个生命周期主要有以下几个阶段:
Pending
:DeepSpeedJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Succeeded
:DeepSpeedJob 成功。Failed
:DeepSpeedJob 失败。Unknown
:控制器无法获得 DeepSpeedJob 的阶段。
在下面的示例中,DeepSpeedJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;DeepSpeedJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;但是 DeepSpeedJob 的训练结果是失败的,所以类型为 Failed
的 condition
被设置为 True
。当前 DeepSpeedJob 运行阶段为 Failed
。
...
status:
conditions:
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "The job has been initialized successfully."
reason: "-"
type: Initializing
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "All pods are running normally."
reason: "-"
type: Running
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "False"
message: "All pods are running normally."
reason: "-"
type: ReplicaFailure
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "False"
message: "The job exited with an error code."
reason: "Failed"
type: Completed
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "True"
message: "The job exited with an error code."
reason: "Failed"
type: Failed
phase: Failed
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和)
- 副本当前的运行阶段
- 副本在集群中对应的 Pod 的索引信息
在下面的示例中,DeepSpeedJob 创建了 2 个训练副本,当前均处于 Running
阶段,分别运行在 deepspeed-example-worker-0
和 deepspeed-example-worker-1
这 2 个 Pod 上。
...
status:
tasks:
- type: worker
restartCount: 0
status:
- phase: Running
name: deepspeed-example-worker-0
uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
containers: []
- phase: Running
name: deepspeed-example-worker-1
uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
containers: []
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面的示例中,DeepSpeedJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
ColossalAIJob
ColossalAIJob 是服务于 ColossalAI 分布式训练框架的 T9k Job。
你可以较为方便地使用 ColossalAIJob 为 ColossalAI 训练脚本提供训练环境,并监控训练进程。
创建 ColossalAIJob
下面是一个基本的 ColossalAIJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: ColossalAIJob
metadata:
name: colossalai-example
spec:
ssh:
authMountPath: /root/.ssh
sshdPath: /usr/sbin/sshd
launcher:
image: hpcaitech/colossalai:0.3.0
workingDir: /workspace
env: []
resources:
limits:
cpu: 1
memory: 2Gi
requests:
cpu: 500m
memory: 1Gi
worker:
replicas: 2
procPerWorker: 1
command:
- train.py
- arg1
torchArgs: []
template:
spec:
restartPolicy: OnFailure
containers:
- image: hpcaitech/colossalai:0.3.0
imagePullPolicy: IfNotPresent
name: worker
resources:
limits:
cpu: 2
memory: 8Gi
nvidia.com/gpu: 1
requests:
cpu: 1
memory: 4Gi
nvidia.com/gpu: 1
volumeMounts:
- mountPath: /workspace
name: code
volumes:
- name: code
persistentVolumeClaim:
claimName: colossalai
在该例中:
- 创建 1 个启动副本,该启动副本是 ColossalAI 在训练中所必须的,启动副本的配置参考 PodTemplate,这里不再赘述(启动副本的配置由
spec.launcher
字段指定)。 - 创建 2 个执行副本(由
spec.worker.replicas
字段指定),每个执行副本上启动 1 个训练进程(由spec.worker.procPerWorker
字段指定),训练脚本和参数为train.py arg1
(由spec.worker.command
字段指定),执行副本的其他配置参考 PodTemplate,这里不再赘述(这些配置由spec.worker.template
字段指定)。 - 执行副本需要执行 sshd 程序,等待启动副本发来训练指令。sshd 的路径为
/user/sbin/sshd
(由spec.ssh.sshdPath
字段指定,使用该字段的原因是 sshd 程序必须使用绝对路径调用,所以需要其具体路径)。
成功和失败
在 ColossalAIJob 分布式训练框架中:
- 如果启动副本执行失败,ColossalAIJob 训练失败。
- 如果启动副本执行成功,ColossalAIJob 并不一定成功:启动副本的作用是启动训练和监测,无论是训练成功还是失败,启动副本都会正常结束,而不是报错。因此,如果要确定 ColossalAIJob 是否成功结束,需要检查启动副本的日志。
重启机制
与其他 TrainingJob 不同,ColossalAIJob 使用 colossalairun
作为启动命令,在这种情况下,Pod 失败重启后不会再加入到训练中。所以 ColossalAIJob 无法像其他 TrainingJob 那样支持 Pod 失败重启。
清除策略
在 ColossalAIJob 训练结束后,ColossalAIJob 控制器可以清理所创建的 Kubernetes 资源,使 ColossalAIJob 不再浪费集群资源(内存、CPU 等)。一般来说,你需要查看启动副本的日志来确定训练结果,所以启动副本不在清理范围之内,ColossalAIJob 控制器只清理执行副本(通过 spec.runPolicy.cleanUpWorkers
字段设置)。
在下面的示例中,ColossalAIJob 在训练结束后会自动删除所有执行副本:
...
spec:
runPolicy:
cleanUpWorkers: true
调度器
目前 ColossalAIJob 支持两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,ColossalAIJob 启用 T9k Scheduler 调度器,将执行副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
调试模式
ColossalAIJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为sleep inf
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
sleep inf
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
ColossalAIJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 ColossalAIJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
ColossalAIJob 状态
ColossalAIJob 的状态和阶段
status.conditions
字段用于描述当前 ColossalAIJob 的状态,包括以下 5 种类型:
Initialized
:ColossalAIJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:ColossalAIJob 成功。Failed
:ColossalAIJob 失败。Paused
:ColossalAIJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 ColossalAIJob 所处的阶段,ColossalAIJob 的整个生命周期主要有以下几个阶段:
Pending
:ColossalAIJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:ColossalAIJob 进入暂停模式。Resuming
:ColossalAIJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:ColossalAIJob 成功。Failed
:ColossalAIJob 失败。Unknown
:控制器无法获得 ColossalAIJob 的阶段。
在下面的示例中,ColossalAIJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;ColossalAIJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;但是 ColossalAIJob 的训练结果是失败的,所以类型为 Failed
的 condition
被设置为 True
。当前 ColossalAIJob 运行阶段为 Failed
。
...
status:
conditions:
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "The job has been initialized successfully."
reason: "-"
type: Initializing
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "All pods are running normally."
reason: "-"
type: Running
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "False"
message: "All pods are running normally."
reason: "-"
type: ReplicaFailure
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "False"
message: "The job exited with an error code."
reason: "Failed"
type: Completed
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "True"
message: "The job exited with an error code."
reason: "Failed"
type: Failed
phase: Failed
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和)
- 副本当前的运行阶段
- 副本在集群中对应的 Pod 的索引信息
在下面的示例中,ColossalAIJob 创建了 1 个启动副本和 2 个执行副本。执行副本当前均处于 Running
阶段,分别运行在 colossalai-example-worker-0
和 colossalai-example-worker-1
这 2 个 Pod 上;启动副本当前处于 Running
阶段,运行在 colossalai-example-launcher
Pod 上。
...
status:
tasks:
- type: launcher
restartCount: 0
status:
- phase: Running
name: colossalai-example-launcher
uid: 66634db2-35e7-4641-a4dc-adbd5479734e
containers: []
- type: worker
restartCount: 0
status:
- phase: Running
name: colossalai-example-worker-0
uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
containers: []
- phase: Running
name: colossalai-example-worker-1
uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
containers: []
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面的示例中,ColossalAIJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
XGBoostTrainingJob
XGBoostTrainingJob 是服务于 XGBoost 分布式计算框架的 T9k Job。
你可以较为方便地使用 XGBoostTrainingJob 为 XGBoost 计算程序提供训练环境,并监控训练进程。
创建 XGBoostTrainingJob
下面是一个基本的 XGBoostTrainingJob 配置示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: XGBoostTrainingJob
metadata:
name: training-iris-xgb
spec:
replicaSpecs:
- type: master
replicas: 1
restartPolicy: OnFailure
template:
spec:
containers:
- name: xgboost
image: t9kpublic/xgboost-dist-iris:3.7
command:
- python3
- /mnt/main.py
- --job_type=Train
- --xgboost_parameter=objective:multi:softprob,num_class:3
- --n_estimators=10
- --learning_rate=0.1
- --model_path=/mnt/xgboost_model/
- --model_storage_type=local
- type: worker
replicas: 2
restartPolicy: OnFailure
template:
containers:
- name: xgboost
image: t9kpublic/xgboost-dist-iris:3.7
command:
- python3
- /mnt/main.py
- --job_type=Train
- --xgboost_parameter=objective:multi:softprob,num_class:3
- --n_estimators=10
- --learning_rate=0.1
- --model_path=/mnt/xgboost_model/
- --model_storage_type=local
在该例中:
- 创建 1 个
master
副本和 2 个worker
副本(由spec.replicaSpecs[*].replicas
字段和spec.replicaSpecs[*].type
字段指定)。 - 每个副本使用
registry.tensorstack.cn/t9kmirror/xgboost-dist-iris:1.1
镜像,执行命令python3 /mnt/main.py --job_type=Train --xgboost_parameter=objective:multi:softprob,num_class:3 --n_estimators=10 --learning_rate=0.1 --model_path=/mnt/xgboost_model/ --model_storage_type=local
(由spec.replicaSpecs<a target="_blank" rel="noopener noreferrer" href="https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates">*].template
字段指定,此处的填写方式参考 [PodTemplate)。 - 当副本失败后,会自动重启(由
spec.replicaSpecs[*].restartPolicy
字段指定)。
成功和失败
在 XGBoost 分布式训练框架中,副本有 2 种类型:Master 和 Worker,其中 Master 是主节点。当分布式训练的主节点成功结束时,XGBoost 分布式训练成功;反之,当分布式训练的主节点执行失败时,XGBoost 分布式训练失败。
但是主节点的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,XGBoostTrainingJob 允许副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit
字段指定),当副本重启次数达到上限后,如果主节点再次失败,则训练失败。此外,XGBoostTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds
字段指定),当超过这个执行时间后,训练失败。
如果 XGBoostTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则训练成功。
重启机制
XGBoostTrainingJob 的 spec.replicaSpec[*].template
字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能满足 XGBoostTrainingJob 的需求,所以 XGBoostTrainingJob 使用 spec.replicaSpec[*].restartPolicy
字段覆盖 spec.replicaSpec[*].template
中指定的重启策略。
可选的重启策略有以下四种:
Never
:不重启OnFailure
:失败后重启Always
:总是重启ExitCode
:特殊退出码重启
使用 Never
重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。
ExitCode
是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:
- 130(128+2):使用
Control+C
终止容器运行。 - 137(128+9):容器接收到
SIGKILL
信号。 - 143(128+15):容器接收到
SIGTERM
信号。 - 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。
重启次数限制
如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),XGBoostTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit
字段来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。
清除策略
在训练结束后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,XGBoostTrainingJob 提供清除策略,在训练结束后删除这些训练节点。
XGBoostTrainingJob 提供以下三种策略:
None
:不删除副本。All
:删除所有副本。Unfinished
:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 XGBoostTrainingJob。
调度器
目前 XGBoostTrainingJob 支持使用以下两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,XGBoostTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
调试模式
XGBoostTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,默认为sleep inf
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行
sleep inf
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
XGBoostTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 XGBoostTrainingJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
XGBoostTrainingJob 状态
XGBoostTrainingJob 的状态和阶段
status.conditions
字段用于描述当前 XGBoostTrainingJob 的状态,包括以下 6 种类型:
Initialized
:XGBoostTrainingJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:XGBoostTrainingJob 成功。Failed
:XGBoostTrainingJob 失败。Paused
:XGBoostTrainingJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 XGBoostTrainingJob 所处的阶段,XGBoostTrainingJob 的整个生命周期主要有以下7个阶段:
Pending
:XGBoostTrainingJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:XGBoostTrainingJob 进入暂停模式。Resuming
:XGBoostTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:XGBoostTrainingJob 成功。Failed
:XGBoostTrainingJob 失败。Unknown
:控制器无法获得 XGBoostTrainingJob 的阶段。
在下面的示例中,XGBoostTrainingJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;XGBoostTrainingJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;XGBoostTrainingJob 的训练成功结束,所以类型为 Completed
的 condition
被设置为 True
(原因是 The job has finished successfully.
)。当前 XGBoostTrainingJob 运行阶段为 Succeeded
。
...
status:
conditions:
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: The job has been initialized successfully.
reason: '-'
status: "True"
type: Initialized
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Running
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "False"
type: Failed
- lastTransitionTime: "2023-12-19T02:53:14Z"
message: The job has finished successfully.
reason: Succeeded
status: "True"
type: Completed
- lastTransitionTime: "2023-12-19T02:40:25Z"
message: All pods are running normally.
reason: '-'
status: "False"
type: ReplicaFailure
phase: Succeeded
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和);
- 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了
Creating
和Deleted
分别表示正在创建和已删除; - 副本在集群中对应的 Pod 的索引信息。
在下面的示例中,XGBoostTrainingJob 创建了 1 个角色为 worker
的副本,当前均处于 Succeeded
阶段,运行在 mnist-trainingjob-5b373-worker-0
这个 Pod 上。
...
status:
tasks:
- replicas:
- containers:
- exitCode: 0
name: pytorch
state: Terminated
name: mnist-trainingjob-5b373-worker-0
phase: Succeeded
uid: d39f91d6-9c48-4c57-bb71-4131226395b6
type: worker
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面示例中,XGBoostTrainingJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
MPIJob
OpenMPI 是一个开源的 MPI(Message Passing Interface)协议的实现项目。
MPIJob 是一种使用 OpenMPI 进行分布式计算的 T9k Job,此资源让你能够方便地在集群环境中使用 OpenMPI 进行训练。
创建 MPIJob
下面的 MPIJob 示例创建了 5 个执行副本,每个执行副本启动 3 个进程,运行随机游走程序:
apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
name: mpi-example
spec:
worker:
replicas: 5
extraMPIArgs:
- -N
- "3"
- --enable-recovery
- --max-restarts
- "100"
- --allow-run-as-root
- -bind-to
- none
cmd:
- ./random_walk
- "20"
- "40"
- "2"
template:
spec:
containers:
- name: mpi-worker
image: t9kpublic/mpi-tutorial:2021022-2
resources:
limits:
cpu: 100m
requests:
cpu: 50m
workingDir: /usr/local/code
mca:
btl: ^openib
runPolicy:
cleanUpWorkers: true
ssh:
sshdPath: /usr/sbin/sshd
mpiHome: /usr/local
在该例中:
- 创建 5 个执行副本(由
spec.worker.replicas
字段指定)。 spec.worker.template
字段沿用 PodTemplate 的规约,配置执行副本和启动副本的环境。每个执行副本包含一个名为mpi-worker
的容器(为了确定用于执行 MPI 进程的容器,执行副本定义中必须有一个名为mpi-worker
的容器)。mpi-worker
容器创建后执行sshd
命令并等待启动副本连接,所以此容器会忽略PodTemplate
定义中的command
和args
字段(因此该例中没有填写这两个字段)。- 在执行副本准备完毕后,启动副本向执行副本发送启动命令,令执行副本创建 3 个 MPI 进程,这些进程分别执行
./random_walk 20 40 2
(由spec.worker.cmd
字段指定)命令。 - 在训练过程中不使用 Infiniband 进行通信(由
spec.mca.btl
字段指定)。 - 在训练结束后自动清除副本(由
spec.runPolicy.cleanUpWorkers
字段指定)来释放集群资源。 - sshd 的路径为
/user/sbin/sshd
(由spec.ssh.sshdPath
字段指定,使用该字段的原因是 sshd 程序必须使用绝对路径调用,所以需要其具体路径)。 - MPI 安装在
/usr/local
处(由spec.mpiHome
字段指定,使用该字段的原因是mpirun
的有些功能需要知道 MPI 的根目录地址才能正确运行)。
运行 Horovod 训练脚本
使用 Horovod 框架的分布式训练脚本也可以使用 MPIJob 进行训练。
在 MPIJob 中需要执行以下操作:
- 在
spec.worker.template.spec.containers[mpi-worker].env
字段中添加NCCL_DEBUG
; - 在
spec.mca
字段中添加pml:ob1
和btl:^openib
。
下面是使用 MPIJob 执行 Horovod 框架的分布式训练脚本的示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
name: mpi-example
spec:
mca:
btl: ^openib
pml: ob1
worker:
template:
spec:
containers:
- name: mpi-worker
env:
- name: "NCCL_DEBUG"
value: "INFO"
...
调度器
目前 MPIJob 支持使用以下两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler
调度策略通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,MPIJob 启用 T9k Scheduler 调度器,将执行副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
调试模式
MPIJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。
该模式可以通过 spec.runMode.debug
字段来设置:
spec.runMode.debug.enabled
表示是否启用调试模式。spec.runMode.debug.replicaSpecs
表示如何配置各个副本的调试模式:spec.runMode.debug.replicaSpecs.type
表示作用于的副本类型。spec.runMode.debug.replicaSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.debug.replicaSpecs.command
表示副本在等待调试的时候执行的命令,launcher
的默认命令为sleep inf
,worker
的默认命令为/usr/bin/sshd -D
。- 如果不填写
spec.runMode.debug.replicaSpecs
字段,则表示所有副本都使用默认设置。
在下面的示例中:
- 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行
sleep inf
。 - 示例二:开启了调试模式,副本使用默认调试设置,即 worker 不跳过 InitContainer,并执行
/usr/bin/sshd -D
。
# 示例一
...
spec:
runMode:
debug:
enabled: true
replicaSpecs:
- type: worker
skipInitContainer: true
command: ["sleep", "inf"]
---
# 示例二
...
spec:
runMode:
debug:
enabled: true
暂停模式
MPIJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。
该模式可以通过 spec.runMode.pause
字段来设置:
spec.runMode.pause.enabled
表示是否启用暂停模式。spec.runMode.pause.resumeSpecs
表示结束暂停后,如何恢复各个副本:spec.runMode.pause.resumeSpecs.type
表示作用于的副本类型。spec.runMode.pause.resumeSpecs.skipInitContainer
表示让副本的 InitContainer 失效,默认为false
。spec.runMode.pause.resumeSpecs.command
和spec.runMode.pause.resumeSpecs.args
表示副本在恢复运行时候执行的命令,默认使用spec.replicaSpecs[0].template
中的命令。- 如果不填写
spec.runMode.pause.resumeSpecs
字段,则表示所有副本都使用默认设置。
用户可以随时修改 spec.runMode.pause.enabled
来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs
,所以如果有暂停 MPIJob 的需求,请提前设置好恢复设置。
在下面的示例中:
- 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行
/usr/bin/sshd
。 - 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行
spec.replicaSpecs[0].template
中设置的命令。
# 示例一
...
spec:
runMode:
pause:
enabled: true
resumeSpecs:
- type: worker
skipInitContainer: true
command: ["/usr/bin/sshd"]
---
# 示例二
...
spec:
runMode:
pause:
enabled: true
MPIJob 状态
MPIJob 的状态和阶段
status.conditions
字段用于描述当前 MPIJob 的状态,包括以下 5 种类型:
Initialized
:MPIJob 已经成功创建各子资源,完成初始化。Running
:开始执行任务。ReplicaFailure
:有一个或多个副本出现错误。Completed
:MPIJob 结束。Failed
:MPIJob 失败。Paused
:MPIJob 进入暂停模式,所有副本都已删除或正在删除。
status.phase
字段用于描述当前 MPIJob 所处的阶段,MPIJob 的整个生命周期主要有以下几个阶段:
Pending
:MPIJob 刚刚创建,等待副本启动。Running
:副本创建成功,开始执行任务。Paused
:MPIJob 进入暂停模式。Resuming
:MPIJob 正从暂停模式中恢复运行。恢复运行后,切换为Running
阶段。Succeeded
:MPIJob 结束。Failed
:MPIJob 失败。Unknown
:控制器无法获得 MPIJob 的阶段。
在下面的示例中,MPIJob 所有子资源创建成功,所以类型为 Initalized
的 condition
被设为 True
;MPIJob 运行结束,所以类型为 Completed
的 condition
被设置为 True
;但是 MPIJob 的训练结果是失败的,所以类型为 Failed
的 condition
被设置为 True
。当前 MPIJob 运行阶段为 Failed
。
...
status:
conditions:
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "The job has been initialized successfully."
reason: "-"
type: Initializing
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
message: "All pods are running normally."
reason: "-"
type: Running
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "False"
message: "All pods are running normally."
reason: "-"
type: ReplicaFailure
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "False"
message: "The job exited with an error code."
reason: "Failed"
type: Completed
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "True"
message: "The job exited with an error code."
reason: "Failed"
type: Failed
phase: Failed
副本的状态
status.tasks
字段用来记录副本的状态,记录的内容主要包括:
- 副本的重启次数(同一种角色的副本的重启次数之和)
- 副本当前的运行阶段
- 副本在集群中对应的 Pod 的索引信息
在下面的示例中,MPIJob 创建了 1 个启动副本和 2 个执行副本。当前均处于 Running
阶段,分别运行在 mpi-example-worker-0
和 mpi-example-worker-1
这 2 个 Pod 上;启动副本当前处于 Running
阶段,运行在 mpi-example-launcher
Pod 上。
...
status:
tasks:
- type: launcher
restartCount: 0
status:
- phase: Running
name: mpi-example-launcher
uid: 66634db2-35e7-4641-a4dc-adbd5479734e
containers: []
- type: worker
restartCount: 0
status:
- phase: Running
name: mpi-example-worker-0
uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
containers: []
- phase: Running
name: mpi-example-worker-1
uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
containers: []
副本状态统计
status.aggregate
字段统计了各个阶段的副本数量。
在下面示例中,MPIJob 创建了 3 个副本,其中 1 个处于 Pending
阶段,另外两个处于 Running
阶段。
...
status:
aggregate:
creating: 0
deleted: 0
failed: 0
pending: 1
running: 2
succeeded: 0
unknown: 0
...
下一步
BeamJob
BeamJob 用于在集群中通过 Apache Beam Python SDK 运行分布式计算任务,并提供多种底层计算引擎,目前支持 Apache Flink,未来会支持 Apache Spark。
创建 BeamJob
下面是一个基本的 BeamJob 配置示例,负责统计输入文件中的英文单词出现次数,并将结果存储在输出文件中:
apiVersion: batch.tensorstack.dev/v1beta1
kind: BeamJob
metadata:
name: beamjob-example
spec:
flinkClusterTemplate:
spec:
flinkVersion: 1.10.1
image:
name: t9kpublic/flink:1.10.1
jobManager:
accessScope: Cluster
resources:
limits:
cpu: "100m"
memory: "1Gi"
taskManager:
replicas: 2
resources:
limits:
cpu: "100m"
memory: "2Gi"
flinkProperties:
taskmanager.numberOfTaskSlots: "1"
jobTemplate:
spec:
template:
spec:
containers:
- image: t9kpublic/apache_beam_python3.7_sdk:2.22.0
name: submit-job
command:
- "python3"
args:
- "-m"
- "apache_beam.examples.wordcount"
- "--input"
- "/mypvc/input.txt"
- "--output"
- "/mypvc/output.txt"
volumeMounts:
- mountPath: "/mypvc"
name: mypvc
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: mypvc
restartPolicy: OnFailure
在该例中:
- 你需要准备好一个名为
mypvc
的 PVC,并将名为input.txt
的输入文件存放在 PVC 的根路径下。 flinkClusterTemplate
字段描述了所要创建的 Flink 集群,其中包含 1 个 Job Manager{target=_blank},所使用的 Flink 版本为 1.10.1。jobTemplate
字段描述了用户如何将所要运行的任务提交给 Flink 集群,其中所使用的 Apache Beam Python SDK 版本为 2.22.0,所运行的程序为 Apache Beam Python SDK 自带的单词统计程序apache_beam.examples.wordcount
。
BeamJob 状态
BeamJob 的状态和阶段
status.conditions
字段用于描述当前 BeamJob 的状态,包括以下 2 种类型:
ClusterRunning
:Flink 集群正在运行JobRunning
:用户提交的任务正在运行
status.phase
字段用于描述当前 BeamJob 所处的阶段,BeamJob 的整个生命周期主要有以下几个阶段:
Initializing
:BeamJob 刚刚创建,等待 Flink 集群启动。Running
:Flink 集群已启动,用户提交的任务正在运行。Succeeded
:BeamJob 成功。Failed
:BeamJob 失败。Unknown
:控制器执行错误,导致未能获取 BeamJob 当前运行阶段。
status.jobURL
字段是 Flink 集群的 Web UI 中用户提交的此次任务对应的详细信息页面。
在下面的示例中,Flink 集群已启动,所以类型为 ClusterRunning
的 condition
被设置为 True
;用户所提交的任务正在运行,所以类型为 JobRunning
的 condition
被设置为 True
。当前 BeamJob 运行阶段为 Running
,如需在 Flink 集群的 Web UI 中查看任务的详细信息,请跳转至 jobURL
。
...
status:
conditions:
- lastTransitionTime: "2021-01-18T02:36:09Z"
status: "True"
type: ClusterRunning
- lastTransitionTime: "2021-01-18T02:36:31Z"
status: "True"
type: JobRunning
phase: Running
jobURL: /t9k/flink-cluster/beamjob-example-flinkcluster/namespace/t9k-example/#/job/c9f62e4d61d089f351ab1f8b29e1df32/overview/
Flink 集群的状态
status.flinkClusterStatus
字段用来记录 Flink 集群的状态,包括所有 Job Manager 和 Task Manager 的运行阶段以及对应的 Pod 索引。
在下面的示例中,BeamJob 创建的 Flink 集群包括 1 个 Job Manager 和 2 个 Task Manager,均处于 Running
阶段(记录在 phase
字段中),对应的 Pod 的索引信息记录在 reference
字段中(包括 Pod 的名称和 UID)。
...
status:
flinkClusterStatus:
jobManagerStatus:
- phase: Running
reference:
name: beamjob-example-flinkcluster-jobmanager-0
uid: 21c67b2d-88d4-4b0a-9044-2311edee5e83
taskManagerStatus:
- phase: Running
reference:
name: beamjob-example-flinkcluster-taskmanager-0
uid: c120c704-0730-49c8-8995-5fb719840af7
- phase: Running
reference:
name: beamjob-example-flinkcluster-taskmanager-1
uid: f1326d53-c5b6-4869-b5e9-8c35b7a7637d
用户提交任务的状态
status.jobStatus
字段用来记录用户所提交的任务的状态,包括运行阶段以及对应的 Pod 索引。
在下面的示例中,BeamJob 创建的用户任务仅包含 1 个 Pod,处于 Succeeded
阶段(记录在 phase
字段中),对应的 Pod 的索引信息记录在 reference
字段中(包括 Pod 的名称和 UID)。用户所提交的任务运行可能出现错误并多次重试,因此 status.jobStatus
字段可能包含多个 Pod。
...
status:
jobStatus:
- phase: Succeeded
reference:
name: beamjob-example-batchjob-szsn8
uid: 9aed0159-fe2a-4096-99a7-1c89af5a6f0e
清除策略
在 BeamJob 成功或失败后,所创建的 Flink 集群仍然在运行,占据较多的计算资源。在下面的示例中,你可以在 spec.runPolicy
字段中将 cleanUpCluster
设置为 true
,在 BeamJob 运行完毕(无论成功还是失败)之后删除 Flink 集群。
...
spec:
runPolicy:
cleanUpCluster: true
...
调度器
目前 BeamJob 支持两种调度器:
- Kubernetes 的默认调度器
- T9k Scheduler 调度器
调度器通过 spec.scheduler
字段设置:
- 不设置
spec.scheduler
字段,则默认使用 Kubernetes 的默认调度器。 - 设置
spec.scheduler.t9kScheduler
字段,则使用 T9k Scheduler 调度器。
在下面的示例中,BeamJob 启用 T9k Scheduler 调度器,将副本插入 default
队列中等待调度,其优先级为 50。
...
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
...
资产管理
所谓 AI 资产,指数据集和模型等人工智能相关的数据。
TensorStack AI 平台的资产管理模块(AssetHub,以下简称 AH)对模型和数据集提供完善的管理功能,包括版本管理、持续开发和协同开发等功能。
产品架构
如上图所示,AH 使用 TensorStack AI 平台自研存储系统 AIStore 存储数据,用户可以通过 AH 控制台、命令行工具和 SDK 工具与 AIStore 连接,实现 AH 的各项功能。
版本控制
AH 支持多版本模型管理,用户可以训练和提交多个临时版本模型,发布其中符合预期的模型。
多版本管理通过以下机制实现:
- Branch:分支,用户可以创建一个新分支来记录模型的临时版本;将新分支合并到主分支上,完成模型的发布。
- Commit:“交付”,相当于版本快照,便于确定版本和追溯历史。
- Tag:标签,用户可以为具有“特殊意义”的 Commit 标记标签,比如 best、v1 等。
数据集同样支持 Branch、Commit 和 Tag 的管理方式,不过数据集不会如模型那样频繁产出,所以一般建议数据集只在主分支上持续更新。
S3 接口
在训练(或部署服务)时,除了将数据集和模型下载到本地使用,大多数框架也支持直接从 S3 数据服务上动态获取数据文件。
AH 提供 S3 接口,用户可以在 AH 控制台上创建 S3 凭证,然后使用页面上生成的 S3 配置文件在训练过程中直接通过 S3 接口获取数据。
协同开发
AH 支持文件夹粒度的权限共享。用户可以将一组模型或数据集分享给其他人,实现多人共同开发和训练结果共享的目的。
可分享的权限包括查看权限或编辑权限,编辑权限包含查看权限。分享的目标可以是另一个用户、用户组或者公开给所有人。
下一步
- 了解如何使用 Asset Hub 管理 AI 资产
实验管理
TensorStack AI 平台的实验管理模块(Experiment Management,以下简称 EM)提供完善的实验数据追踪功能,能够收集实验元数据、实验中间产物,并可视化和比较实验结果,推动模型进步。
产品架构
如上图所示,EM 使用 TensorStack AI 平台自研存储系统 AIStore 存储数据,用户可以通过 EM 控制台、命令行工具和 SDK 工具与 AIStore 连接,实现 EM 的各项功能。
存储结构
EM 使用树状结构组织一个用户的实验数据,在 Web UI 中体现为目录结构。
# EM 目录结构示意图
user:demo
├── em-example/
│ ├── mnist_dataset
│ └── mnist_keras
└── autotune/
└── keras-tune
节点类型
EM 树状结构中,节点根据存储方式分为四类,用 StorageType 表示:
- StorageType == 0:不存储数据文件,仅用于组织 EM 树状结构。EM 中文件夹即该类型节点。
- StorageType == 1:存储一个文件数据。
- StorageType == 2:存储一组数据文件。
- StorageType == 3:该类型节点可以创建和管理多个版本,每一个版本中可以存储一组数据文件。
在这四种存储类型的基础上,EM 根据用途实现以下 7 个节点类型:
- Folder:Storage Type == 0,文件夹结构,用来组织实验数据。
- Shotrcut:Storage Type == 0,快捷方式,指向另一个节点。
- Run:Storage Type == 2,记录实验元数据,包括实验基本信息、实验参数和实验指标。
- Artifact:Storage Type == 2,记录实验的中间产物,也包括未发布的数据集和模型。
- AutoTune:Storage Type == 2,记录超参数调优实验数据,参考超参数调优实验。
- Model:Storage Type == 3,记录机器学习模型。
- Dataset:Storage Type == 3,记录机器学习所使用的数据集。
Artifact 没有特定的文件组织结构,用户可根据需要组织上传。
Model 和 Dataset 由 TensorStack 平台的资产管理模块,具体请参考 EM 和 AssetHub 之间的关系 。
Run 和 Autotune 是实验元数据的存储节点,具有特定的文件组织结构,EM Web 根据这些特定的文件组织结构进行实验数据的可视化。
Run 节点
Run 记录实验元数据,包括实验基本信息、实验参数和实验指标。
Run 节点中包含一个 index.yaml 文件,其中记录其他实验数据在该节点中的相对路径:
hyperparameters: hyperparameters.yaml
metrics:
train: metrics/train.yaml
val: metrics/val.yaml
test: metrics/test.yaml
platform: platform.yaml
git: git.yaml
log: stdout.log
hypterparameters
:机器学习超参数。metrics
:训练指标,由于指标可能产生自不同阶段,同一阶段也可能有多种指标,所以使用上例中的结构记录多个指标文件。platform
:平台信息,包括系统版本、python 包版本等。git
:代码存储位置,我们一半会将机器学习脚本存储在 GitHub 中。log
:日志文件。
上述文件的生成可以由 em 工具自动完成,用户只需要了解如何使用 em 工具。参考 em API 文档。
AutoTune 节点
AutoTune 记录超参数调优实验数据,包括实验的基本配置以及每一次训练的参数和指标。
AutoTune 节点的文件结构如下:
.
├── profile.json
├── 17671/
│ ├── metadata.json
│ └── metrics.yaml
...
profile.json
:记录超参数调优实验的训练配置、超参数搜索空间和调优配置等信息17671
:超参数调优过程中,每一次训练都会创建一个文件夹用来记录训练数据,文件夹名称即训练的 ID(随机生成)。metadata.json
:记录训练参数和训练状态。metrics.yaml
:记录训练指标,超参数调优创建的训练都只会产生一个指标,调优控制器会根据该指标调整超参数。
可视化
EM 支持使用以下方式对 Run 数据进行可视化:
- 数据流图:Run 和 Artifact 之间是存在使用和产出关系的,比如一次实验(Run)使用一个 Artifact 作为训练数据,最后产出另一个 Artifact。这种使用和产出关系构成了一个数据流动路线图,即数据流图。用户可以通过数据流图快速跳转到对应数据节点。
- 指标折线图
EM 支持使用以下方式对 AutoTune 数据进行可视化:
- “超参数-指标”图
- 指标优化曲线
- 各次训练的指标信息
权限管理
EM 支持节点粒度的权限控制:
- 用户可以将一个节点分享给另一个用户、用户组或者公开给所有人。
- 可分享的权限包括查看权限或编辑权限,编辑权限包含查看权限。
- 文件夹权限修改会传递给所有子节点(当用户被分享了一个文件夹的编辑权限,则该用户自动拥有文件夹中所有节点的编辑权限;取消分享同理)。
- 当一个节点被移动到另一个文件夹中,节点完全继承该文件夹的权限,覆盖节点之前的权限设置。
EM 和 AssetHub 之间的关系
AssetHub 是 TensorStack AI 平台的资产管理模块,用于管理数据集和模型。
数据集和模型作为实验的输入和输出,也应当作为实验管理的一部分,所以在 EM 中也可以看到 AssetHub 中的数据集和模型数据,如下图所示:
# EM 目录结构示意图
user:demo
└── t9k-assethub/
├── model/
│ ├── folder1
│ │ ├── model1
│ │ ...
│ ├── folder2
│ ...
└── dataset/
数据集和模型分别记录在 EM 的 ./t9k-assethub/dataset
和 ./t9k-assethub/model
文件夹中,model 文件夹(dataset 文件夹同样)维护文件夹和模型两级结构,每一个模型都是一个具有版本管理功能的节点。
下一步
- 了解如何使用 EM 追踪模型训练
账户和安全
TensorStack AI 平台提供全面、系统性的安全支持,以保障平台本身、平台提供的各种工具(例如模型构建控制台)和用户的各种工作负载(例如训练任务)的安全。
账户
账户是用户在 TensorStack AI 平台身份和权限的代表。
在使用 TensorStack AI 平台前,用户需要先联系集群管理员为其创建一个平台账户。
API Key
在使用浏览器场景下(例如使用模型构建控制台),用户能够直接、同步地参与到身份认证和授权流程。用户可以方便地通过交互式的方式提供安全凭证(用户名 + 密码)来完成认证和授权,并随后通过 Cookie + Access Token 建立安全的交互过程。
但是,还有其他环境或者场景不适合采用前述方式。例如,用户通过命令行(环境受限,无法使用浏览器)或者在自动化脚本中向服务器发送请求,此时要求“用户同步进行交互”来获得访问令牌是非常不便捷的;或者,在此过程中需要通过客户程序输入密码,可能造成密码泄漏。同时,有些场景下,我们希望能够只授予客户端部分权限,但直接使用前述 access token 或者 Cookie 并不能更进一步缩小权限。
API Key 是 TensorStack AI 平台应对上述问题的解决方案。它是一种可撤销的、异步的、持久的安全授权方式,具有以下特点:
- 可以长期持有(适合在脚本中使用)
- 不会泄漏账户信息(无需使用用户名和密码)
- 可以选择性地包含账户的部分权限
- 方便在脚本程序、命令行工具等“非交互场景”进行集成使用
- 可以随时方便地取消该授权
下一步
- 了解如何为账户生成 API Key
- 了解在不同场景使用 API Key
项目
项目(Project)是 TensorStack AI 平台为了有效使用集群资源,实现多用户、多项目同时、安全、共享使用集群而提供的机制;它是一个 CRD。
它具有以下特征:
- 每个项目有一个项目管理员,他可以管理项目的成员。
- 只有项目的管理员和成员可以在项目中执行操作。
- 每个项目对应一个同名的 Kubernetes 命名空间(Namespace),项目的成员拥有当前命名空间中几乎所有 K8s 资源的操作权限。
项目定义
以下是一个项目的定义(Custom Resource)示例:
apiVersion: tensorstack.dev/v1beta1
kind: Project
metadata:
spec:
networkPolicy:
template:
spec:
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: t9k-system
podSelector:
matchLabels:
app: security-console-server
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: t9k-system
policyTypes:
- Ingress
- Egress
useDefaultTemplate: false
quotaProfile: demo
resourceQuota:
template:
spec:
hard:
cpu: '200'
memory: 1280Gi
nvidia.com/gpu: '18'
persistentvolumeclaims: 200Gi
pods: 1k
注:普通用户(包括项目管理员)不可修改上述项目配置,这里仅用该配置进行演示和讲解。
在上述示例中:
- 该项目中设置以下网络策略:
- 该项目中的工作负载可以访问
t9k-system
命名空间中的security-console-server
服务(由字段spec.networkPolicy.template.spec.egress
字段指定)。 - 该项目中的服务可以被
t9k-system
命名空间的任一工作负载访问(由字段spec.networkPolicy.template.spec.ingress
字段指定)。
- 该项目中的工作负载可以访问
- 该项目使用
demo
资源配额模版。
资源配额与配额模版
一个项目的资源配额(由 spec.resourceQuota
字段指定)表示:当前项目中所能使用的资源上限,包括但不限于 CPU、内存、GPU 和 Pod 数量。
值得说明的一点:项目的资源配额中关于 CPU、内存、GPU、Pod 等资源数量的限制都直接作用于 Pod。即如果你创建一个 T9k Job,它即将创建的 pod 需要申请超过项目资源配额的资源数量,则 T9k Job 会被成功创建,但是 T9k Job 创建 Pod 的请求会被拒绝。
管理员可以使用配额模版批量设置或修改项目的资源配额。项目控制器会自动查找配额模版(由 spec.quotaProfile
字段指定)的内容,据此同步项目的资源配额。
网络策略
管理员可以通过项目的网络策略(由字段 spec.networkPolicy
字段指定)实现以下功能:
- 禁止普通用户访问系统级应用,避免保密信息泄漏和系统遭到恶意攻击。
- 阻断项目间通信,避免项目之间的互相干扰。
- 限定项目的访客 IP,构建安全的项目环境。
项目授权
项目授权信息存储在特定的授权服务器而非项目定义中。
普通用户(包括项目管理员)可以在安全控制台(Security Console)查看自己所在和所管理的项目以及项目的成员。
项目管理员可以通过安全控制台编辑项目成员。
项目的使用范围
项目可以被应用到 TensorStack AI 平台的模型构建、模型部署和工作流三个模块,集群管理员可以设置一个项目的使用范围。
目前项目可选的使用范围包括:
build
:用户可以在模型构建和工作流模块中使用此项目。deploy
:用户可以在模型部署模块中使用此项目。
一个项目可以同时设置上述两个使用范围。
项目成员管理
项目管理员可以在安全控制台设置项目成员:
- 项目成员可以是用户或用户组,一个用户组被设置为项目成员表示该组中的所有用户都可以使用该项目。
- 设置项目成员时,可以对每一个成员单独设置项目的使用范围,对成员设置的项目使用范围应为项目所有使用范围的子集。
下一步
- 了解项目管理员如何:添加 Project 成员
计算资源
用户在向集群提交计算任务,使用计算资源时,需要遵循管理员设置的各种策略。
- 资源配额:用户提交的工作负载需要满足集群的配额策略;
- 使用 t9k-scheduler:可能需要通过特定的 scheduler 才能使用特定的资源。
资源配额
管理员可在 Project
和 Queue
分别设置资源(CPU、Memory、GPU、Storage 等)配额。
- 针对
Project
的配额限制单个 Project 里的各种计算资源使用上限; - 设置在
Queue
上的配额则允许管理员设置特定容量的资源池供用户使用。
t9k-scheduler
t9k-scheduler
调度器专为大规模分布式并行计算及异构资源集群设计,可以更加有效地管理 AI 集群的计算资源和计算任务。相比于 K8s 的默认调度器 kube-scheduler
,t9k-scheduler
在对 AI 计算场景的支持方面进行了增强,并增加了额外的机制以对集群进行更加精细化管理。
适用场景
为并行计算性质的工作负载分配资源,当用户需要部署多个 Pod 协同工作以运行任务时,推荐使用 t9k-scheduler
。
Queue & PodGroup
t9k-scheduler
有两个重要的机制:
- Queue:
t9k-scheduler
提供 queue 让用户工作负载申请集群资源,每一个使用t9k-scheduler
的 Pod 都可指定一个 queue 为其分配资源。队列的创建/修改由集群管理员负责。 - PodGroup:PodGroup 是支持 coscheduling 机制重要组成部分。它代表一组 Pod,并定义了这组 Pod 在资源方面的限制条件。当限制条件被满足时,PodGroup 中的 Pod 才会被分配计算资源。
使用
当用户创建 Pod 使用 t9k-scheduler 时,需要进行下列操作:
- 将 Pod 使用的调度器名称设置为 t9k-scheduler;
- 设置 Pod 所属的队列。
当用户创建一组 Pod 协同完成一项任务,并使用 t9k-scheduler,需要进行下列操作 (用户一般通过使用 T9k-Job 自动化地使用 PodGroup):
- 创建一个 PodGroup,并在 PodGroup 中设置所属的队列;
- 将 Pod 使用的调度器名称设置为 t9k-scheduler;
- 设置 Pod 属于步骤一创建的 PodGroup。
下一步
使用 GPU
用户提交的工作负载,如果需要使用 GPU,需要在工作负载的计算资源配置中指定 GPU 扩展资源。
GPU 使用模式
独占使用
独占模式是指在特定时间段,GPU 卡分配给单一工作负载单独使用。
适用场景:GPU 被满负荷使用,并且计算需要尽快完成。例如 AI 模型的训练。
共享使用
共享模式是指单个物理 GPU 可以同时被多个工作负载使用。
适用场景:对于有些计算,例如交互式的 Notebook,小规模或者低使用量的模型推理服务,经常只需要使用 GPU 的部分计算能力。在这些情况下,让多个计算任务共享使用 GPU,将能极大地提高 GPU 的利用率,进而获得有益的投资回报率。
共享 NVIDIA GPU
以 NVIDIA GPU 为例,下面是 NVIDIA 提供的多种 GPU 共享和并发使用的机制,以支持不同的场景。
MPS
CUDA MPS(多进程服务 / Multi-Process Service)是 CUDA API 的客户端-服务器架构的实现,用于提供同一 GPU 同时给多个进程使用。MPS 是一个 “AI 史前”(深度学习尚未在 GPU 上运行)的方案,是 NVIDIA 为了解决在科学计算领域单个 MPI 进程无法有效利用 GPU 的计算能力而推出的技术。
与时间切片(Time Slicing)相比,MPS 通过在多个客户端之间共享一个 CUDA Context 消除了多个 CUDA 应用之间上下文切换的开销,从而带来更好的计算性能。 此外,MPS 为每个 CUDA 程序提供了单独的内存地址空间,因而可以实现对单个 CUDA 程序实施内存大小使用限制,克服了 Time Slicing 机制在这方面的不足。
优点:
- 可以控制单个应用的内存大小使用限制;
- 由于消除了多个 CUDA 应用之间 context swtich 的代价,具有更好的性能;
- 是一个 CUDA 层面的方案,不依赖于 GPU 的特定架构,支持较早的 GPU 硬件。
缺点:
- CUDA 应用之间隔离不足:单个应用的错误可以导致整个 GPU 重置(reset);
- NVIDIA 还未(截止2024/01)正式在 K8s 环境下提供支持。
Time Slicing
时间切片(Time Slicing) 也称为时间共享(Temporal Sharing)是指把多个 CUDA 程序分配到同一个 GPU 上运行,即一个简单的超额订阅(oversubscription)策略。NVIDIA 在 Pascal 架构(GP100,2016 年首发)之上提供了对此技术的支持。这些 GPU 卡上的调度器提供了指令粒度(不再需要等待 CUDA kernel 执行完成)的计算抢占(Compute Premption)技术。当抢占发生时, 当前 CUDA 程序的执行上下文(execution context:寄存器、共享内存等)被交换(swapped)到 GPU DRAM,以便另一个 CUDA 程序运行。
优点:
- 非常容易设置;
- 对分区数量无限制;
- 可在众多 GPU 架构上部署。
缺点:
- 上下文切换引起的效率降低;
- 共享 GPU 设备导致的的隔离不足、潜在的 GPU OOM 等;
- 时间片周期恒定,且无法为每个工作负载设置可用资源的优先级或大小。
MIG
MIG 可以把一个 GPU 划分为最多 7 个独立的 GPU 实例,从而为多个 CUDA 程序提供专用的 GPU 资源,包括流式多处理器 (Streaming Multiprocessors) 和 GPU 引擎。这些 MIG 实例可以为不同的 GPU 客户端(例如进程、容器或 VM)提供更加高级的故障隔离能力和 QoS。
优点:
- 硬件隔离,并发进程安全运行且互不影响;
- 在分区级别提供监控和遥测(monitoring & telemetry)数据;
- 每个分区可以叠加使用其他共享技术,例如 vGPU,time-slicing, MPS。
缺点:
- 仅在最新的 GPU 架构(Ampere, Hopper)上提供;
- 重新配置分区布局需在 GPU 空闲(驱逐所有正在运行的进程)时;
- 一些分区配置会导致部分 SM / DRAM 无法被利用。
vGPU
NVIDIA vGPU 是 NVIDIA 在数据中心提供的 GPU 虚拟化技术,它对具有完整输入输出内存管理单元 (IOMMU) 保护的 VM 提供支持,使得这些 VM 能够同时、直接地访问单个物理 GPU。
除了安全性之外,NVIDIA vGPU 还有其他优势,例如:
- 支持实时虚拟机迁移(live VM migration);
- 可设置不同的调度策略,包括 best-effort、equal-share 和 fixed-sharez:
- 当使用 fixed-share 调度器时可提供可预知的性能;
- 运行混合的 VDI (Virtual Desktop Infrastructure) 和计算工作负载的能力;
- 与业界广泛使用的虚拟机管理程序(hypervisor,如 vmware)的集成能力。
缺点:
- 部署 vGPU 需要额外的软件授权费用;
- 分区仍然通过时间片(time-slicing)完成。
扩展资源名称
如果用户想知道用户所使用的集群有哪些代表 GPU 的扩展资源名称,请咨询集群管理员。下面列举了一些常见的代表 GPU 的扩展资源。
NVIDIA GPU
当集群安装有 NVIDIA GPU 硬件资源时,通常有下列扩展资源名称:
nvidia.com/gpu
:一个扩展资源对应一个 NVIDIA GPU 硬件资源。可以申请使用多个 GPU 资源。例如当声明资源nvidia.com/gpu: 8
时,会有 8 个 NVIDIA GPU 分配给这个工作负载使用。nvidia.com/gpu.shared
:通过这个扩展资源,多个工作负载可以共享使用一个 NVIDIA GPU。需要注意,当共享机制是通过 time slicing 实现时,用户为工作负载设置nvidia.com/gpu.shared
扩展资源的数量不能超过 1(参考)。
NVIDIA 还有其他形式的设备名称,例如,当部署了 MIG 技术时,常见的资源名称有:
nvidia.com/mig-3g.20gb
:一个扩展资源对应的计算能力是物理 GPU 的 3/7,显存大小是 20GB。nvidia.com/mig-2g.10gb
:一个扩展资源对应的计算能力是物理 GPU 的 2/7,显存大小是 10GB。nvidia.com/mig-1g.5gb
:一个扩展资源对应的计算能力是物理 GPU 的 1/7,显存大小是 5GB。
AMD GPU
当集群安装有 AMD GPU 硬件资源时,通常有下列扩展资源名称:
amd.com/gpu
:一个扩展资源对应一个 AMD GPU 硬件资源。同样的,可申请多个 GPU,例如amd.com/gpu: 2
。
其他
请参考对应厂商的 device plugin 文档。
GPU 使用示例
独占 GPU
集群中部署了 NVIDIA GPU 后,一般配置扩展资源 nvidia.com/gpu
支持独占使用 GPU。
下面是一个使用 GPU 的 PytorchTrainingJob
YAML 示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: pytorch-example
spec:
replicaSpecs:
- replicas: 4
restartPolicy: OnFailure
template:
spec:
containers:
- command:
- python
- dist_mnist.py
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
resources:
limits:
nvidia.com/gpu: 4
requests:
cpu: 10
memory: 5Gi
type: worker
在该例中,spec.replicaSpecs[0].template.spec.containers[0].resources.limits
字段设置了资源量 nvidia.com/gpu: 4
,表明一个 replica 会独占使用 4 个 NVIDIA GPU。由于设置了 PyTorchTraiiningJob
的 replica 数量为 4,所以 PyTorchTraiiningJob
总共会占用 16 个 NVIDIA GPU。
共享 GPU
扩展资源 nvidia.com/gpu.shared
代表共享 GPU。
下面是一个以共享方式使用 GPU 的 Notebook YAML 示例:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
requests:
cpu: '8'
memory: 16Gi
nvidia.com/gpu.shared: 1
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu.shared: 1
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
在该例中:spec.template.spec.containers[0].resources.limits
字段定义了资源量 nvidia.com/gpu.shared: 1
,表明这个 Notebook 以共享方式使用一个 NVIDIA GPU。
指定 GPU 型号
不同节点上安装的 GPU 型号经常是不同的,同一厂家的 GPU 对应的扩展资源名称常常是相同的,例如:对于 NVIDIA GPU,在不考虑共享 GPU 的情况下,A100 和 A40 型号对应的扩展资源名称都是 nvidia.com/gpu
。
调度器为工作负载分配资源时忽略型号信息,如果用户想让工作负载使用特定型号的 GPU,例如:NVIDIA A100-80GB
、NVIDIA A40
,用户可以参考下列方式配置工作负载,使其能被分配到安装有特定型号 GPU 的节点上。
设置 nodeSelector
安装有 GPU 硬件的节点会通过节点标签来表明节点上安装的 GPU 型号。用户在创建工作负载时,可以为其设置 nodeSelector
。 nodeSelector
的作用是通过节点标签来筛选节点,从而工作负载会被分配到期望的节点上。
如果用户将工作负载的 nodeSelector
设置为指定型号 GPU 对应的节点标签,并且为工作负载设置了代表 GPU 的扩展资源数量,那么工作负载就可以使用指定型号的 GPU。
常见的节点标签
如果用户想知道用户所使用的集群有哪些表明 GPU 型号的节点标签,请咨询管理员。
下面是一些表明 GPU 型号的节点标签示例:
GPU 型号 | 节点标签 |
---|---|
NVIDIA A100-40GB | nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB |
NVIDIA A100-80GB | nvidia.com/gpu.product: NVIDIA-A100-PCIE-80GB |
NVIDIA GTX 1070 | nvidia.com/gpu.product: NVIDIA-GeForce-GTX-1070 |
NVIDIA TITAN-X | nvidia.com/gpu.product: NVIDIA-TITAN-X |
常见工作负载的 nodeSelector
字段
下面列举了常见的工作负载,以及工作负载用于设置 nodeSelector
的字段:
工作负载 | 字段 |
---|---|
GenericJob | spec.replicaSpecs[*].template.spec.nodeSelector |
PyTorchTrainingJob | spec.replicaSpecs[*].template.spec.nodeSelector |
TensorFlowTrainingJob | spec.replicaSpecs[*].template.spec.nodeSelector |
XGBoostTrainingJob | spec.replicaSpecs[*].template.spec.nodeSelector |
DeepSpeedJob | spec.worker.template.spec.nodeSelector |
ColossalAIJob | spec.worker.template.spec.nodeSelector |
MPIJob | spec.worker.template.spec.nodeSelector |
BeamJob | spec.jobTemplate.spec.template.spec.nodeSelector |
Notebook | spec.template.spec.nodeSelector |
SimpleMLService | 只有使用自定义框架时,才能通过字段 spec.custom.nodeSelector 设置 nodeSelector |
MLService predictor | spec.releases[*].predictor.template.spec.nodeSelector |
MLService transformer | spec.transformer.template..spec.nodeSelector |
Pod | spec.nodeSelector |
示例
下面是一个设置了 nodeSelector 的 notebook 示例:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial-nodeselector
spec:
type: jupyter
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
nodeSelector:
nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
在该例中:
Notebook 的资源量设置了 nvidia.com/gpu: 1
,表明 Notebook 要使用一个 GPU。
Notebook 的 nodeSelector
被设置为 nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB
,所以 Notebook 的 Pod 会被分配到含有标签 nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB
的节点上运行。
从而 Notebook 会被分配一个 NVIDIA GPU A100-40GB。
设置队列
通过 nodeSelector
机制选择特定型号的 GPU 过程繁琐,而且管理员也缺乏对 GPU 使用权限的方便控制。TensorStack 提供了更加便捷的队列机制方便用户使用特定类型的资源。
当满足下列两个要求时,用户可以通过设置队列的方法来使用特定型号的 GPU:
- 管理员为集群提供了恰当的配置。例如,设置了队列
A100
以选择安装有 A100 GPU 的计算节点; - 用户有权限使用这个队列。
用户在创建工作负载时,可以进行下列操作,选择特定型号的 GPU:
- 使用
t9k-scheduler
; - 设置合适队列名称,例如 A100;
- 设置使用 GPU 扩展资源,例如
nvidia.com/gpu
。
示例
假设管理员在集群中配置了两个队列,名称分别是:
a100
:队列可以使用的节点上都安装有 GPU NVIDIA A100-80GBa40
:队列可以使用的节点上都安装有 GPU NVIDIA A40-40GB
并且,用户有权限使用这两个队列。
如果用户想创建一个使用 NVIDIA A100-80GB 的 Notebook,用户可以创建下列 Notebook:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: tutorial
spec:
type: jupyter
scheduler:
t9kScheduler:
queue: a100
template:
spec:
containers:
- name: notebook
image: t9kpublic/torch-2.1.0-notebook:1.77.1
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
resources:
limits:
cpu: '16'
memory: 32Gi
nvidia.com/gpu: 1
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: tutorial
在该例中:
- Notebook 的资源量设置了
nvidia.com/gpu: 1
,表明 Notebook 要使用一个 GPU。 - 字段
spec.scheduler.t9kScheduler.queue
被设置为 a100,表明 Notebook 使用 T9k Scheduler 进行资源调度,并且使用队列 a100。
用户通过队列的方式使用更加简洁、方便。同时,集群管理员可使用权限等机制,更加方便地实施集群资源管理策略。
参考
K8s Extended resources
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources
Consuming extended resources
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#consuming-extended-resources
Schedule GPUs | Kubernetes
https://kubernetes.io/docs/tasks/manage-gpus/scheduling-gpus/
Device Plugins
https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/
Assigning Pods to Nodes
https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
Improving GPU Utilization in Kubernetes
https://developer.nvidia.com/blog/improving-gpu-utilization-in-kubernetes
MIG:NVIDIA Multi-Instance GPU User Guide
https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-operator-mig.html#configuring-mig-profiles
资源配额
为保证集群资源的合理分配和使用,管理员会在以下两个方面限制普通用户的资源使用(CPU、内存、GPU、Storage 等):
- 项目配额:限制用户在一个 Project(项目)中可以使用的资源总量。
- 队列配额:限制一个 Queue(队列中)的工作负载可以使用的资源总量。
用户创建的工作负载(如 T9k Job)不能超过上述两种配额的限制,否则工作负载将被拒绝接受。
队列
概述
队列(Queue)是 T9k-Scheduler 提供的集群资源管理机制。
如果使用了 T9k-Scheduler,用户创建工作负载时,则可以选择使用一个特定的 Queue 申请集群资源。
队列设置
管理员创建在集群中创建多个 Queue ,并可设置:
- Queue 的使用权限,以规定那些人员/组/项目可使用此 queue;
- Queue 对应的计算节点集合,以方便地管理计算节点的使用;
- 资源配额,限制通过此 Queue 使用的资源上限。
使用权限
Queue 的使用权限用于控制哪些用户、组、项目可以使用这个队列。队列的使用权限通过两种方式进行设置:
- 管理员直接设置有权使用队列的用户/用户组。
- 管理员设置队列的
spec.namespaceSelector
(类型是 labelSelector)字段。
当项目满足下列任一条件时,用户有权在项目下创建使用某个队列的工作负载:
- 队列设置了
spec.namespaceSelector
,并且项目对应的 namespace 的标签符合这个namespaceSelector
。 - 项目的用户有权使用这个队列。
节点限制
队列的节点限制用于指定队列可用的集群工作节点(worker node),T9k-Scheduler 只会将队列内的工作负载分配到这些特定的节点上。
队列的 spec.nodeSelector
(类型是 labelSelector)字段用于设置队列的节点权限:
- 字段未设置时,队列可以使用集群内所有的节点
- 字段设置后,队列可以使用节点标签满足 nodeSelector 的节点。
在下面的节点权限示例中:说明队列可以使用节点标签包含 topology.kubernetes.io/zone: peking
或 topology.kubernetes.io/zone: tianjin
的节点。
spec:
nodeSelector:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- peking
- tianjin
资源配额
队列的资源配额用于限制队列可以使用的资源上限,如果用户创建的工作负载(例如 Job,Pod 等)会导致队列超出资源配额限制,那么系统会拒绝接受此工作负载。
队列的 spec.quota
字段定义队列的资源配额,队列的 status.allocated
字段表明队列已经使用的资源量。
在下面的示例中:
- 工作负载的 CPU 资源请求量(
requests
)总和不能超过 40; - Queue 已经被分配了 38 个 CPU。
spec:
quota:
requests:
cpu: 40
status:
allocated:
cpu: "38"
优先级
spec.priority
字段定义队列的优先级,值类型是 int,范围是 [0,100],数值越大代表队列的优先级越高。队列的优先级会影响下列事件:
- 优先级较高的队列会被优先分配资源。
- 如果 T9k-Scheduler 开启了资源抢占行为,优先级较高的队列有权抢占低优先级队列使用的资源。
是否可被抢占资源
spec.preemptible
字段定义队列是否可以被其他队列抢占资源,字段值类型是 bool
:
false
,队列无法被抢占资源;true
,队列可以被抢占资源。
开启/关闭
spec.closed
字段定义队列是否处于关闭状态,当队列被关闭了,用户无法创建使用该队列的工作负载。字段值类型是 bool
:
- 字段未设置或被设置为
false
时,队列处于开启状态; - 字段被设置为
true
时,队列处于关闭状态。
最大运行时长
最大运行时长会限制队列中 Pod 的运行时长,如果 Pod 的存在时长(存在时长=当前时间 - Pod 创建时间)超过最大运行时长,Pod 会被删除。
队列的 spec.maxDuration
字段设置了队列的最大运行时长:
- 值类型是 string,并且需要满足正则表达式
^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$
。 - 支持的时间单位:y, w(周), d, h, m, s, ms。
- 示例:“3w”, “2h45m”。
- 未设置时,队列不受最大运行时长约束。
资源尺寸
资源尺寸(resource shape)会限制队列中工作负载请求资源量的上限,当用户创建超过资源尺寸的工作负载时,工作负载会被系统拒绝。
队列的 spec.resourceShapeProfile
字段设置了队列使用的资源尺寸模版,模型对应的资源尺寸详情存储在 ConfigMap t9k-system/resource-shapes
中。用户可以通过 T9k 产品前端查看队列的资源尺寸设置。
下一步
- 了解如何使用队列
- 队列 API Reference
PodGroup
概述
PodGroup 关联一组协同工作的 Pod,它们共同完成一项计算任务(例如分布式并行模型训练),因此需要作为一个整体来分配资源。通常情况下,用户可以通过创建 T9k Job 类的工作负载来间接使用 PodGroup,而不需要直接创建 PodGroup。
PodGroup 是 T9k 支持 coscheduling 机制的关键组成部分,可以为并行计算提供更好的支持,包括避免死锁场景和提高资源利用率。
规范
下面是一个基本的 PodGroup 示例:
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: chorus
namespace: default
spec:
minMember: 3
priority: 50
queue: default
在该例中:
- 最少运行数量是 3 个成员 Pod(由
spec.minMember
字段指定)。 - PodGroup 的优先级是 50(由
spec.priority
字段指定)。 - PodGroup 使用
default
队列(由spec.queue
字段指定)申请资源。
队列
spec.queue
设置 PodGroup 欲使用的资源队列,默认值是 default。
优先级
spec.priority
字段设置 PodGroup 的优先级 ,值类型是 int
,范围是 [0,100],默认值是 0,数值越大表明优先级越高。在同一个队列中,优先级高的 PodGroup 会被优先分配资源。
最少成员限制
成员数量限制包括两部分,必须同时满足,调度器才会为 PodGroup 分配资源:
- 最少数量(minMember);
- 角色最少数量(role minMember),但非必须字段。当未填写时,则自动满足。
最少数量
spec.minMember
设置 PodGroup 的最小运行数量,表明 PodGroup 的 Pod 数量(不包括失败的 Pod)达到最小运行数量时,调度器才会为 PodGroup 分配资源。
本文开头的示例中设置的最小运行数量是 3,但未设置角色最少数量。
角色最少数量
基于角色(role)的最小运行数量通过字段 spec.roles
的子字段设置。
spec.roles
是一个记录角色名称和该角色的最小运行数量的数组;- PodGroup 的 Pod 通过标签来指定自己的角色。
下面是一个示例:
spec:
roles:
- name: master
minMember: 1
- name: worker
minMember: 3
在该示例中,PodGroup 包含两类角色 master
和 worker
。当可运行的 master
Pod 数量达到 1,worker
Pod 数量达到 3 时,调度器才会为 PodGroup 分配资源。
状态
PodGroup 的状态记录在 status
字段中。
status.conditions
字段记录了当前 PodGroup 的状态,包括下列 2 种类型:
GroupScheduled
: PodGroup 是否已经被分配过资源SufficientGroupMember
: PodGroup 的 Pod 数量是否满足最小运行需求
status.allocated
字段记录了当前 PodGroup 使用的资源量。
PodGroup 的 Pod 的数量:
status.pending
:处于 Pending phase 的 Pod 数量status.running
:处于 Running phase 的 Pod 数量status.succeeded
:处于 Succeeded phase 的 Pod 数量status.failed
:处于 Failed phase 的 Pod 数量status.unknown
:处于 Unknown phase 的 Pod 数量
示例
下面的 YAML 片段展示了一个正常运行中的 PodGroup 的 status
字段:
allocated
:podgroup 被分配的资源总和;running
: 3 个 pod 处于 running 状态;- condition
SufficientGroupMember
为True
,表示 PodGroup 满足最小成员约束,可以被分配资源; - condition
GroupScheduled
为True
,表示整个 PodGroup 已经被分配资源;
status:
allocated:
cpu: 3
memory: 600M
conditions:
- lastTransitionTime: "2023--17T13:54:02Z"
reason: SufficientMemberPods
status: "True"
transitionID: 82ce5bf5-313d-4294-b44b-9b44ffd52213
type: SufficientGroupMember
- lastTransitionTime: "2023-12-17T13:48:16Z"
message: Resources have been allocated to PodGroup
reason: PodGroupScheduled
status: "True"
transitionID: c5a70cac-769c-44c4-a6ba-f4b1227cb135
type: GroupScheduled
running: 3
下一步
- 了解如何使用 PodGroup
- PodGroup API Reference
资源回收
一些交互式工作负载(例如 Notebook、TensorBoard 和 Explorer)的计算资源经常被闲置。例如在非工作时间,用户创建的 Notebook 服务虽然没有用户使用,但仍占用大量集群计算资源,造成资源浪费。
为充分利用集群资源,TensorStack AI 平台提供资源回收机制,自动检测并暂停空闲的 Notebook、TensorBoard 和 Explorer 等服务,释放占用的资源。
原理
以 Notebook 为例,介绍资源回收的原理(TensorBoard、 Explorer 或者其他工作负载同理)。
如上图所示:
- 集群管理员设置 “资源回收配置” 策略;
- 根据配置,Resource Keeper 监听启用回收功能的项目(Project 2)中的 Notebook 状态;
- 当 Notebook 空闲时间达到配置中规定的阈值,则 Resource Keeper 对该资源实施暂停操作,以释放资源。
状态检测
很多在 TensorStack AI 平台上运行的服务,使用 PEP Proxy 来处理身份验证和授权。由于其 proxy 所有客户端请求,这个 PEP Proxy 也可以作为检查服务是否空闲的信息来源。
对于 TensorBoard 和 Explorer,对应控制器会向 PEP Proxy 发送请求,检查其上一次请求的时间,如果给定时间内(比如 1 小时,由集群管理员配置)没有再次请求,则控制器判定其为空闲状态。
Jupyter Notebook 本身的 server 就提供了状态查询功能。因此,对于 Notebook 类型的工作负载,Notebook 的控制器会先尝试向 Notebook server 发送请求检查空闲状态。如果处于空闲或请求失败(可能 Notebook 使用的不是 Jupyter 内核,主要发生在自定义 Notebook 上),则继续向 PEP Proxy 发送请求,查询 PEP Proxy 观测到的服务使用情况:例如,如果 1 小时内(由管理员配置)没有请求,则控制器判定其为空闲状态。
对于 RStudio Notebook,目前没有空闲状态的判定,控制器将其视为永远处于活跃状态。
资源使用监控
在 Tensorstack AI 平台创建工作负载后,用户可以通过控制台或命令行工具查看工作负载的资源使用情况。
控制台
用户可以在下列控制台的工作负载的详情页面查看资源监测图表:
- 模型构建(Build Console):
- Notebook
- T9k Job
- Tensorboard
- Pod
- 模型部署(Deploy Console):
- MLService
当用户定义工作负载时可以选择性地为每个容器设定所需要的资源数量,最常见的可设定资源是 CPU、内存和扩展资源。
以 PyTorchTrainingJob 为例,用户可以查看下面几类资源的使用情况。
CPU / Memory / 扩展资源
CPU(内存)的资源监测图如下所示,图中包含三条折线:
- 请求量:工作负载声明的
resources.requests.cpu
(resources.requests.memory
) - 上限:工作负载声明的
resources.limits.cpu
(resources.limits.memory
) - 使用量:工作负载实际使用的 CPU(内存)资源量
当工作负载声明扩展资源时,显示扩展资源的资源监测图。
在本例中,PytorchTrainingJob 声明了扩展资源 nvidia.com/gpu: 2
,页面显示了工作负载声明的 resources.limits."nvidia.com/gpu"
资源量。
NVIDIA GPU
当工作负载声明的扩展资源是 nvidia.com/gpu
时,资源监测图会展示额外的 GPU 相关指标,包括:利用率、温度、功率、显存使用率、已用显存量、SM Clock、TensorCore 利用率。
下面是展示 GPU 利用率和显存使用率的图表:
网络带宽
网络带宽显示下面两项指标:
- 接收带宽:所有容器接收数据的网络带宽总计。
- 发送带宽:所有容器发送数据的网络带宽总计。
存储 I/O
存储 I/O 显示下面两项指标:
- IOPS(读+写):所有容器在节点的物理磁盘上,进行读写的操作次数之和。
- 吞吐量(读+写):所有容器在节点的物理磁盘上,读写数据的吞吐量。
命令行工具
用户可以在 Notebook 的终端中,使用 kubectl top
命令查看 Pod 的 CPU、内存使用情况。例如:
(base) [/t9k/mnt t9kuser@managed-notebook-933f6-0]
$ kubectl top pods
NAME CPU(cores) MEMORY(bytes)
managed-notebook-933f6-0 25m 153Mi
managed-project-event-ctl-854b96f4dd-f6hn8 1m 29Mi
下一步
- 监控 T9k Job 的资源使用
- 监控推理服务的资源使用
- 监控 Notebook 的资源使用(TODO: 完成
查看 Notebook 资源使用
相关用户文档)
存储
TensorStack 平台支持多种类型的存储服务:Block Storage Volumes(块存储卷),Shared Filesystem Volumes (共享文件系统卷),及基于 S3 协议的对象存储。
存储卷(Storage Volumes)
用户可申请使用两种类型的存储卷(Storage Volumes):块存储卷,或者共享文件系统卷。
这两种高性能的网络存储卷服务,可为各种类型的工作负载,如 Notebook、T9k Jobs、推理服务等提供持久化存储卷(Persistent Volumes)服务。
- 支持在集群中使用不同性能等级的存储服务。例如,管理员可设置集群同时提供高性能的 SSD 和海量的 HDD 两种等级的存储服务;
- 所有 SSD 和 HDD 等级均可创建为 Block Volumes(块存储卷)或 Shared Filesystem Volumes (共享文件系统存储卷);
- 可随时调整 Volume 大小以增加容量;
- 存储与计算分开管理,并且可以在不同实例和硬件类型之间移动;
- 支持存储卷的快照、备份及恢复。
- 可通过 UI 或 命令行工具
kubectl
轻松管理;
块存储卷(Block Storage Volumes)
Block Storage Volumes (块存储卷)可作为高性能虚拟存储盘挂载到各种类型的工作负载上。这些卷被呈现为通用 Block Device (块设备),操作系统将其视为物理连接存储设备,并且独占使用。
如果集群部署了高性能的 NVMe 的存储节点,并使用了足够快的网络,这种类型的存储卷的性能将会超过本地 SATA 接口的 SSD,并且可以扩展到 PB 级别容量。
共享文件系统卷(Shared Filesystem Volumes)
遵守 POSIX 标准的 Filesystem Volumes(文件系统卷)可以挂载到各种工作负载上,以提供原生共享文件系统。
同时,这些卷可以同时附加到多个工作负载实例上,非常适合作在 Notebook、大规模并行计算 Job、推理服务等场景的存储卷。
对象存储
平台提供基于 S3 协议的对象存储服务,支持方便、通用的数据共享机制及低成本的数据归档服务。
使用
TensorStack 的存储卷(Storage Volumes)系统支持建立在 Kubernetes 的 Storage API 基础之上,通过 API Persistent Volumes,Storage Class 等提供用户接口。
同时,为了支持一些特定场景的使用,TensorStack 提供 CRD StorageShim,Explorer 以提供扩展支持。
例 1:获得集群中的存储类型:
$ kubectl get sc
例 2:创建存储请求:
# 使用 StorageClass `generic-hdd` 的 Filesystem Volumes (文件系统卷)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-example
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
storageClassName: generic-hdd
volumeMode: Filesystem
CRD 资源
存储系统中普通用户相关的 CRD 资源,列表如下:
来源 | 说明 | |
---|---|---|
PVC | Kubernetes | 动态申请集群持久存储;用户可日常创建此 Resource 以申请存储资源 |
Storage Class | Kubernetes | 指明存储的类别;管理员创建,用户创建 PVC 时引用 |
StorageShim | TensorStack | 对各种存储系统的便捷支持,为用户自动创建 PVC;用户可日常创建此 Resource |
Explorer | TensorStack | 文件浏览器,查看和管理 PVC 中的文件 |
参考
- API reference Explorer
- API reference StorageShim
PVC(持久卷)
PVC 是一种 Kubernetes 原生资源,是对存储的需求声明,它抽象了底层存储细节,允许用户请求特定大小和访问模式的存储,而不必关心存储的具体实现。
创建 PVC
下面是一个基本的 PVC 配置示例:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: cephfs-hdd
在该例中:
spec.resources.requests.storage
字段定义了所申请的存储空间容量大小为1Gi
。spec.accessModes
字段定义了访问模式为ReadWriteMany
,表示该 PVC 能够同时被多个节点上的 Pod 使用。spec.storageClassName
字段定义了所使用的存储类名称为cephfs-hdd
,集群中可用的存储类由管理员提供。
使用 PVC
下面是在 Pod 中使用 PVC 的示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-demo
在该例中,pod-demo
将 pvc-demo
作为一个数据卷(volume)来使用,其中容器 myfrontend
将该数据卷挂载到 /var/www/html
目录下。
在 TensorStack AI 平台中,PVC 是通用的持久化存储资源,你在 Notebook、Job、MLService、Workflow 等 TensorStack 资源中都可以使用 PVC。以 Notebook 为例:
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: notebook-demo
spec:
type: jupyter
template:
spec:
containers:
- image: t9kpublic/torch-2.0.0-notebook:1.72.0
name: notebook
resources:
limits:
cpu: "4"
memory: 4Gi
requests:
cpu: "0.5"
memory: 500Mi
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: pvc-demo
在该例中,notebook-demo
将 pvc-demo
作为一个数据卷(volume)来使用,其中容器 notebook
将该数据卷挂载到 /t9k/mnt
目录下。
生命周期
PVC 有以下几种状态:
Pending
:PVC 正在由对应的存储类处理。Bound
:PVC 创建成功,可以被使用。Unknown
:无法获取 PVC 状态。
PVC 与 Pod
PVC 的生命周期独立于 Pod。一个 PVC 可以被多个 Pod 使用。当 PVC 正在被 Pod 使用时,它无法被删除。
PVC 与 StorageShim
在 TensorStack AI 平台中,你可以:
- 创建一个独立的 PVC,申请全新的存储空间。
- 创建一个 StorageShim,将已有存储系统的某个子目录挂载为一个 PVC。此时 StorageShim 控制器将为所创建的 StorageShim 创建一个同名的 PVC,此 PVC 的生命周期由 StorageShim 管理。
容量请求
创建 PVC 时,spec.resources.requests.storage
字段用于指定 PVC 的容量,你无法在 PVC 中存储超过此容量限制的文件。
访问模式
创建 PVC 时,spec.accessModes
字段用于指定 PVC 的访问模式,可选择以下几种访问模式:
ReadWriteMany
:PVC 能被多个节点上的 Pod 读写。ReadWriteOnce
:PVC 只能被一个节点上的 Pod 读写。ReadOnlyMany
:PVC 只能被多个节点上的 Pod 读。
一般选择 ReadWriteMany
即可。
存储类
创建 PVC 时,spec.storageClassName
字段用于指定 PVC 的存储类,集群中可用的存储类由管理员提供。
例如,一个集群可能提供两个存储类,名为 cephfs-hdd
和 cephfs-ssd
,分别提供基于 HDD 机械硬盘和 SSD 固态硬盘的存储空间,用于不同的数据存储目的。
下一步
PVC 快照
如果 PVC 存放了重要的数据,用户可适时制作快照(snapshot),以方便恢复。
CRD 资源
存储系统中与快照相关的 CRD 资源,列表如下:
来源 | 说明 | |
---|---|---|
PVC | Kubernetes | 动态申请集群持久存储;用户可日常创建此 Resource 以申请存储资源 |
Volume Snapshot | Kubernetes | 针对某一个 PVC 进行快照;用户可日常创建此 Resource |
Volume Snapshot Class | Kubernetes | 指明快照的类别,与 StorageClass 一一对应;管理员创建,用户创建 Volume Snapshot 时引用 |
创建快照
下面是一个基本的 PVC 配置示例:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
storageClassName: cephfs-hdd
为了对该 PVC 进行快照,用户需要创建如下 VolumeSnapshot 资源:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: pvc-demo-snapshot
spec:
volumeSnapshotClassName: cephfs-hdd-snapshotclass
source:
persistentVolumeClaimName: pvc-demo
其中:
spec.volumeSnapshotClassName
定义了所使用的快照类为cephfs-hdd-snapshotclass
,每个 StorageClass 都有对应的 VolumeSnapshotClass,由管理员负责创建;VolumeSnapshot 指定的spec.volumeSnapshotClassName
应当与 PVC 的spec.storageClassName
对应。spec.source.persistentVolumeClaimName
定义了所要快照的 PVC 名称为pvc-demo
。
创建完成后,用户可以对 PVC 中的数据进行继续修改;若需要放弃修改,则可方便地使用快照恢复到修改前的数据。
从快照中恢复
如果想将 PVC 中的数据恢复至快照创建时刻的状态,用户需要创建一个新的 PVC(之前的 PVC 仍然可以使用,两个 PVC 之间互不影响):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo-restore
spec:
accessModes:
- ReadWriteMany
dataSource:
name: pvc-demo-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
resources:
requests:
storage: 1Gi
storageClassName: cephfs-hdd
其中:
spec.accessModes
必须与原 PVC 一致。spec.dataSource
引用了所要恢复的名为pvc-demo-snapshot
的快照,本 PVC 中的数据将与该快照中的数据完全一致。spec.resources.requests.storage
必须与原 PVC 一致。spec.storageClassName
必须与原 PVC 一致。
下一步
StorageShim
StorageShim 用于将已有的存储系统以 PVC 的形式提供给用户使用,例如 S3 bucket 的某个子路径可以作为一个 PVC,分布式文件系统的某个子目录可以作为一个 PVC。通过 StorageShim,用户能够方便地访问已经上传到各类存储系统中的数据,而无需进行复制。目前支持的存储系统包括 S3 和 CephFS,未来可能支持更多的存储系统类型。
创建 StorageShim
S3 类型
下面是一个 S3 类型的 StorageShim 配置示例:
apiVersion: tensorstack.dev/v1beta1
kind: StorageShim
metadata:
name: storageshim-s3-demo
spec:
type: s3
s3:
uri: "s3://bucket/path/subpath"
readOnly: false
secretRef:
name: s3-secret-demo
其中所引用的 Secret s3-secret-demo
配置如下:
apiVersion: v1
kind: Secret
metadata:
name: s3-secret-demo
labels:
tensorstack.dev/resource: s3-cfg
stringData:
.s3cfg: <s3cfg>
在该例中,StorageShim storageshim-s3-demo
被创建后,StorageShim 控制器将创建一个同名的 PVC storageshim-s3-demo
,该 PVC 的根目录对应 S3 路径 s3://bucket/path/subpath
,访问该 S3 路径的登录凭证存储在 Secret s3-secret-demo
中,该 Secret 必须为 S3-cfg 类型。
CephFS 类型
下面是一个 CephFS 类型的 StorageShim 配置示例:
apiVersion: tensorstack.dev/v1beta2
kind: StorageShim
metadata:
name: storageshim-cephfs-demo
spec:
type: cephfs
cephfs:
path: /cephfs/data/user/mydata
client:
secretRef:
name: ceph-client-key-demo
server:
configMapRef:
name: ceph-cluster-config-demo
其中所引用的 Secret ceph-client-key-demo
配置示例如下:
apiVersion: v1
kind: Secret
metadata:
name: ceph-client-key-demo
labels:
tensorstack.dev/resource: ceph-client
stringData:
userID: <user-id>
userKey: <user-key>
其中所引用的 ConfigMap ceph-cluster-config-demo
配置示例如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: ceph-cluster-config-demo
labels:
tensorstack.dev/resource: ceph-cluster
data:
driver: <driver-name>
clusterID: <cluster-id>
fsName: <fs-name>
在该例中,StorageShim storageshim-cephfs-demo
被创建后,StorageShim 控制器将创建一个同名的 PVC storageshim-cephfs-demo
,该 PVC 的根目录对应 CephFS 文件系统的子目录 /cephfs/data/user/mydata
,访问该子目录的登录凭证存储在 Secret ceph-client-key-demo
中,该 Secret 必须为 S3-cfg 类型,该 CephFS 文件系统的相关信息存储在 ConfigMap ceph-cluster-config-demo
中。
下一步
Explorer
Explorer 提供几种展示和管理集群中数据的方法。
创建 Explorer
下面是一个基本的 Explorer 配置示例:
apiVersion: tensorstack.dev/v1beta1
kind: Explorer
metadata:
name: example
spec:
storageName: test
storageType: pvc
在该例中,Explorer 展示和管理名为 test
的持久卷(Persistent Volume)中的数据。
存储方式
Explorer 目前仅支持展示存储在 PVC 中的文件(即 spec.storageType
字段暂时只能设置为 pvc
)。
展示和管理方式
Explorer 会自动以多种方式展示和管理文件,目前支持文件浏览器和代码编辑器两种。
文件浏览器
使用第三方软件 File Browser 提供文件管理器形式的界面,支持文件系统浏览、文件上传、文件下载、基本的文件编辑等功能。
代码编辑器
使用第三方软件 VS Code 提供云端集成开发环境(IDE)的支持。开发者可以方便地运行网页版 VS Code,进行远程项目开发。
资源回收
Explorer 提供空闲资源回收的支持,在检测到 Explorer 处于空闲状态并超过一定时长时,删除工作负载以释放计算资源。默认情况下(管理员可修改配置):
- Explorer 无人使用超过 1h 后,标记该 Explorer 为
Idle
。 - Explorer 进入
Idle
状态超过 24h 后,删除该 Explorer 底层工作负载。
如果需要再次使用该 Explorer,你可以在模型构建控制台中手动点击恢复按钮。
下一步
辅助
TensorStack AI 平台提供了一些辅助性资源,它们为其他资源提供支持,或者为用户提供便捷、实用的功能。下表总结了所有辅助性资源:
资源 | 来源 | 作用 |
---|---|---|
Secret | Kubernetes | 存储敏感信息并用于配置 |
ConfigMap | Kubernetes | 存储非敏感信息并用于配置 |
Pod | Kubernetes | 运行容器,测试镜像和应用程序 |
ImageBuilder | TensorStack | 构建自定义镜像 |
Secret
Secret 是一种 Kubernetes 原生资源,用于存储少量敏感信息,比如密码、OAuth 令牌、SSH 密钥等。使用 Secret 可以避免将敏感数据直接写入到 Pod 的定义中或者应用程序代码里,从而提高了安全性。
创建 Secret
下面是一个基本的 Secret 配置示例:
apiVersion: v1
kind: Secret
metadata:
name: secret-demo
type: Opaque
data:
key1: dmFsdWUxCg==
key2: dmFsdWUyCg==
在该例中,secret-demo
存储了两对键值对,其中值经过了 base64 编码。
使用 Secret
与 PVC 类似,Secret 可以以同样的方式作为数据卷被 Pod、Notebook、Job 等资源挂载。以 PyTorchTrainingJob 为例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: pytorchtrainingjob-demo
spec:
replicaSpecs:
- type: worker
replicas: 1
restartPolicy: OnFailure
template:
spec:
containers:
- image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
command:
- python
- dist_mnist.py
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- name: data
mountPath: /data
- name: secret
mountPath: /secret
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-demo
- name: secret
secret:
name: secret-demo
在该例中,pytorchtrainingjob-demo
将 pvc-demo
和 secret-demo
均作为数据卷(volume)来使用,其中容器 pytorch
将两个数据卷分别挂载到 /data
和 /secret
目录下。因此,容器 pytorch
的 /secret
目录下将存在两个文件 /secret/key1
和 /secret/key2
,文件内容是经过 base64 解码后的对应的值。
Secret 用途
TensorStack AI 平台通过 label tensorstack.dev/resource
来标识 Secret 的用途,主要有以下几种:
- API Key:拥有 label
tensorstack.dev/resource: apikey
,用于存放 API Key,可在安全管理控制台创建 API Key。 - S3-cfg:拥有 label
tensorstack.dev/resource: s3-cfg
,用于存放 S3 配置文件的内容,可从本地的$HOME/.s3cfg
文件中获取。 - S3-env:拥有 label
tensorstack.dev/resource: s3-env
,用于存放 S3 配置文件的每个字段,请从本地的$HOME/.s3cfg
文件中获取。 - Docker:拥有 label
tensorstack.dev/resource: docker
,用于存放 Docker 配置文件的内容,可从本地的$HOME/.docker/config.json
文件中获取。 - SSH Public Key:拥有 label
tensorstack.dev/resource: ssh
,用于存放 SSH 公钥,可从本地的$HOME/.ssh/id_rsa.pub
文件中获取。 - Ceph Client:拥有 label
tensorstack.dev/resource: ceph-client
,用于存放 Ceph 客户端配置,可从管理员处获取。 - Custom:拥有 label
tensorstack.dev/resource: other
,自定义用途。
例如:
- SSH Public Key 类型的 Secret 可用于 Notebook SSH 访问
- Docker 类型的 Secret 可用于 ImageBuilder 构建并上传镜像
- S3-cfg 类型的 Secret 可用于创建 S3 类型的 StorageShim
- Ceph Client 类型的 Secret 可用于创建 CephFS 类型的 StorageShim
下一步
- 了解 Secret 的概念
- 了解 Secret 的定义
ConfigMap
ConfigMap 是一种 Kubernetes 原生资源,用于存储非机密性配置信息,它可以用来保存配置文件、命令行参数和环境变量等数据。ConfigMap使得容器化应用程序的配置与镜像内容分离,从而提高了应用的可移植性和灵活性。
创建 ConfigMap
下面是一个基本的 ConfigMap 配置示例:
apiVersion: v1
kind: ConfigMap
metadata:
name: configmap-demo
data:
key1: value1
key2: value2
在该例中,configmap-demo
明文存储了两对键值对。
使用 ConfigMap
与 PVC 类似,ConfigMap 可以以同样的方式作为数据卷被 Pod、Notebook、Job 等资源挂载。以 PyTorchTrainingJob 为例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: pytorchtrainingjob-demo
spec:
replicaSpecs:
- type: worker
replicas: 1
restartPolicy: OnFailure
template:
spec:
containers:
- image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
name: pytorch
command:
- python
- dist_mnist.py
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- name: data
mountPath: /data
- name: configuration
mountPath: /config
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-demo
- name: configuration
configMap:
name: configmap-demo
在该例中,pytorchtrainingjob-demo
将 pvc-demo
和 configmap-demo
均作为数据卷(volume)来使用,其中容器 pytorch
将两个数据卷分别挂载到 /data
和 /config
目录下。因此,容器 pytorch
的 /config
目录下将存在两个文件 /config/key1
和 /config/key2
,文件内容分别是 value1
和 value2
。
下一步
- 了解 ConfigMap 的概念
- 了解 ConfigMap 的定义
Pod
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
Pod 是一组(一个或多个)容器;这些容器共享存储、网络、以及怎样运行这些容器的声明。Pod 中的内容总是并置的并且一同调度,在共享的上下文中运行。Pod 模拟一个特定应用的“逻辑主机”,其中包含一个或多个应用容器,这些容器相对紧密地耦合在一起。在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。你也可以在集群支持临时性容器的情况下,为调试的目的注入临时性容器。
通常你不需要直接创建 Pod,甚至单实例 Pod。你会使用诸如 Deployment 或 Job 这类工作负载资源来创建 Pod。如果 Pod 需要跟踪状态,可以考虑 StatefulSet 资源。
Kubernetes 集群中的 Pod 主要有两种用法:
- 运行单个容器的 Pod:最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
- 运行多个协同工作的容器的 Pod:Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众,而另一个单独的 sidecar 容器则刷新或更新这些文件。Pod 将这些容器和存储资源打包为一个可管理的实体。
每个 Pod 都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序(例如,运行多个实例以提供更多的资源),则应该每个实例使用一个 Pod。在 Kubernetes 中,这通常被称为副本。通常使用一种工作负载资源及其控制器来创建和管理一组 Pod 副本。
Pod 示例
以下是一个 Pod 的 YAML 示例:
apiVersion: v1
kind: Pod
metadata:
name: test-sdk
spec:
containers:
- name: sdk
image: t9kpublic/t9k-sdk:0.6.0-torch-2.0.1
command:
- sleep
- inf
resources:
limits:
cpu: 500m
memory: 200Mi
在上述示例中:
- Pod 使用
t9kpublic/t9k-sdk:0.6.0-torch-2.0.1
(由spec.containers[0].image
字段指定)镜像启动容器sdk
(由spec.containers[0].name
字段指定)。 - 容器中执行
sleep inf
(由spec.containers[0].command
字段指定)命令。 sdk
容器最多可使用0.5
个 CPU 和200Mi
内存(由spec.containers[0].resources.limits
字段指定)。
应用场景
在 TensorStack AI 平台,你可以使用 Pod 实现以下操作:
- 测试镜像:在你使用 ImageBuilder 构建镜像后,可通过创建 Pod 并进入 Pod 终端来验证镜像是否符合预期。
- 存储卷预处理:在训练前,需提前下载好数据,此时可以通过创建 Pod 绑定对应 PVC,在 Pod 终端向其中下载数据。
- 测试代码:你在 Notebook 中开发后的脚本在训练镜像中并不一定能正常运行,可以用训练镜像创建一个 Pod,来测试训练脚本在新镜像中是否可用。
下一步
ImageBuilder
TensorStack 平台提供 CRD ImageBuilder
,方便用户在集群中构建容器镜像。
创建 ImageBuilder
下面是一个基本的 ImageBuilder
定义示例:
# image-builder-example.yaml
apiVersion: tensorstack.dev/v1beta1
kind: ImageBuilder
metadata:
name: imagebuilder-example
spec:
dockerConfig:
secret: docker-config
tag: t9kpublic/kaniko-executor:v1.19.2
workspace:
pvc:
name: kaniko
dockerfilePath: ./Dockerfile
contextPath: "."
builder:
kaniko: {}
在该例中:
spec.dockerConfig.secret
字段指定使用 Secretdocker-config
中记录的 docker 配置,以上传镜像。spec.tag
字段指定目标镜像的名称和标签为t9kpublic/kaniko-executor:v1.19.2
。spec.workspace
字段指定构建镜像使用 PVCkaniko
作为工作空间,其中:- 在 PVC 相对路径
./Dockerfile
中存放构建镜像所需的 Dockerfile。 - 在 PVC 相对路径
.
中存放构建镜像所需要的上下文。
- 在 PVC 相对路径
spec.builder
字段指定使用kaniko
来构建镜像。
构建工具
目前 ImageBuilder 支持使用 kaniko 工具来构建镜像。
kaniko
用户可以通过 spec.builder.kaniko
字段来设置 kaniko 的参数。
在下面示例中,ImageBuilder 使用 t9kpublic/kaniko-executor:v1.19.2
启动 kaniko,并在该容器中构建用户镜像;ImageBuilder 不额外设置 kaniko 参数。
spec:
builder:
kaniko:
image: t9kpublic/kaniko-executor:v1.19.2
args: []
spec.builder.kaniko
的参数介绍:
image
:如忽略,ImageBuilder 控制器会指定一个默认镜像,所以一般来说可以不设置该字段。args
:如忽略,ImageBuilder 构建镜像时执行kaniko --destination=[image-tag] --context=[context-path] --dockerfile=[dockerfile-path]
命令。如果用户需要使用其他参数,可以在该字段中指定。参考 kaniko additional flags。
参考
更加详细的 ImageBuilder API 可直接在集群中查询:
kubectl explain imagebuilder
下一步
- 使用控制台:构建镜像
- Github 上的 ImagerBuilder 示例
- kaniko 的详细参考
工作流
AI 应用由很多基础计算步骤构成,具有很大灵活性,在不同场景需要做各种定制计算处理。例如,一个模型训练过程可能包含数据取样、数据转换、模型训练、模型质检、模型导出等步骤。
为此 TensorStack AI 平台提供了一个灵活的工作流服务,将这些计算步骤组合在一起,集中进行管理和调度,自动化复杂的流程。
架构
工作流模块提供了 WorkflowTemplate、WorkflowRun、CronWorkflowRun 等自定义扩展资源,以及控制台、服务器、操作器等组件。整体架构如下图所示:
其中:
- 控制台(Console)提供前端界面,方便用户对 WorkflowTemplate、WorkflowRun 等资源进行创建、查看、删除等操作。
- 用户也可以直接使用命令行工具
kubectl
创建 workflow 的资源。
- 用户也可以直接使用命令行工具
- 服务器(Server)向工作流控制台提供 API 接口,帮助获取 WorkflowTemplate、WorkflowRun 等资源的详细信息。
- 控制器(Controller),负责监控集群中的 WorkflowTemplate、WorkflowRun 等资源,并执行一些与资源相关的操作,使资源当前的状态与其理想状态一致。
与其他模块的关系
如下图所示,Workflow 可以将分布式并行作业、非并行作业组合在一起成为复合作业,而且复合作业中可以嵌套复合作业,并通过 T9k 调度器进行计算资源的匹配,最终完成复杂的多步骤计算。
WorkflowTemplate
WorkflowTemplate 用于在 Kubernetes 中有序、高效、方便地组织运行各类工作负载,例如机器学习流水线中的数据处理、模型训练、推理测试等具有依赖关系的多个步骤。WorkflowTemplate 是一个静态模板,指定了任务的详细规范,最终由 WorkflowRun 实例化并真正开始运行。
创建 WorkflowTemplate
下面的 WorkflowTemplate 示例创建并运行一个 Kubernetes Pod。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: workflowtemplate-sample
spec:
description: This WorkflowTemplate creates and runs a Pod.
type: Pod
pod:
containers:
- name: hello
image: ubuntu:latest
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["echo"]
args: ["Hello TensorStack!"]
在该例中:
description
字段简要介绍了该 WorkflowTemplate 的用途,会在控制台中展示。- WorkflowTemplate 的类型(由
type
字段指定)是 Pod,表示 WorkflowTemplate 会创建并运行一个 Pod。 pod
字段定义所要创建的 Pod 的规约,指示 Pod 运行一个hello
容器,该容器运行镜像ubuntu:latest
并打印一个字符串Hello TensorStack!
。
WorkflowTemplate 类型
WorkflowTemplate 的 spec.type
字段用于指定 WorkflowTemplate 的类型,可能的取值有:
Pod
SeqPod
Resource
DAG
GenericJob
TensorFlowTrainingJob
PyTorchTrainingJob
XGBoostTrainingJob
ColossalAIJob
DeepSpeedJob
MPIJob
BeamJob
Pod WorkflowTemplate
Pod WorkflowTemplate 用于创建一个原生的 Kubernetes Pod。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: pod-workflowtemplate-sample
spec:
type: Pod
pod:
containers:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo Hello World!"]
spec.pod
中可以填写的字段与 Kubernetes Pod 相同。
SeqPod WorkflowTemplate
SeqPod WorkflowTemplate 用于创建一个经过包装的 Pod,在 Pod 中按顺序执行一些步骤。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: seqpod-workflowtemplate-sample
spec:
type: SeqPod
seqPod:
steps:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo Hello World!"]
- name: working
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo I am working!"]
- name: bye
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo Goodbye!"]
SeqPod 中的每个步骤(step)对应 Kubernetes Pod 中的一个容器,但 SeqPod 会按照顺序依次执行每个步骤,直到所有的步骤成功运行完毕,或者其中某个步骤失败(后续的步骤不会再运行)。
在 pod.containers[*].command
、pod.containers[*].args
、seqPod.steps[*].command
、seqPod.steps[*].args
等字段中,你有时候可能需要填写带有引号的字符串,有以下几种合法的方式:
command: ["echo"]
args: ["this is a 'quote'"]
command: ['echo']
args: ['this is a "quote"']
command:
- echo
args:
- this is a "quote"
command:
- echo
args:
- this is a 'quote'
指定 script
SeqPod 的每个步骤可以指定 script
字段,即一段脚本语言(例如 Bash、Python)编写的代码,用于代替 command
字段。script
脚本会在容器开始运行时代替 command
被调用,而 args
会被当做参数传递给 script
脚本。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: seqpod-workflowtemplate-sample-script
spec:
type: SeqPod
seqPod:
steps:
- name: hello
image: python
resources:
limits:
cpu: 100m
memory: 100Mi
script: |
#!/usr/bin/env python3
print("Hello from Python!")
如果 script
脚本的开头不包含以 #!
开头的字符串(shebang),以下字符串会被自动添加到 script
脚本的开头:
#!/bin/bash
set -e # Immediately exit if any command exited with non-zero status.
保留目录
为了 SeqPod WorkflowTemplate 的正常工作,最终生成的 Pod 有一些特殊的保留目录:
/t9k/workspaces
:用于挂载 workspaces,你可以通过$(workspaces.<workspaceName>.path)
来使用该路径。/t9k/results
:用于存储 results,你可以通过$(results.<resultName>.path)
来使用该路径。/t9k/tools
:用于保证 SeqPod 中steps
顺序执行的辅助工具,与用户无关。/t9k/termination
:用于写入 Pod 的 termination message,与用户无关。
Resource WorkflowTemplate
Resource WorkflowTemplate 用于创建另一个 Kubernetes 资源,并监测该资源的运行状态。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: resource-workflowtemplate-sample
spec:
type: Resource
resource:
manifest: |
apiVersion: batch/v1
kind: Job
metadata:
generateName: pi-job-
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
successRules:
fieldSelector: status.succeeded > 0
failureRules:
fieldSelector: status.failed > 3
spec.resource
的各个字段含义如下:
manifest
:所要创建的 Kubernetes 资源的详细配置。successRules
:如果所创建的资源满足该条件,本 WorkflowTemplate 视为成功。failureRules
:如果所创建的资源满足该条件,本 WorkflowTemplate 视为失败。
fieldSelector
的写法与 Kubernetes 标签选择器的语法相同但更强大,除了标签之外还能应用到资源的任意字段,支持的运算符有 >
、<
、==
、!=
、in
、notin
等,多个需要同时满足的条件可以用逗号连接。例如,以下都是合法的 fieldSelector
:
status.succeeded>0
status.succeeded > 0
status.succeeded > 0,status.failed == 0
status.phase in (Succeeded, Failed),status.workflowTemplateSpec.type == DAG
另外,successRules
和 failureRules
还支持设置 conditionSelector
。如果所创建的资源的 status.conditions
字段包含一个 condition
,其 type
和 status
都与 conditionSelector
相同,就认为该资源满足条件。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: resource-workflowtemplate-sample-condition
spec:
type: Resource
resource:
manifest: |
apiVersion: batch.tensorstack.dev
kind: TensorFlowTrainingJob
metadata:
generateName: t9k-training-job-
spec:
...
successRules:
conditionSelector:
type: Succeeded
status: "True"
failureRules:
conditionSelector:
type: Failed
status: "True"
如果所创建的资源类型是下列 T9k Jobs 之一,系统将自动帮助填写 successRules
和 failureRules
,以减轻你的负担:
- GenericJob
- MPIJob
- BeamJob
- TensorFlowTrainingJob
- PyTorchTrainingJob
- XGBoostTrainingJob
创建 Resource WorkflowTemplate 对应的 WorkflowRun 时需要提供一个 Service Account,使得 WorkflowRun 具有在 Kubernetes 中创建该 Resource 的权限。例如:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
name: resource-workflowtemplate-sample-run
spec:
workflowTemplateRef: resource-workflowtemplate-sample
serviceAccountName: managed-project-sa
在网页中创建 WorkflowRun 时,系统将自动为你配置名为 managed-project-sa
的 Service Account,你不用关心这一项的填写。
T9k Jobs WorkflowTemplate
T9k Workflow 系统对 T9k Jobs 提供更进一步的原生支持,添加以下 WorkflowTemplate 类型:
- GenericJob
- TensorFlowTrainingJob
- PyTorchTrainingJob
- XGBoostTrainingJob
- ColossalAIJob
- DeepSpeedJob
- MPIJob
- BeamJob
并在 WorkflowTemplate 的 spec
中添加了相应字段用于填写 T9k Job 的 spec
:
spec.genericJob
spec.tensorflowTrainingJob
spec.pytorchTrainingJob
spec.xgboostTrainingJob
spec.colossalaiJob
spec.deepspeedJob
spec.mpiJob
spec.beamJob
相比于在 Resource 类型中将资源的 spec
视作一个很长的字符串,添加原生类型支持的好处是在创建 WorkflowTemplate 时 T9k Job 的 spec
就会得到语法检查,能更早地发现错误,加深了 T9k Workflow 系统和 T9k Job 系统的集成配合。
例如,创建一个 MPIJob 可以使用如下格式(其中 MPIJob 示例来自 MPIJob 文档):
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: mpijob-workflowtemplate-sample
spec:
type: MPIJob
mpiJob:
spec:
worker:
replicas: 5
processesPerWorker: 3
processRecovery:
enable: true
limit: 100
cmd:
- ./random_walk
- "20"
- "40"
- "2"
template:
spec:
containers:
- name: mpi-worker
image: t9kpublic/mpi-tutorial:2021022-2
resources:
limits:
cpu: 100m
requests:
cpu: 50m
workingDir: /usr/local/code
mca:
btl: ^openib
runPolicy:
cleanUpWorkers: true
ssh:
sshdPath: /usr/sbin/sshd
mpiHome: /usr/local
DAG WorkflowTemplate
DAG WorkflowTemplate 用于创建一个由其他 WorkflowTemplate 组成的有向无环图(DAG,Directed Acyclic Graph),按照有向无环图中的依赖关系按顺序执行这些 WorkflowTemplate。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample
spec:
type: DAG
dag:
templates:
- name: a
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: []
- name: b1
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: ["a"]
- name: b2
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: ["a"]
- name: c
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: ["b1", "b2"]
在上面的示例中,首先运行 WorkflowTemplate a,等待 WorkflowTemplate a 运行完毕之后再同时运行 WorkflowTemplate b1 和 b2。WorkflowTemplate c 会在 b1 和 b2 都结束后运行。这些 WorkflowTemplates 组成一个从上往下顺序执行的有向无环图:
a
/ \
b1 b2
\ /
c
指定参数
你可以为 WorkflowTemplate 指定一些参数,并在 spec
中用 $(params.<paramName>)
来引用参数。WorkflowRun 会在运行时为这些参数提供实际值。支持 params
的 WorkflowTemplate 类型有 Pod、SeqPod、DAG,详见支持变量替换的 WorkflowTemplate 字段。
Pod WorkflowTemplate 示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: pod-workflowtemplate-sample-params
spec:
params:
- name: message
default: "hi"
type: Pod
pod:
containers:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo $(params.message)"]
SeqPod WorkflowTemplate 示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: seqpod-workflowtemplate-sample-params
spec:
params:
- name: message
default: hi
type: SeqPod
seqPod:
steps:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
script: |
#!/bin/sh
echo $(params.message)
DAG WorkflowTemplate 在引用其他的 WorkflowTemplate 作为节点时,必须提供该节点需要的 params
,可以是静态的字符串,也可以引用 DAG WorkflowTemplate 自身的 params
变量或其他变量。示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample-params
spec:
params:
- name: dag-param
type: DAG
dag:
templates:
- name: step0
workflowTemplateRef: pod-workflowtemplate-sample-params
dependencies: []
params:
- name: message
value: Hello World!
- name: step1
workflowTemplateRef: seqpod-workflowtemplate-sample-params
dependencies: ["step0"]
params:
- name: message
value: "$(params.dag-param)"
- name: step2
workflowTemplateRef: seqpod-workflowtemplate-sample-params
dependencies: ["step1"]
params:
- name: message
value: "DAG WorkflowTemplate provides param $(params.dag-param) for you"
指定工作空间
你可以为 WorkflowTemplate 指定可用的存储空间,并在 spec
中用 $(workspaces.<workspaceName>.path)
来引用存储空间的路径。WorkflowRun 会在运行时指定具体挂载何种存储空间,例如 PVC、Secret、ConfigMap 等。支持 workspaces
的 WorkflowTemplate 类型有 Pod、SeqPod、DAG。
Pod WorkflowTemplate 示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: pod-workflowtemplate-sample-workspace
spec:
workspaces:
- name: pod-workspace
type: Pod
pod:
containers:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["sh", "-c"]
args: ["echo Hello World! > $(workspaces.pod-workspace.path)/output.txt"]
SeqPod WorkflowTemplate 示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: seqpod-workflowtemplate-sample-workspaces
spec:
workspaces:
- name: seqpod-workspace
type: SeqPod
seqPod:
steps:
- name: hello
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
script: |
#!/bin/sh
echo Hello World! > $(workspaces.seqpod-workspace.path)/output.txt
DAG WorkflowTemplate 在引用其他的 WorkflowTemplate 作为节点时,必须提供该节点需要的 workspaces
,一般通过 DAG WorkflowTemplate 自身的 workspaces
继承而来。示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample-workspaces
spec:
workspaces:
- name: dag-workspace
type: DAG
dag:
templates:
- name: step0
workflowTemplateRef: pod-workflowtemplate-sample-workspace
dependencies: []
workspaces:
- name: pod-workspace
workspace: dag-workspace
- name: step1
workflowTemplateRef: seqpod-workflowtemplate-sample-workspace
dependencies: ["step0"]
workspaces:
- name: seqpod-workspace
workspace: dag-workspace
- name: step2
workflowTemplateRef: seqpod-workflowtemplate-sample-workspace
dependencies: ["step1"]
workspaces:
- name: seqpod-workspace
workspace: dag-workspace
输出结果
WorkflowTemplate 可以在运行过程中输出一些字符串,并最终展示在 WorkflowRun 的 status
中。支持 results
的 WorkflowTemplate 类型有 SeqPod、DAG。
每个 result
本质上是一个文件,如下例所示,你可以向 $(results.<resultName>.path)
这个路径写入想要输出的内容。注意写入内容的总和不能超过 4096 字节。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: seqpod-workflowtemplate-sample-result
spec:
results:
- name: my-status
description: "My status"
type: SeqPod
seqPod:
steps:
- name: echo
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
script: |
echo I am OK > $(results.my-status.path)
results
更重要的用途是在 DAG WorkflowTemplate 的节点之间传递信息。DAG 的各个节点可以通过 $(templates.<workflowtemplateName>.results.<resultName>)
来引用这些 results
,一般有两种用途:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: add-workflowtemplate
spec:
params:
- name: first
description: the first operand
- name: second
description: the second operand
results:
- name: sum
description: the sum of the first and second operand
type: SeqPod
seqPod:
steps:
- name: add
image: ubuntu
resources:
limits:
cpu: 100m
memory: 100Mi
env:
- name: OP1
value: $(params.first)
- name: OP2
value: $(params.second)
command: ["/bin/sh", "-c"]
args:
- echo -n $((${OP1}+${OP2})) | tee $(results.sum.path);
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: sum-three-workflowtemplate
spec:
params:
- name: first
description: the first operand
- name: second
description: the second operand
- name: third
description: the third operand
type: DAG
dag:
templates:
- name: first-add
workflowTemplateRef: add-workflowtemplate
params:
- name: first
value: $(params.first)
- name: second
value: $(params.second)
- name: second-add
workflowTemplateRef: add-workflowtemplate
params:
- name: first
value: $(templates.first-add.results.sum)
- name: second
value: $(params.third)
results:
- name: total-sum
description: the sum of all three operands
value: $(templates.second-add.results.sum)
- name: partial-sum
description: the sum of first two operands
value: $(templates.first-add.results.sum)
条件分支
在 DAG WorkflowTemplate 中,如果需要在某个条件满足时才执行某个节点,可以设置 when
字段。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: flip-coin
spec:
results:
- name: coin
description: Which side? Heads or tails?
type: SeqPod
seqPod:
steps:
- name: flip-coin
image: python
resources:
limits:
cpu: 100m
memory: 100Mi
script: |
#!/usr/bin/env python3
import random
f = open("$(results.coin.path)", "w")
if random.random() > 0.5:
f.write("heads")
else:
f.write("tails")
f.close()
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample-when
spec:
type: DAG
dag:
templates:
- name: flip-coin
workflowTemplateRef: flip-coin
- name: execute-only-if-heads
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: ["flip-coin"]
when:
- input: "$(templates.flip-coin.results.coin)"
operator: in
values: ["heads"]
when
字段包含一些表达式:
input
:表达式的输入,可以是静态字符串或params
、results
等变量。如果未填写,默认为一个空的字符串。operator
:表示input
和values
的关系,可以是in
或者notin
。values
:字符串数组,可以是静态字符串或params
、results
等变量。
只有当 when
字段包含的所有表达式结果都为真时,该节点才会被运行,否则会跳过该节点继续运行其他节点。
如果一个节点的 when
表达式中引用了其他节点的 results
变量,相当于引入了前者对后者的依赖关系,前者会在后者运行结束后才开始运行。
失败处理
对于 Pod/SeqPod/Resource WorkflowTemplate,一个 WorkflowRun 只对应一次运行,即使失败也不会重启。也就是说,一个 WorkflowRun 对应产生的 Pod 的 spec
中 restartPolicy
永远是 Never
。
对于 DAG WorkflowTemplate,DAG 的每个节点都有可能会失败,我们使用 retries
字段来控制节点的重启。
retries = 0
(默认选项)表示不重启失败的节点。retries > 0
表示会重启失败的节点,并用一个正整数来限制最多可重启的次数。
如果 DAG 的某个节点失败并超过了最大可重启次数,该节点将被视为永久失败,并由 spec.dag.failureStrategy
决定接下来的行为:
failureStrategy = StopAllWorkflowTemplates
(默认选项)表示停止创建任何新的节点。failureStrategy = StopDependentWorkflowTemplates
表示只停止创建依赖于失败节点的节点,其他分支上的节点正常创建。
注意无论是哪种策略,已开始运行的节点都会等待其运行结束。
在下面的 DAG WorkflowTemplate 示例中,共有两个节点 a
和 b
。
- 如果
a
节点运行失败,它最多可以重试 5 次。 - 如果
b
节点运行失败,它不能进行重试,直接被认定为失败。 - 如果任意一个节点被认定为失败,整个 DAG WorkflowTemplate 也会被认定为失败,并且由于
spec.dag.failureStrategy
字段的值为StopAllWorkflowTemplates
,所有未开始运行的节点都不再运行。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample-retries
spec:
type: DAG
dag:
failureStrategy: StopAllWorkflowTemplates
templates:
- name: a
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: []
retries: 5
- name: b
workflowTemplateRef: pod-workflowtemplate-sample
dependencies: ["a"]
retries: 0
下一步
- 了解 WorkflowRun
WorkflowRun
WorkflowRun 是 WorkflowTemplate 的一次执行,为 WorkflowTemplate 提供运行时所需的一切资源,例如参数(params
)、工作空间(workspaces
)。
创建引用某个 WorkflowTemplate 的 WorkflowRun
下面的 WorkflowRun 示例为一个 WorkflowTemplate 创建一次运行。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
name: workflowrun-sample
spec:
workflowTemplateRef: workflowtemplate-sample
在该例中,workflowTemplateRef
字段标明所要运行的 WorkflowTemplate 的名称,该 WorkflowTemplate 必须是一个已经创建好的、与该 WorkflowRun 在同一个命名空间的 WorkflowTemplate。
创建内嵌 WorkflowTemplate 规约的 WorkflowRun
下面的 WorkflowRun 示例也是为一个 WorkflowTemplate 创建一次运行,但是该 WorkflowTemplate 的规约直接在 WorkflowRun 的规约中填写。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
name: embedded-workflowrun-sample
spec:
workflowTemplateSpec:
type: Pod
pod:
containers:
- name: hello
image: ubuntu:latest
command: ["echo"]
args: ["Hello TensorStack!"]
在该例中,workflowTemplateSpec
字段用于填写所要运行的 WorkflowTemplate 的规约,WorkflowTemplate 规约的写法详见 WorkflowTemplateSpec(坏链)。
WorkflowRun 状态
在下面的示例中,首先创建一个类型为 DAG 的 WorkflowTemplate,然后创建一个 WorkflowRun 引用该 WorkflowTemplate。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: dag-workflowtemplate-sample
spec:
type: DAG
dag:
templates:
- name: a
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- a
name: b1
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- a
name: b2
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- b1
- b2
name: c
workflowTemplateRef: pod-workflowtemplate-sample
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
labels:
batch.tensorstack.dev/workflowTemplate: dag-workflowtemplate-sample
name: dag-workflowtemplate-sample-run
spec:
serviceAccountName: ''
workflowTemplateRef: dag-workflowtemplate-sample
status:
completionTime: '2021-04-16T07:39:05Z'
conditions:
- lastTransitionTime: '2021-04-16T07:39:05Z'
status: 'False'
type: Running
- lastTransitionTime: '2021-04-16T07:39:05Z'
status: 'True'
type: Completed
message: All nodes in DAG have succeeded
nodes:
a:
phase: Succeeded
workflowRunName: dag-workflowtemplate-sample-run-a-pmb2m
b1:
phase: Succeeded
workflowRunName: dag-workflowtemplate-sample-run-b1-mssn6
b2:
phase: Succeeded
workflowRunName: dag-workflowtemplate-sample-run-b2-5db66
c:
phase: Succeeded
workflowRunName: dag-workflowtemplate-sample-run-c-sjpb2
phase: Succeeded
startTime: '2021-04-16T07:38:10Z'
workflowTemplateSpec:
dag:
templates:
- name: a
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- a
name: b1
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- a
name: b2
workflowTemplateRef: pod-workflowtemplate-sample
- dependencies:
- b1
- b2
name: c
workflowTemplateRef: pod-workflowtemplate-sample
type: DAG
WorkflowTemplate dag-workflowtemplate-sample
有四个节点,分别是:
a
b1
b2
c
WorkflowRun dag-workflowtemplate-sample-run
被创建后,WorkflowRun 控制器会为这四个节点创建四个 WorkflowRun,分别是
dag-workflowtemplate-sample-run-a-pmb2m
dag-workflowtemplate-sample-run-b1-mssn6
dag-workflowtemplate-sample-run-b2-5db66
dag-workflowtemplate-sample-run-c-sjpb2
如果这四个 WorkflowRun 均运行成功,WorkflowRun dag-workflowtemplate-sample-run
即运行成功。
WorkflowRun dag-workflowtemplate-sample-run
的 status
字段显示,该 WorkflowRun 处于 Succeeded
状态(见 status.phase
字段),原因是 “All nodes in DAG have succeeded”(见 status.message
字段)。status.nodes
字段记录了该 WorkflowRun 中每个 DAG 节点的名称以及对应的 WorkflowRun 名称和状态。
下一步
- 了解如何建立自动化工作流
CronWorkflowRun
CronWorkflowRun 用于方便地定时执行 WorkflowRun,对于创建周期性的、反复重复的任务很有用。
cron 是一种书写定时计划的格式,用一个字符串指定何时触发任务的执行,通常由以空格分隔的 5 个部分组成:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
例如:
1 0 * * *
表示在每天的 00:01 执行。45 23 * * 6
表示在每个星期六的 23:45 执行。*/5 1,2,3 * * *
表示在每天的第 1、2、3 个小时每隔 5 分钟执行一次(即 01:00,01:05,01:10,…,03:55)。
注意 */n
表示每隔 n 个时间单位执行一次,在某个时间单位多次执行可以用逗号连接(例如 1,2,3
)。
为了更方便地创建 cron 表达式,可以使用第三方网页工具,例如 crontab.guru。
创建 CronWorkflowRun
下面的 CronWorkflowRun 示例会每分钟创建一个 WorkflowRun。
apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
name: cronworkflowrun-sample
spec:
schedule: "*/1 * * * *"
workflowRun:
spec:
workflowTemplateRef: workflowtemplate-sample
在该例中:
schedule
字段是一个 cron 格式的字符串,表示每分钟触发一次 WorkflowRun 的运行。- 所要运行的 WorkflowRun 由
workflowRun
字段定义,是一个引用workflowtemplate-sample
的 WorkflowRun。
详细配置 CronWorkflowRun
下面是一个经过详细配置的 CronWorkflowRun 示例,与上一节类似,也会每分钟创建一个 WorkflowRun。
apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
name: cronworkflowrun-sample
spec:
schedule: "*/1 * * * *"
startingDeadlineSeconds: 30
concurrencyPolicy: "Allow"
suspend: true
successfulRunsHistoryLimit: 10
failedRunsHistoryLimit: 10
workflowRun:
spec:
workflowTemplateRef: workflowtemplate-sample
在该例中:
- 如果某个 WorkflowRun 由于任何原因未能准时在预设的时间点开始执行,它在 30 秒钟的期限内必须开始执行(由
startingDeadlineSeconds
字段指定),否则将被认为该次执行已失败。 - 如果到了某个 WorkflowRun 应该开始执行的时间点,但是上一个 WorkflowRun 仍未运行完成,允许这两个 WorkflowRun 同时运行(由
concurrencyPolicy
字段指定)。 suspend
字段为true
表示暂时停止创建新的 WorkflowRun,该字段可以随时变化。- 由该 CronWorkflowRun 创建的所有 WorkflowRun 中,最多保留 10 个运行成功的 WorkflowRun 和 10 个运行失败的 WorkflowRun(分别由
successfulRunsHistoryLimit
和failedRunsHistoryLimit
字段指定),多余的运行时间较早的 WorkflowRun 会被删除。
CronWorkflowRun 状态
下面是 CronWorkflowRun 的状态示例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
name: cronworkflowrun-sample
spec:
schedule: "*/1 * * * *"
startingDeadlineSeconds: 30
concurrencyPolicy: "Allow"
suspend: true
successfulRunsHistoryLimit: 10
failedRunsHistoryLimit: 10
workflowRun:
spec:
workflowTemplateRef: workflowtemplate-sample
status:
active:
- apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
name: cronworkflowrun-sample-1631093400
namespace: t9k-example
resourceVersion: "220623640"
uid: 39634803-d8cf-41d4-8a8e-649e0133b11b
lastScheduleTime: "2021-09-08T09:30:00Z"
conditions:
- lastTransitionTime: "2021-09-08T09:23:00Z"
message: At least one WorkflowRun has started
status: "True"
type: HasStarted
- lastTransitionTime: "2021-09-08T09:30:00Z"
message: There are running WorkflowRuns
status: "True"
type: IsRunning
- lastTransitionTime: "2021-09-08T09:23:35Z"
message: There are successful WorkflowRuns
status: "True"
type: HasSuccessfulRun
- lastTransitionTime: "2021-09-08T09:22:08Z"
message: No failed WorkflowRuns yet
status: "False"
type: HasFailedRun
该 CronWorkflowRun 的 status
字段显示:
- 正在执行中的 WorkflowRun 有一个,其基本信息记录在
status.active
字段中。 - 最新的 WorkflowRun 的创建时间是 2021-09-08T09:30:00Z(由
status.lastScheduleTime
字段描述)。 - 在由该 CronWorkflowRun 创建的 WorkflowRun 中,已开始过至少一次 WorkflowRun(可能已结束或未结束),有正在运行中的 WorkflowRun,有已成功的 WorkflowRun,没有失败的 WorkflowRun(由
status.conditions
字段描述)。
WorkflowTrigger
TensorStack AI 平台提供了一个灵活的工作流服务,除了支持手动执行工作流 WorkflowRun,还提供了 CronWorkflowRun 用于定时执行。
Workflow Trigger 模块额外提供了一种基于特定事件自动触发执行 WorkflowRun 的能力,便于用户在一些特定场景下的自动化工作流运行。
架构
Workflow Trigger 模块提供了 EventListener 和 WorkflowTrigger 自定义扩展资源,整体架构如下图所示:
其中:
- EventListener 作为事件入口接收 JSON 格式的 HTTP POST 请求,同时将请求信息转换成 CloudEvents 格式并转发至事件队列。
- WorkflowTrigger 绑定一个或多个 EventListener 作为事件源,接收来自这些 EventListener 的 CloudEvents 格式的事件消息,并触发一个 WorkflowRun 的运行。特别地,支持对事件内容进行过滤,以及解析事件的某些字段的值填充到 WorkflowRun 的参数中。
快速开始
下面将通过几个简单的步骤来演示 Workflow Trigger 模块的基本使用方法。下面创建的所有资源请确保属于同一个命名空间。
1)创建 WorkflowTemplate
创建文件 workflow-template-sample.yaml:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: workflow-template-sample
spec:
description: This WorkflowTemplate creates and runs a Pod.
params:
- name: message
default: "TensorStack"
type: Pod
pod:
containers:
- name: hello
image: ubuntu:latest
resources:
limits:
cpu: 100m
memory: 100Mi
command: ["echo"]
args: ["Hello $(params.message)!"]
上面的示例定义了一个名为 message
的参数,同时将该参数值以 $(params.message)
的形式传递到 Pod 的容器的 args
参数上,执行下面的命令创建 WorkflowTemplate:
kubectl apply -f workflow-template-sample.yaml
该 WorkflowTemplate 将作为一个静态模版用于执行一次 WorkflowRun 的运行。
2)创建 EventListener
创建文件 event-listener-sample.yaml:
apiVersion: tensorstack.dev/v1beta1
kind: EventListener
metadata:
name: event-listener-sample
spec:
replicas: 1
执行下面的命令创建一个 EventListener:
kubectl apply -f event-listener-sample.yaml
3)创建 WorkflowTrigger
创建文件 workflow-trigger-sample.yaml:
apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
name: workflow-trigger-sample
spec:
eventSources:
- eventListenerName: event-listener-sample
replicas: 1
serviceAccountName: managed-project-sa
workflowRunSpec:
params:
- name: message
value: $(body.hello)
workflowTemplateRef: workflow-template-sample
上面的示例以 $(body.hello)
的形式将 HTTP 请求体中的 hello
字段值传递到 param message
上,执行下面的命令创建 WorkflowTrigger:
kubectl apply -f workflow-trigger-sample.yaml
4)触发事件
通过执行下面的命令来查询 EventListener HTTP 服务的访问地址:
$ kubectl get eventlisteners event-listener-sample -o json | jq .status.address
{
"inClusterURL": "http://event-listener-sample-eventlistener-2dbfe.default.svc.cluster.local",
"url": "https://<tensorstack-host>/t9k/workflow/triggers/default/event-listener-sample"
}
其中 url
字段为集群外部访问 EventListener HTTP 服务的地址,使用 curl 命令向此地址发送 HTTP 请求来模拟触发事件:
curl -X POST https://<tensorstack-host>/t9k/workflow/triggers/default/event-listener-sample \
-d '{"hello": "world"}'
其中 -d '{"hello": "world"}'
标识 HTTP 请求的 JSON 格式的 body 内容为 {"hello": "world"}
,hello
字段值 "world"
将作为参数传递到 WorkflowRun,HTTP 服务将返回 success 表示请求已经发送成功。
5)查看 WorkflowRun
上面的步骤全部执行成功以后,WorkflowTrigger 将会触发一次 WorkflowRun 的运行,通过下面的命令进行查询:
$ kubectl get workflowruns
NAME PHASE
event-listener-sample-workflow-trigger-sample-87a0d Succeeded
根据返回的结果可以看出,WorkflowRun 已经创建成功。该 WorkflowRun 将根据上面 WorkflowTemplate 静态模块的内容创建一个 Pod,通过下面的命令进行查询:
$ kubectl get po -l batch.tensorstack.dev/workflowRun=event-listener-sample-workflow-trigger-sample-87a0d
NAME READY STATUS RESTARTS AGE
event-listener-sample-workflow-trigger-sample-87a0d-pod-6stvb 0/1 Completed 0 3m23s
根据返回的结果可以看出,Pod 已经创建成功,通过查询该 Pod 日志来校验参数传递:
$ kubectl logs event-listener-sample-workflow-trigger-sample-87a0d-pod-6stvb
Hello world!
Pod 日志成功打印出 “world”
内容,其为手动触发事件中发送的 HTTP 请求的 body 内容,参数成功传递。
至此,Workflow Trigger 模块的基本使用方法已经介绍完成,阅读下面的章节来获取更详细的配置信息。
EventListener
EventListener 内部运行着一个 HTTP 服务,用于接收第三方的请求,同时将请求消息转换成 CloudEvents 并将它们转发至事件队列。当前 EventListener 只支持 JSON 格式的 HTTP POST 请求。
创建 EventListener
下面是一个基本的 EventListener 示例:
apiVersion: tensorstack.dev/v1beta1
kind: EventListener
metadata:
name: event-listener-sample
spec:
replicas: 1
resources:
requests:
memory: "100Mi"
cpu: "100m"
limits:
memory: "200Mi"
cpu: "200m"
在该例中:
replicas
字段定义所要创建的 Pod 副本数量,默认是 1。resources
字段定义每个 Pod 的资源限制,上述示例为缺省时的默认值。
EventListener 状态
通过 EventListener 的状态字段可以获取其访问地址和运行状态信息,示例如下:
status:
address:
inClusterURL: http://<eventlistener-service-name>.default.svc.cluster.local
url: https://<tensorstack-host>/t9k/workflow/triggers/default/<eventlistener-name>
conditions:
- lastTransitionTime: "2022-12-05T10:23:49Z"
message: The EventListener is Ready
status: "True"
type: Ready
其中:
status.address
表示 EventListener 所创建的 HTTP 服务的访问地址,第三方可向此地址发送请求,其中:inClusterURL
是只能从集群内部访问的地址。url
是可以从集群外部访问的地址。
status.conditions
表示 EventListener 的状态:type: Ready
表示 EventListener 是否就绪,可能的值有True
、False
、Unknown
。
WorkflowTrigger
WorkflowTrigger 从一个或多个 EventListener 事件源获取事件消息,并触发一个 WorkflowRun 的运行。
WorkflowTrigger 支持对每个 EventListener 配置过滤条件,只有符合过滤条件的事件消息才会被进一步处理;WorkflowTrigger 同时支持将事件消息的某些字段解析并填充到 WorkflowRun 的参数执行。
创建 WorkflowTrigger
下面是一个基本的 WorkflowTrigger 示例:
apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
name: workflow-trigger-sample
spec:
eventSources:
- eventListenerName: event-listener-sample
replicas: 1
resources:
requests:
memory: "100Mi"
cpu: "100m"
limits:
memory: "200Mi"
cpu: "200m"
serviceAccountName: managed-project-sa
workflowRunSpec:
workflowTemplateRef: workflow-template-sample
在该例中:
eventSources
字段定义了该 WorkflowTrigger 需要订阅事件消息的事件源集合,其中:eventListenerName
表示上述 EventListener 的名称,该 EventListener 必须与该 WorkflowTrigger 同命名空间、且已成功创建。replicas
字段定义了该 WorkflowTrigger 创建的 Pod 副本数量,默认是 1。resources
字段定义每个 Pod 的资源限制,上述示例为缺省时的默认值。serviceAccountName
字段定义了该 WorkflowTrigger 创建的 Pod 的 ServiceAccount,为创建 WorkflowRun 提供权限。workflowRunSpec
字段定义了将要创建的 WorkflowRun 的配置规约,其中:workflowTemplateRef
表示所要运行的 WorkflowTemplate 的名称,该 WorkflowTemplate 必须与该 WorkflowTrigger 同命名空间、且已成功创建。该字段同时支持内嵌 WorkflowTemplate 规约,详见 WorkflowRun。
过滤事件
WorkflowTrigger 支持对来自 EventListener 的事件消息进行过滤,只有符合过滤条件的事件消息才会被进一步处理。下面是一个包含过滤条件的 WorkflowTrigger 示例:
apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
name: filter-workflow-trigger-sample
spec:
eventSources:
- eventListenerName: event-listener-sample
filters:
- path: body.object_attributes.work_in_progress
type: bool
values:
- "false"
- path: body.labels.0.id
type: number
values:
- "219"
- "3"
- "99"
- path: body.object_kind
type: string
values:
- "merge_request"
serviceAccountName: managed-project-sa
workflowRunSpec:
workflowTemplateRef: workflow-template-sample
在该例中,spec.eventSources.filters
定义了该 EventListener 的过滤条件集合,其中:
path
表示 HTTP 请求路径,例如 header.X-Github-Event、body.pull_request.state。type
表示该路径指向字段的值的类型,当前支持 bool、number、string。values
表示该路径指向字段的值的可允许值的集合,其为 string 类型。
每个 EventListener 的 filters
互不影响,针对某一个 EventListener,其所有的 filters
必须全部通过才算符合条件。
解析参数
WorkflowTrigger 支持对来自 EventListener 的事件消息进行解析,并将指定字段的值通过参数的形式传递到 WorkflowRun。下面是一个包含解析参数的 WorkflowTrigger 示例:
apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
name: param-workflow-trigger-sample
spec:
eventSources:
- eventListenerName: event-listener-sample
serviceAccountName: managed-project-sa
workflowRunSpec:
params:
- name: bool-name
value: $(body.test.boolT)
- name: number-name
value: $(body.test.numberT)
- name: string-name
value: $(body.test.stringT)
workflowTemplateRef: workflow-template-sample
在该例中,spec.workflowRunSpec.params
定义了将创建的 WorkflowRun 的参数集合,其中:
name
表示参数名称。value
表示参数的值,可通过$()
形式从事件消息中获取指定字段的值。当前不支持$()
嵌套。
WorkflowTrigger 状态
通过 WorkflowTrigger 的状态字段可以获取其运行状态信息,示例如下:
status:
conditions:
- lastTransitionTime: "2022-12-05T10:26:46Z"
message: The WorkflowTrigger is Ready
status: "True"
type: Ready
其中:
status.conditions
表示 WorkflowTrigger 的状态:type: Ready
表示 WorkflowTrigger 是否就绪,可能的值有True
、False
、Unknown
。
操作指南
使用模型构建控制台
模型构建控制台提供了大量功能,你可以在此进行模型构建,并管理 Job、存储和辅助资源。本部分将演示如何在模型构建控制台中使用 Notebook 和 TensorBoard,构建和调试镜像,以及管理存储、配置和隐私信息。
对于如何使用 T9k Job 和 AutoTune,请分别参阅运行模型训练和进行超参数优化。
创建 Notebook
本教程演示如何创建 Notebook。
准备工作
创建 PVC
创建 Notebook 时,需要至少绑定一个 PVC 来存储代码、数据等文件。如果你的项目中已有合适的持久卷,则可以直接进入下一节。
在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入 PVC 管理页面。然后点击右上角的创建 PVC 进入创建页面:
在 PVC 创建页面,名称填写 create-notebook
,存储填写 1Gi
,其他参数保持默认值,然后点击创建:
创建标准的 Notebook
在模型构建控制台的左侧导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击右上角的创建 Notebook 进入创建页面:
在 Notebook 创建页面,如下填写各个参数:
- 名称填写
create-notebook
。 - 存储卷选择上一节创建的
create-notebook
(或其他合适的存储卷)。存储卷会被挂载到 Notebook 的/t9k/mnt
目录下。 - 镜像根据你想使用的机器学习框架(如 TensorFlow、PyTorch 等)及其版本选择一个标准 Notebook 镜像。
- 模版根据你的资源需求选择一个合适大小的资源模版。
其他参数保持默认值,完成之后,点击创建:
回到 Notebook 管理页面查看新创建的 Notebook:
Notebook 就绪后,就可以使用 Notebook。
其他配置
使用 T9k 调度器
计算资源模块还提供了选项,使用调度器 t9k-scheduler
,以支持便捷的资源使用申请,使用 t9k-scheduler
调度任务时必须指定一个队列。相比默认调度器,t9k-scheduler
需要额外填写如下参数:
队列 (queue)
:必填,选择一个队列(如果没有队列,请联系管理员创建一个队列)。优先级 (priority)
:可选,默认值是 0。代表任务在队列内部的优先级。当发生资源抢占时,优先级数字较小的工作负载会比同一个队列中的其他负载优先被驱逐。
使用数据卷
可以为 Notebook 绑定额外的数据卷(存放数据的 PVC),如下图所示:
每绑定一个数据卷需要填写如下参数:
名称
:使用的 PVC 名称。绑定路径
:将 PVC 绑定到 Notebook 的指定路径下。
在上图的示例中,我们将 PVC examples
绑定到了 Notebook 的 /t9k/examples
路径下。你可以在 Notebook 中通过对应路径访问 PVC 中的数据。
启用 SSH 选项
如果你想使用 SSH 连接到 Notebook 容器中来管理其中的文件,或者使用本地的 IDE 来编辑 Notebook 中的代码,启用 SSH 能够帮助你在 Notebook 中运行一个 SSH 服务。
Notebook 的 SSH 服务只允许通过密钥对进行验证,因此你需要上传公钥以使用 SSH 连接。TensorStack AI 平台使用 Secret 存储公钥信息。如果你已经创建了包含公钥的 Secret,则可以直接进入下一节。
在模型构建控制台的左侧导航菜单中点击辅助 > Secret,然后点击右上角的创建 Secret 进入的创建页面:
在 Secret 创建页面,选择类型为 SSH Public Key,填写名称和公钥内容。最后点击创建 Secret 进行创建:
创建 Notebook 时,开启启用 SSH 按钮,然后选择前面创建的 Secret(此处为一个多选框,你可以同时设置多个 SSH 公钥):
点击创建,等待运行之后,你可以通过 SSH 连接远程使用 Notebook。
使用 Notebook
本教程演示如何使用 Notebook 进行模型开发相关的工作。
打开 JupyterLab
在模型构建控制台的左侧导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击运行中的 Notebook 右侧的打开:
进入到 JupyterLab 的页面:
使用 Jupyter Notebook
点击 Launcher 标签页下,Notebook 下方的 Python3 图标以创建 Jupyter Notebook:
Jupyter Notebook 提供了交互式的 Python 开发环境。你可以在这里分块编辑并运行 Python 代码。比如运行 keras_mnist.py
:
from tensorflow.keras import callbacks, datasets, layers, models, optimizers
model = models.Sequential([
layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
layers.MaxPool2D((2, 2)),
layers.Conv2D(64, 3, activation='relu'),
layers.MaxPool2D((2, 2)),
layers.Conv2D(64, 3, activation='relu'),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax'),
])
model.compile(optimizer=optimizers.Adam(learning_rate=0.001),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
(train_images, train_labels), (test_images,
test_labels) = datasets.mnist.load_data()
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))
train_images, test_images = train_images / 255.0, test_images / 255.0
model.fit(train_images,
train_labels,
batch_size=32,
epochs=5,
validation_split=0.2)
model.evaluate(test_images, test_labels)
编辑文件
在左侧的文件系统导航菜单空白处右击,可以创建文件和目录:
创建名为 keras_mnist.py
的文件,双击以进行编辑。复制上文中 keras_mnist.py
的内容,粘贴在文本编辑器中并保存:
使用 Terminal
点击左上角蓝色底色的 + 符号打开新的 Launcher 标签页,然后点击 Other 中的 Terminal 进入命令行终端。你可以在这里运行各种 bash 命令,例如运行 python ./keras_mnist.py
来进行模型训练:
查看详情
在 Notebook 管理页面,点击 Notebook 的名称进入其详情页面:
Notebook 的详情页面展示了 Notebook 的基本信息、状况和事件。点击 Pod 右侧的链接可以查看 Pod 的日志、状况、事件、资源监测等信息:
查看日志
点击日志,查看 Notebook Pod 的运行日志:
查看资源监测
点击资源监测,查看 Notebook Pod 运行时实际使用的资源,包括 CPU、内存、存储 I/O 的使用量:
通过 SSH 远程使用 Notebook
本教程演示如何通过 SSH 连接远程使用 Notebook。
准备
- 创建了一个启用 SSH 选项的 Notebook。
- 确认该 Notebook 处于正常运行状态。
端口转发
命令行工具 t9k-pf
命令行工具 t9k-pf 的功能类似于 kubectl port-forward
,可以让用户能够在本地通过端口转发的方式访问 TensorStack AI 平台的各种资源。
请参照用户指南,下载安装 t9k-pf 并配置身份认证和授权。
端口转发命令
在 Notebook 详情页面,查看并复制SSH 服务提示的命令:
在终端执行该命令以进行端口转发:
$ t9k-pf notebook <URL> <Port>
now you can forward to your target by 127.0.0.1:<Port>
参数说明如下:
URL
:Notebook 的 Web UI 地址。除上述获取方式外,你也可以在打开 Notebook 后,复制浏览器地址栏中的地址作为URL
参数使用。Port
:转发的本地端口。在 SSH 远程连接教程中会使用到该端口。
根据终端打印的提示信息,使用本地的端口与目标 Notebook 建立 SSH 连接,具体命令请参阅 SSH 远程连接。
建立 SSH 连接
使用终端
在终端中运行以下命令以连接到 Notebook:
ssh t9kuser@localhost -p <Port> \
-o StrictHostKeyChecking=no \
-o GlobalKnownHostsFile=/dev/null \
-o UserKnownHostsFile=/dev/null
然后在终端中操作 Notebook:
使用 VSCode
安装 Remote SSH 插件
在 VSCode 中搜索 Remote - SSH 插件并安装:
添加 SSH Config
安装完成后,需要在 SSH Config 中添加主机(Notebook)的信息。
VSCode 提供了编辑 SSH Config 的方式。点击左下角的绿色 >< 符号,选择 Connect to Host,然后拉动滚动条到最下方,点击 Add New SSH Host:
根据提示,输入以下内容,然后按下回车键(Enter):
ssh t9kuser@localhost -p <Port>
VSCode 会提示 Select SSH configuration file to update,第一个选择项通常是位于 $HOME/.ssh/config
的配置文件,你可以选择将主机的信息存储在第一个配置文件中。
连接到 Notebook
点击左下角的绿色 >< 符号,选择 Connect to Host:
然后选择 SSH Config 中对应的主机名(使用上述配置方式时,主机名为 localhost
):
VSCode 会新建一个窗口,等待连接建立之后,左下角会提示 SSH: Host。
点击 Open Folder 可以选择打开的目录或者文件。你可以和本地开发一样使用 VSCode 来操作 Notebook:
使用 PyCharm
使用 PyCharm 远程连接到 Notebook 需要满足以下前提条件:
- 安装了 PyCharm 专业版,且版本不低于 2022.2。PyCharm 有专业版(Professional)和社区版(Community),目前仅 PyCharm Professional 支持远程 SSH 开发。
- Notebook 的资源配置至少为 3 个 CPU,3 GiB 内存,Notebook 绑定的持久卷至少有 2.5 GiB 的可用空间。推荐配置为至少 4 个 CPU,4 GiB 内存,5 GiB 持久卷。
打开 PyCharm,在左侧的导航菜单中点击 Remote Development > SSH,然后点击右侧的 New Connection:
在弹出的对话框中填写如下参数:
Username
:SSH 使用的用户名。Host
:主机地址,通常为127.0.0.1
。Port
:端口。Specify private key
:建议勾选,并选择与你上传的公钥对应的私钥。
点击 Check Connection and Continue,进入下一步:
这里选择了在 Notebook 中安装的 IDE Backend 版本为 PyCharm 2022.2.3,远程打开的项目目录为 /t9k/mnt
。点击 Download IDE and Connect 后,就可以通过 PyCharm 访问 Notebook 中的文件了。
你可以和本地开发一样使用 PyCharm 来操作 Notebook:
参考
- https://code.visualstudio.com/docs/remote/ssh
- https://www.jetbrains.com/help/pycharm/remote-development-overview.html
创建 TensorBoard
本教程演示如何创建 TensorBoard。
准备工作
- 了解 TensorBoard 的基本概念。
- 成为一个项目的管理员或成员。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
查看训练指标
TensorBoard 处于 Running
状态后,进入模型构建控制台的 TensorBoard 页面,可以看到 TensorBoard tensorboard
正在运行:
点击 TensorBoard 右侧的 打开 进入 TensorBoard 页面,查看可视化展示的训练和验证指标:
构建镜像
本教程演示如何在平台上构建容器镜像(container image)并推送到指定的容器镜像仓库(container registry)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
其中,创建包含身份信息的 Secret 这一步骤也可以在模型构建控制台中通过创建 Docker
类型的 Secret 来完成,如下图所示。详情请参阅创建 Secret。
检查构建进度和结果
在模型构建控制台的左侧导航菜单中点击构建 > Image Builder,然后点击刚创建的 Image Builder 右侧的详情,查看其详情和日志。拉取基础镜像、构建镜像和推送镜像都需要花费一定的时间,请耐心等待。
一段时间后,构建完成的镜像被推送到相应的 registry 中。
FAQs
Unpacking rootfs
失败
使用 ImageBuilder 制作镜像时,有时会出现类似以下的错误:
INFO[0009] Unpacking rootfs as cmd RUN apt-get -qq update && apt-get -qq install --no-install-recommends -y curl requires it.
error building image: error building stage: failed to get filesystem from image: stream error: stream ID 17; PROTOCOL_ERROR; received from peer
但是该错误信息并不准确,经分析,实际导致镜像 build 失败的可能原因是:镜像(Dockerfile 中 FROM 语句所引用的镜像)提取失败。
提取失败可能有以下原因:
- 镜像来源于无法访问或下载速度过慢的仓库
解决方法:
- 切换到服务质量更好的的 Registry,例如本地网络部署的私有化 Registry,或其他 caching Regisry。
- 使用代理服务器,通过该代理下载镜像。
调试镜像
本教程演示如何方便地在模型构建控制台通过命令行进入一个镜像,以便对镜像进行探索和测试。
准备工作
示例
假设我们想知道镜像 t9kpublic/tensorflow-2.11.0-notebook-cpu:1.70.0
中安装了哪些 pip 包。
进入模型构建控制台后,点击构建 > Pod 进入 Pod 管理页面。
点击右上角的创建以创建一个 Pod,执行 sleep
命令使镜像保持运行状态,以便我们连接镜像中的 bash
(或 sh
)终端。
分别填写项目名称、镜像名称、运行命令和资源使用量,然后点击创建。
所创建的 Pod 变为运行状态后,点击 Pod 名称进入 Pod 详情页面。
点击终端按钮,打开终端。
在打开的终端中,输入 pip list
显示该镜像中安装的所有 pip 包,或者输入其他任何命令。
最后,点击右上角的 X 关闭终端。
管理 PVC
本教程演示如何在模型构建控制台中管理和使用 PVC。
准备工作
- 了解 PVC 的概念和 Kubernetes API。
- 成为一个项目的管理员或成员。
创建 PVC
进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击存储 > 持久卷进入 PVC 管理页面。
点击 PVC 管理页面右上角的创建 PersistentVolumeClaim 进入 PVC 创建页面。
在 PVC 创建页面填写名称和存储卷大小,选择存储卷访问模式和存储类,然后点击创建。
你可以点击左上角的导入 PersistentVolumeClaim 以加载当前存在的 PVC 的配置。
删除 PVC
在 PVC 管理页面,点击要删除的 PVC 右侧的更多按钮 > 删除。
使用 Explorer
本教程演示如何使用 Explorer 查看和修改存储在 PVC 和 StorageShim 中的文件。
启动 Explorer
在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入 PVC 管理页面,点击 PVC 右侧的启动:
将光标悬停在打开上,等待 File Browser 和 VS Code 就绪。随后点击 File Browser 和 VS Code 即可进入。
使用 File Browser
进入 File Browser 的前端页面,我们可以看到 PVC 中的所有文件和目录:
这里支持以下操作:
- 浏览目录和文本文件
- 创建、删除、重命名、复制、移动目录和文件
- 上传、下载文件
- 修改文本文件
使用 VS Code
进入 File Browser 的前端页面,我们可以看到 PVC 中的所有文件和目录:
这里支持以下操作:
- 浏览目录和文本文件
- 创建、删除、重命名、复制、移动目录和文件
- 修改文本文件,进行轻量级代码修改
- 启动终端并执行命令
- 进行源代码控制
- 安装 VS Code 插件
暂停和关闭 Explorer
使用结束后,我们可以关闭 Explorer。之后重新启用即可。
使用 StorageShim 适配 S3 服务
概述
TensorStack AI 平台支持用户在多个环节使用 S3 协议的存储服务。本教程演示如何通过 StorageShim 把 S3 存储服务转换成 PVC,以方便在一些需要使用 POSIX 文件系统接口的场景。
本教程涉及如下基本概念:
- S3(Simple Storage Service)提供可扩展、安全、高可用的对象存储服务,可以存储和检索任意数量和类型的数据,包括文档、图片、视频、音频等。更多详细信息请参阅附录。
- PVC(PersistentVolumeClaim)是 Kubernetes 提供的一种声明式的存储卷请求,用于向 Kubernetes 集群申请持久化存储卷。PVC 使应用程序与存储资源解耦,提高了存储资源的管理和使用效率。
- StorageShim 提供了把 S3 服务转换为 PVC 的能力,让用户能够以 Kubernetes 原生的方式使用 S3。
详细过程
要访问 S3 服务,需要提供使用其服务的相应配置,包括:
- S3 访问凭证:用于访问 S3 服务的一组密钥,包括访问密钥(access key)和秘密访问密钥(secret key)。S3 访问凭证是必需的,以在访问 S3 服务时进行身份验证和授权。
- S3 服务的终端地址(endpoint):HTTP 或 HTTPS 格式的地址,例如:
http://100.1.1.2:8000
。 - S3 bucket:存储用户数据的容器;访问特定的 bucket 需要有合适权限的访问凭证。
准备 S3 配置
以下面的格式准备一个名为 s3cfg
的文件:
[default]
# Setup access keys
access_key = <you-access-key>
secret_key = <your-secret-key>
# Setup endpoint
host_base = http[s]://<host-or-ip>:<port>
use_https = <False | True>
其中需要修改的内容包括:
access_key
:你的访问密钥(access key)。secret_key
:你的秘密访问密钥(secret key)。host_base
:S3 服务的地址(endpoint)。use_https
:是否使用 HTTPS。
你可以安装 s3cmd,在本地运行命令来验证 s3cfg 是否正确配置:
s3cmd -c s3cfg ls s3://<my-bucket>
创建 Secret
通过控制台
进入模型构建控制台,选择左侧导航菜单的辅助 > Secret,点击创建 Secret。
选择类型为 S3-cfg,填写名称,然后填写 Details 的内容:
- 服务端点:S3 服务的地址(endpoint)
- Access Key ID:你的访问密钥(access key)。
- 密码:你的秘密访问密钥(secret key)。
最后点击创建 Secret:
通过命令行工具
用户也可以使用 kubectl
命令行工具创建 Secret:
kubectl -n <project> create secret generic <s3cfg-secret> \
--from-file=.s3cfg=<s3cfg>
其中需要修改的内容包括:
<project>
:项目名称。<s3cfg-secret>
:Secret 的名称。<s3cfg>
:本地s3cfg
文件的路径。前面的--from-file=.s3cfg=
不需要修改。
验证
运行以下命令,查看 Secret 中保存的 .s3cfg
内容:
kubectl -n <project> get secret <s3cfg-secret> \
-o jsonpath={.data."\.s3cfg"} | base64 -d
其中需要修改的内容包括:
<project>
:项目名称。<s3cfg-secret>
:Secret 的名称。
对比输出内容与你本地的 s3cfg
,确认内容一致,重点是 access_key
、host_base
和 secret_key
字段。
创建 StorageShim
通过控制台
进入模型构建控制台,选择左侧导航菜单的存储 > 持久卷,点击上方的 S3,然后点击右上角的创建 StorageShim:
输入持久卷名称、S3 URI(s3://<your-bucket>
),然后选择 S3 Secret 名称,最后点击右上角的创建 StorageShim 完成创建:
在 S3 标签页查看新创建的 StorageShim:
通过命令行工具
使用以下命令创建 StorageShim 类型的 PVC:
kubectl -n <project> create -f - <<EOF
apiVersion: tensorstack.dev/v1beta1
kind: StorageShim
metadata:
name: dataset
spec:
readOnly: false
s3:
uri: 's3://42a3de90-d9e7-4769-8fc4-48a65fb561d5'
secretRef:
name: s3cfg-secret
EOF
其中需要修改的内容包括:
<project>
:项目名称。.spec.s3.uri
:S3 bucket 的路径,你也可以具体指定 bucket 中的一个文件夹。.spec.secretRef.name
:保存 S3 凭证的 Secret 名称。readOnly
:如果为 true,那么用户只能读取这个 StorageShim 的内容,而不能修改它。
查看 PVC 状态,确认 STATUS 为 Bound:
$ kubectl -n <project> get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
dataset Bound pvc-cc7f789a-6fcb-44a0-8f42-0e6c86e51a1a 1 RWX csi-s3 4m5s
附录
S3 基本概念
S3(Simple Storage Service)提供了可扩展、安全、高可用的对象存储服务,可以存储和检索任意数量和类型的数据,包括文档、图片、视频、音频等。
S3 使用:
- Bucket:Bucket 是 S3 存储中的基本容器,类似于文件夹,用于存储和组织对象。每个 Bucket 必须具有唯一的名称,并且名称必须符合 DNS 命名规则。
- Object:Object 是 S3 存储中的基本数据单元,可以是任意类型的数据,例如文档、图片、视频、音频等。每个 Object 由一个唯一的键(Key)和一个值(Value)组成,键是 Object 在 Bucket 中的唯一标识符,值是 Object 的实际数据。
S3 管理:
- Region:Region 是 S3 存储的物理位置,用于指定 Bucket 存储的地理位置。每个 Region 都由多个可用区域(Availability Zone)组成,以提供高可用性和容错性。
- ACL:ACL(Access Control List)是 S3 存储的访问控制列表,用于控制 Bucket 和 Object 的访问权限。ACL 可以指定特定用户或组的访问权限,也可以指定公共访问权限。
- Versioning:Versioning 是 S3 存储的版本控制功能,用于保留 Object 的所有版本。启用版本控制后,每次更新 Object 时都会创建一个新版本,并可以通过指定版本号来访问特定版本的 Object。
- Lifecycle:Lifecycle 是 S3 存储的生命周期管理功能,用于自动化管理 Bucket 和 Object 的生命周期。Lifecycle 可以指定 Object 的存储期限、转换存储类别、自动删除 Object 等操作,以优化存储成本和管理效率。
S3 基本使用:s3cmd
有多种工具(s3browser、WinSCP、s3cmd、s5cmd、rclone 等)可以访问 S3 存储服务,以下使用 s3cmd 演示 S3 的基本操作:
安装 s3cmd 工具:在 Linux 系统中使用命令行安装 s3cmd 工具,例如在 Ubuntu 系统中可以使用以下命令进行安装:
sudo apt-get install s3cmd
配置 s3cmd 工具:在命令行中执行 s3cmd --configure
命令,按照提示输入 S3 访问密钥和秘密访问密钥,以及 S3 服务的访问地址和区域等参数,完成 s3cmd 工具的配置。
创建 S3 存储桶:使用 s3cmd mb 命令创建 S3 存储桶,例如:
s3cmd mb s3://my-bucket-name
上传对象:使用 s3cmd put 命令上传对象到 S3 存储桶中,例如:
s3cmd put /path/to/local/file s3://my-bucket-name/path/to/remote/file
下载对象:使用 s3cmd get 命令从 S3 存储桶中下载对象到本地,例如:
s3cmd get s3://my-bucket-name/path/to/remote/file /path/to/local/file
删除对象:使用 s3cmd del 命令从 S3 存储桶中删除对象,例如:
s3cmd del s3://my-bucket-name/path/to/remote/file
设置对象 ACL:使用 s3cmd setacl 命令设置对象的 ACL,例如:
s3cmd setacl --acl-public s3://my-bucket-name/path/to/remote/file
对象存储(object storage)
对象存储是一种将数据存储为对象的数据存储架构,这与文件系统将数据作为文件层次结构进行管理不同。 每个对象通常包括数据本身(object)、元数据(metadata)和全局唯一标识符(object key)。
对象存储是存储海量非结构化数据(例如图像、视频和文档)的不错选择,例如大规模机器学习中使用的海量训练数据、特征、模型等。
与其他存储架构相比,对象存储具有许多优势,包括:
- 可扩展性:对象存储可以轻松扩展以满足不断增长的应用程序的需求。
- 耐用性:对象存储被设计成高度耐用的,数据以冗余方式存储在多个位置。
- 可用性:对象存储旨在提供高可用性,可以从世界任何地方访问数据。
- 安全性:对象存储提供了许多安全功能,包括加密和访问控制。
对象存储是一种强大而灵活的数据存储架构,是存储大量非结构化数据、需要从多个位置访问的数据以及需要高可用性和安全性的数据的不错选择。
参考
- Wikipedia: S3 协议
- Wikipedia: 对象存储
- AWS: S3 (Simple Storage Service)
- Kubernetes: PVC(PersistentVolumeClaim)
管理 Secret
本教程演示如何在模型构建控制台中管理和使用 Secret。
准备工作
- 了解 Secret 的概念和 Kubernetes API。
- 成为一个项目的管理员或成员。
创建 Secret
进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击辅助 > Secret 进入 Secret 管理页面。
点击 Secret 管理页面右上角的创建 Secret 进入 Secret 创建页面。
在 Secret 创建页面选择模板,填写名称和要存储的数据,然后点击创建。
你可以点击左上角的导入 Secret 以加载当前存在的 Secret 的配置。
删除 Secret
在 Secret 管理页面,点击要删除的 Secret 右侧的更多按钮 > 删除。
管理 ConfigMap
本教程演示如何在模型构建控制台中管理和使用 ConfigMap。
准备工作
- 了解 ConfigMap 的概念和 Kubernetes API。
- 成为一个项目的管理员或成员。
创建 ConfigMap
进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击辅助 > ConfigMap 进入 ConfigMap 管理页面。
点击 ConfigMap 管理页面右上角的创建 ConfigMap 进入 ConfigMap 创建页面。
在 ConfigMap 创建页面填写名称、标签和要存储的数据,然后点击创建。
你可以点击左上角的导入 ConfigMap 以加载当前存在的 ConfigMap 的配置。
删除 ConfigMap
在 ConfigMap 管理页面,点击要删除的 ConfigMap 右侧的更多按钮 > 删除。
运行模型训练
这一部分演示如何使用 T9k Job 运行不同机器学习框架的模型训练任务。对于常用的机器学习框架,如 PyTorch、TensorFlow、Horovod,你都可以在这里找到相应的教程来帮助你开始训练模型。
使用 PyTorchTrainingJob 进行数据并行训练
本教程演示如何使用 PyTorchTrainingJob 对 PyTorch 模型进行多工作器同步训练(使用 torch.nn.parallel.DistributedDataParallel
分布式数据并行模块)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-trainingjob 的 PyTorchTrainingJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 PyTorchTrainingJob 的基本信息、状况信息和事件信息:
点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:
点击上方标签页的副本,查看 PyTorchTrainingJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的资源监测,查看 PyTorchTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,PyTorchTrainingJob 的状态变为 Succeeded,表示训练成功完成。
若 PyTorchTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 PyTorchTrainingJob 进行参数服务器训练
本教程演示如何使用 PyTorchTrainingJob 对 PyTorch 模型进行基于 RPC 的参数服务器训练(使用分布式 RPC 框架 torch.distributed.rpc
)。示例修改自 PyTorch 官方教程 Implementing a Parameter Server Using Distributed RPC Framework,关于训练脚本的更多细节信息请参考此教程。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-trainingjob-ps 的 PyTorchTrainingJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 PyTorchTrainingJob 的基本信息、状况信息和事件信息:
点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:
点击上方标签页的副本,查看 PyTorchTrainingJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的资源监测,查看 PyTorchTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,PyTorchTrainingJob 的状态变为 Succeeded,表示训练成功完成。
若 PyTorchTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 TensorFlowTrainingJob 进行数据并行训练
本教程演示如何使用 TensorFlowTrainingJob 对 Keras 模型进行数据并行训练(采用 tf.distribute.MultiWorkerMirroredStrategy
分布式策略)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-trainingjob 的 TensorFlowTrainingJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 TensorFlowTrainingJob 的基本信息、状况信息和事件信息:
点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:
点击上方标签页的副本,查看 TensorFlowTrainingJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的资源监测,查看 TensorFlowTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,TensorFlowTrainingJob 的状态变为 Succeeded,表示训练成功完成。
若 TensorFlowTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 TensorFlowTrainingJob 进行参数服务器训练
本教程演示如何使用 TensorFlowTrainingJob 对 Keras 模型进行参数服务器(parameter server)训练(采用 tf.distribute.experimental.ParameterServerStrategy
分布式策略)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-trainingjob-ps 的 TensorFlowTrainingJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 TensorFlowTrainingJob 的基本信息、状况信息和事件信息:
点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:
点击上方标签页的副本,查看 TensorFlowTrainingJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的指标,查看 TensorFlowTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,TensorFlowTrainingJob 的状态变为 Succeeded,表示训练成功完成。
若 TensorFlowTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 Horovod 进行 PyTorch 模型的数据并行训练
本教程演示如何使用 MPIJob 对 PyTorch 模型进行多工作器同步训练(使用 horovod.torch
模块)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-mpijob 的 MPIJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 MPIJob 的基本信息、状况信息和事件信息:
点击上方标签页的副本,查看 MPIJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的指标,查看 MPIJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,MPIJob 的状态变为 Succeeded,表示训练成功完成:
若 MPIJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 Horovod 进行 Keras 模型的数据并行训练
本教程演示如何使用 MPIJob 对 Keras 模型进行多工作器同步训练(使用 horovod.tensorflow.keras
模块)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
检查训练日志和指标
训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-mpijob 的 MPIJob 正在运行:
点击该名称进入详情页面,可以看到刚才创建的 MPIJob 的基本信息、状况信息和事件信息:
点击上方标签页的副本,查看 MPIJob 的 Pod 信息:
点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:
点击上方标签页的指标,查看 MPIJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:
一段时间之后,MPIJob 的状态变为 Succeeded,表示训练成功完成:
若 MPIJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。
使用 Profiler 分析模型训练性能
概述
PyTorch 提供的 profiler 工具允许在训练和推理过程中收集性能指标,从而帮助用户更好地理解运算的代价和内存等资源消耗,测量 CPU 计算代价,CPU-GPU 之间数据复制成本,研究 GPU 内核程序性能并可视化执行追踪等。用户在 Notebook 中可以方便地使用这一工具。
本教程将介绍如何在 Notebook 中对启动 LLM 大规模预训练中的训练进行性能分析。
准备
在启动 LLM 大规模预训练给出的准备工作的基础上,还需要修改 Megatron-DeepSpeed 的训练代码,用 profiler 上下文管理器包装训练循环的代码。直接使用 Notebook 的文本编辑器修改代码即可。
# Megatron-DeepSpeed/megatron/training.py
...
profile_path = os.path.join(os.path.dirname(args.tensorboard_dir), 'profiling')
with torch.profiler.profile(
schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=2),
on_trace_ready=torch.profiler.tensorboard_trace_handler(profile_path),
record_shapes=True,
profile_memory=True,
with_stack=True,
with_flops=True,
with_modules=True
) as prof: # profiler context manager
while iteration < args.train_iters and (args.train_tokens is None or \
args.consumed_train_tokens < args.train_tokens): # training loop
...
prof.step()
...
其中对于 profiler 的配置为:
- profiler 跳过 1 个 step,热身 1 个 step,然后记录 3 个 step;总共重复 2 次。
- 生成用于 TensorBoard 展示的结果文件,与 TensorBoard 日志文件保存到同一父目录下。
- 记录算子的源信息和输入形状,记录模块(module)的调用栈,估计 FLOPS,跟踪张量内存的分配和释放。
启动性能分析
以 4 个 GPU 训练 125M 参数的 GPT 模型,启动训练:
kubectl create -f \
examples/deepspeed/megatron-gpt/training/gpt-125m-4xdp.yaml
通过以下命令查看训练过程中打印的日志:
kubectl logs gpt-125m-4xdp-worker-0 -f
性能分析完成之后,结果文件被保存在 output/gpt-125m-4xdp/profiling
路径下,前往该路径并启动一个 TensorBoard 实例以查看可视化结果。
查看可视化结果
Overview 展示了训练性能的总体情况,包含 GPU 的总体情况、不同执行类别花费的时间和占比,以及自动生成的性能优化建议:
Operator View 展示了所有 PyTorch 算子被调用的次数、花费的时间以及它的调用栈:
Kernel View 展示了所有 GPU 内核被调用的次数、花费的时间的统计以及它是否使用了 Tensor Core 等:
Memory View 展示了内存使用曲线图、内存事件(分配和释放)以及内存统计数据:
TensorBoard 所展示的数据和提供的功能还远不止这些,请参阅官方教程以了解更多。这些数据应当能为用户分析和改进性能提供非常有用的帮助。
调试 Job
本教程演示如何使用 Job 的调试模式这一功能来对计算任务进行调试。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
通过 SSH 远程连接
对于开启了 SSH 服务的容器,建立 SSH 连接的操作步骤和 Notebook 相同,请参照通过 SSH 远程使用 Notebook进行操作。唯一不同的是端口转发使用 t9k-pf pod
命令,而非
t9k-pf notebook
命令:
t9k-pf pod <POD_NAME> 5001:2222 -n <PROJECT_NAME>
进行调试
不论是进入休眠的容器,还是远程连接开启了 SSH 服务的容器,调试都是通过执行一些命令来进行。例如使用 nvidia-smi
命令检查当前可用的 GPU,再使用 ls
命令检查训练脚本是否存在:
# 在容器中
nvidia-smi
ls
然后使用 torchrun
命令启动训练:
# 在容器中
cd ~/tutorial-examples/job/debug
torchrun --nnodes 1 --nproc_per_node 4 --rdzv_backend c10d torch_mnist_trainingjob.py --save_path model_state_dict.pt --log_dir log --backend nccl
随即分布式训练开始进行。如果训练脚本出错,则可以立即在终端中进行调试,不会造成 Job 的失败。调试完成后禁用 debug 模式(将 spec.runMode.debug.enable
设为 false
,或直接注释第 6-12 行),再次创建 PyTorchTrainingJob 则正常启动训练。
进行超参数优化
超参数优化是机器学习中的一项关键任务,其目标是选择一组最佳的超参数来改进模型性能。这一任务面临多重挑战:超参数通常不可微分,搜索空间高维且非凸,评估成本高,手动调参既繁琐又低效。为此 TensorStack AI 平台提供了自动化工具 AutoTune,其支持多种超参数优化算法,能够自动搜索超参数空间、存储搜索结果并进行可视化,并且配置简单,使用方便。
这一部分将使用 AutoTune 进行模型的超参数优化。
使用 AutoTune 进行超参数优化
本教程演示如何使用 AutoTune 对模型进行超参数优化(以 Keras 模型的单机训练为例)。
准备训练脚本
在开始超参数优化实验之前,你需要提前准备训练脚本。你可以使用模型构建控制台中的 Notebook 编辑训练脚本。
创建 PVC
参照创建 PVC 教程创建名为 autotune-mnist-keras
、大小为 1Gi 的 PVC。
创建 Notebook
从模型构建控制台进入 Notebook 列表,点击右上角的创建 Notebook。
创建 Notebook 时,在存储卷选择前面创建的 PVC 的名称 autotune-mnist-keras
。
创建完成之后,点击打开进入 Notebook。
在 Notebook 中编辑训练脚本
以下是一个 Keras 训练脚本,在此基础上做简单的修改以应用在 AutoTune 实验中。
import argparse
import json
import logging
import os
import time
import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers
parser = argparse.ArgumentParser(
description='Distributed training of Keras model for MNIST with '
'MultiWorkerMirroredStrategy.')
parser.add_argument('--log_dir',
type=str,
default=None,
help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
parser.add_argument('--save_path',
type=str,
default=None,
help='Save path of the trained model.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False
if args.no_cuda:
tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
# Print GPU info
logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
os.getenv('NVIDIA_VISIBLE_DEVICES')))
logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
logger.info('Visible GPUs: {}'.format(
tf.config.get_visible_devices('GPU')))
# Set memory growth
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
# # Set GPU memory limit
# tf.config.set_logical_device_configuration(
# gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']
params = {
# Search space:
# 'batch_size': ...
# 'learning_rate': ...
# 'conv_channels1': ...
'epochs': 10,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
'seed': 1,
}
with strategy.scope():
model = models.Sequential([
layers.Conv2D(params['conv_channels1'],
params['conv_kernel_size'],
activation='relu',
input_shape=(28, 28, 1)),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels2'],
params['conv_kernel_size'],
activation='relu'),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels3'],
params['conv_kernel_size'],
activation='relu'),
layers.Flatten(),
layers.Dense(params['linear_features1'], activation='relu'),
layers.Dense(10, activation='softmax'),
])
model.compile(
optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
(train_images, train_labels), (test_images,
test_labels) = datasets.mnist.load_data(
path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = train_images[:48000], train_images[48000:]
train_labels, val_labels = train_labels[:48000], train_labels[48000:]
train_dataset = tf.data.Dataset.from_tensor_slices(
(train_images, train_labels)).shuffle(
48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
(val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
(test_images, test_labels)).batch(1000)
model.fit(train_images,
train_labels,
batch_size=params['batch_size'],
epochs=params['epochs'],
validation_split=0.2,
verbose=2)
# TODO: Automatically save best n models.
# if args.save_path and task_index == 0:
# t9k.autotune.utils.save_best_n_models(model, args.save_path)
model.evaluate(test_images, test_labels, callbacks=test_callbacks, verbose=2)
if task_index > 0:
# wait a while for index 0
time.sleep(1)
在上述脚本中导入 t9k.tuner
模块,在训练模型之前调用 get_next_parameter()
函数获取训练超参数,替换原来的参数。
from t9k import tuner
def main():
...
tuner_params = tuner.get_next_parameter()
params.update(tuner_params)
...
在训练过程中,添加 AutoTuneCallback
上传实验指标。
train_callbacks = []
test_callbacks = []
if task_index == 0:
from t9k.tuner.keras import AutoTuneFitCallback, AutoTuneEvalCallback
train_callbacks.append(AutoTuneFitCallback(metric='accuracy'))
test_callbacks.append(AutoTuneEvalCallback(metric='accuracy'))
if args.log_dir:
tensorboard_callback = callbacks.TensorBoard(log_dir=args.log_dir)
train_callbacks.append(tensorboard_callback)
如下为修改后的训练脚本:
import argparse
import json
import logging
import os
import time
import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers
from t9k import tuner
parser = argparse.ArgumentParser(
description='Distributed training of Keras model for MNIST with '
'MultiWorkerMirroredStrategy.')
parser.add_argument('--log_dir',
type=str,
default=None,
help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
parser.add_argument('--save_path',
type=str,
default=None,
help='Save path of the trained model.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False
if args.no_cuda:
tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
# Print GPU info
logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
os.getenv('NVIDIA_VISIBLE_DEVICES')))
logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
logger.info('Visible GPUs: {}'.format(
tf.config.get_visible_devices('GPU')))
# Set memory growth
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
# # Set GPU memory limit
# tf.config.set_logical_device_configuration(
# gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']
tuner_params = tuner.get_next_parameter()
params = {
# Search space:
# 'batch_size': ...
# 'learning_rate': ...
# 'conv_channels1': ...
'epochs': 10,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
'seed': 1,
}
params.update(tuner_params)
with strategy.scope():
model = models.Sequential([
layers.Conv2D(params['conv_channels1'],
params['conv_kernel_size'],
activation='relu',
input_shape=(28, 28, 1)),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels2'],
params['conv_kernel_size'],
activation='relu'),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels3'],
params['conv_kernel_size'],
activation='relu'),
layers.Flatten(),
layers.Dense(params['linear_features1'], activation='relu'),
layers.Dense(10, activation='softmax'),
])
model.compile(
optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
(train_images, train_labels), (test_images,
test_labels) = datasets.mnist.load_data(
path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = train_images[:48000], train_images[48000:]
train_labels, val_labels = train_labels[:48000], train_labels[48000:]
train_dataset = tf.data.Dataset.from_tensor_slices(
(train_images, train_labels)).shuffle(
48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
(val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
(test_images, test_labels)).batch(1000)
train_callbacks = []
test_callbacks = []
if task_index == 0:
from t9k.tuner.keras import AutoTuneFitCallback, AutoTuneEvalCallback
train_callbacks.append(AutoTuneFitCallback(metric='accuracy'))
test_callbacks.append(AutoTuneEvalCallback(metric='accuracy'))
if args.log_dir:
tensorboard_callback = callbacks.TensorBoard(log_dir=args.log_dir)
train_callbacks.append(tensorboard_callback)
model.fit(train_images,
train_labels,
batch_size=params['batch_size'],
epochs=params['epochs'],
validation_split=0.2,
callbacks=train_callbacks,
verbose=2)
# TODO: Automatically save best n models.
# if args.save_path and task_index == 0:
# t9k.autotune.utils.save_best_n_models(model, args.save_path)
model.evaluate(test_images, test_labels, callbacks=test_callbacks, verbose=2)
if task_index > 0:
# wait a while for index 0
time.sleep(1)
在 Notebook 中创建文件 main.py
,写入上述脚本并保存文件。
创建 download_dataset.py
文件,写入并执行以下脚本来下载实验数据。
import os
import tensorflow as tf
_, _ = tf.keras.datasets.mnist.load_data(os.path.join(os.getcwd(), 'mnist.npz'))
准备数据库
你可以使用实验管理平台(以下称 EM)记录超参数调优实验中的超参数组合和训练结果。(如果你选择不使用 EM 持久记录 AutoTune 实验结果,请忽略这一步,并在开始实验时删掉 AutoTuneExperiment 的 spec.aistore
字段)
在实验管理控制台中新建文件夹
EM 的实验数据是以文件夹形式管理的,所以你首先需要在实验管理控制台点击右上角的 + 新建一个文件夹。
进入文件夹,点击 ID 来复制该文件夹的 ID。
获得访问 EM 所需的 API Key
在超参数优化实验中,如果你希望使用 EM 来存储实验数据,需要生成一个具有访问 EM 文件夹权限的 API Key,你可以通过这个 API Key 上传实验数据。
你需要按照生成 API Key 教程中的步骤,在安全控制台中生成一个 API Key,其中必须勾选 AIStore 选项。
生成 API Key 之后,点击复制按钮复制该 API Key。
然后,你需要按照管理 Secret 教程中的步骤,在模型构建控制台中将所复制的 API Key 存入名为 aistore
的 Secret 中,以方便后续实验使用。
开始实验
在模型构建控制台的 AutoTune 列表页面,点击右上角的创建 AutoTuneExperiment 进入 AutoTuneExperiment 创建页面。
在 AutoTuneExperiment 创建页面,点击预览 YAML,输入以下配置,点击创建:
apiVersion: tensorstack.dev/v1beta1
kind: AutoTuneExperiment
metadata:
name: autotune-mnist-keras
spec:
maxExecSeconds: 3600
maxTrialNum: 20
trialConcurrency: 3
storage: 100Mi
aistore:
secret: 'aistore'
folder: 'b6c17378-965c-4467-9a43-eed65597f976'
searchSpace: |-
{
"batch_size": {"_type": "choice", "_value": [16, 32, 64, 128]},
"learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]},
"conv_channels1": {"_type": "choice", "_value": [16, 32, 64, 128]}
}
trainingConfig:
type: tensorflow
tasks:
- type: worker
replicas: 4
template:
spec:
securityContext:
runAsUser: 1000
containers:
- command:
- sh
- -c
- "python3 main.py --log_dir /mnt/log --no_cuda"
workingDir: /mnt/
imagePullPolicy: IfNotPresent
image: t9kpublic/tensorflow-2.5.1:20220216
name: tensorflow
resources:
requests:
cpu: 2000m
memory: 2Gi
limits:
cpu: 4000m
memory: 4Gi
volumeMounts:
- mountPath: /mnt
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: autotune-mnist-keras
tuner:
builtinTunerName: TPE
classArgs: |-
{
"optimize_mode": "maximize",
"constant_liar_type": "min"
}
在此例中,实验绑定了准备过程中创建的名为 autotune-mnist-keras
的 PVC,其中存有在 Notebook 中编辑的训练脚本;使用了名为 aistore
的存有 API Key 的 Secret;填入了前面创建的 EM Folder 的 ID。
查看实验
你可以在 AutoTune 列表页面看到已创建的 AutoTuneExperiment,点击连接进入实验详情页面。
下图为实验详情页面,你可以在该页面查看实验基本信息、各试验的参数与结果,以及查看试验之间的对比。
部署模型推理服务
这一部分演示如何使用平台的模型部署模块部署推理服务。
- 使用 SimpleMLService 部署 简单模型推理服务
- 使用 MLService 部署 模型推理服务
- 部署 包含 Transformer 的模型推理服务
简单推理服务
本教程演示如何使用 SimpleMLService 快速部署一个模型推理服务。
运行示例
请按照使用方法准备环境,然后前往本教程的示例,参照其 README 文档运行。本示例使用 PVC 中存储的模型创建了一个 SimpleMLService 服务。
查看推理服务状态
部署完成后,进入模型部署控制台的 SimpleMLService 页面,可以看到名为 mnist 的 SimpleMLService。
点击 SimpleMLService 的名称 mnist 可以看见 SimpleMLService 的基本信息,其中 URL 是在集群内访问这个推理服务的地址:
参考
模型推理服务
本教程演示如何使用 MLService 部署一个功能完善、自动化程度高,可用于生产环境的模型推理服务。
运行示例
请按照使用方法准备环境,然后前往本教程的示例,参照其 README 文档运行。本示例使用 PVC 中存储的模型创建了一个 MLService 服务。
查看推理服务状态
部署完成后,进入模型部署控制台的 MLService 页面,可以看到名为 torch-mnist-pvc 的 MLService,稍等片刻,等其进入 Ready 状态:
使用推理服务
你可以直接使用命令行工具访问 MLService 的预测服务。运行命令获取 MLService 的 URL:
url=$(kubectl get mlservice torch-mnist-pvc -o jsonpath='{.status.address.url}') && echo $url
发送推理请求:
curl -T test_data/0.png ${url}/v1/models/mnist:predict # or use `1.png`, `2.png`
监控推理服务
在模型部署控制台,点击对应的 MLService,然后切换到资源监测页面,可以查看该 MLService 的资源统计:
参考
- MLService 介绍
- API 参考:MLService
- API 参考:MLServiceRuntime
包含 Transformer 的推理服务
本教程演示如何使用 TensorStack SDK 创建 Transformer 镜像,然后部署包含该 Transformer 的 MLService。
准备工作
请按照使用方法准备此次部署需要用到的 PVC 和 Notebook。
编写 Transformer 逻辑
接下来开始制作供 MLService 使用的 Transformer 镜像。首先进入 Notebook,启动一个终端,切换到对应目录:
cd ~/tutorial-examples/deployment/mlservice/transformer
查看文件 server.py
,内容如下:
import json
from t9k import mlservice
import argparse
import io
import numpy as np
from PIL import Image
from typing import Dict
# inherit parser to get command-line-args help
# feel free to add your command line args
par = argparse.ArgumentParser(parents=[mlservice.option.parser])
args, _ = par.parse_known_args()
def image_transform(instance):
image = Image.open(io.BytesIO(instance))
a = np.asarray(image)
a = a / 255.0
return a.reshape(28, 28, 1).tolist()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
def get_prediction(prediction: list)->str:
max_value = max(prediction)
max_index = prediction.index(max_value)
return class_names[max_index]
class Transformer(mlservice.MLTransformer):
def preProcess(self, path: str, requestData: bytes, headers: Dict[str, str]) -> any:
return json.dumps({'instances': [image_transform(requestData)]})
def postProcess(self, path: str, statusCode: int, responseContent: bytes, headers: Dict[str, str]) -> bytes:
data = responseContent.decode('utf-8')
jsonData = json.loads(data)
jsonStr = json.dumps({'predictions': [get_prediction(predict) for predict in jsonData['predictions']]})
return jsonStr.encode('utf-8')
if __name__ == "__main__":
transformer = Transformer()
server = mlservice.MLServer()
server.start(transformer=transformer)
代码中使用了 TensorStack SDK,通过重载 preprocess
和 postprocess
方法实现了一个 Transformer:
preprocess
:预处理函数,Transformer 收到用户发送的数据,使用preprocess
对数据进行处理,然后再发送给推理服务。在这个示例中,先转换输入图片的数据格式,需要保持与训练的模型的输入数据一致,然后再转换为推理服务的输入格式。postprocess
:后处理函数,Transformer 收到推理服务返回的结果,使用postprocess
对其进行处理,然后再返回给用户。在这个示例中,模型用于处理分类问题,从推理服务返回的预测概率向量中解析出该图片的分类类别,并返回给用户。
用户可以参考该文件来实现自定义的 Transformer 逻辑。
制作镜像
基于上述代码,我们创建对应的 Dockerfile 如下:
FROM python:3.8-slim
COPY t9k-sdk.tar.gz t9k-sdk.tar.gz
COPY server.py server.py
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple \
numpy \
pillow \
requests
RUN pip install t9k-sdk.tar.gz -i https://pypi.tuna.tsinghua.edu.cn/simple
ENTRYPOINT ["python", "server.py"]
上述 Dockerfile 引入了相关依赖,并将上一步的 server.py
文件作为启动命令。用户可以参考该文件来实现自定义的镜像。
然后我们通过运行一个 ImageBuilder 来制作镜像,为了使用 ImageBuilder,首先我们需要参照创建 Secret准备上传镜像所需要的 DockerConfig Secret
。
完成后修改 imagebuilder.yaml
文件,将 spec.dockerConfig.secret
修改为上一步中创建的 DockerConfig Secret
的名称,并将 spec.tag
修改为目标镜像,并执行以下命令:
kubectl apply -f imagebuilder.yaml
查看 ImageBuilder
状态,等待 Phase 一栏变为 Succeeded
:
kubectl get -f imagebuilder.yaml -w
部署 MLService
进入模型部署控制台,先点击左侧导航栏辅助一栏下的的 MLServiceRuntime,再点击 创建 MLServiceRuntime ,然后点击 预览 YAML, 并将下面内容复制到 YAML 编辑框中,最后点击 创建 创建 MLServiceRuntime。
apiVersion: tensorstack.dev/v1beta1
kind: MLServiceRuntime
metadata:
name: t9k-tensorflow-serving
spec:
enabled: true
template:
spec:
containers:
- name: user-container
image: t9kpublic/tensorflow-serving:2.13.1
command:
- /usr/bin/tensorflow_model_server
args:
- --model_name={{if .MODEL_NAME}}{{.MODEL_NAME}}{{else}}model{{end}}
- --port={{if .GRPC_PORT}}{{.GRPC_PORT}}{{else}}9000{{end}}
- --rest_api_port=8000
- --model_base_path=/var/lib/t9k/model
resources:
limits:
cpu: "200m"
memory: 200Mi
ports:
- containerPort: 8000
protocol: TCP
进入模型部署控制台的 MLService 页面,点击右上角创建 MLService,然后点击预览 YAML。如下图所示,将下述内容复制到右侧的 YAML 编辑框,最后点击 创建 创建 MLService:
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
name: pic-mnist
spec:
default: origin
transformer:
minReplicas: 1
template:
spec:
containers:
- name: user-container
image: "<your-docker-registry-address>/mnist-transformer:test"
releases:
- name: origin
predictor:
minReplicas: 1
model:
runtime: t9k-tensorflow-serving
modelUri: pvc://tutorial/tutorial-examples/deployment/mlservice/transformer/model/
<<<<<<< HEAD 你可以直接使用命令行工具访问 MLService 的预测服务。运行命令获取 MLService 的 URL:
发送预测请求
使用图片 shoe.png
作为测试数据发送预测请求。
>>>>>>> parent of 816714b (Update mlservice (#51))
address=$(kubectl get mls pic-mnist -ojsonpath='{.status.address.url}') && echo $address
curl --data-binary @./shoe.png ${address}/v1/models/model:predict
参考
- MLService 介绍
- API 参考:MLService
- API 参考:MLServiceRuntime
管理 AI 资产
这一部分演示如何使用 AsestHub 上传、使用和分享模型和数据集。
操作文件夹、模型和数据集
本教程演示如何通过多种方式操作文件夹、模型和数据集,包括创建、查看和删除。
准备工作
通过命令行工具
切换到你的工作路径下:
$ cd /your/workpath
假设当前用户(这里假设用户名为 demo
)没有可以访问的文件夹,使用 ah create
命令创建一个模型文件夹和一个数据集文件夹:
$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created
$ ah create dataset/text
AH INFO: Folder /demo/t9k-assethub/dataset/text created
然后使用 ah create
命令在模型文件夹中创建一个模型,以及在数据集文件夹中创建一个数据集:
$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
$ ah create dataset/text/openwebtext
AH INFO: Dataset openwebtext created for Folder /demo/t9k-assethub/dataset/text
创建完成之后,使用 ah ls
命令查看当前用户的模型文件夹和数据集文件夹:
$ ah ls model
NAME PATH LABELS PERMISSION
llm /demo/t9k-assethub/model/llm own
$ ah ls dataset
NAME PATH LABELS PERMISSION
text /demo/t9k-assethub/dataset/text own
使用 ah ls
命令查看模型文件夹下的所有模型以及数据集文件夹下的所有数据集:
$ ah ls model/llm
NAME PATH LABELS PERMISSION
gpt2 /demo/t9k-assethub/model/llm/gpt2 own
$ ah ls dataset/text
NAME PATH LABELS PERMISSION
openwebtext /demo/t9k-assethub/dataset/text/openwebtext own
最后使用 ah delete
命令删除所有创建的模型、数据集和文件夹:
$ ah delete model/llm/gpt2
AH INFO: Model /demo/t9k-assethub/model/llm/gpt2 deleted
$ ah delete dataset/text/openwebtext
AH INFO: Dataset /demo/t9k-assethub/dataset/text/openwebtext deleted
# 可以直接删除文件夹, 其中的模型或数据集都会被一并删除
$ ah delete model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm deleted
$ ah delete dataset/text
AH INFO: Folder /demo/t9k-assethub/dataset/text deleted
通过 Python SDK
切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。
导入 t9k.ah
模块,使用 ah.login()
函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):
from t9k import ah
ah.login(host='<asset-hub-server-url>',
api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>
假设当前用户(这里假设用户名为 demo
)没有可以访问的文件夹,使用 ah.create()
函数创建一个模型文件夹和一个数据集文件夹,各返回一个 Folder
实例:
model_folder = ah.create('model/llm')
dataset_folder = ah.create('dataset/text')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Folder /demo/t9k-assethub/dataset/text created
继续使用 ah.create()
函数在模型文件夹中创建一个模型,以及在数据集文件夹中创建一个数据集:
model = ah.create('model/llm/gpt2')
dataset = ah.create('dataset/text/openwebtext')
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
AH INFO: Dataset openwebtext created for Folder /demo/t9k-assethub/dataset/text
创建完成之后,使用 ah.list()
函数返回当前用户的文件夹:
from pprint import pprint
pprint(ah.list('model'))
pprint(ah.list('dataset'))
[{'description': '',
'editor': 'demo',
'extra': '{"createdTimestamp": "2023-08-17T08:05:24.044319Z"}',
'id': '967a5135-8b13-4283-9fad-ba53503612b3',
'labels': [],
'modifiedTimestamp': '2023-08-17T08:05:24.390002Z',
'name': 'llm',
'path': '/demo/t9k-assethub/model/llm',
'permission': 'own',
'storageType': 0,
'type': 'Folder'}]
[{'description': '',
'editor': 'demo',
'extra': '{"createdTimestamp": "2023-08-17T08:05:24.196610Z"}',
'id': 'd0d9f4b2-6c15-4dbb-b2d1-0619b6774c4a',
'labels': [],
'modifiedTimestamp': '2023-08-17T08:05:24.519213Z',
'name': 'text',
'path': '/demo/t9k-assethub/dataset/text',
'permission': 'own',
'storageType': 0,
'type': 'Folder'}]
继续使用 ah.list()
函数返回模型文件夹下的所有模型和数据集文件夹下的所有数据集:
pprint(ah.list('model/llm'))
pprint(ah.list('dataset/text'))
[{'description': '',
'editor': 'demo',
'extra': '{"createdTimestamp": "2023-08-17T08:11:09.948554Z"}',
'id': '2157a139-e20b-4736-9e25-d4495e287af8',
'labels': [],
'modifiedTimestamp': '2023-08-17T08:11:10.327166Z',
'name': 'gpt2',
'path': '/demo/t9k-assethub/model/llm/gpt2',
'permission': 'own',
'storageType': 3,
'type': 'Model'}]
[{'description': '',
'editor': 'demo',
'extra': '{"createdTimestamp": "2023-08-17T08:11:10.508407Z"}',
'id': '6826131c-2c88-483e-8a48-0f6d8fa59cfa',
'labels': [],
'modifiedTimestamp': '2023-08-17T08:11:10.830665Z',
'name': 'openwebtext',
'path': '/demo/t9k-assethub/dataset/text/openwebtext',
'permission': 'own',
'storageType': 3,
'type': 'Dataset'}]
最后使用 ah.delete()
函数删除所有创建的模型、数据集和文件夹:
ah.delete('model/llm/gpt2')
ah.delete('dataset/text/openwebtext')
ah.delete('model/llm') # 可以直接删除文件夹, 其中的模型或数据集都会被一并删除
ah.delete('dataset/text')
AH INFO: Model /demo/t9k-assethub/model/llm/gpt2 deleted
AH INFO: Dataset /demo/t9k-assethub/dataset/text/openwebtext deleted
AH INFO: Folder /demo/t9k-assethub/model/llm deleted
AH INFO: Folder /demo/t9k-assethub/dataset/text deleted
通过控制台
数据集文件夹、数据集的控制台操作分别和模型文件夹、模型完全一致。本教程后续仅展示模型文件夹和模型的创建、查看、删除、分享功能,你可以用同样的方式操作数据集文件夹和数据集。
在左侧的导航菜单中点击模型,选择查看范围为 My Own,查看当前用户的所有模型文件夹。然后点击右上角的 + 创建新的模型文件夹:
填写名称 image-classification
,点击创建:
接下来分享这个文件夹。点击文件夹右侧的 更多 > 分享:
点击添加分享目标,选择分享的对象为 Public(所有用户可见),分享的权限是 Edit,最后点击分享:
回到 Asset Hub 控制台,点击模型文件夹 image-classification 查看其中的模型:
新创建的模型文件夹中没有模型,点击右上角的 + 创建一个模型:
填写名称 mnist
,然后点击创建:
创建成功后,在模型文件夹中可以看到模型信息:
点击更多 > 删除,删除创建的模型,然后点击左上角的返回,返回模型文件夹的页面:
最后,返回 Asset Hub 控制台,点击更多 > 删除,删除模型文件夹:
通过 S3 访问模型和数据集
本教程演示如何 S3 访问模型。
数据集同理。
准备工作
- 完成教程操作文件夹、模型和数据集。
创建 S3 凭证
在 AssetHub 控制台进入模型详情页面,点击 S3 凭证可以查看目前已有的所有 S3 凭证。然后点击表格右上角的 + 创建一个 S3 凭证:
填写名称 s3-rw
,选择类型为可读/可写,最后点击创建:
查看 S3 凭证
创建完成后,点击表格左上角的可读/可写,查看所有类型为可读/可写的 S3 凭证:
点击刚刚创建的 S3 凭证 s3-rw
,查看其详情:
S3 凭证有三种格式:
.s3cfg
:命令行工具 s3cmd 的配置文件。S3-cfg Secret
:s3cfg 形式的 Secret YAML,创建后可在 Notebook、Job、Workflow 等工作负载时挂载此 Secret。S3-env Secret
:s3 环境变量形式的 Secret YAML,创建后可在 Notebook、Job、Workflow 等工作负载时挂载此 Secret。
通过 s3cmd 访问模型
点击右侧的复制,复制 .s3cfg
格式的 S3 凭证,保存在 $HOME/.s3cfg
文件中,即可通过 s3cmd 命令行工具访问此模型中的文件。
例如,在上述示例中,所创建的 S3 凭证 s3-rw
仅可用于访问名为 neox
的模型。根据页面上的提示,此模型对应的 bucket 名称为 adb2a768-f01a-467b-b146-e82c0693c16b
,用户可以通过以下命令查看此模型的 main
分支的 README.md
文件:
s3cmd ls s3://baa98ded-2f93-4e9b-835a-6515a63a6eb4/main/README.md
通过以下命令下载此模型的某个分支下某个路径的文件:
s3cmd get s3://baa98ded-2f93-4e9b-835a-6515a63a6eb4/branch-name/path/to/object
通过 StorageShim 访问模型
除了通过命令行工具访问,用户还可以创建一个 StorageShim,将 S3 bucket 的某个子路径形式化为一个持久卷,以便在 Notebook、Job、Workflow 等工作负载中挂载,直接以文件系统的形式查看、编辑 S3 bucket 中的文件。
在创建 StorageShim 之前,用户首先需要创建一个 Secret 保存 S3 bucket 的相关信息。在 S3 凭证的详情页面,点击左侧的 S3-cfg Secret 标签,然后点击右上角的复制:
在模型构建控制台的左侧导航菜单中点击辅助 > Secret 进入 Secret 管理页面,然后点击右上角的创建 Secret进入 Secret 创建页面:
在 Secret 创建页面,点击预览 YAML,将所复制的 S3-cfg Secret
粘贴到 YAML 编辑框中,最后点击创建。
在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入持久卷管理页面,然后点击上方的 S3 进入 S3 类型的持久卷管理页面,最后点击右上角的创建进入 StorageShim 创建页面:
在 StorageShim 创建页面,
- 名称填写
neox
; - 类型选择
S3
; - S3 URI 填写
s3://adb2a768-f01a-467b-b146-e82c0693c16b/main
,以便把上述示例模型的 main 分支挂载为持久卷; - S3 Secret 选择刚刚创建的
s3-rw
。
最后点击创建。
StorageShim 创建完成后,等待其阶段变为 Bound,用户即可通过以下方式使用这个名为 neox
的持久卷:
- 点击启动,创建一个 Explorer 来浏览持久卷中的文件。
- 在创建 Notebook 时,添加持久卷
neox
,以便在 Notebook 中查看和编辑此模型中的文件。 - 在创建 Job 时,添加持久卷
neox
,以便在 Job 中使用此模型中的文件。
修改文件夹、模型和数据集的基本信息
本教程演示如何通过多种方式修改文件夹、模型和数据集的基本信息。
准备工作
- 完成教程操作文件夹、模型和数据集。
通过命令行工具
切换到你的工作路径下:
$ cd /your/workpath
修信息的方式对于文件夹、模型和数据集都是相同的。下面将以模型文件夹和模型为例进行演示(这里假设用户名为 demo
)。
依次创建模型文件夹和模型:
$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created
$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
使用 ah update
命令修改文件夹和模型的名称:
$ ah update model/llm -n chat
AH INFO: Folder /demo/t9k-assethub/model/llm updated to /demo/t9k-assethub/model/chat
$ ah update model/chat/gpt2 -n gpt3
AH INFO: Model /demo/t9k-assethub/model/chat/gpt2 updated to /demo/t9k-assethub/model/chat/gpt3
使用 ah ls
命令查看文件夹和模型的标签:
$ ah ls model --detail
NAME PATH ... LABELS ...
chat /demo/t9k-assethub/model/chat
$ ah ls model/chat
NAME PATH LABELS ...
gpt3 /demo/t9k-assethub/model/chat/gpt3
两者都没有标签,再次使用 ah update
命令为它们添加标签:
$ ah update model/chat --label "NLP" --label "AIGC"
AH INFO: Folder /demo/t9k-assethub/model/chat updated
$ ah ls model --detail
NAME PATH ... LABELS ...
chat /demo/t9k-assethub/model/chat AIGC, NLP
$ ah update model/chat/gpt3 --label "GPT"
AH INFO: Model /demo/t9k-assethub/model/chat/gpt3 updated
$ ah ls model/chat
NAME PATH LABELS PERMISSION
gpt3 /demo/t9k-assethub/model/chat/gpt3 GPT own
通过 Python SDK
切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。
导入 t9k.ah
模块,使用 ah.login()
函数登录到 AssetHub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):
from t9k import ah
ah.login(host='<asset-hub-server-url>',
api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>
修改信息的方式对于文件夹、模型和数据集都是相同的。下面将以模型文件夹和模型为例进行演示(这里假设用户名为 demo
)。
依次创建模型文件夹和模型:
model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
使用 ah.update()
函数修改文件夹和模型的名称:
ah.update('model/llm', name='chat')
ah.update('model/chat/gpt2', name='gpt3')
AH INFO: Folder /demo/t9k-assethub/model/llm updated to /demo/t9k-assethub/model/chat
AH INFO: Model /demo/t9k-assethub/model/chat/gpt2 updated to /demo/t9k-assethub/model/chat/gpt3
使用 ah.list()
函数查看文件夹和模型的标签:
from pprint import pprint
pprint(ah.list('model'))
pprint(ah.list('model/chat'))
[{...
'labels': [],
'name': 'chat',
'path': '/demo/t9k-assethub/model/chat',
'type': 'Folder'}]
[{...
'labels': [],
'name': 'gpt3',
'path': '/demo/t9k-assethub/model/chat/gpt3',
'type': 'Model'}]
两者都没有标签,继续使用 ah.update()
函数为它们添加标签:
ah.update('model/chat', labels=['NLP', 'AIGC'])
ah.update('model/chat/gpt3', labels=['GPT'])
AH INFO: Folder /demo/t9k-assethub/model/chat updated
AH INFO: Model /demo/t9k-assethub/model/chat/gpt3 updated
pprint(ah.list('model'))
pprint(ah.list('model/chat'))
[{...
'labels': ['AIGC', 'NLP'],
'name': 'chat',
'path': '/demo/t9k-assethub/model/chat',
'type': 'Folder'}]
[{...
'labels': ['GPT'],
'name': 'gpt3',
'path': '/demo/t9k-assethub/model/chat/gpt3',
'type': 'Model'}]
通过控制台
数据集文件夹、数据集的控制台操作分别和模型文件夹、模型完全一致。本教程后续仅展示如何修改模型文件夹和模型的基本信息,你可以用同样的方式操作数据集文件夹和数据集。
在进行教程之前,先按照操作文件夹、模型和数据集一节完成模型文件夹和模型的创建(chat/gpt2)。
在模型文件夹列表中,选中需要修改的模型文件夹,点击更多 > 编辑:
填写新的名称和描述信息,添加新标签,点击更新按钮:
回到文件夹列表,可以看到文件夹信息发生改变:
点击文件夹名称,进入模型列表,选中需要修改的模型,点击更多 > 编辑:
填写新的名称和描述信息,添加新标签,点击更新按钮:
回到模型列表,可以看到模型信息发生改变:
操作模型和数据集的分支、tag 和 commit
本教程演示如何通过多种方式操作模型的分支、tag 和 commit,包括创建、查看和删除分支,创建、查看和删除 tag,以及查看 commit。
数据集同理。
准备工作
- 完成教程操作文件夹、模型和数据集。
通过命令行工具
切换到你的工作路径下:
$ cd /your/workpath
操作 tag 和 commit 的方式对于模型和数据集都是相同的,只有模型允许操作分支。下面将以模型为例进行演示(这里假设用户名为 demo
)。
依次创建模型文件夹和模型:
$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created
$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
继续使用 ah create
命令为模型创建一个分支:
$ ah create model/llm/gpt2:v1
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah ls --branch
命令查看模型的所有分支:
$ ah ls model/llm/gpt2 --branch
NAME COMMIT_ID
main fe46da7e
v1 fe46da7e
继续使用 ah create
命令为模型创建一个 tag:
$ ah create model/llm/gpt2:20230101 --tag --source v1
AH INFO: Tag 20230101 created from branch v1 for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah ls --tag
命令查看模型的所有 tag:
$ ah ls model/llm/gpt2 --tag
NAME COMMIT_ID
20230101 fe46da7e
使用 ah ls --commit
命令查看模型的一个分支下的所有 commit:
$ ah ls model/llm/gpt2:v1 --commit
COMMIT_ID MESSAGE CREATED
fe46da7e Repository created 3m16s ago
最后使用 ah delete
命令删除所有创建的分支和 tag:
$ ah delete model/llm/gpt2:v1
AH INFO: Branch v1 deleted for Model /demo/t9k-assethub/model/llm/gpt2
$ ah delete model/llm/gpt2:20230101
AH INFO: Tag 20230101 deleted for Model /demo/t9k-assethub/model/llm/gpt2
通过 Python SDK
切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。
导入 t9k.ah
模块,使用 ah.login()
函数登录到 AssetHub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):
from t9k import ah
ah.login(host='<asset-hub-server-url>',
api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>
操作 tag 和 commit 的方式对于模型和数据集都是相同的,只有模型允许操作分支。下面将以模型为例进行演示(这里假设用户名为 demo
)。
依次创建模型文件夹和模型:
model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
继续使用 ah.create()
函数为模型创建一个分支:
branch = ah.create('model/llm/gpt2:v1')
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah.list()
函数查看模型的所有分支:
from pprint import pprint
pprint(ah.list('model/llm/gpt2', resource='branch'))
[{'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
'id': 'main'},
{'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
'id': 'v1'}]
继续使用 ah.create()
函数为模型创建一个 tag:
tag = ah.create('model/llm/gpt2:20230101', create_tag=True, source='v1')
AH INFO: Tag 20230101 created from branch v1 for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah.list()
函数查看模型的所有 tag:
pprint(ah.list('model/llm/gpt2', resource='tag'))
[{'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
'id': '20230101'}]
最后使用 ah.delete()
函数删除所有创建的分支和 tag:
ah.delete('model/llm/gpt2:v1')
ah.delete('model/llm/gpt2:20230101')
AH INFO: Branch v1 deleted for Model /demo/t9k-assethub/model/llm/gpt2
AH INFO: Tag 20230101 deleted for Model /demo/t9k-assethub/model/llm/gpt2
操作模型和数据集的对象
本教程演示如何通过多种方式操作模型的对象,包括修改、查看和下载 AssetHub 中存储的对象文件。
数据集同理。
准备工作
通过命令行工具
切换到你的工作路径下:
$ cd /your/workpath
操作对象的方式对于模型和数据集都是相同的,除了数据集只允许操作主分支(main
分支)中的对象。下面将以模型为例进行演示(这里假设用户名为 demo
)。
依次创建模型文件夹、模型和分支:
$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created
$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
$ ah create model/llm/gpt2:v1
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah commit
命令向该分支上传本地文件(这里以 model_state_dict.pt
和 README.md
为例)作为对象存储:
$ ah commit model/llm/gpt2:v1 --message "Add model file" --add model_state_dict.pt --add README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object 1/2 model_state_dict.pt:
Done
AH INFO: Uploading object 2/2 README.md:
Done
AH INFO: Commit 29d6f29e created
使用 ah ls
命令查看分支的所有对象:
$ ah ls model/llm/gpt2:v1
PATH BYTES CHECKSUM MODIFIED
README.md 110B d1f0e72bd20091c3869cefff8c72661b 1m29s ago
model_state_dict.pt 375943B 1203ee282c235c9fb4c2ea932a7b7cc8 1m29s ago
再次使用 ah commit
命令,当重复上传文件到同一路径时,原有的对象会被替换:
$ ah commit model/llm/gpt2:v1 --message "Update README" --add README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object 1/1 README.md:
Done
AH INFO: New commit 53097cba created
$ ah ls model/llm/gpt2:v1
PATH BYTES CHECKSUM MODIFIED
README.md 221B 84c44f1510389ea7de91e550be8a7130 15s ago
model_state_dict.pt 375943B 1203ee282c235c9fb4c2ea932a7b7cc8 5m37s ago
使用 -d PATH
选项以删除指定路径的对象:
$ ah commit model/llm/gpt2:v1 --message "Remove README" --delete README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Deleting object README.md:
Done
AH INFO: Commit cf8dcc26 created
$ ah ls model/llm/gpt2:v1
PATH BYTES CHECKSUM MODIFIED
model_state_dict.pt 375943B 1203ee282c235c9fb4c2ea932a7b7cc8 6m2s ago
每次使用 ah commit
命令修改分支(添加、覆盖或删除对象)时,分支都会创建一个新的 commit。使用 ah ls commit
命令查看上面的操作所创建的 3 个 commit:
$ ah ls model/llm/gpt2:v1 --commit
COMMIT_ID MESSAGE CREATED
cf8dcc26 Remove README 5m47s ago
53097cba Update README 21m46s ago
29d6f29e Add model file 33m8s ago
c4bebb3a Repository created 33m18s ago # 初始 commit
之后想要使用这些对象时,使用 ah download
命令下载对象保存为本地文件:
$ ah download model/llm/gpt2:v1
AH INFO: Downloading object 1/1 model_state_dict.pt:
━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 375.9/375.9 kB • 2.6 MB/s • 0:00:00
$ ls
model_state_dict.pt ...
通过 Python SDK
切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。
导入 t9k.ah
模块,使用 ah.login()
函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):
from t9k import ah
ah.login(host='<asset-hub-server-url>',
api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>
操作对象的方式对于模型和数据集都是相同的,除了数据集只允许操作主分支(main
分支)中的对象。下面将以模型为例进行演示(这里以 user
表示当前用户)。
依次创建模型文件夹、模型和分支:
model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
branch = ah.create('model/llm/gpt2:v1')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2
使用 ah.commit()
函数向该分支上传本地文件作为对象存储:
commit1 = ah.commit('model/llm/gpt2:v1',
msg='Add model file',
add=['model_state_dict.pt', 'README.md'])
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object model_state_dict.pt:
Done
AH INFO: Uploading object README.md:
Done
AH INFO: Commit 6a57546b created
使用 ah.list()
函数查看分支的所有对象:
from pprint import pprint
pprint(ah.list('model/llm/gpt2:v1'))
[{'checksum': 'f0db68fc4327c528b3a23fdc47c30c9e',
'content_type': 'application/octet-stream',
'mtime': 1683881423,
'path': 'README.md',
'path_type': 'object',
'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjoi2hci2stu7un0',
'size_bytes': 110},
{'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
'content_type': 'application/octet-stream',
'mtime': 1683881423,
'path': 'model_state_dict.pt',
'path_type': 'object',
'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
'size_bytes': 375943}]
再次使用 ah.commit()
函数,当重复上传文件到同一路径时,原有的对象会被替换:
commit2 = ah.commit('model/llm/gpt2:v1', msg='Update README', add=['README.md'])
pprint(ah.list('model/llm/gpt2:v1'))
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object README.md:
Done
AH INFO: Commit 8183e1df created
[{'checksum': '1cbd5021ee923905bbdc29883c50a1b0',
'content_type': 'application/octet-stream',
'mtime': 1683881478,
'path': 'README.md',
'path_type': 'object',
'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevs1gi2hci2stu7uog',
'size_bytes': 221},
{'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
'content_type': 'application/octet-stream',
'mtime': 1683881423,
'path': 'model_state_dict.pt',
'path_type': 'object',
'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
'size_bytes': 375943}]
使用 delete
选项以删除指定路径的对象:
commit3 = ah.commit('model/llm/gpt2:v1', msg='Remove README', delete=['README.md'])
pprint(branch.list_object())
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Deleting object README.md:
Done
AH INFO: Commit 00af1151 created
[{'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
'content_type': 'application/octet-stream',
'mtime': 1683881423,
'path': 'model_state_dict.pt',
'path_type': 'object',
'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
'size_bytes': 375943}]
每次使用 ah.commit()
函数修改分支(添加、覆盖或删除对象)时,分支都会创建一个新的 commit。继续使用 ah.list()
函数查看上面的操作所创建的 3 个 commit:
pprint(ah.list('model/llm/gpt2:v1', resource='commit'))
[{'committer': 'admin',
'creation_date': 1683881538,
'id': '00af1151865121a79233af326b21864f2f6dbcc3b5bebb2f8768e2b13154f754',
'message': 'Remove README', # commit3
'meta_range_id': 'c959b9ce4301591b82517c97ca277b034fd4a4d181b63db7571a2a8174844848',
'metadata': {},
'parents': ['8183e1dfb0dcded478aff1b5cb2975ae22e83ca4f37333fb904e5bcd27897923']},
{'committer': 'admin',
'creation_date': 1683881479,
'id': '8183e1dfb0dcded478aff1b5cb2975ae22e83ca4f37333fb904e5bcd27897923',
'message': 'Update README', # commit2
'meta_range_id': '2184d241abdc0ce3e26db44ad2c1df3e1e6a7a6b231fa1f17db7684982a55243',
'metadata': {},
'parents': ['6a57546b1275ba6b7f1399e0f7213552ac7bdf545de8692e494db47b93623b9d']},
{'committer': 'admin',
'creation_date': 1683881423,
'id': '6a57546b1275ba6b7f1399e0f7213552ac7bdf545de8692e494db47b93623b9d',
'message': 'Add model file', # commit1
'meta_range_id': '0b8943e0b3b4a3b8661f6146f47f85562aea5c7eb88bc2c66f2adf7443a08451',
'metadata': {},
'parents': ['610af4d2991e5c9b9d527dedf34db3cd11c8bd5bb7cc0e8ed0b97505319f8f11']},
{'committer': '',
'creation_date': 1683881388,
'id': '610af4d2991e5c9b9d527dedf34db3cd11c8bd5bb7cc0e8ed0b97505319f8f11',
'message': 'Repository created', # 初始 commit
'meta_range_id': '',
'metadata': {},
'parents': []}]
之后想要使用这些对象时,使用 ah.download()
函数下载对象保存为本地文件:
ah.download('model/llm/gpt2:v1')
import os
print(os.listdir())
AH INFO: Downloading object 1/1 model_state_dict.pt:
━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 375.9/375.9 kB • 2.6 MB/s • 0:00:00
['model_state_dict.pt', ...]
通过控制台
数据集的控制台操作和模型完全一致。本教程后续仅展示模型对象的上传和下载,你可以用同样的方式操作数据集。
在进行教程之前,先按照操作文件夹、模型和数据集一节完成模型文件夹和模型的创建(chat/gpt3)。
进入模型详情页后,点击所有文件 > 上传图标:
点击选择文件选择所要上传的文件,填写描述信息,然后点击提交:
完成提交后,可以在所有文件中看到刚刚上传的文件,点击下载图标下载该文件:
点击介绍 > 添加介绍:
在编辑框中按照 markdown
格式编辑模型的描述信息,填写提交信息,点击提交:
添加完介绍后,在模型详情页可以看到模型介绍:
模型介绍本质上是 README.md 文件,在所有文件中可以看到:
追踪模型训练
在复杂的 AI 实验中,研究人员或工程师需要处理数以百计的实验配置和结果,在缺乏有效管理工具的情况下很容易迷失在海量的数据和文件中。因此,追踪和记录实验变得十分重要,它能够帮助研究人员快速识别最佳模型,比较不同模型的差异,洞悉关键因素的作用,并且迅速迭代改进,从而大幅提升研究和开发的效率。
这一部分将使用实验管理模块和 Python SDK 追踪模型的训练过程和结果。Python SDK 负责自动记录超参数、指标、平台信息以及任何重要的输入输出文件,实验管理控制台则提供直观的可视化界面以及便捷的团队协作体验。我们将从介绍实验管理控制台与 Python SDK 的基本用法开始,进而到实际场景中追踪模型的训练,最后我们查看 AutoTune 进行超参数优化的结果。
本部分常见任务如下:
在实验管理控制台查看和管理数据
本教程演示如何使用实验管理控制台来查看和管理记录的模型训练数据。
进入实验管理控制台
在 TensorStack AI 平台的首页,点击实验管理进入实验管理控制台。
浏览文件夹
当前用户的所有数据以类似于文件系统的方式组织,每个 Run(或 Artifact、AutoTune)都位于特定的路径之下。点击一个文件夹(Folder)以进入,查看其下的所有子文件夹和 Run(或 Artifact、AutoTune)。
使用上方的面包屑导航或左侧的导航菜单可以返回上级文件夹或跳转到其他文件夹。
创建和删除文件夹
若要创建一个文件夹,点击右上角的添加,在对话框中提供文件夹名称并点击创建。
若要删除一个文件夹,点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,然后点击删除。
共享文件夹
点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,点击分享,在对话框中管理文件夹的分享成员列表。空白表示文件夹当前没有被分享给任何其他用户。
分享成员列表可以任意添加(点击加号)或移除(点击用户项右侧的减号)平台的其他用户或用户组,选择用户或用户组的名称和权限,最后点击保存以确定。
来自其他用户分享的文件夹、Run、Artifact 或 AutoTune 将出现在导航菜单的分享给我的标签下。
其他文件夹操作
同样点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,你还可以进行创建快捷方式、移动以及重命名操作。
查看 Run 和 Artifact
点击一个 Run 或 Artifact 的名称以进入它的详情页面。
Run 的详情页面中,多个标签页分别展示了平台信息、指标、超参数以及数据流。
Artifact 的详情页面中,多个标签页分别展示了文件列表以及数据流。
创建和删除 Run、Artifact 和 AutoTune
创建 Run 和 Artifact 的方法请参阅使用 Python SDK 记录和上传数据;创建 AutoTune 的方法请参阅使用 AutoTune 进行超参数优化。
若要删除一个 Run(或 Artifact、AutoTune,下同),与删除文件夹的操作相同,点击 Run 项右侧的操作,或点击面包屑导航中的当前 Run,然后点击删除。
分享 Run、Artifact 和 AutoTune 以及其他操作
分享 Run(或 Artifact、AutoTune)或者进行其他操作的方法都与文件夹相同,这里不再赘述。
退出登录或切换用户
如果你想要退出当前用户的登录,点击右上角的用户头像,然后点击退出登录。
再次进入实验管理控制台时,你需要输入用户名和密码以重新登录。
使用 Python SDK 记录和上传数据
本教程介绍如何使用 Python SDK 进行创建、加载、上传 Run 和 Artifact,设定超参数,记录指标等操作。
创建 Run
基本方法
在模型的训练脚本中,你需要首先创建一个 Run,通过调用 t9k.em.create_run()
函数。其返回的 Run
实例即代表了一次训练的运行。此方法调用后,Run 将被创建,具有状态“Running”,其本地文件默认保存在相对路径 .em/runs
下,每个 Run 拥有一个独立的名为 <run_name>_<date>_<time>_<random_suffix>
(称为该 Run 的备用名称)的子目录。
最基本的初始化方法只需要提供名称作为参数。
from t9k import em
run = em.create_run(name='mnist_torch') # 返回Run实例
自动上传
如果想要自动异步上传 Run 的更新,可以设定 auto_upload=True
,并提供文件夹路径,以及设定是否创建不存在的各级文件夹。在这种情况下,你在创建 Run 之前需要先登录到 AIStore 服务器。
run = em.create_run(name='mnist_torch',
auto_upload=True, # 启用自动上传
folder='new-folder', # 文件夹路径
make_folder=True) # 创建不存在的各级文件夹
如果目标文件夹已经存在同名的 Run,则需要指定 conflict_strategy
参数以处理冲突,参数接受以下值:
'skip'
:跳过上传。'error'
:错误退出。'new'
:以 Run 的备用名称上传。'replace'
:替换同名的 Run。
例如,运行以下代码两次,第二次创建的 Run 会以类似 mnist_torch_231231_235959_61p5jc
的名称被上传到 new-folder
文件夹下。
run = em.create_run(name='mnist_torch',
auto_upload=True,
folder='new-folder',
make_folder=True,
conflict_strategy='new')
提供标签和描述
你可以为创建的 Run 提供用于分类或介绍的标签或描述。
run = em.create_run(
name='mnist_torch',
labels=['torch', 'CNN'], # 标签
description= # 描述
'Train a simple CNN model that classifies images of handwritten digits.')
提供配置文件
你可以将上面的所有配置(以及下面将要提到的超参数)都写进一个 YAML 文件里,然后传入该配置文件的路径即可。
run = em.create_run(config_path='./run_config.yaml') # 提供配置文件
其中 run_config.yaml
的内容如下:
name: mnist_torch
auto_upload: true
folder: new-folder
make_folder: true
conflict_strategy: new
labels:
- torch
- CNN
description: Train a simple CNN model that classifies images of handwritten digits.
设定超参数
基本方法
超参数是影响模型训练效果的重要因素,记录训练的超参数十分必要,尤其是当你聚焦于某几个特定的超参数时。Run
实例的 hparams
属性是一个容器对象,用于保存你想要记录的所有超参数,你可以像操作 Python 字典一样操作它。一种推荐的设定超参数的方法是调用一次该容器对象的 update()
方法完成所有超参数的设定。
run.hparams.update({
'batch_size': 32,
'epochs': 10,
'learning_rate': 0.001,
'conv_channels': 32,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features': 64,
})
hparams = run.hparams # 便于之后访问
另一种推荐的方法是在创建 Run 的时候就传入所有超参数,此时可以将超参数也写进配置文件。
run = em.create_run(
name='mnist_torch',
hparams={
'batch_size': 32,
'epochs': 10,
'learning_rate': 0.001,
'conv_channels': 32,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features': 64,
})
# 或
run = em.create_run(config_path='./run_config.yaml')
其中 run_config.yaml
的内容如下:
name: mnist_torch
hparams:
batch_size: 32
epochs: 10
learning_rate: 0.001
conv_channels: 32
conv_kernel_size: 3
maxpool_size: 2
linear_features: 64
当然,你也可以多次调用 update()
方法,或者使用类似 Python 字典的键值对赋值方法设定单个超参数。
run.hparams['batch_size'] = 32
设定完成之后,使用这些超参数配置模型,同样使用类似 Python 字典的键值对访问方法。
from tensorflow.keras import layers, models, optimizers
model = models.Sequential()
model.add(layers.Conv2D(hparams['conv_channels'], # 使用超参数配置模型
hparams['conv_kernel_size'],
input_shape=(28, 28, 1)))
...
optimizer = optimizers.Adam(learning_rate=hparams['learning_rate'])
model.compile(
optimizer=optimizer,
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
...
model.fit(train_images,
train_labels,
batch_size=hparams['batch_size'],
epochs=hparams['epochs'])
设定作为标记的超参数
在上面的示例中,所有超参数都是直接传入各函数以配置模型。你也可以设定一些作为标记的超参数,例如网络类型、优化器类型、损失函数类型、激活函数类型等,以便日后快速回顾重要信息。
run.hparams.update({
'network_structure': 'CNN',
'optimizer': 'Adam',
'loss': 'sparse categorical crossentropy',
'linear_acti': 'relu',
})
配合 argparse 模块使用
许多训练脚本的超参数都是从命令行传入,由 argparse
模块解析。这些超参数可以方便地转换为字典对象并传入 update()
方法。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(...)
args = parser.parse_args()
run.hparams.update(args.__dict__)
记录指标
手动记录
Run
实例的 log()
方法用于记录模型在训练、验证或测试过程中产生的指标。被传入的字典对象会被作为指标记录,与此同时还需要提供指标的类型、当前的全局训练步数以及(可选的)当前的回合数。
# PyTorch模型
for epoch in range(1, epochs + 1):
model.train()
for step, (data, target) in enumerate(train_loader, 1):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if step % 500 == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
run.log(
type='train', # 指标类型
metrics={'loss': train_loss}, # 指标名称及相应值
step=global_step, # 当前全局步数
epoch=epoch) # 当前回合数
自动记录
对于建立在 Keras API 上的模型,更简单的方法是在模型的训练和测试方法中分别添加回调 t9k.em.keras.EMFitCallback
和 t9k.em.keras.EMEvalCallback
的实例。回调会相应地调用 log()
方法以自动记录各指标并同步到服务器。
# Keras模型
# 训练/验证过程和测试过程分别使用不同的回调
from t9k.em.keras import EMFitCallback, EMEvalCallback
model.fit(train_images,
train_labels,
epochs=10,
validation_split=0.2,
callbacks=EMFitCallback(run))
model.evaluate(test_images,
test_labels,
callbacks=EMEvalCallback(run))
结束 Run
模型的训练与测试全部完成后,你需要结束 Run,通过调用 Run
实例的 finish()
方法。此方法调用后,Run 的状态将更新为“Complete”。
run.finish()
创建 Artifact
基本方法
如要记录和保存与训练过程有关的文件,你需要创建一个 Artifact,通过调用 t9k.em.create_artifact()
函数。此方法调用后,Artifact 将被创建,其本地文件默认保存在相对路径 .em/artifacts
下。与 Run 相同,每个 Artifact 拥有一个独立的名为 <artifact_name>
最基本的初始化方法只需要提供名称作为参数。
dateset_artifact = em.create_artifact(name='mnist_dataset')
提供标签和描述
你可以为创建的 Artifact 提供用于分类或介绍的标签或描述。
dateset_artifact = em.create_artifact(
name='mnist_dataset',
labels=['dataset', 'MNIST'], # 标签
description='Image dataset of handwritten digits.') # 描述
为 Artifact 添加文件
与训练过程有关的文件通过 Artifact
实例的 add_file()
和 add_dir()
方法添加到 Artifact 中。
dateset_artifact.add_file(file_path='./mnist.npz') # 添加单个文件
dateset_artifact.add_dir(dir_path='./mnist/') # 添加目录
Artifact 中的文件对象具有层次结构,你可以指定文件或目录位于 Artifact 的何路径下。
dateset_artifact.add_file(file_path='./mnist.npz', obj_path='dataset/')
dateset_artifact.add_dir(dir_path='./mnist/', obj_path='dataset/')
还可以通过 add_reference()
方法为 Artifact 添加一个网络文件的引用。
dateset_artifact.add_reference(uri='https://storage.googleapis.com/cvdf-datasets/mnist/train-images-idx3-ubyte.gz', obj_path='dataset/')
标记 Artifact 为 Run 的输入输出
为了构成 Run 与 Artifact 之间的数据流,需要调用 Run
实例的 mark_input()
和 mark_output()
方法以标记 Artifact
实例为其输入或输出。
run.mark_input(dateset_artifact)
run.mark_output(model_artifact)
上传数据
基本方法
上传数据之前,你需要先登录到 AIStore 服务器,通过调用 t9k.em.login()
函数。
em.login(ais_host='<your-server-host>', api_key='<your-api-key>')
然后调用 Run
或 Artifact
实例的 upload()
方法。
run.upload()
artifact.upload()
上传本地保存的数据
你也可以在训练结束之后将本地保存的数据上传到 AIStore 服务器,以应对训练时无网络连接、最初未打算上传、误删服务器中的数据等情形。
首先登录到 AIStore 服务器,然后加载保存在本地的 Run 或 Artifact,调用其 upload()
方法。
run = em.load_run(path='.em/runs/mnist_torch_231222_141932_61p5jc')
run.upload(folder='default', make_folder=True)
artifact = em.load_artifact(path='.em/runs/mnist_torch_saved_model_230908_165433_tou3ai')
artifact.upload(folder='default', make_folder=True)
下一步
- 进一步学习如何在单设备训练场景下追踪模型训练
单设备训练场景
本教程演示如何记录并展示单设备训练场景下的训练产生的信息、指标和文件(以 PyTorch 模型在单个 CPU 或 GPU 上的训练为例)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
下面介绍训练脚本进行了哪些修改以追踪训练。
准备训练脚本
准备一个 PyTorch 训练脚本,其模型对 MNIST 数据集的图像进行分类,具体代码如下所示。接下来将在此脚本的基础上进行简单的修改以进行追踪。
torch_mnist.py
import argparse
import logging
import os
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
parser = argparse.ArgumentParser(
description='Recording of training data of PyTorch model for MNIST with EM.'
)
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 64, 1)
self.conv3 = nn.Conv2d(64, 64, 3, 1)
self.pool = nn.MaxPool2d(2, 2)
self.dense1 = nn.Linear(576, 64)
self.dense2 = nn.Linear(64, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.dense1(x))
output = F.softmax(self.dense2(x), dim=1)
return output
def train(scheduler):
global global_step
for epoch in range(1, epochs + 1):
model.train()
for step, (data, target) in enumerate(train_loader, 1):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if step % 500 == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
scheduler.step()
global_step = epoch * steps_per_epoch
test(val=True, epoch=epoch)
def test(val=False, epoch=None):
label = 'val' if val else 'test'
model.eval()
running_loss = 0.0
correct = 0
with torch.no_grad():
loader = val_loader if val else test_loader
for data, target in loader:
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target)
running_loss += loss.item()
prediction = output.max(1)[1]
correct += (prediction == target).sum().item()
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
logging.info(msg)
if __name__ == '__main__':
args = parser.parse_args()
use_cuda = not args.no_cuda and torch.cuda.is_available()
if use_cuda:
logging.info('Using CUDA')
device = torch.device('cuda' if use_cuda else 'cpu')
kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
torch.manual_seed(1)
model = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)
dataset_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'data')
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5), (0.5))])
train_dataset = datasets.MNIST(root=dataset_path,
train=True,
download=True,
transform=transform)
train_dataset, val_dataset = torch.utils.data.random_split(
train_dataset, [48000, 12000])
test_dataset = datasets.MNIST(root=dataset_path,
train=False,
download=True,
transform=transform)
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=32,
shuffle=True,
**kwargs)
val_loader = torch.utils.data.DataLoader(val_dataset,
batch_size=400,
shuffle=False,
**kwargs)
test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=1000,
shuffle=False,
**kwargs)
global_step = 0
epochs = 10
steps_per_epoch = len(train_loader)
train(scheduler)
test()
torch.save(model.state_dict(), 'model_state_dict.pt')
创建 Run
在建立模型之前,创建并初始化一个 Run
实例。
from t9k import em
if __name__ == '__main__':
...
run = em.create_run(name='mnist_torch') # Run 的名称
...
Run
实例的 hparams
属性用于保存超参数,使用类似 Python 字典的方法更新它以设定超参数。
if __name__ == '__main__':
...
run.hparams.update({
'batch_size': 32,
'epochs': 10,
'learning_rate': 0.001,
'learning_rate_decay_period': 1,
'learning_rate_decay_factor': 0.7,
'conv_channels1': 32,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
'seed': 1,
})
hparams = run.hparams
...
使用设定的超参数配置模型
使用上面设定的试验的超参数替换直接提供的超参数值,以配置模型各层、数据集、优化器、训练流程等。
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, hparams['conv_channels1'],
hparams['conv_kernel_size'], 1)
self.conv2 = nn.Conv2d(hparams['conv_channels1'],
hparams['conv_channels2'],
hparams['conv_kernel_size'], 1)
self.conv3 = nn.Conv2d(hparams['conv_channels2'],
hparams['conv_channels3'],
hparams['conv_kernel_size'], 1)
self.pool = nn.MaxPool2d(hparams['maxpool_size'],
hparams['maxpool_size'])
self.dense1 = nn.Linear(576, hparams['linear_features1'])
self.dense2 = nn.Linear(hparams['linear_features1'], 10)
...
if __name__ == '__main__':
...
torch.manual_seed(hparams['seed'])
...
optimizer = optim.Adam(model.parameters(), lr=hparams['learning_rate'])
scheduler = optim.lr_scheduler.StepLR(
optimizer,
step_size=hparams['learning_rate_decay_period'],
gamma=hparams['learning_rate_decay_factor'])
...
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=hparams['batch_size'],
shuffle=True,
**kwargs)
...
epochs = hparams['epochs']
...
记录指标
在模型的训练和测试过程中调用 Run
实例的 log()
方法,以记录模型在此期间产生的指标。
def train(scheduler):
...
if step % 500 == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
run.log(type='train', # 记录训练指标
metrics={'loss': train_loss}, # 指标名称及相应值
step=global_step, # 当前全局步数
epoch=epoch) # 当前回合数
...
def test(val=False, epoch=None):
...
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
logging.info(msg)
run.log(type=label, # 记录验证/测试指标
metrics={
'loss': test_loss,
'accuracy': test_accuracy,
},
step=global_step,
epoch=epoch)
创建 Artifact 并添加模型检查点文件
在保存模型检查点文件之后,创建并初始化一个新的 Artifact
实例,为其添加该检查点文件,并标记为 Run 的输出。
if __name__ == '__main__':
...
torch.save(model.state_dict(), 'model_state_dict.pt')
model_artifact = em.create_artifact(name='mnist_torch_saved_model')
model_artifact.add_file('model_state_dict.pt')
run.mark_output(model_artifact)
...
结束和上传 Run
模型的训练和测试结束后,调用 Run
实例的 finish()
和 upload()
方法以结束和上传 Run(Artifact 也会被一并上传)。在上传之前需要调用 em.login()
函数以登录到 AIStore 服务器。
if __name__ == '__main__':
...
run.finish()
em.login()
run.upload(folder='em-examples', make_folder=True)
检查 Run 和 Artifact
训练结束后,进入实验管理控制台,可以看到名为 mnist_torch 的 Run 及其输出的 Artifact 被上传:
点击 Run 或 Artifact 的名称进入其详情页面,可以看到 Run 的平台信息、指标、超参数和数据流,以及 Artifact 的文件和数据流。并且它们的数据流是连通的。
下一步
- 进一步学习如何在分布式训练场景下追踪模型训练
- 进一步学习如何在实验管理控制台查看 AutoTune
分布式训练场景
本教程演示如何记录并展示 PyTorchTrainingJob 分布式训练场景下的训练产生的信息、指标和文件(以 PyTorch 模型的数据并行训练为例)。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
下面介绍训练脚本进行了哪些修改以追踪训练。该方法是通用的,可以推广到任意类型的 TrainingJob、DeepSpeedJob、ColossalAIJob、MPIJob 或 GenericJob。
准备训练脚本
准备一个 PyTorch 训练脚本,其模型对 MNIST 数据集的图像进行分类,使用 DistributedDataParallel
(DDP)模块进行分布式训练,具体代码如下所示(这里使用与使用 PyTorchTrainingJob 进行数据并行训练相同的脚本)。接下来将在此脚本的基础上进行简单的修改以进行追踪。
torch_mnist_trainingjob_em.py
import argparse
import logging
import os
import shutil
import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parallel import DistributedDataParallel as DDP
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms
parser = argparse.ArgumentParser(
description='Distributed training of Keras model for MNIST with DDP.')
parser.add_argument(
'--backend',
type=str,
help='Distributed backend',
choices=[dist.Backend.GLOO, dist.Backend.NCCL, dist.Backend.MPI],
default=dist.Backend.GLOO)
parser.add_argument('--log_dir',
type=str,
default='/mnt/log',
help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.conv3 = nn.Conv2d(64, 64, 3, 1)
self.pool = nn.MaxPool2d(2, 2)
self.dense1 = nn.Linear(576, 64)
self.dense2 = nn.Linear(64, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = F.relu(self.conv3(x))
x = torch.flatten(x, 1)
x = F.relu(self.dense1(x))
output = F.softmax(self.dense2(x), dim=1)
return output
def train(scheduler):
global global_step
for epoch in range(1, epochs + 1):
model.train()
for step, (data, target) in enumerate(train_loader, 1):
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
if step % (500 // world_size) == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
if args.log_dir and rank == 0:
writer.add_scalar('train/loss', train_loss, global_step)
scheduler.step()
global_step = epoch * steps_per_epoch
test(val=True, epoch=epoch)
def test(val=False, epoch=None):
label = 'val' if val else 'test'
model.eval()
running_loss = 0.0
correct = 0
with torch.no_grad():
loader = val_loader if val else test_loader
for data, target in loader:
data, target = data.to(device), target.to(device)
output = model(data)
loss = criterion(output, target)
running_loss += loss.item()
prediction = output.max(1)[1]
correct += (prediction == target).sum().item()
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
logging.info(msg)
if args.log_dir and rank == 0:
writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
global_step)
if __name__ == '__main__':
args = parser.parse_args()
use_cuda = not args.no_cuda and torch.cuda.is_available()
if use_cuda:
logging.info('Using CUDA')
device = torch.device("cuda" if use_cuda else "cpu")
kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}
logging.info('Using distributed PyTorch with {} backend'.format(
args.backend))
dist.init_process_group(backend=args.backend)
rank = dist.get_rank()
world_size = dist.get_world_size()
torch.manual_seed(1)
model = Net().to(device)
model = DDP(model)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001 * world_size)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5), (0.5))])
train_dataset = datasets.MNIST(root='./data',
train=True,
download=False,
transform=transform)
train_dataset, val_dataset = torch.utils.data.random_split(
train_dataset, [48000, 12000])
test_dataset = datasets.MNIST(root='./data',
train=False,
download=False,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset,
batch_size=32 * world_size,
shuffle=True,
**kwargs)
val_loader = torch.utils.data.DataLoader(val_dataset,
batch_size=400,
shuffle=False,
**kwargs)
test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size=1000,
shuffle=False,
**kwargs)
if args.log_dir and rank == 0:
log_dir = args.log_dir
if os.path.exists(log_dir):
shutil.rmtree(log_dir, ignore_errors=True)
writer = SummaryWriter(log_dir)
global_step = 0
epochs = 10
steps_per_epoch = len(train_loader)
train(scheduler)
test()
创建 Run
创建一个包含所有(想要记录的)超参数的 Python 字典。
from t9k import em
if __name__ == '__main__':
...
hparams = {
'batch_size': 32 * world_size,
'epochs': 10,
'learning_rate': 0.001 * world_size,
'learning_rate_decay_period': 1,
'learning_rate_decay_factor': 0.7,
'conv_channels1': 32,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
'seed': 1,
}
...
指定一个工作器负责在建立模型之前创建并初始化一个 Run
实例,传入名称和上面的超参数字典。
if __name__ == '__main__':
...
if rank == 0:
run = em.create_run(name='mnist_torch_distributed', hparams=hparams)
...
使用设定的超参数配置模型
使用上面的超参数字典的值替换直接提供的超参数值,以配置模型各层、数据集、优化器、训练流程等。
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, hparams['conv_channels1'],
hparams['conv_kernel_size'], 1)
self.conv2 = nn.Conv2d(hparams['conv_channels1'],
hparams['conv_channels2'],
hparams['conv_kernel_size'], 1)
self.conv3 = nn.Conv2d(hparams['conv_channels2'],
hparams['conv_channels3'],
hparams['conv_kernel_size'], 1)
self.pool = nn.MaxPool2d(hparams['maxpool_size'],
hparams['maxpool_size'])
self.dense1 = nn.Linear(576, hparams['linear_features1'])
self.dense2 = nn.Linear(hparams['linear_features1'], 10)
...
if __name__ == '__main__':
...
torch.manual_seed(hparams['seed'])
...
optimizer = optim.Adam(model.parameters(), lr=hparams['learning_rate'])
scheduler = optim.lr_scheduler.StepLR(
optimizer,
step_size=hparams['learning_rate_decay_period'],
gamma=hparams['learning_rate_decay_factor'])
...
train_loader = torch.utils.data.DataLoader(
train_dataset,
batch_size=hparams['batch_size'],
shuffle=True,
**kwargs)
...
epochs = hparams['epochs']
...
记录指标
在模型的训练和测试过程中,被指定的工作器调用 Run
实例的 log()
方法以记录模型在此期间产生的指标。
def train(scheduler):
...
if step % (500 // world_size) == 0:
train_loss = loss.item()
logging.info(
'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
format(epoch, epochs, step, steps_per_epoch, train_loss))
global_step = (epoch - 1) * steps_per_epoch + step
if rank == 0:
run.log(type='train', # 记录训练指标
metrics={'loss': train_loss}, # 指标名称及相应值
step=global_step, # 当前全局步数
epoch=epoch) # 当前回合数
...
def test(val=False, epoch=None):
...
test_loss = running_loss / len(loader)
test_accuracy = correct / len(loader.dataset)
msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
label, test_loss, label, test_accuracy)
if val:
msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
logging.info(msg)
if rank == 0:
run.log(type=label, # 记录验证/测试指标
metrics={
'loss': test_loss,
'accuracy': test_accuracy,
},
step=global_step,
epoch=epoch)
创建 Artifact 并添加模型检查点文件
在保存模型检查点文件之后,被指定的工作器创建并初始化一个新的 Artifact
实例,为其添加该检查点文件,并标记为 Run 的输出。
if __name__ == '__main__':
...
if rank == 0:
torch.save(model.state_dict(), 'model_state_dict.pt')
model_artifact = em.create_artifact(name='mnist_torch_saved_model')
model_artifact.add_file('model_state_dict.pt')
run.mark_output(model_artifact)
...
结束和上传试验
模型的训练和测试结束后,被指定的工作器调用 Run
实例的 finish()
和 upload()
方法以结束和上传 Run(Artifact 也会被一并上传)。在上传之前需要调用 em.login()
函数以登录到服务器。
if __name__ == '__main__':
...
if rank == 0:
run.finish()
em.login()
run.upload(folder='em-examples', make_folder=True)
检查 Run 和 Artifact
训练结束后,进入实验管理控制台,可以看到名为 mnist_torch_distributed 的 Run 及其输出的 Artifact 被上传:
点击 Run 或 Artifact 的名称进入其详情页面,可以看到 Run 的平台信息、指标、超参数和数据流,以及 Artifact 的文件和数据流。并且它们的数据流是连通的。
在实验管理控制台查看 AutoTune
如果 AutoTune 使用 AIStore 作为数据库,那么 AutoTune 会自动记录实验以及其中所有试验的数据到 AIStore 中。
参照使用 AutoTune 进行超参数优化创建一个 AutoTuneExperiment。唯一需要修改的部分是,将 AutoTuneExperiment 配置文件的 spec.em.folder
字段修改为文件夹 em-examples
的 ID。
创建完成之后,进入实验管理控制台,可以看到 em-examples/
路径下出现了一个名为 keras-mnist-autotune 的 AutoTune:
点击其名称进入详情页面,可以看到 AutoTuneExperiment 的信息、当前进度、各试验的信息以及可视化图表:
点击任意一个试验的右侧的详情可以看到试验使用的超参数以及指标:
构建自动化工作流
这一部分演示如何使用工作流系统进行 AI 开发和实验,帮助管理 AI 项目中数据清洗、特征工程、模型训练、评估等多个步骤之间的依赖关系,确保它们以正确的顺序执行,并提高可复用性。
创建工作流的基本单元
本教程演示如何创建工作流的基本单元。
准备工作
- 了解 WorkflowTemplate 和 WorkflowRun 的基本概念。
- 成为一个项目的管理员或成员。
创建 WorkflowTemplate
在浏览器中进入工作流控制台之后,点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击右上角的 Project 框选择一个 Project,然后点击列表右上角的 + 在该 Project 中创建一个 WorkflowTemplate。
进入创建 WorkflowTemplate 页面之后,左侧的表格和右侧的 YAML 都可以进行编辑,并且两侧始终是同步变化的。你可以在此填写所要创建的 WorkflowTemplate。
首先,你需要在名为 WorkflowTemplate Name 的文本框中填写 WorkflowTemplate 的名称,然后在名为 Type 的下拉框中选择 WorkflowTemplate 的类型(可以是 Pod
、SeqPod
、Resource
等),最后根据 WorkflowTemplate 类型的不同,继续填写余下配置。
编辑好 WorkflowTemplate 之后,点击表格右上角的 Create WorkflowTemplate 创建该 WorkflowTemplate,右下角会有悬浮框提示是否创建成功。
创建 WorkflowRun
再次点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,找到你刚才创建的 WorkflowTemplate hello,点击 WorkflowTemplate 的名称进入 WorkflowTemplate 的详情页面。
在 WorkflowTemplate 的详情页面,你可以点击 SPECS 或 YAML 标签查看 WorkflowTemplate 的详细情况,检查是否有错误。如果没有错误,点击右上角的 Create WorkflowRun 为该 WorkflowTemplate 创建一个 WorkflowRun。
在弹出的创建 WorkflowRun 对话框中,按步骤依次填写 WorkflowRun 所需要的参数,最后点击 Create 创建 WorkflowRun,右下角会有悬浮框提示是否创建成功。
查看 WorkflowRun 运行情况
点击左侧导航菜单的 WorkflowRun 进入 WorkflowRun 列表页面,找到你刚刚创建的 WorkflowRun hello-run-3xrlm,点击 WorkflowRun 的名称进入 WorkflowRun 的详情页面。
在 WorkflowRun 的详情页面,你可以点击 LOGS、STATUS、SPECS 和 YAML 等标签,分别查看 WorkflowRun 的日志、状态、规约和 YAML。如果 WorkflowRun 正在运行而且其类型是 Pod 或 SeqPod,你可以点击 TERMINAL 标签,连接到 WorkflowRun 创建的 Pod 的某个容器的终端(shell),利用命令行工具进行调试。
创建执行各类任务的工作流单元
本教程演示如何创建执行各类任务的工作流单元。
准备工作
- 完成教程创建工作流的基本单元。
- 成为一个项目的管理员或成员。
创建类型为 Pod
和 SeqPod
的 WorkflowTemplate
如 WorkflowTemplate 介绍中所述,Pod
和 SeqPod
类型的区别在于,Pod
中的所有容器是一起(近乎同时)开始运行的,而 SeqPod
中的每个步骤是按照定义的顺序依次执行的。如无特殊情况,我们一般使用 SeqPod
类型即可。以下均以 SeqPod
类型为基础进行讲解。
选择镜像
在教程创建工作流的基本单元中,我们已经完成了 SeqPod
类型的 WorkflowTemplate 的创建和运行。如教程中所述,在 SeqPod
的每个步骤(step)中,都要填写所使用的镜像。一般来说,镜像的来源可能有以下几种:
- TensorStack AI 平台预先提供的镜像:例如 Notebook 镜像,或者 TensorStack 镜像站中的任何镜像。
- 第三方镜像:例如来自 Docker 官方镜像站 Docker Hub 的镜像。
- 自制镜像:你可以利用 TensorStack 命令行工具、Docker 命令行工具自行编译镜像。
准备好镜像之后,在 Image 框中填入镜像的地址。
执行 PVC 中的脚本
当你在 Notebook 中编写了一些 Python 脚本或 Shell 脚本后,你可以创建 WorkflowTemplate 以及对应的 WorkflowRun 来运行该脚本。只要 WorkflowRun 和 Notebook 绑定的是同一个 PVC,WorkflowRun 就能访问到你在 Notebook 中编写的脚本。
首先,在 Notebook 中编写想要运行的脚本,并 Ctrl+S 保存。
查看 Notebook 所绑定的 PVC 名称,以便创建 WorkflowRun 时使用。
按照下图所示填写表格,创建一个 SeqPod
类型的 WorkflowTemplate。
或者,你也可以复制粘贴下面的 YAML 配置文件来创建 WorkflowTemplate:
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
name: run-script
labels: {}
spec:
params: []
results: []
seqPod:
steps:
- args:
- $(workspaces.notebook-pvc.path)/run.py
command:
- python
image: 'registry.tensorstack.cn/t9k/tensorflow-2.8.0-notebook-cpu:1.50.0'
name: step1
resources:
limits:
cpu: 100m
memory: 200Mi
type: SeqPod
workspaces:
- description: the pvc used by notebook
name: notebook-pvc
然后,创建 WorkflowRun 来运行该 WorkflowTemplate。
WorkflowRun 运行完成后,可以看到打印结果与所编写的脚本运行预期结果一致。
执行自定义脚本
除了在 Notebook 中编写脚本,你还可以在创建 WorkflowTemplate 的过程中现场编写 Python 或 Shell 脚本。
如下图所示,创建 WorkflowTemplate 时选择类型为 SeqPod
,然后点击 Add Step,在 Step 中选择 Script 即可嵌入自定义脚本。
目前支持 Python 和 Shell 两种语言,可通过下拉框进行选择。
创建 WorkflowTemplate 和对应的 WorkflowRun 来运行,可以看到打印结果与脚本运行与其结果一致。
创建类型为 Resource
的 WorkflowTemplate
如 WorkflowTemplate 介绍中所述,Resource
类型的 WorkflowTemplate 用于创建一个 Kubernetes 资源。下面展示两个常用示例。
创建分布式训练
假设你已经有一个可以运行的 TrainingJob YAML 配置文件:
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
name: mnist
spec:
tensorboardSpec: # TensorBoard服务器规约
trainingLogFilesets:
- t9k://pvc/mnist/log # 日志文件路径
image: tensorflow/tensorflow:2.8.0
# TensorBoard服务器使用的镜像
replicaSpecs:
- type: worker # 工作器
replicas: 4 # 工作器数量
restartPolicy: ExitCode
template:
spec:
securityContext:
runAsUser: 1000
containers:
- image: tensorflow/tensorflow:2.8.0
# 容器的镜像
workingDir: /mnt
name: tensorflow
command: # 执行`python`命令以执行训练脚本
- sh
- '-c'
- >-
python /mnt/keras_mnist_trainingjob.py --log_dir /mnt/log --save_path /mnt/saved_model
--no_cuda
env: []
resources:
limits: # 限制量
cpu: '4' # CPU
memory: 2Gi # 内存
requests: # 请求量
cpu: '2'
memory: 1Gi
volumeMounts:
- name: data
mountPath: /mnt
volumes:
- name: data
persistentVolumeClaim:
claimName: mnist
如果你想将创建 TrainingJob 插入工作流中成为其中一个步骤,可以使用 Resource
类型的 WorkflowTemplate。如下图所示,在 WorkflowTemplate 创建页面,选择类型为 Resource
,然后将上面的 YAML 配置文件复制粘贴到 Resource Manifest 文本框中,即可创建一个 WorkflowTemplate 来运行这个 TrainingJob。
但是,由于在同一个项目中不能创建两个同名的 TrainingJob,上述方式创建的 WorkflowTemplate 只能运行一次,不具备可复用性。因此我们可以对 TrainingJob 配置文件做一些修改,利用 WorkflowTemplate 的指定参数功能,使其能被重复使用。
经过修改的 TrainingJob 配置文件如下:
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
name: $(params.trainingjob_name)
spec:
tensorboardSpec: # TensorBoard服务器规约
trainingLogFilesets:
- t9k://pvc/mnist/log # 日志文件路径
image: tensorflow/tensorflow:2.8.0
# TensorBoard服务器使用的镜像
replicaSpecs:
- type: worker # 工作器
replicas: 4 # 工作器数量
restartPolicy: ExitCode
template:
spec:
securityContext:
runAsUser: 1000
containers:
- image: tensorflow/tensorflow:2.8.0
# 容器的镜像
workingDir: /mnt
name: tensorflow
command: # 执行`python`命令以执行训练脚本
- sh
- '-c'
- >-
python /mnt/keras_mnist_trainingjob.py --log_dir /mnt/log --save_path /mnt/saved_model
--no_cuda
env: []
resources:
limits:
cpu: '4'
memory: 4Gi
requests:
cpu: '2'
memory: 2Gi
volumeMounts:
- name: data
mountPath: /mnt
volumes:
- name: data
persistentVolumeClaim:
claimName: $(params.pvc_name)
改动有两处:
metadata.name
从固定的mnist
改为$(params.trainingjob_name)
。spec.replicaSpecs.template.volumes.persistentVolumeClaim.claimName
从固定的mnist
改为$(params.pvc_name)
。
这两个改动使得 TrainingJob 的名称和所使用的 PVC 的名称在运行时才被传入,这样创建的 WorkflowTemplate 就能够多次重复使用了。
在 WorkflowTemplate 创建页面,将上述改动过的 Trainingjob 配置文件复制粘贴到 Resource Manifest 文本框中,并为 WorkflowTemplate 添加两个参数,分别名为 trainingjob_name
和 pvc_name
,然后点击 Create WorkflowTemplate 进行创建。
在创建 WorkflowRun 时,为 trainingjob_name
和 pvc_name
这两个参数提供实际值。
等待 WorkflowRun 完成运行。
创建推理服务
与创建分布式训练类似,我们可以在简单推理服务的 YAML 配置文件基础上,加入可变的参数:
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: $(params.simplemlservice_name)
spec:
replicas: 1
storage:
pvc:
containerPath: /var/lib/t9k/models/mnist
name: tutorial
subPath: tutorial-examples/deployment/model/tensorflow/mnist
tensorflow:
image: t9kpublic/tensorflow-serving:2.6.0
在 WorkflowTemplate 创建页面,将上述 YAML 配置文件复制粘贴到 Resource Manifest 文本框中,并为 WorkflowTemplate 添加一些参数。
创建 WorkflowTemplate,然后创建对应的 WorkflowRun 并提供参数的实际值。
与分布式训练不同,推理服务是一个长时间运行的服务,没有结束时间。因此所创建的 WorkflowRun 也不会结束运行,而是一直处于 Running 状态。
创建存在依赖关系的工作流
本教程演示如何创建存在依赖关系的工作流。
准备工作
- 完成教程创建工作流的基本单元。
- 了解 DAG WorkflowTemplate 的基本概念。
- 成为一个项目的管理员或成员。
创建一些简单的 WorkflowTemplate
在浏览器中进入工作流控制台之后,点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击右上角的 Project 选择框选择一个 Project。
本教程使用创建工作流的基本单元教程中创建好的 WorkflowTemplate hello 即可。如果有需要,你可以点击列表右上角的加号,按照创建工作流的基本单元教程中的步骤,创建一些简单的 WorkflowTemplate。
创建 DAG WorkflowTemplate
点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击列表右上角的树状图标来创建一个 DAG WorkflowTemplate。
进入创建 DAG WorkflowTemplate 页面之后,除了最左侧的导航菜单之外整个页面分为三个部分,左边是 WorkflowTemplate 列表,中间是用于组建 DAG 的画布,右边是 DAG WorkflowTemplate 的详情。你可以从左边的 WorkflowTemplate 列表中用鼠标选取一个 WorkflowTemplate 拖拽到中间的画布上,然后通过绿色锚点连接多个 WorkflowTemplate,表示它们的执行顺序。画布中所有的 WorkflowTemplate 由依赖关系组成一个有向无环图(DAG)。
建立好有向无环图之后,你可以在右边的表格编辑 DAG WorkflowTemplate 的详情,例如 WorkflowTemplate 的名称、工作空间、参数等。点击画布中的方块即可编辑该节点的详情,点击画布的空白处可以编辑整个 DAG WorkflowTemplate 的详情。
最后,点击表格上方的 Create DAG WorkflowTemplate 创建该 DAG WorkflowTemplate,右下角会有悬浮框提示是否创建成功。
创建 WorkflowRun
再次点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,找到你刚刚创建的 WorkflowTemplate hello-again,点击 WorkflowTemplate 的名称进入 WorkflowTemplate 的详情页面。
在 WorkflowTemplate 的详情页面,点击右上角的 Create WorkflowRun 为该 WorkflowTemplate 创建一个 WorkflowRun。
在弹出的创建 WorkflowRun 对话框中。按步骤依次填写 WorkflowRun 所需要的参数,最后点击 Create 创建 WorkflowRun,右下角会有悬浮框提示是否创建成功。
查看 WorkflowRun 运行情况
点击左侧导航菜单的 WorkflowRun 进入 WorkflowRun 列表页面,找到你刚刚创建的 WorkflowRun hello-again-run-9214x,点击 WorkflowRun 的名称进入 WorkflowRun 的详情页面。
在 WorkflowRun 的详情页面,你可以点击 GRAPH 标签,查看 DAG 的详细情况,点击 DAG 的节点可以在弹框中查看节点的详细情况。
建立从数据采样到模型导出的自动化工作流
本教程演示如何建立一个端到端的机器学习工作流,包括数据预处理、模型训练、模型分析等步骤。本教程使用的机器学习应用样例是一个二分类问题,根据乘客搭乘出租车的位置、路程、用时等特征数据预测乘客是否会付小费。
准备工作
- 完成教程创建存在依赖关系的工作流。
- 成为一个项目的管理员或成员。
运行示例
请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。
查看运行结果
成功创建 WorkflowRun 之后,进入工作流控制台的 WorkflowRun 列表页面,可以看到名为 taxi-tips-prediction-run-75v60 的 WorkflowRun 正在运行:
点击该名称 进入详情页面,可以看到刚才创建的 WorkflowRun 的详细运行状态:
本页面会自动刷新以获取 WorkflowRun 的最新状态,你也可以点击右上角的刷新图标手动刷新。
调度工作负载
使用队列
概述
队列是 T9k 平台中资源管理的机制,用于补充 K8s 原生平台在 scheduling 方面的不足。管理员可以为队列设定使用权限,资源来源的集群节点,资源配额,最大运行时长等属性,以精细化管理集群。
用户在创建使用调度器 T9k Scheduler 的工作负载时,需为工作负载指定一个队列。
为工作负载指定队列
根据工作负载的种类,指定队列的方式如下。
v1/Pod
创建 Pod 时,有两种指定所属队列的方式:
- 直接指定队列:此类 Pod 不属于任何 PodGroup。
- 通过 PodGroup 间接指定队列:此类 Pod 属于所指定的 PodGroup。
直接指定队列
Pod 通过标签来表明他属于哪一个队列,标签的 key 是 scheduler.tensorstack.dev/queue
。
在下面的示例中,Pod 指定了队列 demo:
apiVersion: v1
kind: Pod
metadata:
name: test1
labels:
scheduler.tensorstack.dev/queue: demo
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 1
memory: 200Mi
通过 PodGroup 指定队列
如果 Pod 属于某个 PodGroup,那么 PodGroup 指定的队列就是这个 Pod 所属的队列。
Pod 如何指定 PodGroup 请参考 使用 PodGroup
T9k Jobs
T9k Job 包括 TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、GenericJob、MPIJob、ColossalAIJob、DeepSpeedJob 和 BeamJob,这些 Job 中都有相同的 spec.scheduler
字段。
创建 T9k Job 时,用户可以通过设置 spec.scheduler
字段来表明使用 T9k scheduler,并指定 Job 使用哪个队列。
在下面的示例中:spec.scheduler.t9kScheduler.queue
字段表明 Job 使用的队列是 demo,GenericJob 控制器会自动创建使用队列 demo 的 PodGroup 和 Pod。
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
name: job-sample
spec:
scheduler:
t9kScheduler:
queue: demo
priority: 10
replicaSpecs:
- type: worker
replicas: 4
...
- type: ps
replicas: 1
...
T9k PodGroup
创建 PodGroup 时,通过 spec.queue
字段来表明 PodGroup 所使用的队列。
在下面的示例中,PodGroup 表明自己使用的队列是 demo:
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: test
spec:
minMember: 2
queue: demo
priority: 50
batch/v1/Job
与 v1/Pod 类似,创建 batch/v1 Job 使用队列时,需要通过设置 Pod 的标签来表明 Pod 所使用的队列。有两种设置 Pod 标签的方法:
- 直接指定队列:为 Pod 设置标签
scheduler.tensorstack.dev/queue:<queue-name>
表明 Pod 所使用的队列。 - 通过 PodGroup 间接指定队列:为 Pod 设置标签
scheduler.tensorstack.dev/group-name:<group-name>
表明 Pod 所属的 PodGroup,PodGroup 使用的队列就是 Pod 使用的队列。
在下面的示例中,Job 通过为 Pod 设置标签 scheduler.tensorstack.dev/queue:demo
来表明使用队列 demo。
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
parallelism: 2
template:
metadata:
labels:
scheduler.tensorstack.dev/queue: demo
spec:
schedulerName: t9k-scheduler
containers:
- name: create
image: nginx:latest
command:
- sleep
- 10s
resources:
requests:
cpu: 1
memory: 100Mi
restartPolicy: Never
使用 PodGroup
概念
PodGroup 是 namespaced-scoped 资源对象,代表一组协同工作的 Pod。PodGroup spec 中定义了 coscheduling 和其他相关的配置信息,调度器 T9k Scheduler 会根据这些信息为 Pod 分配资源。
使用 PodGroup
根据工作负载的种类,创建并使用 PodGroup 的方式如下。
Pod
一般仅需要通过 Job 控制器自动化地实现对 PodGroup 的使用。工作负载控制器的编程者,或者需手工设定 pod 的 PodGroup,可参考本节内容。
用户创建一组使用调度器 T9k Scheduler 进行协同工作的 Pod 时,需要:
- 先在相同的 namespace 中创建一个 PodGroup
- 为 Pod 添加标签
scheduler.tensorstack.dev/group-name: <PodGroup-name>
来表明 Pod 属于步骤一创建的 PodGroup
示例1 - 基本场景
首先需要创建一个 PodGroup:
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: dance
spec:
minMember: 2
queue: default
priority: 50
然后创建 2 个 Pod 并指定 PodGroup,Pod 通过标签 scheduler.tensorstack.dev/group-name: dance
表明他们属于 PodGroup dance。
apiVersion: v1
kind: Pod
metadata:
name: test1
labels:
scheduler.tensorstack.dev/group-name: dance
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 1
memory: 200Mi
--
apiVersion: v1
kind: Pod
metadata:
name: test2
labels:
scheduler.tensorstack.dev/group-name: dance
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 1
memory: 200Mi
示例2 - 使用 role
本示例展示有 2 个 role 并设置了 role minMember 的 PodGroup 使用场景。
创建 PodGroup
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: role-test
spec:
roles:
- name: master
minMember: 1
- name: worker
minMember: 1
minMember: 3
queue: default
priority: 50
说明:上面这个 PodGroup 的最小运行需求如下,这些需求都被满足了,调度器才会为 PodGroup 中的 Pod 分配资源:
- PodGroup 的 Pod 数量需要达到 3
- 角色名称是 master 的 Pod 数量需要达到 1
- 角色名称是 worker 的 Pod 数量需要达到 1
创建 Pod:
apiVersion: v1
kind: Pod
metadata:
name: master
labels:
scheduler.tensorstack.dev/group-name: role-test
scheduler.tensorstack.dev/role: master
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 100m
memory: 200Mi
--
apiVersion: v1
kind: Pod
metadata:
name: worker
labels:
scheduler.tensorstack.dev/group-name: role-test
scheduler.tensorstack.dev/role: worker
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 100m
memory: 200Mi
--
apiVersion: v1
kind: Pod
metadata:
name: worker1
labels:
scheduler.tensorstack.dev/group-name: role-test
scheduler.tensorstack.dev/role: worker
spec:
schedulerName: t9k-scheduler
containers:
- image: nginx:latest
name: test
resources:
requests:
cpu: 100m
memory: 200Mi
Pod 通过标签 scheduler.tensorstack.dev/role: <role-name>
来表明自己的角色名称。
T9k Jobs
T9k Job 包括 TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、GenericJob、MPIJob、ColossalAIJob、DeepSpeedJob 和 BeamJob,这些 Job 中都有相同的 spec.scheduler
字段。
创建 T9k Job 时,用户可以通过设置 spec.scheduler
字段来表明使用 T9k scheduler,并指定 Job 使用哪个队列,然后控制器会自动地创建 PodGroup、并创建 Pod 使用这个 PodGroup。
基本示例
本示例适用于未启用弹性训练的 Job。
以下面这个 GenericJob 为例:
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
name: job-sample
spec:
scheduler:
t9kScheduler:
queue: default
priority: 10
replicaSpecs:
- type: worker
replicas: 4
...
- type: ps
replicas: 1
...
控制器在监测到上述 CRD 后,会创建一个 PodGroup:
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: job-sample
ownerReferences: [...]
spec:
minMember: 5
priority: 10
queue: default
其中,priority 和 queue 字段参考 job 的 spec.scheduler.t9kScheduler
中的信息设置,minMember 即为 job 所有副本的总数。
随后,控制器会在创建副本的 Pod 时,为 Pod 设置标签 scheduler.tensorstack.dev/group-name: job-sample
来使用上述 PodGroup。
apiVersion: v1
kind: Pod
metadata:
labels:
genericjob: job-sample
genericjob-replica: job-sample-worker-2
scheduler.tensorstack.dev/group-name: job-sample
scheduler.tensorstack.dev/queue: default
tensorstack.dev/component: genericjob
tensorstack.dev/component-type: user
name: job-sample-worker-0
namespace: dev-wangdi
ownerReferences: [...]
弹性训练
弹性训练要求训练规模可以动态调整,所以对 PodGroup 的设置也有所不同。
T9k Job 中,PyTorchTrainingJob 和 DeepSpeedJob 支持弹性训练,他们具有相同的 spec.elastic
字段,以此启动弹性训练。
以下面的 PyTorchTrainingJob 为例:
spec.elastic.enabled
是 true 表明启用弹性训练- PyTorchTrainingJob 支持最少 3 个副本、最多 10 个副本的训练规模
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
name: torch-mnist-trainingjob
spec:
scheduler:
t9kScheduler:
queue: default
priority: 10
elastic:
enabled: true
minReplicas: 3
maxReplicas: 10
expectedReplicas: 7
...
控制器在监测到上述 CRD 后,会创建下列 PodGroup,使用 spec.elastic.minReplicas
作为 PodGroup 的 spec.minMember
:
apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
name: torch-mnist-trainingjob
ownerReferences: [...]
spec:
minMember: 3
priority: 10
queue: default
使用平台存储
上传和下载文件
通过 PVC 使用集群存储非常方便,它可作为存储卷被挂载到 Notebook、Job、MLService 等各种工作负载的 Pod 中。例如在进行模型训练时,你可以把训练脚本以及训练数据存放到 PVC,然后挂载在 Job 的 Pod 中。
本教程将分场景介绍如何从集群外部上传文件到 PVC,以及如何从 PVC 下载文件到集群外部。
由于下面的部分方法需要使用到命令行工具,而 Notebook 提供了终端并且 Notebook 的镜像中预装了这些命令行工具,因此我们推荐把 PVC 挂载到一个 Notebook 上,然后在 Notebook 中进行操作。
本地文件系统
Notebook
把 PVC 挂载到 Notebook 上,本地文件系统和 PVC 之间的文件传输,可直接在 Notebook 的前端页面上操作:
File Browser
在 PVC 上启动 Explorer 之后,则可通过 File Browser :
云存储中转
也可通过其他云存储服务进行中转,即 本地 -> 云存储 -> 集群 PVC
:
- 本地与云存储之间的文件传输方法请参阅相应云存储的文档;
- 云存储与 PVC 之间的文件传输方法请参阅云存储服务。
云存储服务
要在云存储与 PVC 之间复制或同步文件,可以在 Notebook 的终端中使用命令行工具 rclone。这里以 Amazon S3 为例,首先参照 Amazon S3 Config 进行配置,完成后执行以下命令:
rclone copy <REMOTE>:<BUCKET>/path/to/the/file . # 从 S3 存储下载
rclone copy ./file <REMOTE>:<BUCKET>/path/to/the/ # 上传到 S3 存储
rclone sync <REMOTE>:<BUCKET>/path/to/the/dir . # 从 S3 存储同步
rclone sync . <REMOTE>:<BUCKET>/path/to/the/dir # 同步到 S3 存储
rclone 之外,还有其他方便的工具可供使用,例如 s3cmd、s5cmd 等。
HTTP/FTP 服务
要通过 HTTP(S)、(S)FTP 等协议从网络下载文件到 PVC,可以在 Notebook 的终端中使用 wget
或 curl
命令进行下载:
wget <URL>
curl -O <URL>
Git 仓库
可以在 Notebook 的终端中使用 git
命令,从 GitHub 等代码托管平台克隆或拉取项目,并在提交修改后推送回去:
git clone <repository>
git pull
git fetch
git push
Hugging Face Hub
Hugging Face Hub 是一个拥有超过 35 万个模型和 7.5 万个数据集的平台,所有这些模型和数据集都是开源并且公开可用的。从 Hugging Face Hub 下载一个模型或数据集有多种方法,下面以模型 mistralai/Mistral-7B-v0.1
为例进行演示,首先来到该模型的 Files and versions 标签页:
使用脚本
点击 Use in Transformers,按照提示进行操作,即在 Python 程序中调用 transformers
库加载模型。首次加载时,模型文件会被下载到缓存目录下,即 PVC 的 .cache/huggingface/hub/models--mistralai--Mistral-7B-v0.1/
路径下。
from transformers import pipeline
pipe = pipeline("text-generation", model="mistralai/Mistral-7B-v0.1")
# 或
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1")
使用 git
点击 Clone repository,按照提示进行操作,即使用 git
命令将模型的 Git 仓库直接克隆到 PVC 中:
# git lfs install # Notebook 的镜像中已经预装了 git-lfs,因此不必再执行
git clone https://huggingface.co/mistralai/Mistral-7B-v0.1
单个文件
如果只需要下载个别文件,例如只下载模型的 safetensors 文件,那么可以复制相应文件的下载链接,然后在终端中使用 wget
命令下载:
wget https://huggingface.co/mistralai/Mistral-7B-v0.1/resolve/main/model-00001-of-00002.safetensors?download=true
wget https://huggingface.co/mistralai/Mistral-7B-v0.1/resolve/main/model-00002-of-00002.safetensors?download=true
大规模数据
在处理大规模数据(如 100TB 级别)的导入和导出时,根据数据源的不同,我们采用不同的策略以确保数据传输的效率和安全性。以下是针对不同数据源的一些方法:
数据源为云存储时:
- 参照云存储服务操作。
数据源为 HDD/SDD 外置驱动器或类似设备时:
- 将驱动器连接到集群外的与集群网络连接速度较快的计算机上,然后参照本地文件系统继续操作。
- 或者,请求管理员操作,将驱动器连接到存储集群的节点上,直接使用存储系统的工具进行数据传输。这种方法的数据传输速度一般较快,但需要能够访问存储集群的工具和接口。
参考
https://github.com/s3tools/s3cmd
管理个人账户
这一部分演示如何使用生成并使用 API Key 来进行身份验证,以及如何管理自己负责的项目(如果你是项目管理员)。
生成 API Key
本教程演示如何生成一个 API Key。
准备工作
- 了解 API Key 的基本概念。
开启 API Key 服务
进入安全管理控制台之后,在左侧的导航菜单中点击账号 > API Key 进入 API Key 管理页面。如果你是第一次使用 API Key 服务,需要进行一次额外的登录认证。点击启用开始登录认证。
在弹出的对话框中,输入你的用户名和密码,并点击启用以开启 API Key 服务,右下角会有悬浮框提示是否成功。
生成一个 API Key
开启 API Key 服务之后,再次进入 API Key 管理页面,此时会列出你拥有的所有 API Key。点击右上角的创建新的 API Key 以生成一个新的 API Key。
在 API Key 生成页面,填写名称并勾选你想要包含在 API Key 中的权限,然后点击创建新的 API Key,右下角会有悬浮框提示是否成功。
使用 API Key
本教程演示几种 API Key 的使用实例。
在 TensorStack CLI 中使用 API Key
你可以使用以下命令并按照提示信息完成 API Key 的录入,随后命令行工具将使用该 API Key 作为用户身份凭证向平台服务器发送请求。
t9k config auth <server-address> -u <user-name> -k
登录操作实质上就是将身份信息记录在 T9k Config 文件中作为一个上下文(context),该配置文件中可以同时记录多个上下文,使用以下命令查看、切换和删除:
# 查看所有上下文
% t9k config get-contexts
CURRENT NAME SERVER AUTH_TYPE
* <config-name> <server-address> apikey
# 切换所要使用的上下文,即当前上下文
% t9k config use-context <config-name>
# 删除上下文
% t9k config delete-context <config-name>
关于 TensorStack CLI 的详细使用说明,请参阅CLI 用户指南。
使用 API Key 作为凭证向 AIStore 上传数据
你可以在模型训练中使用 API Key 作为凭证向 AIStore 上传数据。
通常的模型训练
在使用 Python SDK 将数据上传到 AIStore 中时,你需要调用 t9k.em
模块的 login()
函数进行身份验证,在不设置 login()
函数参数的情况下,SDK 会自动使用 T9k Config 文件中当前上下文中的身份信息,如果你想在训练时使用其他身份信息,则可以设置 ais_host
和 api_key
参数。
from t9k import em
# 使用 T9k Config 中当前上下文中的身份信息
em.login()
# 使用其他身份信息
em.login(ais_host='url-of-em-server', api_key='api-key-of-user')
AutoTuneExperiment
为了让 AutoTuneExperiment 能够使用 API Key,你需要创建一个 Secret 来存储 API Key,Secret 的格式如下:
apiVersion: v1
kind: Secret
metadata:
name: aistore-secret
namespace: t9k-example
data:
apikey: ZDQyMjJjZjUtMmI0Ni00Mjk2LWFiMzYtYWI4NmVhZGUwZjQx # API Key 的 Base64 编码
type: Opaque
在上述 Secret 中,在 data.apikey
字段中记录 API Key 的 Base64 编码。然后在 AutoTuneExperiment 的配置中引用这个 Secret,具体方式请参阅 AutoTuneExperiment 文档。
添加项目成员
本教程演示如何为一个项目添加成员。
准备工作
- 了解项目的基本概念。
- 成为一个项目的管理员。如果你不是任何一个项目的管理员,请联系平台管理员为你创建一个项目。
查看自己的项目
在浏览器中进入安全管理控制台之后,在左侧的导航菜单中点击资源 > 项目进入项目列表页面。其中,我的项目部分列出了所有你作为管理员的项目,分享给我的项目部分列出了所有你作为成员的项目。
为项目添加用户
在我的项目部分,点击其中一个项目的名称进入该项目的详情页面,这里展示了项目的所有成员(你是项目的管理员)。
点击成员右侧的修改按钮,再点击 ⊕ 为该项目添加成员。在弹出的对话框中,你需要选择所要添加的成员名以及该成员可使用的范围(scope),填写完成之后点击保存提交更改,右下角会有悬浮框提示是否添加成功。
小技巧
本教程汇总了一些实用的小技巧,可以帮助用户更好地使用平台。
让 Notebook 不被资源回收
如果想要让 Notebook 不被资源回收,可以在该 Notebook 中创建一个 Jupyter Notebook,并运行以下代码:
# To keep the kernel active
import time
while True:
time.sleep(60)
上述代码使 Notebook 保持活跃状态,而又不占用额外的计算资源。如要恢复对该 Notebook 的资源回收,只需停止上述代码的运行即可。
在终端中了解 Kubernetes API 资源及其字段
在创建、查看或调试 Kubernetes API 资源(包括 Kubernetes 原生资源和平台提供的 CRD)时,我们需要了解资源有哪些字段以及它们的含义。要获取这些信息,一种方法是查阅相应的参考文档,但更便捷的方式是在终端使用 kubectl explain
命令:
# 获取资源及其字段的描述
kubectl explain pod
# 获取资源的指定字段及其子字段的描述
kubectl explain pod.spec.containers
# 获取资源的所有子字段
kubectl explain pod --recursive
例如现在我们想要启用 DeepSpeedJob 的调试模式,但不知道该如何编写 YAML 配置文件,那么可以在 Notebook 的终端中执行以下命令:
kubectl explain dj --recursive # `dj` 是 DeepSpeedJob 的简称
输出应类似于:
KIND: DeepSpeedJob
VERSION: batch.tensorstack.dev/v1beta1
DESCRIPTION:
DeepSpeedJob defines the schema for the DeepSpeedJob API.
FIELDS:
...
spec <Object>
...
runMode <Object>
debug <Object>
enabled <boolean>
replicaSpecs <[]Object>
command <[]string>
skipInitContainer <boolean>
type <string>
pause <Object>
enabled <boolean>
resumeSpecs <[]Object>
args <[]string>
command <[]string>
skipInitContainer <boolean>
type <string>
...
...
由此我们得以写出正确的配置:
apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepspeedJob
metadata:
name: deepspeed-example
spec:
runMode:
debug:
enabled: true
...
查看容器的日志
查看 Pod 中的容器的日志有两种方法。第一种方法是在终端使用 kubectl logs
命令:
# 首先列举所有 Pod
kubectl get pod
# 返回指定 Pod 的(唯一容器的)日志快照
kubectl logs nginx
# 持续输出日志
kubectl logs -f nginx
# 返回日志的最后 20 行
kubectl logs --tail=20 nginx
# 返回最近 1 个小时的日志
kubectl logs --since=1h nginx
第二种方法是在控制台中查看。进入模型构建控制台,在左侧的导航菜单中点击构建 > Pod 进入 Pod 管理页面,然后点击 Pod 的名称进入详情页面:
点击日志右侧的按钮即可查看日志:
此外,部分 CRD 所创建的 Pod 的容器日志也可以从相应 CRD 的详情页面查看,请参阅:
命令行工具和 SDK
除了在网页控制台进行操作外,你还可以使用命令行工具和 Python SDK 来与 TensorStack AI 平台进行交互。
此外,命令行工具和 Python SDK 也为平台的部分功能提供支持。
命令行工具:t9k
TensorStack CLI(简称 T9k CLI)是 TensorStack AI 平台的命令行工具,用于对 TensorStack AI 平台的各种资源对象进行增、删、改、查操作。
功能
TensorStack CLI 目前包含了两大功能:其一是管理 T9k 集群计算资源分配,主要的使用者是 TensorStack AI 平台管理员;其二是管理 TensorStack AI 平台中被创建的作业、服务等资源,主要的使用者是使用平台进行机器学习模型开发、训练、部署等工作的数据科学家。
TensorStack CLI 的目标是:提供对于 T9k 自定义资源的有效支持。对于平台管理员来说,这些功能可以作为 kubectl 的补充来管理 TensorStack AI 平台。对于数据科学家来说,这些功能和控制台一起,帮助他们在 TensorStack AI 平台上开展机器学习相关的工作,而不需要过多的 Kubernetes 基础知识。
资源类型
T9k CLI 支持的资源类型有:
- 基于 Kubernetes 定义的,用来解决机器学习相关问题的 TensorStack AI 平台资源:
- AutoTune
- BeamJob
- ColossalAIJob
- DeepSpeedJob
- GenericJob
- MLService
- MPIJob
- Notebook
- PyTorchTrainingJob
- SimpleMLService
- TensorFlowTrainingJob
- WorkflowTemplate
- WorkflowRun
- XGBoostTrainingJob
- 基于 Kubernetes 定义的,用来管理集群资源及权限的 TensorStack AI 平台资源:
- PodGroup
- Project
- Queue
用户指南
下载安装
下载
TensorStack CLI(以下简称 T9k CLI)可以从平台首页下载。请根据操作系统和架构(可以在命令行运行 uname -om
获取)选择适当的版本。
安装
你需要根据下载的版本,设置 T9k CLI 的版本和系统架构等变量:
version=1.78.6
os=darwin
arch=amd64
然后解压下载好的 T9k CLI,并把得到的二进制文件移动到 /usr/local/bin
路径下:
tar -zxvf "$HOME/Downloads/t9k-$version-$os-$arch.tar.gz"
mv t9k-$os-$arch /usr/local/bin/t9k
rm -f "$HOME/Downloads/t9k-$version-$os-$arch.tar.gz"
你可以运行以下命令来验证 T9k CLI 安装完成:
t9k version
卸载
删除二进制文件以卸载 T9k CLI。
rm -f /usr/local/bin/t9k
配置文件
TensorStack CLI 使用 T9k Config 作为配置文件。T9k Config 文件的路径通过命令行参数 -c, --config
进行指定,在未被指定时,使用默认路径 $HOME/.t9k/t9k-config.yaml
。第一次使用时,可以通过 t9k config auth
命令来生成配置文件,详情请参阅 t9k config auth。
T9k Config 示例如下:
current-context: default-context
contexts:
- name: default-context
server: https://<example.com>
image-registry: https://<example.io>
prefixes:
aistore: /t9k/aistore/server
asset-hub: /t9k/asset-hub/server
build-console: /t9k/build-console/server
cluster-admin: /t9k/cluster-admin/server
deploy-console: /t9k/deploy-console/server
security-console: /t9k/security/server
workflow-manager: /t9k/workflow/server
auth:
apikey: <your-apikey>
token: <your-token>
extension:
codepack:
data-copy-image: <your-image>
T9k Config 包括以下两个部分:
current-context
:字符串,记录默认使用的 Context 名称。你可以通过设置命令行参数-x, --context
访问其他的 Context。contexts
:数组,包含集群相关信息。name
:字符串,Context 的名称。server
:字符串,记录访问这个集群服务的域名。image-registry
:字符串,记录这个集群使用镜像仓库的地址。prefixes
:数组,记录这个集群中的 T9k Servers 路径前缀。auth
:,记录认证信息,支持apikey
和token
两种认证方式,需要填写其中一种。extension
:记录其他工具需要用到的拓展配置。
全局选项
TensorStack CLI 定义了以下的全局命令行参数:
-c, --config string t9k config file (default: $HOME/.t9k/t9k-config.yaml)
-x, --context string name of the context to use (default: current-context in t9k config)
-h, --help t9k help
-n, --namespace string alias of -p and --project, invalid if --project is set by user.
-p, --project string project to use (default: from t9k config file)
-v, --verbose int Set level-based filter in logging (default -1)
具体说明如下:
-c, --config
:字符串,指定 T9k Config 文件的路径。对于子命令config
,设置的 T9k Config 文件会被创建或修改。默认路径是$HOME/.t9k/t9k-config.yaml
。-x, --context
:字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中current-context
字段指定的 Context。-h, --help
:查看当前指令的帮助信息和示例。-p, --project
:字符串,指定使用的项目(本文档中的项目和命名空间同义)。-n, --namespace
:字符串,和-p, --project
作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。-v, --verbose
:指定输出 log 信息的详细程度。
项目(命名空间)的使用优先级是(排在前面的优先级更高):
- 你通过命令行参数
-p, --project
设置的项目。 - 你通过命令行参数
-n, --namespace
设置的项目。 - 使用项目
default
。
命令
autotune
用于管理 AutoTune。
delete
删除指定的 AutoTune。
使用
t9k autotune delete [names...] [--all] [-f]
t9k autotune delete
也可以用 t9k autotune rm
代替。
选项
--all 删除当前 Project 中的所有 AutoTunes。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 AutoTune:
t9k autotune delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 AutoTune:
t9k autotune delete foo -p demo -f
删除 Project demo 下所有的 AutoTune:
t9k autotune delete foo -p demo --all
describe
查看某个 AutoTune 的详细信息。
使用
t9k at describe <name> [--color]
t9k at describe
也可以用 t9k at desc
代替。
选项
--color 使用彩色的输出信息(默认全是黑色)。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 AutoTune 的详细描述:
t9k at describe foo -p demo
get
查看 AutoTune 相关信息。
使用
t9k at get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 AutoTune:
t9k at get -p example
以默认格式查看所有 Project 下的所有 AutoTune:
t9k at get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 AutoTune:
t9k at get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 AutoTune:
t9k at get foo -p example -o yaml
wait
等待 AutoTune 完成。
使用
t9k at wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 AutoTune foo 完成:
t9k at wait foo -p example
等待 Project example 下的 AutoTune foo 完成,只等待 10 分钟:
t9k at wait foo -p example --timeout 10m
等待 Project example 下的 AutoTune foo 完成,同时打印 server 的日志:
t9k at wait foo -p example --print-log
beamjob
用于管理 BeamJob。
delete
删除指定的 BeamJob。
使用
t9k beamjob delete [names...] [--all] [-f]
t9k beamjob delete
也可以用 t9k bj rm
代替。
选项
--all 删除当前 Project 中所有的 BeamJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 BeamJob:
t9k beamjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 BeamJob:
t9k beamjob delete foo -p demo -f
删除 Project demo 下所有的 BeamJob:
t9k beamjob delete foo -p demo --all
describe
查看某个 BeamJob 的详细信息。
使用
t9k bj describe <name>
t9k bj describe
也可以用 t9k bj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 BeamJob 的详细描述:
t9k bj describe foo -p demo
get
查看 BeamJob 相关信息。
使用
t9k bj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 BeamJob:
t9k bj get -p example
以默认格式查看所有 Project 下的所有 BeamJob:
t9k bj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 BeamJob:
t9k bj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 BeamJob:
t9k bj get foo -p example -o yaml
logs
查看 BeamJob 某个计算节点的日志。
使用
t9k bj logs [--type=jobmanager|taskmanager|batchjob] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `taskmanager`,`batchjob` 以及默认值 `jobmanager`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 BeamJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k bj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 BeamJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k bj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 BeamJob foo 第 0 个 jobmanager 节点的最后 20 行日志:
t9k bj logs foo --tail 20
wait
等待 BeamJob 完成。
使用
t9k bj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=jobmanager|taskmanager|batchjob] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `taskmanager`,`batchjob` 以及默认值 `jobmanager`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 BeamJob foo 完成:
t9k bj wait foo -p example
等待 Project example 下的 BeamJob foo 完成,只等待 10 分钟:
t9k bj wait foo -p example --timeout 10m
等待 Project example 下的 BeamJob foo 完成,同时打印节点 flinkcluster-taskmanager-0 的日志:
t9k bj wait foo -p example --print-log --type taskmanager --index 0
colossalaijob
用于管理 ColossalAIJob。
delete
删除指定的 ColossalAIJob。
使用
t9k colossalaijob delete [names...] [--all] [-f]
t9k colossalaijob delete
也可以用 t9k caij rm
代替。
选项
--all 删除当前 Project 中所有的 ColossalAIJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 ColossalAIJob:
t9k colossalaijob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 ColossalAIJob:
t9k colossalaijob delete foo -p demo -f
删除 Project demo 下所有的 ColossalAIJob:
t9k colossalaijob delete foo -p demo --all
describe
查看某个 ColossalAIJob 的详细信息。
使用
t9k caij describe <name>
t9k caij describe
也可以用 t9k caij desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 ColossalAIJob 的详细描述:
t9k caij describe foo -p demo
get
查看 ColossalAIJob 相关信息。
使用
t9k caij get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 ColossalAIJob:
t9k caij get -p example
以默认格式查看所有 Project 下的所有 ColossalAIJob:
t9k caij get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 ColossalAIJob:
t9k caij get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 ColossalAIJob:
t9k caij get foo -p example -o yaml
logs
查看 ColossalAIJob 某个计算节点的日志。
使用
t9k caij logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 ColossalAIJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k caij logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 ColossalAIJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k caij logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 ColossalAIJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k caij logs foo --tail 20
wait
等待 ColossalAIJob 完成。
使用
t9k caij wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 ColossalAIJob foo 完成:
t9k caij wait foo -p example
等待 Project example 下的 ColossalAIJob foo 完成,只等待 10 分钟:
t9k caij wait foo -p example --timeout 10m
等待 Project example 下的 ColossalAIJob foo 完成,同时打印节点 master-0 的日志:
t9k caij wait foo -p example --print-log --type master --index 0
config
对指定的 T9k Config 进行生成、管理、查看。T9k Config 默认使用文件 ${HOME}/.t9k/t9k-config.yaml
,可通过全局选项 -c, --config
指定该文件路径。
auth
完成用户身份认证,生成 T9k Config。用户第一次使用 T9k 命令行工具时,需要使用此命令来进行身份认证。认证成功后,此命令会修改(如果是首次认证会新建)T9k Config。之后用户便可以通过该认证信息去使用 T9k 其他命令。
使用
t9k config auth <server> [--apikey] [--user=<username>]
选项
-k, --apikey 启用交互式输入 API Key。
-u, --user string 字符串,指定用户密码登录的用户名称。
全局选项
-c, --config 字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定新增 Context 的名称。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
通过用户密码完成认证
用户指定要登录的域名,然后输入用户名和密码完成认证。认证完成后,当前的 T9k Config 中便会新增一个 <用户名>-<域名>
的 Context,用户也可以自己指定 Context 的名称。
$ t9k config auth <http://example.com>
Authenticating using username and password by default, add --apikey to use apikey.
Please enter your username: demo
Please enter your password:
Please enter Context name [default: demo-example.com]: demo
Login succeeded!
!!! note “注意” Context 的名称需要满足 DNS Subdomain Names 的要求,如果 Context 名字重复,可以选择覆盖原内容或者重新输入。
通过 API Key 完成认证
用户指定要登录的域名,然后输入 API Key。认证完成后,当前的 T9k Config 中便会新增一个 apikey-<hash>-<域名>
的 Context,用户也可以自己指定 Context 的名称。
$ t9k config auth <http://example.com> --apikey
Authenticating using API Key...
Please enter your API Key:
Please enter Context name [default: apikey-<hash>-example.com]: demo-apikey
Login succeeded!
delete-context
删除指定的 Context。
!!! note “注意” 即使指定的 Context 是 current-context,此命令也会直接删除掉。所以务必确认之后再删除。
使用
t9k config delete-context <name>
全局选项
-c, --config 字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Context demo:
t9k config delete-context demo
get-contexts
用于获取当前使用的 T9k Config 中 Context 的相关信息。具体包括:
CURRENT
:是否是当前正在使用的 ContextNAME
:Context 的名称SERVER
:T9k 平台的地址AUTH_TYPE
:认证信息的类型(token 或者 apikey)
使用
t9k config get-contexts [name]
全局选项
-c, --config 字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
获取当前 T9k Config 中所有 Context 的信息:
t9k config get-contexts
获取指定 Context 的信息:
t9k config get-contexts my-context
use-context
切换当前使用的 Context,此命令会修改当前 T9k Config 中 current-context 的值。
使用
t9k config use-context <name>
全局选项
-c, --config 字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
切换到 Context foo:
t9k config use-context foo
将文件 $HOME/t9kConfig.yaml
下的 Context 切换到 foo:
t9k config use-context foo -c $HOME/t9kConfig.yaml
create
通过文件创建 TensorStack AI 平台的资源或者其他支持的资源 (PVC 和 secret)。
使用
t9k create --filename=<file>
选项
-f, --filename 文件路径
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
通过文件在 Project demo 下创建一个 Notebook 资源。
t9k create -f notebook.yaml -p demo
delete
根据文件删除资源。
使用
t9k delete --filename=<file>
选项
-f, --filename 文件路径
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
根据文件内容删除 Project demo 下相应的 Notebook 资源。
t9k delete -f notebook.yaml -p demo
deepspeedjob
用于管理 DeepSpeedJob。
delete
删除指定的 DeepSpeedJob。
使用
t9k deepspeedjob delete [names...] [--all] [-f]
t9k deepspeedjob delete
也可以用 t9k dj rm
代替。
选项
--all 删除当前 Project 中所有的 DeepSpeedJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 DeepSpeedJob:
t9k deepspeedjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 DeepSpeedJob:
t9k deepspeedjob delete foo -p demo -f
删除 Project demo 下所有的 DeepSpeedJob:
t9k deepspeedjob delete foo -p demo --all
describe
查看某个 DeepSpeedJob 的详细信息。
使用
t9k dj describe <name>
t9k dj describe
也可以用 t9k dj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 DeepSpeedJob 的详细描述:
t9k dj describe foo -p demo
get
查看 DeepSpeedJob 相关信息。
使用
t9k dj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 DeepSpeedJob:
t9k dj get -p example
以默认格式查看所有 Project 下的所有 DeepSpeedJob:
t9k dj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 DeepSpeedJob:
t9k dj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 DeepSpeedJob:
t9k dj get foo -p example -o yaml
logs
查看 DeepSpeedJob 某个计算节点的日志。
使用
t9k dj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 DeepSpeedJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k dj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 DeepSpeedJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k dj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 DeepSpeedJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k dj logs foo --tail 20
wait
等待 DeepSpeedJob 完成。
使用
t9k dj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 DeepSpeedJob foo 完成:
t9k dj wait foo -p example
等待 Project example 下的 DeepSpeedJob foo 完成,只等待 10 分钟:
t9k dj wait foo -p example --timeout 10m
等待 Project example 下的 DeepSpeedJob foo 完成,同时打印节点 master-0 的日志:
t9k dj wait foo -p example --print-log --type master --index 0
genericjob
用于管理 GenericJob。
delete
删除指定的 GenericJob。
使用
t9k genericjob delete [names...] [--all] [-f]
t9k genericjob delete
也可以用 t9k gj rm
代替。
选项
--all 删除当前 Project 中所有的 GenericJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 GenericJob:
t9k genericjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 GenericJob:
t9k genericjob delete foo -p demo -f
删除 Project demo 下所有的 GenericJob:
t9k genericjob delete foo -p demo --all
describe
查看某个 GenericJob 的详细信息。
使用
t9k gj describe <name>
t9k gj describe
也可以用 t9k gj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 GenericJob 的详细描述:
t9k gj describe foo -p demo
get
查看 GenericJob 相关信息。
使用
t9k gj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 GenericJob:
t9k gj get -p example
以默认格式查看所有 Project 下的所有 GenericJob:
t9k gj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 GenericJob:
t9k gj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 GenericJob:
t9k gj get foo -p example -o yaml
logs
查看 GenericJob 某个计算节点的日志。
使用
t9k gj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 GenericJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k gj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 GenericJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k gj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 GenericJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k gj logs foo --tail 20
wait
等待 GenericJob 完成。
使用
t9k gj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 GenericJob foo 完成:
t9k gj wait foo -p example
等待 Project example 下的 GenericJob foo 完成,只等待 10 分钟:
t9k gj wait foo -p example --timeout 10m
等待 Project example 下的 GenericJob foo 完成,同时打印节点 master-0 的日志:
t9k gj wait foo -p example --print-log --type master --index 0
mlservice
用于管理 MLService。
canary
设置金丝雀发布。
使用
t9k mlservice set-canary [--default=default-release] [--canary=canary-release] [--traffic=canary-percentage] [--dry-run] [-o yaml|json]
选项
--canary string 字符串,指定金丝雀发布的版本名称
--default string 字符串,指定默认发布的版本名称
--dry-run 只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string 字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
--traffic int 整数,指定金丝雀发布的路由权重
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
将 Project demo 下 MLService maskdetection 的默认发布版本设为 foo
,金丝雀发布版本设为 bar
且权重为 20%:
t9k mlservice set-canary maskdetection --default=foo --canary=bar --traffic=20 -n demo
将 Project demo 下 MLService maskdetection 的金丝雀发布版本权重设为 30%:
t9k mlservice set-canary maskdetection --traffic=30 -n demo
将 Project demo 下 MLService maskdetection 的默认发布版本设为 foo
:
t9k mlservice set-canary maskdetection --default=foo
将 Project demo 下 MLService maskdetection 的金丝雀发布版本设为 bar
:
t9k mlservice set-canary maskdetection --canary=bar -n demo
delete
删除指定的 MLService。
使用
t9k mls delete [names...] [-f] [--all]
t9k mls delete
也可以用 t9k mls rm
代替。
选项
--all 删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 MLService:
t9k mls delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 MLService:
t9k mls delete foo -p demo -f
删除 Project demo 下所有的 MLService:
t9k mls delete foo -p demo --all
describe
查看 MLService 详细信息。
使用
t9k mls describe <name> [--color]
选项
--color 使用彩色的输出信息(默认全是黑色)。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 MLService 的详细描述:
t9k mls describe foo -p demo
get
查看 MLService 相关信息。
使用
t9k mls get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 MLService:
t9k mls get -p example
以默认格式查看所有 Project 下的所有 MLService:
t9k mls get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 MLService:
t9k mls get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 MLService:
t9k mls get foo -p example -o yaml
delete-release
删除 MLService 中发布的版本。
使用
t9k delete-release <name> [--release=release-names...]
选项
--release string 字符串,删除的版本名称,如要删除多个版本,用 `,` 进行分割。
--dry-run 只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string 字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下的推理服务 maskdetection 的 foo 和 bar 两个已发布的版本:
t9k delete-release maskdetection --release foo,bar -p demo
mpijob
用于管理 MPIJob。
delete
删除指定的 MPIJob。
使用
t9k mpijob delete [names...] [--all] [-f]
t9k mpijob delete
也可以用 t9k mj rm
代替。
选项
--all 删除当前 Project 中所有的 MPIJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 MPIJob:
t9k mpijob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 MPIJob:
t9k mpijob delete foo -p demo -f
删除 Project demo 下所有的 MPIJob:
t9k mpijob delete foo -p demo --all
describe
查看某个 MPIJob 的详细信息。
使用
t9k mj describe <name>
t9k mj describe
也可以用 t9k mj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 MPIJob 的详细描述:
t9k mj describe foo -p demo
get
查看 MPIJob 相关信息。
使用
t9k mj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 MPIJob:
t9k mj get -p example
以默认格式查看所有 Project 下的所有 MPIJob:
t9k mj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 MPIJob:
t9k mj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 MPIJob:
t9k mj get foo -p example -o yaml
logs
查看 MPIJob 某个计算节点的日志。
使用
t9k mj logs [--type=launcher|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `launcher` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 MPIJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k mj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 MPIJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k mj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 MPIJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k mj logs foo --tail 20
wait
等待 MPIJob 完成。
使用
t9k mj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=launcher|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `launcher` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 MPIJob foo 完成:
t9k mj wait foo -p example
等待 Project example 下的 MPIJob foo 完成,只等待 10 分钟:
t9k mj wait foo -p example --timeout 10m
等待 Project example 下的 MPIJob foo 完成,同时打印节点 launcher 的日志:
t9k mj wait foo -p example --print-log --type launcher
notebook
用于管理 Notebook。
delete
删除指定的 Notebook。
使用
t9k notebook delete [names...] [--all] [-f]
t9k notebook delete
也可以用 t9k nb rm
代替。
选项
--all 删除当前 Project 中所有的 Notebook。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 Notebook:
t9k notebook delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 Notebook:
t9k notebook delete foo -p demo -f
删除 Project demo 下所有的 Notebook:
t9k notebook delete foo -p demo --all
describe
查看某个 Notebook 的详细信息。
使用
t9k nb describe <name>
t9k nb describe
也可以用 t9k nb desc
代替。
选项
--color 使用彩色的输出信息(默认全是黑色)。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 Notebook 的详细描述:
t9k nb describe foo -p demo
get
查看 Notebook 相关信息。
使用
t9k nb get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 Notebook:
t9k nb get -p example
以默认格式查看所有 Project 下的所有 Notebook:
t9k nb get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 Notebook:
t9k nb get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 Notebook:
t9k nb get foo -p example -o yaml
podgroup
用于管理 PodGroup,只有集群管理员才有相关权限。
get
查看 PodGroup 相关信息。
使用
t9k podgroup get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 PodGroup:
t9k podgroup get -p example
以默认格式查看所有 Project 下的所有 PodGroup:
t9k podgroup get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 PodGroup:
t9k podgroup get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 PodGroup:
t9k podgroup get foo -p example -o yaml
project
用于管理 Project。
create
创建新项目,只有集群管理员才有权限创建新项目。
使用
t9k project create <name> <owner> [--build] [--deploy]
选项
--build 项目拥有者是否拥有模型构建权限
--deploy 项目拥有者是否拥有模型部署权限
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
创建一个名为 sample 的项目,管理员为 admin,且 admin 只有模型构建的权限,没有模型部署的权限:
t9k project create sample admin --build
describe
查看项目详细描述,只能查看当前用户所拥有的项目。
使用
t9k proj describe <name>
t9k proj describe
也可以用 t9k proj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
详细描述项目 demo:
t9k proj describe demo
get
查看项目的相关信息,只能查看用户拥有权限的项目。
使用
t9k project get [name...]
可以通过指定 name 获取一个或多个 project,不指定的话默认获取所有当前用户有权限的项目。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看当前用户有权限的所有项目:
t9k project get
查看当前用户有权限的项目中名为 foo 的项目:
t9k project get foo
pytorchtrainingjob
用于管理 PyTorchTrainingJob。
delete
删除指定的 PyTorchTrainingJob。
使用
t9k pytorchtrainingjob delete [names...] [--all] [-f]
t9k pytorchtrainingjob delete
也可以用 t9k pj rm
代替。
选项
--all 删除当前 Project 中所有的 PyTorchTrainingJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 PyTorchTrainingJob:
t9k pytorchtrainingjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 PyTorchTrainingJob:
t9k pytorchtrainingjob delete foo -p demo -f
删除 Project demo 下所有的 PyTorchTrainingJob:
t9k pytorchtrainingjob delete foo -p demo --all
describe
查看某个 PyTorchTrainingJob 的详细信息。
使用
t9k pj describe <name>
t9k pj describe
也可以用 t9k pj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 PyTorchTrainingJob 的详细描述:
t9k pj describe foo -p demo
get
查看 PyTorchTrainingJob 相关信息。
使用
t9k pj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 PyTorchTrainingJob:
t9k pj get -p example
以默认格式查看所有 Project 下的所有 PyTorchTrainingJob:
t9k pj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 PyTorchTrainingJob:
t9k pj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 PyTorchTrainingJob:
t9k pj get foo -p example -o yaml
logs
查看 PyTorchTrainingJob 某个计算节点的日志。
使用
t9k pj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 PyTorchTrainingJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k pj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 PyTorchTrainingJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k pj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 PyTorchTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k pj logs foo --tail 20
wait
等待 PyTorchTrainingJob 完成。
使用
t9k pj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 PyTorchTrainingJob foo 完成:
t9k pj wait foo -p example
等待 Project example 下的 PyTorchTrainingJob foo 完成,只等待 10 分钟:
t9k pj wait foo -p example --timeout 10m
等待 Project example 下的 PyTorchTrainingJob foo 完成,同时打印节点 master-0 的日志:
t9k pj wait foo -p example --print-log --type master --index 0
queue
用于管理 Queue,只有集群管理员才有相关权限。
close
关闭 Queue。
使用
t9k queue close <name>
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
关闭 Queue foo:
t9k queue close foo
get
查看 Queue 相关信息。
使用
t9k queue get [names...] [-o json|yaml|template]
选项
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看所有 Queue:
t9k queue get
以默认格式查看名为 foo 和 bar 的两个 Queue:
t9k queue get foo bar
以 yaml 格式查看名为 foo 的 Queue:
t9k queue get foo -o yaml
open
打开 Queue。
使用
t9k queue open <name>
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-v, --verbose 指定输出 log 信息的详细程度。
示例
打开 Queue foo:
t9k queue open foo
simplemlservice
用于管理 SimpleMLService
create
创建一个新的 SimpleMLService。
使用
t9k simplemlservice create <name> --model=<model-url> -image=<serving-image> [--secret=<serect-name>] [--tech tensorflow|pytorch|xgboost] [--dry-run] [-o yaml|json]
选项
--model string 字符串,推理服务使用的模型地址
--image string 字符串,推理服务使用的镜像
--dry-run 只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string 字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
--tech string 字符串,推理服务使用的机器学习框架,如果 image 中已经含有关键字,可不填此参数。可选值有 `tensorflow`,`pytorch`,`xgboost`。
--secret string 字符串,加载模型所使用的密钥名称
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
在 Project demo 下创建一个名为 mnist 的推理服务。其使用的镜像为registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0
,模型地址为 mms://aihub.tensorstack.dev/t9kpublic/mnist:v1
:
t9k simplemlservice create mnist \
--model="mms://aihub.tensorstack.dev/t9kpublic/mnist:v1" \
--image="registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0" \
-n demo
在 Project t9k-sample 下创建一个名为 mnist-cnn 的推理服务。其使用的镜像为registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0
,模型地址为 mms://aihub.tensorstack.dev/private/mnist:v2
,模型下载使用的密钥为同一个 Project demo 下的 secret mms-access
:
t9k mls create mnist-cnn \
--project=t9k-sample \
--model="mms://aihub.tensorstack.dev/private/mnist:v2" \
--image="registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0" \
--tech="tensorflow" \
--secret="mms-access"
delete
删除指定的 SimpleMLService。
使用
t9k smls delete [names...] [-f] [--all]
t9k smls delete
也可以用 t9k smls rm
代替。
选项
--all 删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 SimpleMLService:
t9k smls delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 SimpleMLService:
t9k smls delete foo -p demo -f
删除 Project demo 下所有的 SimpleMLService:
t9k smls delete foo -p demo --all
describe
查看 SimpleMLService 详细信息。
使用
t9k mls describe <name>
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 SimpleMLService 的详细描述:
t9k mls describe foo -p demo
get
查看 SimpleMLService 相关信息。
使用
t9k smls get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 SimpleMLService:
t9k smls get -p example
以默认格式查看所有 Project 下的所有 SimpleMLService:
t9k smls get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 SimpleMLService:
t9k smls get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 SimpleMLService:
t9k smls get foo -p example -o yaml
tensorflowtrainingjob
用于管理 TensorFlowTrainingJob。
delete
删除指定的 TensorFlowTrainingJob。
使用
t9k tensorflowtrainingjob delete [names...] [--all] [-f]
t9k tensorflowtrainingjob delete
也可以用 t9k tj rm
代替。
选项
--all 删除当前 Project 中所有的 TensorFlowTrainingJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 TensorFlowTrainingJob:
t9k tensorflowtrainingjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 TensorFlowTrainingJob:
t9k tensorflowtrainingjob delete foo -p demo -f
删除 Project demo 下所有的 TensorFlowTrainingJob:
t9k tensorflowtrainingjob delete foo -p demo --all
describe
查看某个 TensorFlowTrainingJob 的详细信息。
使用
t9k tj describe <name>
t9k tj describe
也可以用 t9k tj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 TensorFlowTrainingJob 的详细描述:
t9k tj describe foo -p demo
get
查看 TensorFlowTrainingJob 相关信息。
使用
t9k tj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 TensorFlowTrainingJob:
t9k tj get -p example
以默认格式查看所有 Project 下的所有 TensorFlowTrainingJob:
t9k tj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 TensorFlowTrainingJob:
t9k tj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 TensorFlowTrainingJob:
t9k tj get foo -p example -o yaml
logs
查看 TensorFlowTrainingJob 某个计算节点的日志。
使用
t9k tj logs <name> [--type=chief|ps|evaluator|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `chief`,`ps`,`evaluator` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 TensorFlowTrainingJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k tj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 TensorFlowTrainingJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k tj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 TensorFlowTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k tj logs foo --tail 20
wait
等待 TensorFlowTrainingJob 完成。
使用
t9k tj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=chief|ps|evaluator|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `chief`,`ps`,`evaluator` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 TensorFlowTrainingJob foo 完成:
t9k tj wait foo -p example
等待 Project example 下的 TensorFlowTrainingJob foo 完成,只等待 10 分钟:
t9k tj wait foo -p example --timeout 10m
等待 Project example 下的 TensorFlowTrainingJob foo 完成,同时打印节点 chief-0 的日志:
t9k tj wait foo -p example --print-log --type chief --index 0
version
查看当前 T9k CLI 版本信息。
使用
t9k version
示例
查看当前 t9k 二进制文件的版本信息。
t9k version
workflowrun
用于管理 WorkflowRun。
delete
删除指定的 WorkflowRun。
使用
t9k workflowrun delete [names...] [--all] [-f]
t9k workflowrun delete
也可以用 t9k wr rm
代替。
选项
--all 删除当前 Project 中所有的 WorkflowRun。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 WorkflowRun:
t9k workflowrun delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 WorkflowRun:
t9k workflowrun delete foo -p demo -f
删除 Project demo 下所有的 WorkflowRun:
t9k workflowrun delete foo -p demo --all
describe
查看某个 WorkflowRun 的详细信息。
使用
t9k wr describe <name>
t9k wr describe
也可以用 t9k wr desc
代替。
选项
--color 使用彩色的输出信息(默认全是黑色)。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 WorkflowRun 的详细描述:
t9k wr describe foo -p demo
get
查看 WorkflowRun 相关信息。
使用
t9k wr get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 WorkflowRun:
t9k wr get -p example
以默认格式查看所有 Project 下的所有 WorkflowRun:
t9k wr get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 WorkflowRun:
t9k wr get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 WorkflowRun:
t9k wr get foo -p example -o yaml
logs
查看 WorkflowRun 某个容器的日志,不支持直接查看 DAG 类型的 WorkflowRun 的日志。
使用
t9k wr logs [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下 WorkflowRun foo 唯一容器的日志:
t9k wr logs foo -p demo
流式查看 Project demo 下 WorkflowRun foo 容器 mnist 的日志:
t9k wr logs foo --container=mnist -p demo -f
查看 Project demo 下 WorkflowRun foo 唯一容器的最后 20 行日志:
t9k wr logs foo -p demo --tail=20
wait
等待 WorkflowRun 完成,该命令不支持 DAG 类型的 WorkflowRun。
使用
t9k wr wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--timestamps 是否展示时间戳。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 WorkflowRun foo 完成:
t9k wr wait foo -p example
等待 Project example 下的 WorkflowRun foo 完成,只等待 10 分钟:
t9k wr wait foo -p example --timeout 10m
等待 Project example 下的 WorkflowRun foo 完成,同时打印其容器 mnist 的日志:
t9k wr wait foo -p example --print-log --container mnist
workflowtemplate
用于管理 WorkflowTemplate。
delete
删除指定的 WorkflowTemplate。
使用
t9k workflowtemplate delete [names...] [--all] [-f]
t9k workflowtemplate delete
也可以用 t9k wr rm
代替。
选项
--all 删除当前 Project 中所有的 WorkflowTemplate。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 WorkflowTemplate:
t9k workflowtemplate delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 WorkflowTemplate:
t9k workflowtemplate delete foo -p demo -f
删除 Project demo 下所有的 WorkflowTemplate:
t9k workflowtemplate delete foo -p demo --all
describe
查看某个 WorkflowTemplate 的详细信息。
使用
t9k wt describe <name>
t9k wt describe
也可以用 t9k wt desc
代替。
选项
--color 使用彩色的输出信息(默认全是黑色)。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 WorkflowTemplate 的详细描述:
t9k wt describe foo -p demo
get
查看 WorkflowTemplate 相关信息。
使用
t9k wt get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 WorkflowTemplate:
t9k wt get -p example
以默认格式查看所有 Project 下的所有 WorkflowTemplate:
t9k wt get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 WorkflowTemplate:
t9k wt get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 WorkflowTemplate:
t9k wt get foo -p example -o yaml
start
执行 WorkflowTemplate。
使用
t9k wt start <name> [-l <labelStrings>] [-r <paramStrings>] [-s <serviceAccount>] [--timeout=<timeoutTime>] [-w <workplaceStrings>] [--use-param-defaults] [--dry-run] [-o yaml|json]
选项
-l, --label strings 以键值对的方式指定 workflowRun 的 label。例如 -l "LABEL_1=VAL_1,LABEL_2=VAL_2"。
-r, --param strings 以键值对的方式指定 workflowRun 的参数。例如 -l "KEY_1=VAL_1,KEY_2=VAL_2"。
-w, --workspace strings 以键值对的方式指定 workspace 相关信息。例如 -w "name=$workspace_name,type=$workspace_type,$key$value"。
--use-param-defaults 是否采用默认参数
--timeout string 字符串,指定 workflowRun 的超时时间。
--dry-run 只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string 指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
-s, --serviceaccount string 指定 workflowRun 的 serviceAccount。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
执行 Project demo 下的 WorkflowTemplate foo:
t9k wt start foo -p demo
根据指定的 workspace 信息执行 Project demo 下的 WorkflowTemplate foo:
t9k wt start foo --workspace=name=bar,type=pvc,claimName=bar-pvc,subPath=/user/local/Document -p demo
执行 Project demo 下的 WorkflowTemplate foo,并设置参数 bar 值为 hello:
t9k wt start foo --param=bar=hello
xgboosttrainingjob
用于管理 XGBoostTrainingJob。
delete
删除指定的 XGBoostTrainingJob。
使用
t9k xgboosttrainingjob delete [names...] [--all] [-f]
t9k xgboosttrainingjob delete
也可以用 t9k xj rm
代替。
选项
--all 删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force 跳过确认,直接执行删除操作。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
删除 Project demo 下名为 foo 和 bar 的两个 XGBoostTrainingJob:
t9k xgboosttrainingjob delete foo bar -p demo
跳过确认,直接删除 Project demo 下名为 foo 的 XGBoostTrainingJob:
t9k xgboosttrainingjob delete foo -p demo -f
删除 Project demo 下所有的 XGBoostTrainingJob:
t9k xgboosttrainingjob delete foo -p demo --all
describe
查看某个 XGBoostTrainingJob 的详细信息。
使用
t9k xj describe <name>
t9k xj describe
也可以用 t9k xj desc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project demo 下名为 foo 的 XGBoostTrainingJob 的详细描述:
t9k xj describe foo -p demo
get
查看 XGBoostTrainingJob 相关信息。
使用
t9k xj get [names...] [-A] [-o json|yaml|template]
选项
-A, --all-namespaces 获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string 字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
以默认格式查看 Project example 下所有 XGBoostTrainingJob:
t9k xj get -p example
以默认格式查看所有 Project 下的所有 XGBoostTrainingJob:
t9k xj get -A
以默认格式查看 Project example 下名为 foo 和 bar 的两个 XGBoostTrainingJob:
t9k xj get foo bar -p example
以 yaml 格式查看 Project example 下名为 foo 的 XGBoostTrainingJob:
t9k xj get foo -p example -o yaml
logs
查看 XGBoostTrainingJob 某个计算节点的日志。
使用
t9k xj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]
选项
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow 流式查看日志。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--tail int 整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
查看 Project example 下 XGBoostTrainingJob foo 第 replicaIndex
个 replicaType
节点的日志:
t9k xj logs foo --type=replicaType --index=replicaIndex -p example
流式查看 Project example 下 XGBoostTrainingJob foo 第 replicaIndex
个 replicaType
节点的容器 mnist
的日志:
t9k xj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow
查看 XGBoostTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:
t9k xj logs foo --tail 20
wait
等待 XGBoostTrainingJob 完成。
使用
t9k xj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]
选项
--timeout string 字符串,最长等待时间。默认值:"1h",1 小时。
--period string 字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log 是否在等待时流式查看日志。
以下参数只有在开启了 `--print-log` 后才生效。
--container string 字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string 字符串,要查看的计算节点的序号。默认值:0。
--timestamps 是否展示时间戳。
--type string 字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context 字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help 查看当前指令的帮助信息和示例。
-p, --project 字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace 字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose 指定输出 log 信息的详细程度。
示例
等待 Project example 下的 XGBoostTrainingJob foo 完成:
t9k xj wait foo -p example
等待 Project example 下的 XGBoostTrainingJob foo 完成,只等待 10 分钟:
t9k xj wait foo -p example --timeout 10m
等待 Project example 下的 XGBoostTrainingJob foo 完成,同时打印节点 master-0 的日志:
t9k xj wait foo -p example --print-log --type master --index 0
命令行工具:t9k-pf
TensorStack AI 平台提供了命令行工具 t9k-pf,其功能类似于 kubectl port-forward
,使用户能够在本地通过端口转发的方式访问 TensorStack AI 平台的各种资源。目前支持的资源类型有 Notebook、Pod、Service。
用户指南
下载安装
下载
t9k-pf 可以从平台首页下载。请根据操作系统和架构(可以在命令行运行 uname -om
获取)选择适当的版本。
安装
根据下载的版本,设置 t9k-pf 的版本和系统架构等变量:
version=0.2.6
os=darwin
arch=amd64
然后解压下载好的 t9k-pf,并把得到的二进制文件移动到 /usr/local/bin
路径下:
tar -zxvf "$HOME/Downloads/t9k-pf-$version-$os-$arch.tar.gz"
mv t9k-pf-$os-$arch /usr/local/bin/t9k-pf
rm -f "$HOME/Downloads/t9k-pf-$version-$os-$arch.tar.gz"
安装完成后,运行以下命令来验证安装是否成功:
t9k-pf version
卸载
删除二进制文件即可卸载 t9k-pf。
rm -f /usr/local/bin/t9k-pf
身份认证和授权
通过 T9k Config 进行身份认证和授权
t9k-pf 默认使用 T9k Config 来进行身份认证和授权。你可以通过命令行参数 -c, --config
来指定 t9k-pf 使用的 T9k Config 文件的路径,未指定时,默认使用 $HOME/.t9k/t9k-config.yaml
路径下 T9k Config 中 current-context 的认证信息。
下面是一个 T9k Config 的示例,其中 current-context 为 demo1
,该 Context 的 token 字段不为空,因此最终 t9k-pf 使用该值 demo1-token
来完成身份验证(如果 apikey 和 token 均不为空,t9k-pf 优先使用 apikey)。
current-context: demo1
contexts:
- name: demo1
server: https://<example.com>
image-registry: https://<example.io>
prefixes:
aistore: /t9k/aistore/server
asset-hub: /t9k/asset-hub/server
build-console: /t9k/build-console/server
cluster-admin: /t9k/cluster-admin/server
deploy-console: /t9k/deploy-console/server
security-console: /t9k/security/server
workflow-manager: /t9k/workflow/server
auth:
apikey: ""
token: demo1-token
extension:
codepack:
data-copy-image: <your-image>
- name: demo2
server: https://<example.com>
...
通过 API Key 进行临时身份认证和授权
t9k-pf 支持通过命令行参数 -k,--apikey
直接指定 API Key,完成单次端口转发的身份认证和授权。
例如输入以下指令(其中 notebook <URL>
会在命令中介绍,此处只用关注 --apikey
的使用):
t9k-pf notebook <url> --apikey
命令行会进入交互式输入界面,粘贴你的 API Key 再按下回车即可。
全局选项
-
-c, –config
使用的 T9k Config 文件的路径。默认路径是
$HOME/.t9k/t9k-config.yaml
。 -
-k, –apikey
开启交互式输入 API Key。
-
-n, –namespace
使用的项目(命名空间)名称。
-
-h, –help
查看当前指令的帮助信息和示例。
-
–address
本地监听地址。默认为
localhost
。 -
–retryMaxTimes
整数,最大重试次数。默认为
10
。 -
–retryPeriod
整数,重试间隔时间(单位:秒)。默认为
10
。
命令
notebook
针对 TensorStack AI 平台的 Notebook 资源,我们提供了直接通过其 URL 地址获取 SSH 连接方式的功能。使用该命令,你不需要指定名称、命名空间等信息。关于 SSH 连接的详细内容请参阅通过 SSH 连接远程使用 Notebook。
使用
t9k-pf notebook <url> <localPort>
其中 <url>
代表地址栏中的地址,<localPort>
代表你指定的本地端口号(小于 1024 的本地端口需要管理员权限才可以绑定),如果不指定,会随机使用一个本地端口。
t9k-pf notebook
也可以用 t9k-pf nb
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-n, --namespace 字符串,指定使用的项目(命名空间)名称。
-k, --apikey 开启交互式输入 API Key。
--address 本地监听地址。默认为 `localhost`。
--retryMaxTimes 整数,最大重试次数。默认为 `10`。
--retryPeriod 整数,重试间隔时间(单位:秒)。默认为 `10`。
示例
通过本地 127.0.0.1 的随机端口访问 Project demo 下 Notebook ml-labs 的 SSH 端口。
t9k-pf notebook <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab
通过本地 127.0.0.1:8888 访问 Project demo 下 Notebook ml-labs 的 SSH 端口。
t9k-pf nb <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab 8888
通过本地 0.0.0.0:8888 访问 Project demo 下 Notebook ml-labs 的 SSH 端口。
t9k-pf nb <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab 8888 --address 0.0.0.0
pod
访问指定 Pod 的指定端口。
使用
t9k-pf pod <name> [<localPort>:]<targetPort>
其中 <localPort>
代表本地监听的端口(小于 1024 的本地端口需要管理员权限才可以绑定),<targetPort>
代表目标 Pod 的端口。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-n, --namespace 字符串,指定使用的项目(命名空间)名称。
-k, --apikey 开启交互式输入 API Key。
--address 本地监听地址。默认为 `localhost`。
--retryMaxTimes 整数,最大重试次数。默认为 `10`。
--retryPeriod 整数,重试间隔时间(单位:秒)。默认为 `10`。
示例
通过本地 127.0.0.1:3333 访问命名空间 dev 下的 Pod example 的 2222 端口。
t9k-pf pod example 3333:2222 -n dev
通过本地 0.0.0.0:3333 访问命名空间 dev 下的 Pod example 的 2222 端口。
t9k-pf pod example 3333:2222 -n dev --address 0.0.0.0
通过本地 127.0.0.1 的随机端口访问命名空间 dev 下的 Pod example 的 2222 端口。
t9k-pf pod example 2222 -n dev
service
访问指定 Service 的指定端口。
使用
t9k-pf service <name> [<localPort>:]<targetPort>
其中 <localPort>
代表本地监听的端口(小于 1024 的本地端口需要管理员权限才可以绑定),<targetPort>
代表目标 Service 的端口。
t9k-pf service
也可以用 t9k-pf svc
代替。
全局选项
-c, --config 字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help 查看当前指令的帮助信息和示例。
-n, --namespace 字符串,指定使用的项目(命名空间)名称。默认是 `default`。
-k, --apikey 开启交互式输入 API Key。
--address 本地监听地址。默认为 `localhost`。
--retryMaxTimes 整数,最大重试次数。默认为 `10`。
--retryPeriod 整数,重试间隔时间(单位:秒)。默认为 `10`。
示例
通过本地 127.0.0.1:8888 访问默认命名空间 default 下的 Service myservice 的 80 端口。
t9k-pf service myservice 8888:80
通过本地 0.0.0.0:8888 访问默认命名空间 default 下的 Service myservice 的 80 端口。
t9k-pf service myservice 8888:80 --address 0.0.0.0
通过本地 127.0.0.1 的随机端口访问命名空间 dev 下的 Service myservice 的 80 端口。
t9k-pf service myservice 80 -n dev
Python SDK:t9k
TensorStack AI 平台提供了 Python SDK t9k,其为平台中的多种功能提供支持。
用户指南
安装
目前 TensorStack SDK 仅提供用于本地安装的 Python 包,你可以从平台首页下载。
然后使用以下命令进行安装:
pip install t9k-sdk-<version>.tar.gz [-i <pypi-mirror-url>]
配置
配置文件
TensorStack SDK 没有单独的配置文件,而是使用 TensorStack CLI 的配置文件。在导入 t9k
模块时,会自动读取位于路径 ~/.t9k/t9k-config.yaml
的配置文件(如果设置了环境变量 T9K_CONFIG
,则读取其值给出的路径)。如果配置文件不存在或缺少部分配置项,则缺少的这些配置项会被设置为 None
,这可能导致 TensorStack SDK 的部分功能不能正常工作。
使用和修改配置
在 Python 脚本中导入 t9k
模块之后,t9k.CONFIG
对象就代表了 TensorStack SDK 的配置,你可以像操作 Python 字典一样操作它,例如获取、设置、更新值。
import t9k
print(t9k.CONFIG['api_key'])
t9k.CONFIG['api_key'] = 'e4ccd2a3-3425-44b0-8b44-148bd303a0f9'
t9k.CONFIG.update({'api_key': 'e4ccd2a3-3425-44b0-8b44-148bd303a0f9'})
命令行工具
TensorStack SDK 提供了两个命令行工具:
em
:对应于t9k.em
模块,用于用户登录和登出 AIStore 服务器(会修改配置文件),查看和上传本地保存的 Run 和 Artifact 数据。执行em --help
和em COMMAND --help
以查看相应命令的详细使用方法。ah
:对应于t9k.ah
模块,用于用户登录和登出 Asset Hub 服务器(会修改配置文件),查看、创建、修改和删除资产和资产目录,以及上传、修改和下载资产文件。执行ah --help
和ah COMMAND --help
命令以查看相应命令的详细使用方法。
各主题教程
- AI 资产管理相关:请参阅管理 AI 资产。
- 实验管理相关:请参阅追踪模型训练。
- 模型构建相关:请参阅进行超参数优化。
- 模型部署相关:请参阅制作 Transformer。
API
t9k.ah
t9k.ah.commit
commit(path: str, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None, force: bool = False) ‑> Optional[t9k.ah.core.Commit]
Commits changes to a branch of an Asset.
First delete, then add.
If no branch is provided, :main
will be used.
For Windows platform, if you provide absolute paths for parameter add
, change its format from ‘C:\local\path’ to ‘\C\local\path’.
Examples
Add a file as object to specified branch of Model:
ah.commit('model/llm/gpt2:v1', msg='add ...', add=['model.pt'])
Specify a path in Asset for a file to add:
ah.commit('model/llm/gpt2:v1', msg='add ...', add={'model.pt': 'saved_model/'})
Add all files under a directory as objects (with the directory):
ah.commit('model/llm/gpt2:v1', msg='add ...', add=['./saved_model'])
Add all files under a directory as objects (without the directory):
ah.commit('model/llm/gpt2:v1', msg='add ...', add=['./saved_model/*'])
Specify a path in Asset for a directory to add:
ah.commit('model/llm/gpt2:v1', msg='add ...', add={'./saved_model': 'path/to/[saved_model]'})
## or
ah.commit('model/llm/gpt2:v1', msg='add ...', add={'./saved_model': 'path/to/renamed_dir'})
Delete an object from a Dataset:
ah.commit('dataset/images/cifar10', msg='delete ...', delete=['0.png'])
Delete all objects under the specified path:
ah.commit('dataset/images/cifar10', msg='delete ...', delete=['data/'])
Args
-
path (str)
Path of the branch.
-
msg (str)
Commit message.
-
delete (Optional[Sequence[str]])
Files or directories to delete from the branch, can be a sequence of paths in branch or
None
. If empty sequence orNone
, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here formata/.../b
signifies a file, whilea/.../b/
signifies a directory. -
add (Union[Sequence[str], Mapping[str, str], None])
Files or directories to add to the branch, can be a sequence of local paths, a mapping from local paths to their paths in Asset, or
None
. If empty sequence, empty mapping orNone
, add nothing. -
force (bool)
Whether to create a new commit if unknown changes or unimplemented changes are found.
Returns
A Commit
instance representing created commit if changes are
commited, None
if not.
t9k.ah.create
create(path: str, labels: Optional[Sequence[str]] = None, description: str = '', exist_ok: bool = False, create_tag: bool = False, source: str = 'main') ‑> Union[t9k.ah.core.Folder, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag]
Creates a resource.
Note that you cannot create a Folder for another user.
Examples
Create a Folder:
folder = ah.create('model/llm')
Create a Model with labels:
model = ah.create('model/llm/gpt2', labels=['PyTorch'])
Create a Dataset with a description:
description = 'CIFAR-10 is a widely used benchmark dataset ...'
dataset = ah.create('dataset/images/cifar10', description=description)
Create a non-main branch of specified Model:
branch = ah.create('model/llm/gpt2:v1')
Create a tag:
tag = ah.create('model/llm/gpt2:20220101', create_tag=True, source='v1')
## or
tag = ah.create('model/llm/gpt2:20220101', create_tag=True, source='model/llm/gpt2:v1')
Create a Model for another user:
model = ah.create('/user/t9k-assethub/model/llm/gpt2')
Args
-
path (str)
Path of the resource.
-
labels (Optional[Sequence[str]])
Labels of the resource. Only applicable for creating a Folder, Model or Dataset.
-
description (str)
Description of the resource. Only applicable for creating a Folder, Model or Dataset.
-
exist_ok (bool)
If True and the resource already exists, return a corresponding instance representing the resource; if False and resource exists, raise a
RuntimeError
. Only applicable for creating a Folder, Model or Dataset. -
create_tag (bool)
Whether to create a tag instead of a branch. Only applicable for creating a branch or tag.
-
source (str)
Name/ID or path of the source reference (branch, tag or commit) from which a tag is created. Only applicable for creating a tag.
Returns
A corresponding instance representing retrieved resource.
t9k.ah.delete
delete(path: str, force: bool = False) ‑> None
Deletes a resource.
Examples
Delete a Folder:
ah.delete('model/llm')
Delete a Model:
ah.delete('model/llm/gpt2')
Delete a Dataset:
ah.delete('dataset/images/cifar10')
Delete a non-main branch of specified Model:
ah.delete('model/llm/gpt2:v1')
Delete a tag:
ah.delete('model/llm/gpt2:20220101')
Delete another user’s Folder:
ah.delete('/user/t9k-assethub/model/llm')
If the Folder does not exist, do nothing:
ah.delete('model/llm', force=True)
Args
-
path (str)
Path of the resource.
-
force (bool)
If True, ignore non-existent resources.
t9k.ah.download
download(path: str, objects: Optional[Sequence[str]] = None, save_dir: str = '.')
Download objects of a reference of an Asset.
If no reference is provided, :main
will be used.
Examples
Download all objects of specified branch of Model to current working directory:
ah.download('model/llm/gpt2:v1')
Download an object to specified directory:
ah.download('model/llm/gpt2:v1', objects=['model.pt'], save_dir='./saved_model')
Download all objects under the same path:
ah.download('model/llm/gpt2:v1', objects=['saved_model/'])
Specify the reference by tag:
ah.download('dataset/images/cifar10:20220101')
Specify the reference by commit:
ah.download('dataset/images/cifar10:a41ac4ec')
Args
-
path (str)
Path of the reference from which objects are downloaded.
-
objects (Optional[Sequence[str]])
Objects to download.
-
save_dir (str)
Local directory which objects are downloaded to.
t9k.ah.get
get(path: str) ‑> Union[t9k.ah.core.Folder, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]
Gets a resource.
To get a commit, please provide a commit ID with a length of at least 4 to avoid potential conflicts with branches or tags.
Examples
Get a Folder:
folder = ah.get('model/llm')
Get a Model:
model = ah.get('model/llm/gpt2')
Get a Dataset:
dataset = ah.get('dataset/images/cifar10')
Get a non-main branch of specified Model:
branch = ah.get('model/llm/gpt2:v1')
Get a tag:
tag = ah.get('model/llm/gpt2:20220101')
Get another user’s Folder:
folder = ah.get('/user/t9k-assethub/model/llm')
Args
-
path (str)
Path of the resource.
Returns
A instance representing retrieved resource.
t9k.ah.list
list(path: str, resource: str = 'default') ‑> List[Dict[str, Any]]
Lists resources.
Based on the provided path
, list Folders with the specified Asset kind, Assets within the specified Folder, or all objects of the specified reference (branch, tag or commit) of Asset.
To list Folders that are shared with you, set path='shared/model'
(or path='shared/dataset'
); to list Folders that are public, set path='/public/t9k-assethub/model'
(or path='/public/t9k-assethub/dataset'
).
To list branches, provide a path
that points to an Asset and set resource='branch'
; to list tags, provide a path
that points to an Asset and set resource='tag'
; to list commits, provide a path
that points to a branch of an Asset and set resource='commit'
.
If a reference is expected but omitted, :main
will be used.
Examples
List Model Folders that you own:
folders = ah.list('model')
List Model Folders that are shared with you:
folders = ah.list('shared/model')
List Model Folders that are public:
folders = ah.list('/public/t9k-assethub/model')
List Models in your own Folder:
models = ah.list('model/llm')
List Models in another user’s Folder:
models = ah.list('/user1/t9k-assethub/model/llm')
List objects of specified branch of Model:
objects = ah.list('model/llm/gpt2:v1')
List objects of specified tag of Dataset:
objects = ah.list('dataset/images/cifar10:20220101')
List branches of specified Model:
branches = ah.list('model/llm/gpt2', resource='branch')
List tags of specified Model:
tags = ah.list('model/llm/gpt2', resource='tag')
List commits of specified branch of Model:
commits = ah.list('model/llm/gpt2:v1', resource='commit')
List commits of specified Dataset:
commits = ah.list('dataset/images/cifar10', resource='commit')
Args
-
path (str)
Path to be listed.
-
resource (str)
Kind of the resources, must be
'default'
,'branch'
, ‘tag
’ or'commit'
. This parameter is used to list branches, tags or commits: to list branches, provide apath
that points to an Asset and setresource='branch'
; to list tags, provide apath
that points to an Asset and setresource='tag'
; to list commits, provide apath
that points to a branch of an Asset and setresource='commit'
.
Returns
A list of resources.
t9k.ah.login
login(ah_host: Optional[str] = None, ais_host: Optional[str] = None, api_key: Optional[str] = None, timeout: Optional[int] = None) ‑> None
Logs in to AIStore server and Asset Hub server.
Sets up the client that corresponds with AIStore server and Asset Hub server.
Args
-
ah_host (Optional[str])
URL of Asset Hub server. Defaults to
t9k.CONFIG['asset_hub_host']
. -
ais_host (Optional[str])
URL of AIStore server. Defaults to
t9k.CONFIG['aistore_host']
. -
api_key (Optional[str])
API Key for requesting server. Defaults to
t9k.CONFIG['api_key']
. -
timeout (Optional[int])
How many seconds to wait for server to send data before giving up.
Raises
-
requests.HTTPError
Unable to connect to the server.
t9k.ah.logout
logout() ‑> None
Logs out from the current AIStore server and Asset Hub server.
The client is unset, it can no longer correspond with AIStore server and Asset Hub server until it is set up again.
t9k.ah.merge
merge(path: str) ‑> None
Merges a branch of a Model to the main branch.
Here, the specific operation of “merge” involves deleting all objects from the main branch and then copying all objects from the specified branch to the main branch.
Note that the specified branch itself cannot be the main branch.
Examples
ah.merge('model/llm/gpt2:v1')
Args
-
path (str)
Path of the branch.
t9k.ah.reset
reset(path: str) ‑> None
Resets a branch to clear all uncommitted changes.
Examples
ah.reset('model/llm/gpt2:main')
Args
-
path (str)
Path of the branch.
t9k.ah.update
update(path: str, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None
Updates a resource.
Only Folders and Assets can be updated.
If none of the args is provided, do nothing.
Examples
Rename a Folder:
ah.update('model/llm', name='generative-language-model')
Relabel a Model:
ah.update('model/llm/gpt2', labels=['JAX'])
Args
-
name (Optional[str])
New name of the resource.
-
labels (Optional[Sequence[str]])
New labels of the resource.
-
description (Optional[str])
New description of the resource.
t9k.ah.core
t9k.ah.core.Branch
Branch(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], name: str, commit_id: str)
Represents a branch of Asset.
Attributes
-
path (str)
Path of the branch.
-
asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])
A
Model
orDataset
instance corresponding to the Asset that the branch belongs to. -
kind (str)
A string
'branch'
. -
name (str)
Name of the branch.
-
commit_id (str)
ID of the commit that the branch points to.
-
alive (bool)
Whether the branch is alive.
Ancestors
t9k.ah.core._Ref
Methods
create_commit
create_commit(self, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None, force: bool = False) ‑> Optional[t9k.ah.core.Commit]
Commits changes to this branch.
First delete, then add.
Examples
Add a file as object to this branch:
branch.create_commit(msg='add ...', add=['model.pt'])
Specify a path in Asset for a file to add:
branch.create_commit(msg='add ...', add={'model.pt': 'saved_model/'})
Add all files under a directory as objects (with the directory):
branch.create_commit(msg='add ...', add=['./saved_model'])
Add all files under a directory as objects (without the directory):
branch.create_commit(msg='add ...', add=['./saved_model/*'])
Specify a path in Asset for a directory to add:
branch.create_commit(msg='add ...', add={'./saved_model': 'path/to/[saved_model]'})
## or
branch.create_commit(msg='add ...', add={'./saved_model': 'path/to/renamed_dir'})
Delete an object from this branch:
branch.create_commit(msg='delete ...', delete=['model.pt'])
Delete all objects under the specified path:
branch.create_commit(msg='delete ...', delete=['saved_model/'])
Args
-
msg (str)
Commit message.
-
delete (Optional[Sequence[str]])
Files or directories to delete from the branch, can be a sequence of paths in branch or
None
. If empty sequence orNone
, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here formata/.../b
signifies a file, whilea/.../b/
signifies a directory. -
add (Union[Sequence[str], Mapping[str, str], None])
Files or directories to add to the branch, can be a sequence of local paths, a mapping from local paths to their paths in Asset, or
None
. If empty sequence, empty mapping orNone
, add nothing. -
force (bool)
Whether to create a new commit if unknown changes or unimplemented changes are found.
Returns
A Commit
instance representing created commit if changes are
commited, None
if not.
create_tag
create_tag(self, name: str) ‑> t9k.ah.core.Tag
Creates a tag that points to this branch.
Args
-
name (str)
Name of the tag.
Returns
A Tag
instance representing created tag.
delete
delete(self) ‑> None
Deletes this branch.
download
download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None
Downloads objects of this branch.
Args
-
paths (Optional[Sequence[str]])
Files or directories to download from this branch, is a sequence of paths in branch. Here format
a/.../b
signifies a file whilea/.../b/
signifies a directory. Defaults to all objects. -
save_dir (str)
Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.
get_commit
get_commit(self, index: Optional[int] = None, id: Optional[str] = None) ‑> t9k.ah.core.Commit
Gets a commit of this branch.
If neither index
or id
is provided, return the last commit. If both
index
and id
are provided, id
will not be used.
Args
-
index (Optional[int])
Index of the commit in this branch,
0
for the last commit,-1
for the first commit. -
id (Optional[str])
A prefix of ID of the commit.
Returns
A Commit
instance representing retrieved commit.
list_commit
list_commit(self) ‑> List[Dict[str, Any]]
Lists commits of this branch.
list_object
list_object(self) ‑> List[Dict[str, Any]]
Lists objects of this branch.
merge
merge(self) ‑> None
Merges this branch to the main branch.
Here, the specific operation of “merge” involves deleting all objects from the main branch and then copying all objects from this branch to the main branch.
Note that this branch itself cannot be the main branch.
reset
reset(self) ‑> None
Resets this branch to clear all uncommitted changes.
t9k.ah.core.Commit
Commit(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], id_: str)
Represents a commit of Asset.
Attributes
-
path (str)
Path of the commit.
-
asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])
A
Model
orDataset
instance corresponding to the Asset that the commit belongs to. -
kind (str)
A string
'commit'
. -
name (str)
First 8 characters of ID of the commit.
-
id (str)
ID of the commit.
-
alive (bool)
Whether the commit is alive.
Ancestors
t9k.ah.core._Ref
Methods
create_tag
create_tag(self, name: str) ‑> t9k.ah.core.Tag
Creates a tag that points to this commit.
Args
-
name (str)
Name of the tag.
Returns
A Tag
instance representing created tag.
download
download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None
Downloads objects of this commit.
Args
-
paths (Optional[Sequence[str]])
Files or directories to download from this commit, is a sequence of paths in commit. Here format
a/.../b
signifies a file whilea/.../b/
signifies a directory. Defaults to all objects. -
save_dir (str)
Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.
list_commit
list_commit(self) ‑> List[Dict[str, Any]]
Lists commits of this commit.
list_object
list_object(self) ‑> List[Dict[str, Any]]
Lists objects of this commit.
t9k.ah.core.Dataset
Dataset(id_: str, folder: t9k.ah.core.Folder, name: str, labels: List[str], description: str, extra: str)
Represents a Dataset in server.
Attributes
-
path (str)
Path of the Dataset in server.
-
id (str)
ID of the Dataset in server.
-
folder (t9k.ah.core.Folder)
A
Folder
instance corresponding to the Folder that the Dataset belongs to. -
kind (str)
A string
'Dataset'
. -
name (str)
Name of the Dataset.
-
labels (List[str])
Labels of the Dataset.
-
description (str)
Description of the Dataset.
-
commit_id (str)
ID of the commit that the main branch points to.
-
extra (str)
Extra information about the Dataset.
-
alive (bool)
Whether the Dataset is alive.
Ancestors
t9k.ah.core._Dataset
Methods
create_commit
create_commit(self, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None) ‑> Optional[t9k.ah.core.Commit]
Commits changes to this Dataset.
First delete, then add.
Examples
Add a file as object to this Dataset:
dataset.create_commit(msg='add ...', add=['0.png'])
Specify a path in Dataset for an object to add:
dataset.create_commit(msg='add ...', add={'0.png': 'data/'})
Add all files under a directory as objects:
dataset.create_commit(msg='add ...', add=['./data'])
Delete an object from this Dataset:
dataset.create_commit(msg='delete ...', delete=['0.png'])
Delete all objects under the specified path:
dataset.create_commit(msg='delete ...', delete=['data/'])
Args
-
msg (str)
Commit message.
-
delete (Optional[Sequence[str]])
Files or directories to delete from the Dataset, can be a sequence of paths in Dataset or
None
. If empty sequence orNone
, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here formata/.../b
signifies a file, whilea/.../b/
signifies a directory. -
add (Union[Sequence[str], Mapping[str, str], None])
Files or directories to add to the Dataset, can be a sequence of local paths, a mapping from local paths to their paths in Dataset, or
None
. If empty sequence, empty mapping orNone
, add nothing.
Returns
A Commit
instance representing created commit if changes are
commited, None
if not.
delete
delete(self) ‑> None
Deletes this Dataset.
download
download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None
Downloads objects of this Dataset.
Args
-
paths (Optional[Sequence[str]])
Files or directories to download from this Dataset, is a sequence of paths in Dataset. Here format
a/.../b
signifies a file whilea/.../b/
signifies a directory. Defaults to all objects. -
save_dir (str)
Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.
get_commit
get_commit(self, index: Optional[int] = None, id: Optional[str] = None) ‑> t9k.ah.core.Commit
Gets a commit of this Dataset.
If neither index
or id
is provided, return the last commit. If both
index
and id
are provided, id
will not be used.
Args
-
index (Optional[int])
Index of the commit in this branch,
0
for the last commit,-1
for the first commit. -
id (Optional[str])
A prefix of ID of the commit.
Returns
A Commit
instance representing retrieved commit.
get_tag
get_tag(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Tag
Gets a tag of this Dataset.
Args
-
name (str)
Name of the tag.
-
verbose (bool)
Whether to log error.
Returns
A Tag
instance representing retrieved tag.
list_branch
list_branch(self) ‑> List[Dict[str, Any]]
Lists branches in this Dataset.
list_commit
list_commit(self) ‑> List[Dict[str, Any]]
Lists commits of this Dataset.
list_object
list_object(self) ‑> List[Dict[str, Any]]
Lists objects of this Dataset.
list_tag
list_tag(self) ‑> List[Dict[str, Any]]
Lists tags of this Dataset.
update
update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None
Updates the metadata of this Dataset.
If none of the args is provided, do nothing.
Args
-
name (Optional[str])
New name of this Dataset.
-
labels (Optional[Sequence[str]])
New labels of this Dataset.
-
description (Optional[str])
New description of this Dataset.
t9k.ah.core.Folder
Folder(path: str, id_: str, owner: str, asset_kind: str, name: str, labels: List[str], description: str, extra: str)
Represents a Asset Hub Folder in server.
Attributes
-
path (str)
Path of the Folder.
-
id (str)
ID of the Folder in server.
-
owner (str)
Owner of the Folder.
-
kind (str)
Kind of the Folder, is a string
'Model'
or'Dataset'
. -
name (str)
Name of the Folder.
-
labels (List[str])
Labels of the Folder.
-
description (str)
Description of the Folder.
-
extra (str)
Extra information about the Folder.
-
alive (bool)
Whether the Folder is alive.
Methods
create_asset
create_asset(self, name: str, labels: Optional[Sequence[str]] = None, description: str = '', exist_ok: bool = False) ‑> Union[t9k.ah.core.Model, t9k.ah.core.Dataset]
Creates an Asset in this Folder.
Args
-
name (str)
Name of the Asset.
-
labels (Optional[Sequence[str]])
Labels of the Asset.
-
description (str)
Description of the Asset.
-
exist_ok (bool)
If True and Asset with
name
already exists, return aModel
orDataset
instance representing this Asset; if False and Asset exists, raise aRuntimeError
.
Returns
A Model
or Dataset
instance representing created Model or
Dataset, depending on Asset kind of this Folder.
delete
delete(self) ‑> None
Deletes this Folder.
get_asset
get_asset(self, name: str) ‑> Union[t9k.ah.core.Model, t9k.ah.core.Dataset]
Gets an Asset in this Folder.
If you want to get Asset directly by its path, use ah.get_asset()
.
Args
-
name (str)
Name of the Asset.
Returns
A Model
or Dataset
instance representing retrieved Model or
Dataset, depending on Asset kind of this Folder.
list_asset
list_asset(self) ‑> List[Dict[str, Any]]
Lists Assets in this Folder.
update
update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None
Updates the metadata of this Folder.
If none of the args is provided, do nothing.
Args
-
name (Optional[str])
New name of this Folder.
-
labels (Optional[Sequence[str]])
New labels of this Folder.
-
description (Optional[str])
New description of this Folder.
t9k.ah.core.Model
Model(id_: str, folder: t9k.ah.core.Folder, name: str, labels: List[str], description: str, extra: str)
Represents a Model in server.
Attributes
-
path (str)
Path of the Model in server.
-
id (str)
ID of the Model in server.
-
folder (t9k.ah.core.Folder)
A
Folder
instance corresponding to the Folder that the Model belongs to. -
kind (str)
A string
'Model'
. -
name (str)
Name of the Model.
-
labels (List[str])
Labels of the Model.
-
description (str)
Description of the Model.
-
extra (str)
Extra information about the Model.
-
alive (bool)
Whether the Model is alive.
Ancestors
t9k.ah.core._Model
Methods
create_branch
create_branch(self, name: str) ‑> t9k.ah.core.Branch
Creates an empty branch of this Model.
Args
-
name (str)
Name of the branch.
Returns
A Branch
instance representing created branch.
delete
delete(self) ‑> None
Deletes this Model.
download
download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None
Downloads objects of this Model.
Args
-
paths (Optional[Sequence[str]])
Files or directories to download from this Dataset, is a sequence of paths in Dataset. Here format
a/.../b
signifies a file whilea/.../b/
signifies a directory. Defaults to all objects. -
save_dir (str)
Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.
get_branch
get_branch(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Branch
Gets a branch of this Model.
Args
-
name (str)
Name of the branch.
-
verbose (bool)
Whether to log error.
Returns
A Branch
instance representing retrieved branch.
get_commit
get_commit(self, id: str) ‑> t9k.ah.core.Commit
Gets a commit of this Model.
If no commit matches id
, or two or more commits matche id
,
raise a RuntimeError
.
Args
-
id (str)
A prefix of ID of the commit.
Returns
A Commit
instance representing retrieved commit.
get_tag
get_tag(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Tag
Gets a tag of this Model.
Args
-
name (str)
Name of the tag.
-
verbose (bool)
Whether to log error.
Returns
A Tag
instance representing retrieved tag.
list_branch
list_branch(self) ‑> List[Dict[str, Any]]
Lists branches in this Model.
list_object
list_object(self) ‑> List[Dict[str, Any]]
Lists objects of this Model.
list_tag
list_tag(self) ‑> List[Dict[str, Any]]
Lists tags of this Model.
update
update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None
Updates the metadata of this Model.
If none of the args is provided, do nothing.
Args
-
name (Optional[str])
New name of this Model.
-
labels (Optional[Sequence[str]])
New labels of this Model.
-
description (Optional[str])
New description of this Model.
t9k.ah.core.Tag
Tag(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], name: str, commit_id: str)
Represents a tag of Asset.
Attributes
-
path (str)
Path of the tag.
-
asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])
A
Model
orDataset
instance corresponding to the Asset that the tag belongs to. -
kind (str)
A string
'tag'
. -
name (str)
Name of the tag.
-
commit_id (str)
ID of the commit that the tag points to.
-
alive (bool)
Whether the tag is alive.
Ancestors
t9k.ah.core._Ref
Methods
create_tag
create_tag(self, name: str) ‑> t9k.ah.core.Tag
Creates another tag that points to this tag.
Args
-
name (str)
Name of the tag.
Returns
A Tag
instance representing created tag.
delete
delete(self) ‑> None
Deletes this tag.
download
download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None
Downloads objects of this tag.
Args
-
paths (Optional[Sequence[str]])
Files or directories to download from this tag, is a sequence of paths in tag. Here format
a/.../b
signifies a file whilea/.../b/
signifies a directory. Defaults to all objects. -
save_dir (str)
Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.
list_commit
list_commit(self) ‑> List[Dict[str, Any]]
Lists commits of this tag.
list_object
list_object(self) ‑> List[Dict[str, Any]]
Lists objects of this tag.
t9k.config
t9k.config.Config
Config()
SDK config.
Methods
get
get(self, key: str, default: Any = None) ‑> Any
items
items(self) ‑> ItemsView[str, Any]
to_dict
to_dict(self) ‑> Dict[str, Any]
update
update(self, new_config: Dict[str, Any]) ‑> None
t9k.config.ConfigItem
ConfigItem(name: str, value: Optional[Any] = None, processor: Union[Callable, Sequence[Callable], None] = None, validator: Union[Callable, Sequence[Callable], None] = None, hook: Union[Callable, Sequence[Callable], None] = None)
SDK config item.
Attributes
-
name (str)
Name of config item.
-
value (Any)
Value of config item.
t9k.em
t9k.em.artifact.Artifact
Artifact(metadata: Dict[str, Any], objects: Optional[Dict[str, Dict[str, Any]]] = None)
Implementation of Artifact, a set of files that a Run inputs or outputs.
Args
-
metadata (Dict[str, Any])
Metadata to initialize a new Artifact.
-
objects (Optional[Dict[str, Dict[str, Any]]])
Data of objects of the Artifact.
Attributes
-
name (str)
Name of the Artifact.
-
labels (List[str])
Labels of the Artifact.
-
description (str)
Description of the Artifact.
-
created_timestamp (str)
Created timestamp of the Artifact.
-
alternative_name (str)
Alternative name of the Artifact.
-
objects (List[Dict[str, str]])
Data of objects of the Artifact.
-
remote (List[Dict[str, str]])
Upload and download history of the Artifact.
-
local (str)
Local directory of the Artifact.
Methods
add_dir
add_dir(self, dir_path: str, obj_path: Optional[str] = None) ‑> None
Adds all files under a local directory as objects of the Artifact.
The directory will be copied to local directory of the Artifact, the specific subpath depends on its obj_path, for example:
# dir copied to `<local-dir>/a`
artifact.add_dir(dir_path='a/')
# or
artifact.add_dir(dir_path='a')
# or
artifact.add_dir(dir_path='a/', obj_path='a')
# dir copied to `<local-dir>/b/a`
artifact.add_dir(dir_path='a/', obj_path='b/')
# or
artifact.add_dir(dir_path='a/', obj_path='b/a')
add_file
add_file(self, file_path: str, obj_path: Optional[str] = None) ‑> None
Adds a local file as an object of the Artifact.
The file will be copied to local directory of the Artifact, the specific subpath depends on its object path, for example:
# file copied to `<local-dir>/1.png`
artifact.add_file(file_path='1.png')
# or
artifact.add_file(file_path='1.png', obj_path='1.png')
# file copied to `<local-dir>/a/1.png`
artifact.add_file(file_path='1.png', obj_path='a/')
# or
artifact.add_file(file_path='1.png', obj_path='a/1.png')
add_reference
add_reference(self, uri: str, obj_path: Optional[str] = None) ‑> None
Adds a URI as an object reference to the Artifact.
parse_from_dict
parse_from_dict(self, data: Dict[str, Any]) ‑> None
Parses an Artifact instance from a dict.
to_dict
to_dict(self) ‑> Dict[str, Any]
Converts Artifact instance to a dict and returns it.
upload
upload(self, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None
Uploads this Artifact to server.
Args
-
folder (str)
Path of the Folder to which the Artifact is uploaded. If the provided path does not start with ‘/’,
/<current-user>/
is prepended to it. -
make_folder (bool)
If True and Folder with path
folder
does not exist, make the Folder and parent Folders as needed. -
conflict_strategy (str)
Strategy adopted when an Artifact with the same name as the Artifact to be uploaded already exists in the Folder, must be ‘skip’, ‘error’, ‘new’ or ‘replace’. If ‘skip’, skip the upload; if ‘error’, error out; if ‘new’, upload with the alternative name of Artifact; if ‘replace’, delete the existing Artifact and upload.
t9k.em.containers.Params
Params(upload: Callable, init_hparams: Dict[str, Union[str, int, float, bool, None, List[~T], Tuple[], Dict[~KT, ~VT]]] = None)
Container class to hold hyperparameters of Run.
It is recommended to set all hyperparameters by calling update
method once before building the model. Nevertheless, you are free to operate hyperparameters like items of a dict or attributes of an object.
Examples
Recommended method of setting hyperparameters:
run.update({
'batch_size': 32,
'epochs': 10,
})
Assign parameter like an item of dict or attribute of object:
run.params['batch_size'] = 32
run.params.epochs = 10
Args
-
upload (Callable)
Function that is called to upload hyperparameters every time hyperparameters are updated.
-
init_hparams (Dict[str, Union[str, int, float, bool, None, List[~T], Tuple[], Dict[~KT, ~VT]]])
Initial hyperparameters.
Ancestors
collections.abc.MutableMapping
Methods
as_dict
as_dict(self)
items
items(self)
D.items() -> a set-like object providing a view on D’s items
keys
keys(self)
D.keys() -> a set-like object providing a view on D’s keys
parse
parse(self, dist_tf_strategy=None, dist_torch_model=None, dist_hvd=None)
Parses hyperparameters from various objects of various frameworks.
Args
-
dist_tf_strategy
TensorFlow distribution strategy instance if
tf.distribute
is used for distributed training. -
dist_torch_model
PyTorch model wrapped with DP or DDP if
torch.distributed
is used for distributed training. -
dist_hvd
Used module such as
horovod.keras
andhorovod.torch
if Horovod is used for distributed training.
update
update(self, new_params: Dict[str, Any], override: bool = True)
Updates with new params.
Args
-
new_params (Dict[str, Any])
New params to be updated with.
-
override (bool)
Whether to override current params.
values
values(self)
D.values() -> an object providing a view on D’s values
t9k.em.create_artifact
create_artifact(name: str, labels: Optional[Sequence[str]] = None, description: str = '') ‑> t9k.em.artifact.Artifact
Creates and initializes a new Artifact.
The local files of Artifact are placed under the parent directory specified by the environment variable EM_ARTIFACT_PARENT_DIR
(default is relative path .em/artifacts
).
Examples
tensorboard_artifact = em.create_artifact(name='tensorboard_logs')
Args
-
name (str)
Name of the Artifact.
-
labels (Optional[Sequence[str]])
Labels of the Artifact.
-
description (str)
Description of the Artifact.
Returns
An Artifact instance created and initialized.
t9k.em.create_run
create_run(config_path: Optional[str] = None, name: str = 'default', hparams: Optional[Dict[str, Any]] = None, labels: Optional[Sequence[str]] = None, description: str = '', auto_upload: bool = False, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> t9k.em.run.Run
Creates and initializes a new Run.
The local files of Run are placed under the parent directory specified by the environment variable EM_RUN_PARENT_DIR
(default is relative path .em/runs
).
Examples
Basic usage:
from t9k import em
run = em.create_run(name='cnn_keras',
folder='cv/image-classification/mnist')
Provide initial parameters of Run:
hparams = {
'batch_size': 32,
'epochs': 1,
'learning_rate': 0.001,
'conv_channels1': 32,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
}
run = em.create_run(name='cnn_keras',
hparams=hparams,
folder_path='cv/image-classification/mnist')
Provide a Run config file:
run = em.create_run(config_path='./run_config.yaml')
where the config file run_config.yaml
is like:
name: cnn_keras
hparams:
batch_size: 32
epochs: 1
learning_rate: 0.001
conv_channels1: 32
conv_channels2: 64
conv_channels3: 64
conv_kernel_size: 3
maxpool_size: 2
linear_features1: 64
labels:
- Keras
description: Train a simple CNN model that classifies images of handwritten digits.
Args
-
config_path (Optional[str])
Local path of the Run config file. For all of the following args, the values parsed from the config file take precedence over values passed in.
-
name (str)
Name of the Run.
-
hparams (Optional[Dict[str, Any]])
Initial hyperparameters of the Run.
-
labels (Optional[Sequence[str]])
Labels of the Run.
-
description (str)
Description of the Run.
-
auto_upload (bool)
Whether to upload the Run and its data automatically and asynchronously. If False, all of the following args will not be used.
-
folder (str)
Path of the Folder to which the Run is uploaded. If the provided path does not start with ‘/’,
/<current-user>/
is prepended to it. Ifauto_upload
is False, this arg will not be used. -
make_folder (bool)
If True and Folder with path
folder
does not exist, make the Folder and parent Folders as needed. Ifauto_upload
is False, this arg will not be used. -
conflict_strategy (str)
Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be ‘skip’, ‘error’, ‘new’ or ‘replace’. If ‘skip’, skip the upload; if ‘error’, error out; if ‘new’, upload with the alternative name of Run; if ‘replace’, delete the existing Run and upload. If
auto_upload
is False, this arg will not be used.
Returns
A Run instance created and initialized.
t9k.em.load_artifact
load_artifact(path: str) ‑> t9k.em.artifact.Artifact
Loads an Artifact from local or server.
This function will first search for the corresponding local directory, followed by remote path. If the path is not found in either location, raise a RuntimeError
.
In the case of the remote path, if the provided path does not start with ‘/’, /<current-user>/
is prepended to it.
Examples
Load by local path:
em.load_artifact(path=
'.em/artifacts/tensorboard_logs_220823_194728_4e48t2')
Load by remote path:
em.load_artifact(path='/user/path/to/tensorboard_logs')
Args
-
path (str)
Local directory of the Artifact, or path of the Artifact in server.
Returns
An Artifact instance loaded.
t9k.em.load_run
load_run(path: str, auto_upload: bool = False, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> t9k.em.run.Run
Loads a Run from local or server.
This function will first search for the corresponding local path, followed by remote path. If the path is not found in either location, raise a RuntimeError
.
In the case of the remote path, if the provided path does not start with ‘/’, /<current-user>/
is prepended to it.
Examples
Load by local path:
em.load_run(path='.em/runs/cnn_keras_220823_194728_4e48t2')
Load by remote path:
em.load_run(path='/user/path/to/cnn_keras')
Args
-
path (str)
Local directory of the Run, or path of the Run in server.
-
auto_upload (bool)
Whether to upload the Run and its data automatically and asynchronously. If False, all of the following args will not be used.
-
folder (str)
Path of the Folder to which the Run is uploaded. If the provided path does not start with ‘/’,
/<current-user>/
is prepended to it. Ifauto_upload
is False, this arg will not be used. -
make_folder (bool)
If True and Folder with path
folder
does not exist, make the Folder and parent Folders as needed. Ifauto_upload
is False, this arg will not be used. -
conflict_strategy (str)
Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be ‘skip’, ‘error’, ‘new’ or ‘replace’. If ‘skip’, skip the upload; if ‘error’, error out; if ‘new’, upload with the alternative name of Run; if ‘replace’, delete the existing Run and upload. If
auto_upload
is False, this arg will not be used.
Returns
A Run instance loaded.
t9k.em.login
login(ais_host: Optional[str] = None, api_key: Optional[str] = None, timeout: Optional[int] = None) ‑> None
Logs in to AIStore server.
Sets up the client that corresponds with AIStore server.
Args
-
ais_host (Optional[str])
URL of AIStore server. Defaults to
t9k.CONFIG['aistore_host']
. -
api_key (Optional[str])
API Key for requesting server. Defaults to
t9k.CONFIG['api_key']
. -
timeout (Optional[int])
How many seconds to wait for server to send data before giving up.
Raises
-
requests.HTTPError
Unable to connect to the server and
unable_to_connect_ok
is False.
t9k.em.logout
logout() ‑> None
Logs out from the current AIStore server.
The client is unset, it can no longer correspond with AIStore server until it is set up again.
t9k.em.run.Run
Run(metadata: Dict[str, Any], hparams: Optional[Dict[str, Any]] = None, metrics: Optional[Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]]] = None, platform: Optional[Dict[str, Any]] = None, git: Optional[Dict[str, Any]] = None)
Implementation of Run, a run of a specific model for certain ML task.
Args
-
metadata (Dict[str, Any])
Metadata to initialize a new Run.
-
hparams (Optional[Dict[str, Any]])
Hyperparameters of the Run.
-
metrics (Optional[Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]]])
Metrics of the Run.
-
platform (Optional[Dict[str, Any]])
Platform information of the Run.
-
git (Optional[Dict[str, Any]])
Git information of the Run.
Attributes
-
name (str)
Name of the Run.
-
labels (List[str])
Labels of the Run.
-
description (str)
Description of the Run.
-
start_timestamp (str)
Start timestamp of the Run.
-
end_timestamp (str)
End timestamp of the Run.
-
status (str)
Status of the Run.
-
alternative_name (str)
Alternative name of the Run.
-
associations (Dict[str, List[Dict[str, str]]])
Input and output resources of the Run.
-
hparams (Any)
Hyperparameters of the Run.
-
metrics (Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]])
Metrics produced in the Run.
-
platform (Dict[str, Any])
Platform information of the Run.
-
git (Dict[str, Any])
Git information of the Run.
-
remote (List[Dict[str, str]])
Upload and download history of the Run.
-
local (str)
Local directory of the Run.
Methods
finish
finish(*args, **kwargs)
log
log(self, type: str, metrics: Dict[str, float], step: int, epoch: Optional[int] = None) ‑> None
Logs a set of metrics of Run.
Args
-
type (str)
Type of the metrics, ‘train’ (or ‘training’), ‘val’ (or ‘validate’, ‘validation’) and ‘test’ (or ‘testing’, ‘eval’, ‘evaluate’, ‘evaluation’) for training, validation and testing metrics respectively. Besides, you can also use other arbitrary string as custom type of the metrics.
-
metrics (Dict[str, float])
Additional metrics to be logged.
-
step (int)
Number of the step that the metrics belong to.
-
epoch (Optional[int])
Number of the epoch that the metrics belong to.
mark_input
mark_input(self, resource: Union[t9k.em.artifact.Artifact, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]) ‑> None
Marks an Artifact, Model or Dataset as an input of this Run.
mark_output
mark_output(self, resource: Union[t9k.em.artifact.Artifact, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]) ‑> None
Marks an Artifact, Model or Dataset as an output of this Run.
parse_from_dict
parse_from_dict(self, data: Dict[str, Any]) ‑> None
Parses a Run instance from a dict.
to_dict
to_dict(self) ‑> Dict[str, Any]
Converts Run instance to a dict and returns it.
upload
upload(self, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None
Uploads this Run to server.
If this Run has input or output Artifacts, these Artifacts are uploaded as well if they have not been uploaded, and these associations are uploaded.
Args
-
folder (str)
Path of the Folder to which the Run is uploaded. If the provided path does not start with ‘/’,
/<current-user>/
is prepended to it. -
make_folder (bool)
If True and Folder with path
folder
does not exist, make the Folder and parent Folders as needed. -
conflict_strategy (str)
Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be ‘skip’, ‘error’, ‘new’ or ‘replace’. If ‘skip’, skip the upload; if ‘error’, error out; if ‘new’, upload with the alternative name of Run; if ‘replace’, delete the existing Run and upload.
t9k.em.upload
upload(path: str, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None
Upload local Runs or Artifacts.
Examples
Upload a Run by its local directory:
em.upload(path='.em/runs/cnn_keras_220823_194728_4e48t2')
Upload all Artifact under the parent directory:
em.upload(path='.em/artifacts')
Specify the path of Folder to which the Run is uploaded:
em.upload(path='.em/runs/cnn_keras_220823_194728_4e48t2',
folder='image_classification/mnist')
Args
-
path (str)
Local directory of the Run to be uploaded, or parent directory that contains one or more Runs.
-
folder (str)
Path of the Folder to which the Run is uploaded. If the provided path does not start with ‘/’,
/<current-user>/
is prepended to it. -
make_folder (bool)
If True and Folder with path
folder
does not exist, make the Folder and parent Folders as needed. -
conflict_strategy (str)
Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be ‘skip’, ‘error’, ‘new’ or ‘replace’. If ‘skip’, skip the upload; if ‘error’, error out; if ‘new’, upload with the alternative name of Run; if ‘replace’, delete the existing Run and upload.
t9k.tuner
t9k.tuner.get_current_parameter
get_current_parameter(tag: Optional[str] = None)
Gets current hyper parameters generated by tuner. It returns the same group of hyper parameters as the last call of get_next_parameter returns.
Args
-
tag (Optional[str])
hyper parameter key.
t9k.tuner.get_experiment_id
get_experiment_id()
Gets experiment ID.
Returns
Identifier of current experiment.
t9k.tuner.get_next_parameter
get_next_parameter()
Gets the hyper paremeters generated by tuner. For a multiphase experiment, it returns a new group of hyper parameters at each call of get_next_parameter. For a non-multiphase (multiPhase is not configured or set to False) experiment, it returns hyper parameters only on the first call for each trial job, it returns None since second call. This API should be called only once in each trial job of an experiment which is not specified as multiphase.
Returns
A dict object contains the hyper parameters generated by tuner, the keys of the dict are defined in search space. Returns None if no more hyper parameters can be generated by tuner.
t9k.tuner.get_sequence_id
get_sequence_id()
Gets trial job sequence nubmer. A sequence number is an integer value assigned to each trial job base on the order they are submitted, incremental starting from 0. In one experiment, both trial job ID and sequence number are unique for each trial job, they are of different data types.
Returns
Sequence number of current trial job which is calling this API.
t9k.tuner.get_trial_id
get_trial_id()
Gets trial job ID which is string identifier of a trial job, for example ‘MoXrp’. In one experiment, each trial job has an unique string ID.
Returns
Identifier of current trial job which is calling this API.
t9k.tuner.report_final_result
report_final_result(metric: Any)
Reports final result to TUNER.
Args
-
metric (Any)
Usually (for built-in tuners to work), it should be a number, or a dict with key “default” (a number), and any other extra keys.
t9k.tuner.report_intermediate_result
report_intermediate_result(metric: Any, step: int)
Reports intermediate result to TUNER.
Args
-
metric (Any)
serializable object.
Codepack
Codepack 以简洁明了的形式定义在平台上开发、运行、部署一个机器学习项目所需要的全部信息,例如代码、配置文件、各种参数等。其相关工具能够根据这些信息自动地执行相应的操作,从而大幅减少用户的操作量,显著改善实验的可重复性。
例如对于 MNIST 手写数字图像分类任务,在已经准备好了训练代码、数据集和资源配置文件的情况下,你只需要再创建一个 Codepack 定义文件,然后使用 Codepack CLI 执行一条命令,就可以在平台上启动分布式训练:
这里 Codepack 定义文件的内容如下:
apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
- name: prepare-env # Prepare running env
actions:
- name: workspace-for-training
verb: apply
files: [pvc.yaml]
- name: copy-file # Copy training code and dataset to PVC
deps: ["prepare-env"]
actions:
- name: copy-code
verb: copy
src: .
dst: codepack-example:.
- name: run-distributed-training # Run a distributed training
deps: ["prepare-env", "copy-file"]
actions:
- name: trainingjob
verb: create
files: [trainingjob.yaml]
整个 Codepack 的文件结构如下:
mnist-keras
├── codepack.yaml
├── main.py
├── mnist.npz
├── pvc.yaml
└── trainingjob.yaml
由于 Codepack 的全部信息都维护在一个定义文件中,用户创建一个新的 Codepack 或者将既有的机器学习项目修改为 Codepack 都非常容易,并且用户可以使用 Git 来轻松地对 Codepack 进行版本控制和分发。
Codepack 的相关工具包括命令行工具和集群内组件,前者负责读取 Codepack 定义并执行用户指定的 action,后者负责进行安全访问控制以及为命令行工具执行 action 提供支持。
下一步
- 了解 Codepack 的概念
- 了解 Codepack 的定义
- 了解命令行工具
- 学习具体的使用示例
概念
Codepack
Codepack 是对用户想要在平台上运行的机器学习项目的抽象,其实质上是一个包含项目文件(模型代码、资源配置文件等)以及 Codepack 定义文件的文件系统的目录,该定义文件包含了 Codepack 的基本信息(版本、名称、描述等)和运行信息(target 和 action 的定义),见 Codepack 定义。
target
target 是对 Codepack 的一个具体任务的抽象,例如在平台上完成模型训练、部署模型为推理服务等。每个 target 可以指定其依赖的其他 target(例如创建推理服务需要先完成模型训练),命令行工具在运行一个 target 时,将递归地解析依赖,然后运行一个工作流。
action
action 是对 target 的一个具体的可执行的操作的抽象,例如在平台中创建一个 PVC、创建一个进行分布式训练的 TrainingJob 等。action 定义了多个动词(verb),每个动词针对某一类的具体操作,由命令行工具和集群内组件提供实现。
Codepack 定义
一个包含机器学习代码及相关文件的文件系统目录,加上 Codepack 的定义文件就构成了一个 Codepack。Codepack 定义文件是一个通常名为 codepack.yaml
的 YAML 文件,其包含 Codepack 的版本、名称、描述等基本信息以及 target 定义、action 定义等运行相关的信息。
下面将具体介绍 Codepack 定义文件中的各个字段以及它们的作用,从而指导用户如何创建一个 Codepack。
创建 Codepack 定义文件
下面是一个基本的 Codepack 定义文件的示例:
apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
targets:
- name: prepare-env # target definition
actions:
- name: workspace-for-training # action definition
verb: apply
files: [pvc.yaml]
- name: copy-code
verb: copy
src: .
dst: codepack-pvc:.
在该例中:
- 指定 Codepack 的版本、名称和详细描述(分别由
apiVersion
、name
和description
字段指定)。 targets
字段定义一个 target,这个 target 又通过actions
字段定义两个 action。这里 target 的name
字段是必需的;action 的name
字段不是必需的,但verb
字段以及相应动词需要提供的字段是必需的(请参阅 action 动词)。
指定默认项目和 target
可以通过 project
和 default
字段指定 Codepack 的默认项目和 target,这样在使用命令行工具运行 Codepack 时如果不提供相应的参数,则会使用这些默认值。
apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo # default project to run in
default: prepare-env # default target to run
targets:
- name: prepare-env
actions:
- name: workspace-for-training
verb: apply
files: [pvc.yaml]
- name: copy-code
verb: copy
src: .
dst: codepack-pvc:.
工作流机制
target 是对 Codepack 的一个具体任务的抽象,多个 target 之间可能存在依赖关系,例如负责从本地复制文件到 PVC 的 target 需要依赖负责创建 PVC 的 target 运行完毕。每一个 target 可以通过 deps
字段传入一个 target 名称列表来指定其依赖的其他 target。
在使用命令行工具运行某一个 target 时,命令行工具会递归地解析所有依赖的 target,动态地构建一个有向无环图,然后串行或者并行地运行图中当前没有依赖或依赖已经运行完毕的 target,直到所有 target 全部运行。
利用工作流机制,可以将上面示例中的 target prepare-env
拆分为具有依赖关系的两个 target,并且在此基础上再创建一个依赖它们的负责启动分布式训练的 target。
apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
- name: prepare-env # Prepare running env
actions:
- name: workspace-for-training
verb: apply
files: [pvc.yaml]
- name: copy-file # Copy the Codepack to PVC
deps: ["prepare-env"]
actions:
- name: copy-code
verb: copy
src: .
dst: codepack-pvc:.
- name: run-distributed-training # Run a distributed training
deps: ["prepare-env", "copy-file"]
actions:
- name: trainingjob
verb: create
files: [trainingjob.yaml]
action 动词
action 的动词通过 verb
字段指定,表示其操作类型,目前定义了下列值。
apply
应用配置到资源,类似于 kubectl apply
。若同名资源已经存在,则更新其配置,否则创建该资源。
需要提供以下字段:
files
:定义资源的 YAML 配置文件的路径、文件路径的列表或者包含 YAML 配置文件的目录的路径。
示例:
actions:
- name: workspace-for-training
verb: apply
files: [pvc.yaml]
copy
将文件或目录从源位置复制到目标位置,具体实现取决于源和目标的类型:
- 若都为本地路径,则直接在本地进行 rsync 操作。
- 若一个为本地路径,一个为 PVC 路径,则在集群中创建一个挂载这个 PVC 并且运行 sshd 服务的 Pod,在本地进行远程 rsync 操作。
- 若都为 PVC 路径,则在集群中创建一个挂载这两个 PVC 的 Pod,在 Pod 中进行 rsync 操作。
需要提供以下字段:
-
src
:文件或目录的源位置,可以是本地路径或 PVC 路径,格式如下:-
本地路径:
.
(Codepack 的全部文件)./data
(Codepack 的子目录)./data/
(Codepack 的子目录下的全部文件)./train.py
(Codepack 的文件)
-
PVC 路径:
<pvc-name>:.
(PVC 的根目录)<pvc-name>:data
(PVC 的子目录)<pvc-name>:data/
(PVC 的子目录下的全部文件)<pvc-name>:data/mnist.npz
(PVC 的文件)
-
-
dst
:文件或目录的目标位置,可以是本地路径或 PVC 路径,格式同上。
示例:
actions:
- name: copy-code
verb: copy
src: .
dst: codepack-pvc:.
create
创建资源,类似于 kubectl create
。若同名资源已经存在,则错误退出,或为名称添加随机后缀再进行创建。
需要提供以下字段:
files
:定义资源的 YAML 配置文件的路径、文件路径的列表或者包含 YAML 配置文件的目录的路径。new
:若为True
,并且同名资源已经存在,则为名称添加随机后缀再进行创建;若为False
则错误退出。默认为 True。
示例:
actions:
- name: trainingjob
verb: create
files: [trainingjob.yaml]
命令行工具
Codepack CLI(命令行工具)用于在命令行终端中运行 Codepack。
安装
前置条件
Codepack CLI 使用 Python 3 编写,在安装之前请确保你的本地环境安装了 3.6 或以上版本的 Python 以及 pip 工具。
为使 Codepack CLI 提供的文件复制功能正常运行,还需要安装 3.1.0 及以上版本的 rsync。macOS 执行以下命令安装:
brew install rsync
基于 Debian 的 Linux 发行版执行以下命令安装:
apt-get install rsync
基于 rpm 的 Linux 发行版执行以下命令安装:
yum install rsync
然后你可以执行以下命令来验证安装完成,并且确认安装的 rsync 版本。
rsync --version
安装
目前 TensorStack SDK 仅提供用于本地安装的 Python 包,你可以从平台首页下载。
然后使用以下命令进行安装:
pip install codepack-<version>.tar.gz [-i <pypi-mirror-url>]
命令
check
检查 Codepack 的有效性。
使用
codepack check [CODEPACK_PATH]
CODEPACK_PATH Codepack 或 Codepack 定义文件的路径, 默认为当前路径
示例
$ codepack check examples/mnist-keras
Checked, no errors found in codepack mnist-keras
config
查看、修改 Codepack CLI 的配置。
Codepack CLI 各项配置的含义如下:
配置项 | 含义 | 默认值 |
---|---|---|
api_key | 用于身份验证的 API Key | None |
copy_pod_image | copy 动词创建的 Pod 所使用的镜像 | None |
使用
$ codepack config [--list] [--get KEY] [--set KEY=VALUE]
--list, -l 列出所有 CLI 配置项
--get=KEY, -g 获取 CLI 配置项
--set=KEY=VALUE, -s 设置 CLI 配置项
示例
$ codepack config --list
api_key=None
copy_pod_image=t9kpublic/sshd-rsync:0.0.0.6
$ codepack config --get api_key
api_key=None
$ codepack config --set api_key=5b398842-7c92-4922-a472-c905553beefd
api_key=5b398842-7c92-4922-a472-c905553beefd
config items set
$ codepack config --get api_key
api_key=5b398842-7c92-4922-a472-c905553beefd
describe
查看 Codepack 的详细信息。
使用
codepack describe [CODEPACK_PATH]
CODEPACK_PATH Codepack 或 Codepack 定义文件的路径, 默认为当前路径
示例
$ codepack describe examples/mnist-keras
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
targets:
- prepare-env
- copy-file
- create-notebook
- run-distributed-training
- run-e2e-workflow
run
运行 Codepack 的指定 target。
使用
codepack run [--project PROJECT_NAME] [--target TARGET_NAME] [--verbose] [--wait-timeout INTEGER] [CODEPACK_PATH]
--project=PROJECT_NAME, -p 项目名称, 运行在该项目下
--target=TARGET_NAME, -t target 名称, 运行该 target
--verbose, -v 打印更多信息
--wait-timeout=INT, -W 设定以秒为单位的 Pod 超时等待时间
CODEPACK_PATH Codepack 或 Codepack 定义文件的路径, 默认为当前路径
示例
$ codepack run examples/mnist-keras -t run-distributed-training -p demo
RUN target run-distributed-training of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> run-distributed-training
Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim with the name codepack-example already exists, skip
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: run-distributed-training
CREATE by files ['trainingjob.yaml']
TensorFlowTrainingJob codepack-example created
配置
配置文件
Codepack CLI 没有单独的配置文件,而是使用 TensorStack CLI 的配置文件。在执行 codepack
命令时,会自动读取位于路径 ~/.t9k/t9k-config.yaml
的配置文件(如果设置了环境变量 T9K_CONFIG
,则读取其值给出的路径)。如果配置文件不存在或缺少部分配置项,则缺少的这些配置项会被设置为 None
,这可能导致 Codepack CLI 的部分功能不能正常工作。
扩展配置
配置文件中的 contexts[*].extension.codepack
字段是 Codepack CLI 的扩展配置,其包含以下字段:
字段 | 功能 |
---|---|
copy-pod-image | 用于复制文件的 Pod 使用的镜像 |
查看配置
使用 codepack config -l
命令以查看所有配置项的值。
身份验证
Codepack CLI 支持下列身份验证方式,你可以选择其中的一种进行相应的配置。
平台内运行(incluster)
用户需要在平台资源内(平台所在 Kubernetes 集群的 Pod 内)使用 Codepack CLI,例如在 Notebook 的终端中使用。
注意在运行 target 时只能指定当前项目(不指定则默认为当前项目)。
在此方式下,Codepack CLI 直接利用 Kubernetes 提供给 Pod 的 Service Account 向 kube-apiserver 发送请求以执行各 action。
kubeconfig 文件
用户需要持有平台所在 Kubernetes 集群的 kubeconfig 文件,并将其放置在路径 ~/.kube/config
下(如果设置了环境变量 KUBECONFIG
,则放置在其值给出的路径下)。
在此方式下,Codepack CLI 直接利用 kubeconfig 文件向 kube-apiserver 发送请求以执行各 action。
t9kconfig 文件
用户持有的配置文件需要提供 API Key 或 token。
在此方式下,Codepack CLI 向平台的各服务器发送请求,再由它们向 kube-apiserver 转发请求以执行各 action。
示例
下面是一个简单但完整的创建和运行 Codepack 的示例。
创建 Codepack
这里以进行 MNIST 手写数字图像分类的 Keras 模型为例,在工作路径下创建一个名为 mnist-keras
的目录。
准备代码、数据集和资源配置文件
首先编写一个进行模型构建、训练和测试的 Python 脚本,使用 Keras 框架和简单的卷积神经网络结构。为了在平台上进行分布式训练,训练过程采用 tf.distribute.MultiWorkerMirroredStrategy
分布式策略。具体代码如下:
import argparse
import json
import logging
import os
import shutil
import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers
parser = argparse.ArgumentParser(
description='Distributed training of Keras model for MNIST with '
'MultiWorkerMirroredStrategy.')
parser.add_argument('--aimd',
action='store_true',
default=False,
help='Use AIMD to record training data.')
parser.add_argument('--api_key',
type=str,
help='API Key for requesting AIMD server. '
'Required if --aimd is set.')
parser.add_argument(
'--folder_path',
type=str,
default='aimd-example',
help='Path of AIMD folder in which trial is to be created. '
'Required if --aimd is set.')
parser.add_argument('--log_dir',
type=str,
help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
action='store_true',
default=False,
help='Disable CUDA training.')
parser.add_argument(
'--server_url',
type=str,
default='https://proxy.nc201.kube.tensorstack.net/t9k/aimd/server',
help='URL of AIMD server. Required if --aimd is set.')
parser.add_argument('--save_path',
type=str,
default=None,
help='Save path of the trained model.')
parser.add_argument('--trial_name',
type=str,
default='mnist_keras_distributed',
help='Name of AIMD trial to create. '
'Required if --aimd is set.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False
if args.no_cuda:
# Sets all GPUs invisible
tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
# Print GPU info
logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
os.getenv('NVIDIA_VISIBLE_DEVICES')))
logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
logger.info('Visible GPUs: {}'.format(
tf.config.get_visible_devices('GPU')))
# Set memory growth
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
# # Set GPU memory limit
# tf.config.set_logical_device_configuration(
# gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']
if args.aimd and task_index == 0:
from t9k import aimd
trial = aimd.init(server_url=args.server_url,
trial_name=args.trial_name,
folder_path=args.folder_path,
api_key=args.api_key)
params = {
'batch_size': 32 * world_size,
'epochs': 10,
'learning_rate': 0.001 * world_size,
'conv_channels1': 32,
'conv_channels2': 64,
'conv_channels3': 64,
'conv_kernel_size': 3,
'maxpool_size': 2,
'linear_features1': 64,
'seed': 1,
}
if args.aimd and task_index == 0:
trial.params.update(params)
trial.params.parse(dist_tf_strategy=strategy)
with strategy.scope():
model = models.Sequential([
layers.Conv2D(params['conv_channels1'],
params['conv_kernel_size'],
activation='relu',
input_shape=(28, 28, 1)),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels2'],
params['conv_kernel_size'],
activation='relu'),
layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
layers.Conv2D(params['conv_channels3'],
params['conv_kernel_size'],
activation='relu'),
layers.Flatten(),
layers.Dense(params['linear_features1'], activation='relu'),
layers.Dense(10, activation='softmax'),
])
model.compile(
optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
print(os.path.join(os.getcwd(), 'mnist.npz'))
(train_images, train_labels), (test_images,
test_labels) = datasets.mnist.load_data(
path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = tf.split(train_images, [48000, 12000], axis=0)
train_labels, val_labels = tf.split(train_labels, [48000, 12000], axis=0)
train_dataset = tf.data.Dataset.from_tensor_slices(
(train_images, train_labels)).shuffle(
48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
(val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
(test_images, test_labels)).batch(1000)
train_callbacks = []
test_callbacks = []
if args.aimd and task_index == 0:
from t9k.aimd.keras import AIMDFitCallback, AIMDEvalCallback
train_callbacks.append(AIMDFitCallback(trial))
test_callbacks.append(AIMDEvalCallback(trial))
if args.log_dir and task_index == 0:
log_dir = args.log_dir
if os.path.exists(log_dir):
shutil.rmtree(log_dir, ignore_errors=True)
tensorboard_callback = callbacks.TensorBoard(log_dir=log_dir)
train_callbacks.append(tensorboard_callback)
model.fit(train_dataset,
epochs=params['epochs'],
steps_per_epoch=48000 // params['batch_size'],
validation_data=val_dataset,
callbacks=train_callbacks,
verbose=2)
if args.save_path:
if task_index == 0:
save_path = args.save_path
else:
dirname = os.path.dirname(args.save_path)
basename = os.path.basename(
args.save_path) + '_temp_' + str(task_index)
save_path = os.path.join(dirname, basename)
if os.path.exists(save_path):
shutil.rmtree(save_path, ignore_errors=True)
model.save(save_path)
if task_index != 0:
shutil.rmtree(save_path, ignore_errors=True)
model.evaluate(test_dataset, callbacks=test_callbacks, verbose=2)
if args.aimd and task_index == 0:
trial.finish()
编写一个下载数据集的脚本并运行,以将数据集文件 mnist.npz
下载到 Codepack 中。具体代码如下:
import os
import tensorflow as tf
_, _ = tf.keras.datasets.mnist.load_data(
os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mnist.npz'))
考虑在平台上运行时需要创建 PVC、Notebook(可选,便于进一步开发或对 PVC 中的文件进行修改)和 TensorFlowTrainingJob,分别编写相应的资源配置文件如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: codepack-example
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
name: codepack-example
spec:
template:
spec:
containers:
- name: notebook
image: 'registry.tensorstack.cn/t9k/tensorflow-2.8.0-notebook-cpu:1.50.0'
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: 500m
memory: 500Mi
volumeMounts:
- name: workingdir
mountPath: /t9k/mnt
volumes:
- name: workingdir
persistentVolumeClaim:
claimName: codepack-example
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
name: codepack-example
spec:
scheduler:
t9kScheduler:
queue: default
priority: 50
runPolicy:
cleanUpPolicy: Unfinished
backoffLimit: 20 # 所有Pod最多共重启20次
tensorboardSpec:
trainingLogFilesets:
- t9k://pvc/codepack-example/mnist-keras/log
image: t9kpublic/tensorflow-2.7.0:cpu
replicaSpecs:
- type: worker
replicas: 4
restartPolicy: OnFailure
template:
spec:
securityContext:
runAsUser: 1000
containers:
- command:
- python # 运行脚本的命令
- main.py
- "--no_cuda"
- "--log_dir"
- "log"
- "--save_path"
- "saved-model"
workingDir: /mnt/mnist-keras/ # 工作路径,与定义文件中Codepack的
imagePullPolicy: IfNotPresent # 复制路径一致
image: t9kpublic/tensorflow-2.7.0:cpu
name: tensorflow
resources:
requests:
cpu: 2000m
memory: 2Gi
limits:
cpu: 4000m
memory: 4Gi
volumeMounts:
- mountPath: /mnt
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: codepack-example
现在 Codepack 的文件结构如下:
mnist-keras
├── download_dataset.py
├── main.py
├── mnist.npz
├── notebook.yaml
├── pvc.yaml
└── trainingjob.yaml
编写 Codepack 定义文件
然后编写 Codepack 的定义文件。考虑在平台中运行该 Codepack 的过程,将其拆分为 4 个具体的任务,分别是:
- 准备环境,这里只包含创建 PVC。使用 verb apply 并提供
pvc.yaml
文件的路径。 - 复制整个 Codepack 到 PVC。使用 verb copy 并提供源和目标位置的路径。
- 创建 Notebook。使用 verb create 并提供
notebook.yaml
文件的路径。需要依赖 1 和 2。 - 进行分布式训练,即创建 TrainingJob。使用 verb create 并提供
trainingjob.yaml
文件的路径。需要依赖 1 和 2。
据此完成的定义文件如下:
apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
- name: prepare-env # Prepare running env
actions:
- name: workspace-for-training
verb: apply
files: [pvc.yaml]
- name: copy-file # Copy training code and dataset to PVC
deps: ["prepare-env"]
actions:
- name: copy-code
verb: copy
src: .
dst: codepack-example:.
- name: create-notebook # Create a notebook with the codepack in it
deps: ["prepare-env", "copy-file"]
actions:
- name: notebook
verb: create
files: [notebook.yaml]
- name: run-distributed-training # Run a distributed training
deps: ["prepare-env", "copy-file"]
actions:
- name: trainingjob
verb: create
files: [trainingjob.yaml]
最终 Codepack 的文件结构如下:
mnist-keras
├── codepack.yaml
├── download_dataset.py
├── main.py
├── mnist.npz
├── notebook.yaml
├── pvc.yaml
└── trainingjob.yaml
对 Codepack 进行版本控制(可选)
将 Codepack 创建为一个 Git 仓库以进行版本控制,之后你就可以使用任意的本地或远程仓库方便地进行版本控制和分发。
运行 Codepack
使用 Codepack CLI 运行 Codepack。
配置身份验证信息
Codepack CLI 支持多种身份验证方式,你可以选择其中一种并进行相应的配置。详细步骤请参阅身份验证。
使用命令行工具运行 Codepack
先使用以下命令运行 target create-notebook
:
$ codepack run examples/mnist-keras -t create-notebook -p demo
RUN target create-notebook of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> create-notebook
Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim codepack-example created
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: create-notebook
CREATE by files ['notebook.yaml']
Notebook codepack-example created
再使用以下命令运行 target run-distributed-training
:
$ codepack run examples/mnist-keras -t run-distributed-training -p demo
RUN target run-distributed-training of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> run-distributed-training
Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim with the name codepack-example already exists, skip
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: run-distributed-training
CREATE by files ['trainingjob.yaml']
TensorFlowTrainingJob codepack-example created
可以看到在运行这两个 target 的过程中,Codepack CLI 自动解析了工作流并顺序运行各个依赖的 target,按照 YAML 配置文件创建了各资源以及复制整个 Codepack 到 PVC。在运行 target run-distributed-training
的过程中,Codepack CLI 跳过了第一个 target(因为 PVC 已经创建),第二个 target 也实际上没有更新 PVC 中的文件(因为背后调用的是 rsync)。
参考
术语表
本术语表记录了 TensorStack AI 平台的一些专有名词,方便用户随时查阅。
API Key
API Key 是一种 TensorStack AI 平台的安全认证方式,主要应用场景为非交互式程序化身份认证,例如自动化脚本等;或者受限制的交互式场景,例如命令行工具。详见 API Key 文档。
Assessor 算法
Assessor 算法是一系列训练评估算法的统称,用于在 AutoTune 中判断当前超参数的训练中间结果是否符合预期。详见 AutoTune 文档。
AutoTune
AutoTune 是 TensorStack AI 平台提供的自动化机器学习工具,用于自动地进行特征工程、神经网络架构搜索、超参调优和模型压缩。详见 AutoTune 文档。
AutoTuneExperiment
AutoTuneExperiment 是一种 TensorStack 资源,用于自动化机器学习超参数调优。详见 AutoTuneExperiment 文档。
BeamJob
BeamJob 是一种 TensorStack 资源,用于通过 Apache Beam 框架和 Apache Flink 等底层计算引擎运行分布式计算任务。详见 BeamJob 文档。
ClusterRole
与 Role 类似,但 Role 只能指定某个命名空间范围内的权限,ClusterRole 是整个集群范围。
ClusterRoleBinding
与 RoleBinding 类似,但 RoleBinding 只能指定某个命名空间范围内的权限,ClusterRoleBinding 是整个集群范围。
ConfigMap
ConfigMap 是一种以键值对的形式存储非机密信息的 Kubernetes 资源。Pod 可以挂载 ConfigMap,并以环境变量、命令行参数或配置文件的形式使用 ConfigMap 中的信息。详见 ConfigMap 和 管理 ConfigMap。
Container(容器)
容器是可移植、可执行的轻量级的镜像,包含其中的软件及其相关依赖。容器使应用和底层的主机基础设施解耦,降低了应用在不同云环境或者操作系统上的部署难度,便于应用扩展。
Controller(控制器)
控制器负责监控集群中某种 Kubernetes 资源的所有实例,并设法将资源的当前状态转变为期望状态。
CRD(Custom Resource Definition,定制资源定义)
CRD 是 Kubernetes 提供的一种扩展机制,允许开发者定制自己的资源,并开发对应的控制器。TensorStack AI 平台定义了一系列资源,以方便你在 Kubernetes 集群上构建机器学习应用。
CronWorkflowRun
CronWorkflowRun 是一种 TensorStack 资源,用于方便地定时执行 WorkflowRun。详见 CronWorkflowRun 文档。
Docker
Docker 是一个提供操作系统级别的虚拟化技术的软件,用于将软件应用及其相关依赖打包成所谓的容器(Container),能够在一个操作系统实例中运行多个其他操作系统中构建的容器。Kubernetes 支持使用 Docker 作为容器运行时。详见 Docker 文档。
Explorer
Explorer 是一种 TensorStack 资源,用于通过浏览器访问文件管理器和集成开发环境(IDE)。详见 Explorer 文档。
GenericJob
GenericJob 是一种 TensorStack 资源,用于统一协调多个 Pod 共同完成一项任务。详见 GenericJob 文档。
Image(镜像)
镜像是保存的容器实例,它打包了应用运行所需的一组软件。你可以将镜像存储在容器镜像仓库、拉取到本地系统并作为应用来运行。
Job
在 TensorStack AI 平台中,Job 是一类统一协调多个 Pod 共同完成一项任务的资源,包括 GenericJob、TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、MPIJob、BeamJob 等。
Kubernetes(K8s)
Kubernetes 是一个开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理。TensorStack AI 平台构建在 Kubernetes 的坚实基础之上。详见 Kubernetes 文档。
Label(标签)
标签是附属在资源上的键值对,用于标明资源的属性。你可以通过标签来选取一组资源的某个子集。
MLService
MLService 是一种 TensorStack 资源,用于部署机器学习模型预测服务,以供外部用户使用。详见 MLService 文档。
MPIJob
MPIJob 是一种 TensorStack 资源,用于通过 OpenMPI 协议进行分布式机器学习训练。详见 MPIJob 文档。
Namespace(命名空间)
命名空间是一组资源所属的工作空间,提供了一种划分集群、隔离资源的方式。同一命名空间内的资源名称必须不同,不同命名空间的资源名称可以相同。
Node(节点)
节点是 Kubernetes 中的工作机器。通常,Kubernetes 集群由一系列节点组成,少则一个,多则上千个。
Notebook
Notebook 是一种 TensorStack 资源,用于在集群中运行 Jupyter Notebook,同时提供 GPU 支持、SSH 访问支持等补充功能。详见 Notebook 文档。
Pod
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod 是一组(一个或多个)容器,这些容器共享存储、网络以及怎样运行这些容器的声明。详见 Kubernetes 文档。
PodGroup
PodGroup 是一组 Pod 的集合,它们需要协同工作、一起被调度。详见 PodGroup 文档。
Project
Project 是 TensorStack AI 平台对计算集群的抽象,建立在 Kubernetes 命名空间 (namespace)之上。不同的用户通常在不同的 Project 下工作,并且可以互相分享自己 Project。详见 Project 文档。
PVC(PersistentVolumeClaim,持久卷申领)
PVC 是一种持久化的存储资源,可以被 Pod 挂载、作为 Pod 的卷被访问。你可以在 TensorStack AI 平台的模型构建控制台中创建一个 PVC,并指定它的存储空间(例如 100M、1G)和访问模式(例如只读、可读写、可运行),详见 PVC 和管理 PVC。
PyTorchTrainingJob
PyTorchTrainingJob 是一种 TensorStack 资源,用于通过 PyTorch 框架进行分布式机器学习训练。详见 PyTorchTrainingJob 文档。
Queue(队列)
队列是一种 TensorStack 资源,用于存放 PodGroup 并根据它们的优先级进行调度。详见队列文档。
RBAC(Role Based Access Control)
RBAC 是一种管理访问控制的方式,详见 Kubernetes 文档。你可以通过 ServiceAccount、Role、RoleBinding、ClusterRole、ClusterRoleBinding 等资源来管理访问控制。
Role
Role 中包含一组代表相关权限的规则,例如获取 Pod、创建 Pod、删除 Pod、获取 Secret、创建 Secret、删除 Secret 等。
RoleBinding
RoleBinding 将 Role 中定义的权限赋予一个用户或者一个 ServiceAccount,这样绑定 ServiceAccount 的 Pod 就能进行 Role 中定义的操作。
Scheduler(调度器)
调度器负责将 Pod 分配到合适的节点上,保证节点满足 Pod 声明的计算资源(CPU、内存、GPU等)、亲和度偏好(希望与其他 Pod 一起运行、希望运行在拥有某个标签的节点上等)等需求。
Secret
Secret 是一种存储密码、令牌、SSH Key 等敏感信息的 Kubernetes 资源。Pod 可以将 Secret 挂载为一个文件,并读取其中的信息。详见 Secret 和管理 Secret。
ServiceAccount
ServiceAccount 为 Pod 提供一个身份凭证。当你创建一个 Pod 时,如果没有指定 ServiceAccount,该 Pod 会默认绑定一个名为 default
的 ServiceAccount。
SimpleMLService
SimpleMLService 是一种 TensorStack 资源,用于部署机器学习模型预测服务,以供内部开发者快速测试。详见 SimpleMLService 文档。
TensorBoard
TensorBoard 是 TensorFlow 提供的机器学习可视化工具。TensorStack AI 平台提供在集群中一键部署 TensorBoard 的功能,详见 TensorBoard 文档。
TensorFlowTrainingJob
TensorFlowTrainingJob 是一种 TensorStack 资源,用于通过 TensorFlow 框架进行分布式机器学习训练。详见 TensorFlowTrainingJob 文档。
Tuner 算法
Tuner 算法是一系列超参数调优算法的统称,用于在 AutoTune 中选取合适的超参数组合。详见 AutoTune 文档。
Volume(卷)
卷是一个包含数据的文件夹,可以被 Pod 中的容器访问。详见 Kubernetes 文档。
WorkflowRun
WorkflowRun 是一种 TensorStack 资源,用于实例化 WorkflowTemplate 并提供 WorkflowTemplate 运行时所需的参数、工作空间等资源。详见 WorkflowRun 文档。
WorkflowTemplate
WorkflowTemplate 是一种 TensorStack 资源,用于在 Kubernetes 中有序、高效、方便地组织运行各类工作负载。详见 WorkflowTemplate 文档。
XGBoostTrainingJob
XGBoostTrainingJob 是一种 TensorStack 资源,用于通过 XGBoost 框架进行分布式机器学习训练。详见 XGBoostTrainingJob 文档。
API 参考
- Project
- GenericJob
- TensorFlowTrainingJob
- PyTorchTrainingJob
- XGBoostTrainingJob
- ColossalAIJob
- DeepSpeedJob
- MPIJob
- BeamJob
- TensorBoard
- Notebook
- Explorer
- StorageShim
- Scheduler
- Workflow
- WorkflowTrigger
- SimpleMLService
- MLService
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
EventControllerStatus
Appears in:
Field | Description |
---|---|
deployment EventDeploymentStatus |
EventDeploymentStatus
Appears in:
Field | Description |
---|---|
name string | |
readyReplicas integer | |
podStatus EventPodStatus |
EventPodStatus
Appears in:
Field | Description |
---|---|
name string | |
uid UID | |
phase PodPhase |
NetworkPolicy
Appears in:
Field | Description |
---|---|
useDefaultTemplate boolean | If true , the default NetworkPolicy defined by the administrator will be applied. |
template NetworkPolicyTemplate | A NethworkPolicy defined for this project. |
NetworkPolicyTemplate
Appears in:
Field | Description |
---|---|
spec NetworkPolicySpec |
Project
Project is the Schema for the projects API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | Project |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec ProjectSpec | |
status ProjectStatus |
ProjectCondition
Appears in:
Field | Description |
---|---|
type ProjectConditionType | Type is the type of the condition. |
status ConditionStatus | Status is the status of the condition. Can be True, False, Unknown. |
lastUpdateTime Time | Last time we probed the condition. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
reason string | Unique, one-word, CamelCase reason for the condition’s last transition. |
message string | Human-readable message indicating details about last transition. |
ProjectConditionType
Underlying type: string
Appears in:
ProjectList
ProjectList contains a list of Project
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | ProjectList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items Project array |
ProjectSpec
ProjectSpec defines the desired state of Project
Appears in:
Field | Description |
---|---|
resourceQuota ResourceQuota | |
networkPolicy NetworkPolicy | |
quotaProfile string | |
defaultScheduler SchedulePolicy | DefaultScheduler defines the default scheduler and queue information for the project. It is just a configuration information, the controller does not need to do anything. |
ProjectStatus
ProjectStatus defines the observed state of Project
Appears in:
Field | Description |
---|---|
conditions ProjectCondition array | |
eventController EventControllerStatus | |
resourceQuota ResourceQuotaStatus |
QuotaProfile
QuotaProfile is the Schema for the quotaprofiles API. This API resource represents a template for project/namespace resource quota specifications, defined as an instance of corev1.ResourceQuotaSpec
.
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | QuotaProfile |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec ResourceQuotaSpec |
QuotaProfileList
QuotaProfileList contains a list of QuotaProfile
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | QuotaProfileList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items QuotaProfile array |
ResourceQuota
Appears in:
Field | Description |
---|---|
template ResourceQuotaTemplate | A corev1.ResourceQuota defined for this project. |
ResourceQuotaStatus
Appears in:
Field | Description |
---|---|
name string | |
ResourceQuotaStatus ResourceQuotaStatus |
ResourceQuotaTemplate
Appears in:
Field | Description |
---|---|
spec ResourceQuotaSpec |
SchedulePolicy
SchedulePolicy specifies preferences for resource allocation requests, including the name of the preferred scheduler and additional configuration parameters.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler |
T9kScheduler
Appears in:
Field | Description |
---|---|
queue string | Name of the resource Queue of a T9kScheduler . |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
Aggregate
Aggregate records the number of replica pods at each phase.
Appears in:
Field | Description |
---|---|
creating integer | Pod has been created, but resources have not been scheduled. |
pending integer | Pod has been accepted by the system, but one or more of the containers has not been started. This includes time before being bound to a node, as well as time spent pulling images onto the host. |
running integer | Pod has been bound to a node and all of the containers have been started. At least one container is still running or is in the process of being restarted. |
succeeded integer | All containers in the pod have voluntarily terminated with a container exit code of 0, and the system is not going to restart any of these containers. |
failed integer | All containers in the pod have terminated, and at least one container has terminated in failure (exited with a non-zero exit code or was stopped by the system). |
unknown integer | For some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod. |
deleted integer | Pod has been deleted. |
CleanUpPolicy
Underlying type: string
CleanUpPolicy specifies the collection of replicas that are to be deleted upon job completion.
Appears in:
ContainerStatus
ContainerStatus defines the observed state of the container.
Appears in:
DebugMode
DebugMode configs whether and how to start a job in debug mode.
Appears in:
Field | Description |
---|---|
enabled boolean | Whether to enable debug mode. |
replicaSpecs ReplicaDebugSet array | If provided, these specs provide overwriting values for job replicas. |
FinishRule
A finishRule is a condition used to check if the job has finished. A finishRule identifies a set of replicas, and the controller determines the job’s status by checking the status of all of these replicas.
Appears in:
GenericJob
GenericJob represents the schema for a general-purpose batch job API. While it offers less automation compared to specialized APIs like PyTorchTrainingJob, it allows for greater flexibility in specifying parallel replicas/pods. This design serves as a comprehensive job definition mechanism when more specialized APIs are not applicable or available.
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | GenericJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec GenericJobSpec | |
status GenericJobStatus |
GenericJobList
GenericJobList contains a list of GenericJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | GenericJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items GenericJob array |
GenericJobSpec
GenericJobSpec defines the desired state of GenericJob
Appears in:
Field | Description |
---|---|
successRules FinishRule array | Rules used to check if a generic job has succeeded. The job succeeded when any one of the successRules is fulfilled. Each item of successRules may refer to a series of replicas, and the job succeeded only if all of the replicas referred in this series are completed successfully. |
failureRules FinishRule array | Rules used to check if a generic job has failed. The job failed when any one of failureRules is fulfilled. Each item of failureRules refers to a series of replicas, and the job failed only if all of the replicas in this series failed. |
service ServiceOption | Details of v1/Service for replica pods. Optional: Defaults to empty and no service will be created. |
runMode RunMode | Job running mode. Defaults to Immediate mode. |
cleanUpPolicy CleanUpPolicy | To avoid wasting resources on completed tasks, controller will reclaim resource according to the following policies: None: (default) no resources reclamation; Unfinished: only finished pods is to be deleted; All: all the pods are to be deleted. |
scheduler SchedulePolicy | If specified, the pod will be dispatched by the specified scheduler. Otherwise, the pod will be dispatched by the default scheduler. |
replicaSpecs ReplicaSpec array | List of replica specs belonging to the job. There must be at least one replica defined for a Job. |
GenericJobStatus
GenericJobStatus defines the observed state of GenericJob
Appears in:
Field | Description |
---|---|
tasks Tasks array | An array of status of individual tasks. |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
aggregate Aggregate | Records the number of replicas at each phase. |
conditions JobCondition array | The latest available observations of a job’s current state. |
JobCondition
JobCondition describes the current state of a job.
Appears in:
Field | Description |
---|---|
type JobConditionType | Type of job condition: Complete or Failed. |
status ConditionStatus | Status of the condition, one of True, False, Unknown. |
lastTransitionTime Time | Last time the condition transited from one status to another. |
reason string | Brief reason for the condition’s last transition. |
message string | Human readable message indicating details about last transition. |
JobConditionType
Underlying type: string
JobConditionType defines all possible types of JobStatus. Can be one of: Initialized, Running, ReplicaFailure, Completed, or Failed.
Appears in:
JobPhase
Underlying type: string
Appears in:
PauseMode
PauseMode configs whether and how to start a job in pause mode.
Appears in:
Field | Description |
---|---|
enabled boolean | Whether to enable pause mode. |
resumeSpecs ResumeSpec array | If provided, these specs provide overwriting values for job replicas when resuming. |
ReplicaDebugSet
ReplicaDebugSet describes how to start replicas in debug mode.
Appears in:
Field | Description |
---|---|
type string | Replica type. |
skipInitContainer boolean | Skips creation of initContainer, if true. |
command string | Entrypoint array. Optional: Default to [“sleep”, “inf”] |
ReplicaSpec
ReplicaSpec defines the desired state of replicas.
Appears in:
Field | Description |
---|---|
type string | Replica type. |
replicas integer | The desired number of replicas of this replica type. Defaults to 1. |
restartPolicy RestartPolicy | Restart policy for replicas of this replica type. One of Always, OnFailure, Never. Optional: Default to OnFailure. |
template PodTemplateSpec | Defines the template used to create pods. |
ReplicaStatus
ReplicaStatus defines the observed state of the pod.
Appears in:
Field | Description |
---|---|
name string | Pod name. |
uid UID | Pod uid. |
phase PodPhase | Pod phase. The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle. |
containers ContainerStatus array | Containers status. |
RestartPolicy
RestartPolicy describes how the replica should be restarted.
Appears in:
Field | Description |
---|---|
policy RestartPolicyType | The policy to restart finished replica. |
limit integer | The maximum number of restarts. Optional: Default to 0. |
RestartPolicyType
Underlying type: string
Appears in:
ResumeSpec
ResumeSpec describes how to resume replicas from pause mode.
Appears in:
Field | Description |
---|---|
type string | Replica type. |
skipInitContainer boolean | Skips creation of initContainer, if true. |
command string | Entrypoint array. Provides overwriting values if provided; otherwise, values in immediate mode are used. |
args string | Arguments to the entrypoint. Arguments in immediate mode are used if not provided. |
RunMode
RunMode defines the job’s execution behavior: Immediate mode: (Default) Tasks are executed immediately upon submission. Debug mode: Job pods are created, but regular executions are replaced with null operations (e.g., sleep) for convenient debugging purposes. Pause mode: Job execution is halted, and pods are deleted to reclaim resources. A graceful pod termination process is initiated to allow pods to exit cleanly.
Appears in:
SchedulePolicy
SchedulePolicy signals to K8s how the job should be scheduled.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler | T9k Scheduler. TODO: link to t9k scheduler docs. |
ServiceOption
Details of a replicas’ servivce.
Appears in:
Field | Description |
---|---|
ports ServicePort array | The list of ports that are exposed by this service. |
T9kScheduler
T9kScheduler provides additonal configurations needed for the scheduling process.
Appears in:
Field | Description |
---|---|
queue string | Specifies the name of the queue should be used for running this workload. TODO: link to t9k scheduler docs. |
priority integer | Indicates the priority of the PodGroup; valid range: [0, 100]. Optional: Default to 0. |
Tasks
Task defines the observed state of the task.
Appears in:
Field | Description |
---|---|
type string | Replica type. |
restartCount integer | The number of restarts that have been performed. |
replicas ReplicaStatus array | Replicas status array. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
ReplicaSpec
ReplicaSpec describes the spec of a replica.
Appears in:
Field | Description |
---|---|
type ReplicaType | ReplicaType is the type of the replica, one of “chief ”, “worker ”, “ps ”, or “evaluator ”. |
replicas integer | The desired number of replicas created for the current replica type. If unspecified, defaults to 1. |
template PodTemplateSpec | Describes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will create new pods if restart is required. |
restartPolicy RestartPolicy | The restart policy for this replica, one of Always , OnFailure , Never , or ExitCode . |
ReplicaType
Underlying type: string
ReplicaType is the type of the replica, one of “chief
”, “worker
”, “ps
”, or “evaluator
”.
Appears in:
RestartPolicy
Underlying type: string
RestartPolicy describes how the replicas should be restarted. Can be one of: Always
, OnFailure
, Never
, or ExitCode
.
Appears in:
RunPolicy
RunPolicy encapsulates various runtime policies of the distributed training job, for example how to clean up resources and how long the job can stay active.
Appears in:
Field | Description |
---|---|
activeDeadlineSeconds integer | Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer. |
backoffLimit integer | Optional number of retries before marking this job failed. |
cleanUpPolicy CleanUpPolicy | Clean the tasks after the training job finished. |
TensorFlowTrainingJob
TensorFlowTrainingJob is the Schema for the TensorFlowTrainingJob API.
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | TensorFlowTrainingJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec TensorFlowTrainingJobSpec | |
status TensorFlowTrainingJobStatus |
TensorFlowTrainingJobList
TensorFlowTrainingJobList contains a list of TensorFlowTrainingJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | TensorFlowTrainingJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items TensorFlowTrainingJob array |
TensorFlowTrainingJobSpec
TensorFlowTrainingJobSpec outlines the intended configuration and execution parameters for a TensorFlowTrainingJob.
Appears in:
Field | Description |
---|---|
replicaSpecs ReplicaSpec array | Describes the spec of the replicas of the job. |
runMode RunMode | Job’s execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission. |
tensorboardSpec TensorBoardSpec | Describes the Tensorboard to be created for showing training logs. |
runPolicy RunPolicy | Execution policy configurations governing the behavior of the TensorFlowTrainingJob. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
TensorFlowTrainingJobStatus
TensorFlowTrainingJobStatus defines the observed state of TensorFlowTrainingJob
Appears in:
Field | Description |
---|---|
tasks Tasks array | The statuses of individual tasks. |
tensorboard DependentStatus | The status of tensorboard. |
backoffCount integer | The number of restarts being performed. |
aggregate Aggregate | |
conditions JobCondition array | Represents the latest available observations of a TensorFlowTrainingJob’s current state. |
phase JobPhase | Phase is the phase-style status of the TensorFlowTrainingJob. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
ElasticConfig
Configuration governing the elastic scaling behavior of the job.
Appears in:
Field | Description |
---|---|
enabled boolean | Set true to use elastic training. |
minReplicas integer | The minimum number of replicas to start to run this elastic compute. The autoscaler cannot scale down an elastic job below this number. This value cannnot be changed once the job is created. |
maxReplicas integer | The maximum number of replicas to start to run this elastic compute. The autoscaler cannot scale up an elastic job over this number. This value cannnot be changed once the job is created. |
expectedReplicas integer | Number of replicas to be created. This number can be set to an initial value upon creation. This value can be modified dynamically by an external entity, such as a user or an autoscaler, to scale the job up or down. |
PyTorchTrainingJob
PyTorchTrainingJob is the Schema for the pytorchtrainingjobs API.
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | PyTorchTrainingJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec PyTorchTrainingJobSpec | |
status PyTorchTrainingJobStatus |
PyTorchTrainingJobList
PyTorchTrainingJobList contains a list of PyTorchTrainingJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | PyTorchTrainingJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items PyTorchTrainingJob array |
PyTorchTrainingJobSpec
PyTorchTrainingJobSpec outlines the intended configuration and execution parameters for a PyTorchTrainingJo.
Appears in:
Field | Description |
---|---|
replicaSpecs ReplicaSpec array | An array of ReplicaSpec. Specifies the pytorch cluster configuration. |
elastic ElasticConfig | Configurations for how to launch an elastic training. Elastic training is effective only in torchrun mode. |
torchrunConfig TorchrunConfig | Whether and how to use torchrun to launch a training process. |
runMode RunMode | Job’s execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission. |
runPolicy RunPolicy | Execution policy configurations governing the behavior of a PytorchTrainingJob. |
tensorboardSpec TensorBoardSpec | If specified, controller will create a Tensorboard for showing training logs. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
PyTorchTrainingJobStatus
PyTorchTrainingJobStatus defines the observed state of PyTorchTrainingJob.
Appears in:
Field | Description |
---|---|
tasks Tasks array | The status details of individual tasks. |
tensorboard DependentStatus | The status of the tensorboard. |
backoffCount integer | The number of restarts having been performed. |
aggregate Aggregate | The number of tasks in each state. |
conditions JobCondition array | The latest available observations of an object’s current state. |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
ReplicaSpec
ReplicaSpec is a description of the job replica.
Appears in:
Field | Description |
---|---|
type string | ReplicaType is the type of the replica. |
replicas integer | The desired number of replicas of the current template. Defaults to 1. |
scalingWeight integer | Scaling weight of the current replica used in elastic training. |
template PodTemplateSpec | Describes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired. |
restartPolicy RestartPolicy | Restart policy for all replicas within the job. One of Always , OnFailure , Never , or ExitCode . |
TorchrunConfig
Describes how to launch pytorch training with torchrun.
Appears in:
Field | Description |
---|---|
enabled boolean | Set true to use torchrun launch pytorch training. |
maxRestarts integer | |
procPerNode string | Number of processes to be started on every replica. |
rdzvBackend string | Communication backed used for the group. Defaults to c10d . |
extraOptions string array | Extra options for torchrun. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
ReplicaSpec
ReplicaSpec outlines the intended configuration and execution parameters for a XGBoostTrainingJob.
Appears in:
Field | Description |
---|---|
type ReplicaType | ReplicaType is the type of the replica, one of “master” or “worker”. |
replicas integer | The desired number of replicas of the current template. If unspecified, defaults to 1. |
template PodTemplateSpec | Describes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired. |
restartPolicy RestartPolicy | Restart policy for all replicas within the job. One of Always, OnFailure, Never, or ExitCode. Defaults to OnFailure . |
ReplicaType
Underlying type: string
ReplicaType is the type of the replica, one of “master
” or “worker
”.
Appears in:
XGBoostTrainingJob
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | XGBoostTrainingJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec XGBoostTrainingJobSpec | |
status XGBoostTrainingJobStatus |
XGBoostTrainingJobList
XGBoostTrainingJobList contains a list of XGBoostTrainingJob.
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | XGBoostTrainingJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items XGBoostTrainingJob array |
XGBoostTrainingJobSpec
Appears in:
Field | Description |
---|---|
replicaSpecs ReplicaSpec array | An array of ReplicaSpec. Specifies the XGBoost replica configurations. |
runMode RunMode | Job’s execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission. |
runPolicy RunPolicy | Execution policy configurations governing the behavior of the XGBoostTrainingJob. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
XGBoostTrainingJobStatus
XGBoostTrainingJobStatus defines the observed state of XGBoostTrainingJob.
Appears in:
Field | Description |
---|---|
tasks Tasks array | The status details of individual tasks. |
backoffCount integer | The number of restarts being performed. |
aggregate Aggregate | |
conditions JobCondition array | The latest available observations of an object’s current state. |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
ColossalAIJob
ColossalAIJob is the Schema for the colossalaijobs API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | ColossalAIJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec ColossalAIJobSpec | |
status ColossalAIJobStatus |
ColossalAIJobList
ColossalAIJobList contains a list of ColossalAIJob.
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | ColossalAIJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items ColossalAIJob array |
ColossalAIJobSpec
ColossalAIJobSpec defines the configurations of a ColossalAI training job.
Appears in:
Field | Description |
---|---|
ssh SSHConfig | SSH configs. |
runMode RunMode | The desired running mode of the job, defaults to Immediate . |
runPolicy RunPolicy | Controls the handling of completed replicas and other related processes. |
scheduler SchedulePolicy | Specifies the scheduler to request for resources. Defaults to cluster default scheduler. |
launcher Launcher | Specication for the launcher replica. |
worker Worker | Specication for the launcher replica. |
ColossalAIJobStatus
ColossalAIJobStatus describes the observed state of ColossalAIJob.
Appears in:
Field | Description |
---|---|
tasks Tasks array | The statuses of individual tasks. |
aggregate Aggregate | The number of replicas in each phase. |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
conditions JobCondition array | The latest available observations of an object’s current state. |
Launcher
Specification of replica launcher
.
Appears in:
Field | Description |
---|---|
image string | Container image name. |
workingDir string | Working directory of container launcher . If not specified, the container runtime’s default will be used, which might be configured in the container image. Cannot be updated. |
env EnvVar array | List of environment variables set for the container. Cannot be updated. |
resources ResourceRequirements | Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ |
RunPolicy
RunPolicy dictates specific actions to be taken by the controller upon job completion.
Appears in:
Field | Description |
---|---|
cleanUpWorkers boolean | Defaults to false. |
SSHConfig
SSHConfig specifies various configurations for running the SSH daemon (sshd).
Appears in:
Field | Description |
---|---|
authMountPath string | SSHAuthMountPath is the directory where SSH keys are mounted. Defaults to “/root/.ssh”. |
sshdPath string | The location of the sshd executable file. |
Worker
Specification of the worker replicas.
Appears in:
Field | Description |
---|---|
replicas integer | Number of replicas to launch. Defaults to 1. |
procPerWorker integer | The number of processes of a worker. Defaults to 1. |
command string array | Specifies the command used to start the workers. |
torchArgs string array | Args of torchrun. |
template PodTemplateSpec | Template defines the workers that will be created from this pod template. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
Config
Configuration information for running a DeepSpeed job. Details are outlined in the official DeepSpeed documentation (https://www.deepspeed.ai/getting-started/) for comprehensive guidance.
Appears in:
Field | Description |
---|---|
customCommand string | Custom launch commands, when enabled, other options in Config except for slotsPerWorker will not take effect. |
slotsPerWorker integer | The number of slots for each worker/replica. This is normally set to the number of GPUs requested for each replica. |
localRank boolean | If parameter local_rank should be passed to training programs. |
autotune AutotuneType | Parameters for running the autotuning process to find configurations for a training job on a particular cluster/machine. |
run RunType | Mechanism to start the training program. |
otherArgs string array | Seting up other command line args for the deepspeed job. |
DeepSpeedJob
DeepSpeedJob defines the schema for the DeepSpeedJob API.
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | DeepSpeedJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec DeepSpeedJobSpec | |
status DeepSpeedJobStatus |
DeepSpeedJobList
DeepSpeedJobList contains a list of DeepSpeedJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | DeepSpeedJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items DeepSpeedJob array |
DeepSpeedJobSpec
DeepSpeedJobSpec outlines the intended configuration and execution parameters for a DeepSpeedJob.
Appears in:
Field | Description |
---|---|
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
runPolicy RunPolicy | Execution policy configurations governing the behavior of the distributed training job. |
runMode RunMode | Job’s execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission. |
elastic ElasticConfig | Configurations for how to launch an elastic training. |
config Config | Key configurations for executing DeepSpeed training jobs. |
disableCustomEnv boolean | Setting environment variables during DeepSpeed training necessitates creating an env file to store the desired variables. The launcher will then distribute these variables to each worker process. Nevertheless, certain scenarios require disabling this automated behavior, and this flag enables control over this functionality. |
false : (default) The environment variables set in job specs are used in the training processes. The controller will automatically put the environment variables into the env file so that the launcher can send them to each worker; | |
true : The environment variables set in the job specs are only used to start the container entrypoint program, and the training program does not need these environment variables. | |
worker Worker | Specifications for the worker replicas. |
DeepSpeedJobStatus
DeepSpeedJobStatus represents the observed state of a DeepSpeedJob.
Appears in:
Field | Description |
---|---|
tasks Tasks array | |
aggregate Aggregate | |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
backoffCount integer | The number of restarts being performed. |
conditions JobCondition array | The latest available observations of an object’s current state. |
ElasticConfig
Configuration governing the elastic scaling behavior of the job.
Appears in:
Field | Description |
---|---|
enabled boolean | Set true to use elastic training. |
minReplicas integer | The minimum number of replicas to start to run this elastic compute. The autoscaler cannot scale down an elastic job below this number. This value cannnot be changed once the job is created. |
maxReplicas integer | The maximum number of replicas to start to run this elastic compute. The autoscaler cannot scale up an elastic job over this number. This value cannnot be changed once the job is created. |
expectedReplicas integer | Number of replicas to be created. This number can be set to an initial value upon creation. This value can be modified dynamically by an external entity, such as a user or an autoscaler, to scale the job up or down. |
RunPolicy
RunPolicy encapsulates various runtime policies of the distributed training job, for example how to clean up resources and how long the job can stay active.
Appears in:
Field | Description |
---|---|
activeDeadlineSeconds integer | Specifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer. |
backoffLimit integer | Optional number of retries before marking this job failed. |
cleanUpPolicy CleanUpPolicy | Clean the tasks after the training job finished. |
RunType
How the training program should be started. Exactly one of the 3 choices should be set.
Appears in:
Field | Description |
---|---|
python string array | Using a python script |
module string array | Using a python module |
exec string array | Using an executable program |
Worker
Worker defines the configurations for DeepSpeedJob worker replicas.
Appears in:
Field | Description |
---|---|
replicas integer | The number of workers to launch. |
template PodTemplateSpec | Describes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired. |
restartPolicy RestartPolicy | Restart policy for all replicas owned by the job. One of Always, OnFailure, Never, or ExitCode. Defaults to OnFailure . |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
MPIJob
MPIJob is the Schema for the mpijobs API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | MPIJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec MPIJobSpec | |
status MPIJobStatus |
MPIJobList
MPIJobList contains a list of MPIJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | MPIJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items MPIJob array |
MPIJobSpec
MPIJobSpec outlines the intended configuration and execution parameters for a MPIJob.
Appears in:
Field | Description |
---|---|
worker WorkerConfig | Specifications for the worker replicas. |
mca object (keys:string, values:string) | Open MPI uses Modular Component Architecture (MCA) parameters to provide a way to tune your runtime environment. |
ssh SSHConfig | SSH configs. |
runPolicy RunPolicy | Execution policy configurations governing the behavior of the MPI job. |
runMode RunMode | Job’s execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission. |
mpiHome string | Open MPI installation path. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. Use k8s default scheduler by default. |
MPIJobStatus
MPIJobStatus represents the observed state of a MPIJob.
Appears in:
Field | Description |
---|---|
tasks Tasks array | Individual task status details of the job. |
aggregate Aggregate | |
phase JobPhase | Provides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine. |
conditions JobCondition array | The latest available observations of an object’s current state. |
RunPolicy
RunPolicy encapsulates various runtime policies of the MPI job, for example how to clean up resources.
Appears in:
Field | Description |
---|---|
cleanUpWorkers boolean | If worker replicas should be cleand up after they finish. Defaults false. |
SSHConfig
SSHConfig specifies various configurations for running the SSH daemon (sshd).
Appears in:
Field | Description |
---|---|
sshAuthMountPath string | SSHAuthMountPath is the directory where SSH keys are mounted. Defaults to “/root/.ssh”. |
sshdPath string |
WorkerConfig
WorkerConfig defines the configurations for MPI worker replicas.
Appears in:
Field | Description |
---|---|
replicas integer | The number of workers to launch. Default 1. |
extraMPIArgs string array | Extra args for mpirun. |
cmd string array | Command line to start the MPI programs inside a worker pod. This is invoked by the launcher after all the worker pods have been created and entered ready state. |
template PodTemplateSpec | Defines the pod template used to create workers. Users are responsible for ensuring that container images and configurations are properly set to guarantee the worker operates in the state anticipated by the launcher . |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the batch v1beta1 API group
Resource Types
BeamJob
BeamJob is the Schema for the beamjobs API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | BeamJob |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec BeamJobSpec | |
status BeamJobStatus |
BeamJobList
BeamJobList contains a list of BeamJob
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/v1beta1 |
kind string | BeamJobList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items BeamJob array |
BeamJobSpec
BeamJobSpec defines the desired state of BeamJob
Appears in:
Field | Description |
---|---|
flinkClusterTemplate FlinkClusterTemplateSpec | Specifies the FlinkCluster that will be created when executing a BeamJob. |
jobTemplate JobTemplateSpec | Specifies the Job that will be created when executing a BeamJob. |
runPolicy RunPolicy | Runtime policies governing the behavior of the BeamJob. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
runMode RunMode | Normal mode and debug mode are supported now. |
BeamJobStatus
BeamJobStatus defines the observed state of BeamJob
Appears in:
Field | Description |
---|---|
phase JobPhase | Phase is a label for the condition of the job at the current time. |
conditions JobCondition array | The latest available observations of the BeamJob’s current state. |
tasks Tasks array | The statuses of individual tasks. |
aggregate Aggregate | |
jobURL string | The URL to Web UI of the cluster where details of the job is displayed. |
FlinkClusterTemplateSpec
FlinkClusterTemplateSpec describes the data a FlinkCluster should have when created from a template
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec FlinkClusterSpec | Specification of the desired behavior of the FlinkCluster. |
RunPolicy
RunPolicy encapsulates runtime policies governing the behavior of the BeamJob.
Appears in:
Field | Description |
---|---|
cleanUpCluster boolean | Whether or not delete cluster after the job finished. Default false. |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
HttpDataSource
Details of HTTP data source.
Appears in:
Field | Description |
---|---|
url string array | Url pointing to the log files. |
PVCDataSource
Details of PVC data source.
Appears in:
Field | Description |
---|---|
name string | PVC name. |
subPath string array | The relative paths of logs in the PVC. |
PodReference
PodReference references to a v1.pod
.
Appears in:
Field | Description |
---|---|
name string | Name of the Pod. |
uid string | UID of the Pod. |
PodStatus
Pod defines the observed state of a replica.
Appears in:
Field | Description |
---|---|
reference PodReference | References to the subordinate v1.Pod . |
phase PodPhase | Replicated from the corresponding field in the subordinate v1.Pod . |
S3DataSource
Details of S3 data source.
Appears in:
Field | Description |
---|---|
secretRef SecretRef | S3 data source uses a secret to transmit access/secret key and service enpoint. |
uri string array | S3 object uri. |
SchedulePolicy
SchedulePolicy specifies the preferred scheduler responsible for handling resource allocation requests.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler |
SecretRef
Appears in:
Field | Description |
---|---|
name string | Secret name. |
T9kScheduler
Appears in:
Field | Description |
---|---|
queue string | Name of the queue to use with the T9kScheduler. |
TensorBoard
TensorBoard is the Schema for the tensorboards API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | TensorBoard |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec TensorBoardSpec | |
status TensorBoardStatus |
TensorBoardCondition
TensorBoardCondition defines the observed condition of TensorBoard
Appears in:
Field | Description |
---|---|
type TensorBoardConditionType | Type is the type of the condition. Possible values are Idle, etc |
status ConditionStatus | Status is the status of the condition type. Possible values of type Idle are True |
message string | Message is the reason of the status |
lastTransitionTime Time | LastTransitionTime is the last time the status was changed |
lastProbeTime Time | LastProbeTime is the last time the condition was probed |
TensorBoardConditionType
Underlying type: string
Appears in:
TensorBoardDataSource
TensorBoardDataSource represents the location and type of the tensorboard data source. It includes three types of data sources: PVC, S3, and HTTP. In a tensorboard service, these three types of data sources can be used simultaneously.
Appears in:
Field | Description |
---|---|
pvc PVCDataSource array | PVC represents PVCs that are mounted to workload as directories to provide log data. |
s3 S3DataSource | S3 represents a s3 service and access/secret key to access the service. |
http HttpDataSource | HTTP provides several urls. |
TensorBoardList
TensorBoardList contains a list of TensorBoard
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | TensorBoardList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items TensorBoard array |
TensorBoardPhase
Underlying type: string
Appears in:
TensorBoardSpec
TensorBoardSpec defines the desired state of TensorBoard
Appears in:
Field | Description |
---|---|
trainingLogFilesets string array | TrainingLogFilesets is the list of filesets containing training log. The format of fileset: t9k://pvc/[pvc-name]/[subpath] t9k://minio/[secret-name]/[bucket]/[subpath] To be deprecated: Use spec.logDir instead. |
logDir TensorBoardDataSource | LogDir is a series of data source containing training log. |
image string | The container image used to run the tensorboard. |
suspend boolean | suspend specifies whether the TensorBoard controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the TensorBoard. Defaults to false. |
scheduler SchedulePolicy | |
resources ResourceRequirements | Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/ |
TensorBoardStatus
TensorBoardStatus defines the observed state of TensorBoard
Appears in:
Field | Description |
---|---|
phase TensorBoardPhase | |
pod PodStatus | |
conditions TensorBoardCondition array | Conditions is an array of current conditions |
url string | The URL to Web UI of the tensorboard |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
Notebook
Notebook is the Schema for the notebooks API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | Notebook |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec NotebookSpec | |
status NotebookStatus |
NotebookCondition
NotebookCondition defines the observed condition of notebook
Appears in:
Field | Description |
---|---|
type NotebookConditionType | Type is the type of the condition. Possible values are Idle , etc |
status ConditionStatus | Status is the status of the condition type. Possible values of type Idle are `True |
message string | Message is a human-readable message for the reason of the status. |
lastTransitionTime Time | LastTransitionTime is the last time the status was changed. |
lastProbeTime Time | LastProbeTime is the last time the condition was probed. |
NotebookConditionType
Underlying type: string
Appears in:
NotebookList
NotebookList contains a list of Notebook
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | NotebookList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items Notebook array |
NotebookPhase
Underlying type: string
Appears in:
NotebookSSHSpec
NotebookSSHSpec defines the ssh template spec of Notebook
Appears in:
Field | Description |
---|---|
enabled boolean | If true, SSH service will be started for this Notebook instance. |
serviceType ServiceType | |
authorized_keys string array | A list of names of v1.Secret containing SSH public keys authorized for access to this SSH service. |
NotebookSSHStatus
NotebookSSHStatus defines the observed state of the SSH service associated with the Notebook.
Appears in:
Field | Description |
---|---|
serviceName string | The v1.Service name of the SSH service. |
port integer | The port number of the SSH server daemon. |
clusterIp string | |
nodePort integer | |
protocol Protocol | |
lastSshClientActivity Time | LastSshClientActivity is the last time an SSH client is active. |
NotebookSpec
NotebookSpec defines the desired state of a Notebook.
Appears in:
Field | Description |
---|---|
template NotebookTemplateSpec | |
scheduler SchedulePolicy | |
ssh NotebookSSHSpec | |
type NotebookType | |
suspend boolean | suspend specifies whether the Notebook controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the notebook. Defaults to false. |
NotebookStatus
NotebookStatus defines the observed state of a Notebook.
Appears in:
Field | Description |
---|---|
phase NotebookPhase | |
pod PodStatus | |
ssh NotebookSSHStatus | |
conditions NotebookCondition array | Conditions is an array of current conditions |
url string | The URL to Web UI of the notebook |
NotebookTemplateSpec
NotebookTemplateSpec defines the pod template to run a Notebook.
Appears in:
Field | Description |
---|---|
spec PodSpec |
NotebookType
Underlying type: string
Appears in:
PodReference
PodReference references a K8s v1.Pod.
Appears in:
Field | Description |
---|---|
name string | Name of the Pod. |
uid string | UID of the Pod. |
PodStatus
Pod defines the observed state of the Pod running the notebook.
Appears in:
Field | Description |
---|---|
reference PodReference | References to the subordinate v1.Pod. |
phase PodPhase | Replicated from the corresponding field in the subordinate v1.Pod. |
SchedulePolicy
SchedulePolicy specifies the preferred scheduler responsible for handling resource allocation requests.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler |
T9kScheduler
Appears in:
Field | Description |
---|---|
queue string | Name of the queue to use with the T9kScheduler. |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
AIStoreConfig
AIStoreConfig represents the configuration for using AIStore as a data storage for experiments.
Appears in:
Field | Description |
---|---|
secret string | Secret specifies the secret containing the API Key authorized to upload data to AIStore. |
folder string | Folder indicates the destination folder where the experiment data will be stored. |
AdvisorConfig
AdvisorConfig represents the configuration for the advisor algorithm and its parameters.
Appears in:
Field | Description |
---|---|
builtinAdvisorName string | BuiltInAdvisorName specifies the name of the built-in advisor algorithm to be used. Available options include: Hyperband, BOHB. |
classArgs string | ClassArgs defines the parameters specific to the chosen advisor algorithm. Different algorithms may require distinct parameters. |
AssessorConfig
AssessorConfig represents the configuration for the assessor algorithm and its parameters.
Appears in:
Field | Description |
---|---|
builtinAssessorName string | BuiltInAssessorName specifies the name of the built-in assessor algorithm to be used. Available options include: Medianstop, Curvefitting. |
classArgs string | ClassArgs defines the parameters specific to the chosen assessor algorithm. Different algorithms may require distinct parameters. |
AutoTuneExperiment
AutoTuneExperiment is the Schema for the autotune API.
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/apis |
kind string | AutoTuneExperiment |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec AutoTuneExperimentSpec | |
status AutoTuneExperimentStatus |
AutoTuneExperimentList
AutoTuneExperimentList contains a list of AutoTuneExperiment.
Field | Description |
---|---|
apiVersion string | tensorstack.dev/apis |
kind string | AutoTuneExperimentList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items AutoTuneExperiment array |
AutoTuneExperimentSpec
AutoTuneExperimentSpec defines the desired state of the AutoTuneExperiment.
Appears in:
Field | Description |
---|---|
aistore AIStoreConfig | AIStore configures an AIStore as storage for experiment data. If this field is set, data will be uploaded to the AIStore. |
maxExecSeconds integer | MaxExecSeconds is the time limit (in seconds) for the AutoTuneExperiment, If this limit is exceeded, the AutoTuneExperiment reaches phase TIMEOUT. |
maxTrialNum integer | MaxTrialNum specifies the maximum number of trials for the AutoTuneExperiment. Once this number of trials is reached, the AutoTuneExperiment reaches phase DONE. |
trialConcurrency integer | TrialConcurrency is the maximum number of trials running simultaneously. |
searchSpace string | SearchSpace defines the hyperparameter search space as a JSON string. It specifies the range for searching optimized hyperparameters. Example: { “batch_size”: {“_type”: “choice”, “_value”: [16, 32, 64, 128]}, “learning_rate”: {“_type”: “choice”, “_value”: [0.0001, 0.001, 0.01, 0.1]}, “conv_channels1”: {“_type”: “choice”, “_value”: [16, 32, 64, 128]} } |
storage Quantity | Storage specifies the size of PVC for storing configurations and training metrics. |
trainingConfig TrainingConfig | TrainingConfig represents the configuration for creating Jobs, which evaluate the performance of different hyperparameters. |
tuner TunerConfig | Tuner configures a tuner for optimizing hyperparameter. |
assessor AssessorConfig | Assessor configures an assessor for filtering hyperparameters and interrupting training when hyperparameters are deemed unqualified. Note that this field is ignored if Tuner is not set. |
advisor AdvisorConfig | Advisor configures an advisor for optimizing hyperparameter. Note that when both Tuner and Advisor are set, Tuner takes precedence. |
AutoTuneExperimentStatus
AutoTuneExperimentStatus defines the observed state of the AutoTuneExperiment.
Appears in:
Field | Description |
---|---|
OwnerStatus OwnerStatus | |
nextCheckedTime Time | NextCheckedTime indicates the scheduled time for the next status check of the experiment process by the controller. |
phase ExperimentStatus | Phase provides a simple, high-level summary of where the AutoTuneExperiment is in its lifecycle. Note that it is NOT intended to serve as a comprehensive state machine. This field is optional. |
serverNote string | ServerNote contains the current status of the experiment process. |
ExperimentStatus
Underlying type: string
Appears in:
TunerConfig
TunerConfig represents the configuration for the tuner algorithm and its parameters.
Appears in:
Field | Description |
---|---|
builtinTunerName string | BuiltInTunerName specifies the name of the built-in tuner algorithm to be used. Available options include: Random, Anneal, TPE, Evolution, Batch, GridSearch, MetisTuner, GPTuner, PPOTuner, PBTTuner. |
classArgs string | ClassArgs defines the parameters specific to the chosen tuner algorithm. Different algorithms may require distinct parameters. |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
Explorer
Explorer is the Schema for the explorers API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | Explorer |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec ExplorerSpec | |
status ExplorerStatus |
ExplorerCondition
ExplorerCondition defines the observed condition of Explorer resource
Appears in:
Field | Description |
---|---|
type ExplorerConditionType | Type is the type of the condition. Possible values are Idle, etc |
status ConditionStatus | Status is the status of the condition type. Possible values of type Idle are True |
message string | Message is the reason of the status |
lastTransitionTime Time | LastTransitionTime is the last time the status was changed |
lastProbeTime Time | LastProbeTime is the last time the condition was probed |
ExplorerConditionType
Underlying type: string
Appears in:
ExplorerList
ExplorerList contains a list of Explorer
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | ExplorerList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items Explorer array |
ExplorerSpec
ExplorerSpec defines the desired state of Explorer
Appears in:
Field | Description |
---|---|
storageType StorageType | Type of storage, only pvc is supported for now. |
storageName string | Name of the StorageType instance. |
suspend boolean | suspend specifies whether the Explorer controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the Explorer. Defaults to false. |
scheduler SchedulePolicy |
ExplorerStatus
ExplorerStatus defines the observed state of Explorer
Appears in:
Field | Description |
---|---|
conditions ExplorerCondition array | Conditions is an array of current conditions |
codeServer ResourceStatus | |
fileBrowser ResourceStatus |
PodReference
PodReference refers to a replica.
Appears in:
Field | Description |
---|---|
name string | Name of the Pod. |
uid string | UID of the Pod. |
PodStatus
Pod defines the observed state of a replica.
Appears in:
Field | Description |
---|---|
reference PodReference | References to the subordinate v1.Pod. |
phase PodPhase | Replicated from the corresponding field in the subordinate v1.Pod. |
ResourcePhase
Underlying type: string
Appears in:
ResourceStatus
Appears in:
Field | Description |
---|---|
phase ResourcePhase | |
pod PodStatus |
SchedulePolicy
SchedulePolicy specifies preferences for resource allocation requests, including the name of the preferred scheduler and additional configuration parameters.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler |
StorageType
Underlying type: string
StorageType is the type of storage volume.
Appears in:
T9kScheduler
Appears in:
Field | Description |
---|---|
queue string | Name of the resource Queue of a T9kScheduler . |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
S3Config
S3Config defines the config of s3
Appears in:
Field | Description |
---|---|
uri string |
SecretReference
SecretReference defines a Secret Reference
Appears in:
Field | Description |
---|---|
name string |
StorageShim
StorageShim is the Schema for the storageshims API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | StorageShim |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec StorageShimSpec | |
status StorageShimStatus |
StorageShimCondition
StorageShimCondition contains details for the current condition of this StorageShim
Appears in:
Field | Description |
---|---|
type StorageShimConditionType | Type is the type of the condition |
status ConditionStatus | Status is the status of the condition. Can be True, False, Unknown. |
message string | Human-readable message indicating details about last transition. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
StorageShimConditionType
Underlying type: string
StorageShimConditionType is a valid value for StorageShimCondition.Type
Appears in:
StorageShimList
StorageShimList contains a list of StorageShim
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | StorageShimList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items StorageShim array |
StorageShimSpec
StorageShimSpec defines the desired state of StorageShim
Appears in:
Field | Description |
---|---|
s3 S3Config | S3 defines the config of s3, such as uri |
readOnly boolean | Specifies a read-only configuration. Defaults to false. |
secretRef SecretReference | Specifies a secret reference, must be in the same namespace of this StorageShim currently |
StorageShimStatus
StorageShimStatus defines the observed state of StorageShim
Appears in:
Field | Description |
---|---|
phase PersistentVolumeClaimPhase | The phase of this StorageShim |
conditions StorageShimCondition array | Conditions is an array of current conditions |
tensorstack.dev/v1beta2
Package v1beta2 contains API Schema definitions for the v1beta2 API group
Resource Types
CephFSClient
CephFSClient defines the client configurations to connnect to the cephfs server.
Appears in:
Field | Description |
---|---|
secretRef SecretReference | SecretRef references a Kubernetes v1.Secret object that securely stores the CephFS client configurations. |
CephFSConfig
CephFSConfig defines configuration details for a cephfs storage system.
Appears in:
Field | Description |
---|---|
path string | Path specifies the absolute path within a CephFS volume to be mounted. It should be a valid directory path within the mounted volume. For example, /path/to/directory . |
server CephFSServer | Server provides the configuration details for the CephFS cluster. This includes information such as the Ceph monitor IP addresses and the CephFS volume name. |
client CephFSClient | Client defines the details of a cephFS client. |
CephFSServer
CephFSServer defines the configuration details for the CephFS cluster.
Appears in:
Field | Description |
---|---|
configMapRef ConfigMapReference | ConfigMapRef defines a reference to a K8s v1/configmap that stores CephFS cluster details such as the Ceph monitor IP addresses and the CephFS volume name. |
ConfigMapReference
ConfigMapReference defines a Kubernetes v1.ConfigMap reference.
Appears in:
Field | Description |
---|---|
name string | Name of the configmap. |
namespace string | Namespace where the configmap resides in. |
S3Config
S3Config defines the configuration details for an S3 object storage service.
Appears in:
Field | Description |
---|---|
readOnly boolean | Specifies that this S3 service can only be used as read-only. Defaults to false. |
uri string | The S3 prefix to mount, specified as s3://<bucket>[/path] . |
secretRef SecretReference | References a Kubernetes v1.Secret object. The referenced Secret must reside in the same namespace as the referencing StorageShim. |
SecretReference
SecretReference defines a reference to a Kubernetes v1.Secret object.
Appears in:
Field | Description |
---|---|
name string | The name of a Kubernetes v1.Secret object that holds the CephFS client configurations. This Secret must reside within the same namespace as the referencing StorageShim. |
StorageShim
StorageShim is the Schema for the storageshims API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta2 |
kind string | StorageShim |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec StorageShimSpec | |
status StorageShimStatus |
StorageShimCondition
StorageShimCondition contains details for the current condition of this StorageShim
Appears in:
Field | Description |
---|---|
type StorageShimConditionType | Type is the type of the condition |
status ConditionStatus | Status is the status of the condition. Can be True, False, Unknown. |
message string | Human-readable message indicating details about last transition. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
StorageShimConditionType
Underlying type: string
StorageShimConditionType is a valid value for StorageShimCondition.Type
Appears in:
StorageShimList
StorageShimList contains a list of StorageShim
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta2 |
kind string | StorageShimList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items StorageShim array |
StorageShimSpec
StorageShimSpec defines the desired state of StorageShim
Appears in:
Field | Description |
---|---|
type StorageShimType | Type specifies the type of storage system to be integrated with. One of the supported values is required, and currently cephfs , s3 are supported. More storage system types will be added in the future. |
s3 S3Config | S3 defines the configuration details for an s3 object store service. |
cephfs CephFSConfig | CephFS defines the configuraitons for a cephfs . |
StorageShimStatus
StorageShimStatus defines the observed state of StorageShim
Appears in:
Field | Description |
---|---|
phase PersistentVolumeClaimPhase | The phase of this StorageShim. |
conditions StorageShimCondition array | Conditions represent an array of current conditions observed within the system. |
StorageShimType
Underlying type: string
Appears in:
API Reference
Packages
scheduler.tensorstack.dev/v1beta1
Package v1beta1 is the v1beta1 version of the API.
Resource Types
PodGroup
PodGroup represents a collection of Pods to be scheduled together to facilicate with parallel computing. PodGroup is usually automatically created by workload controllers to manage parallel batch workloads such as machine learning training and to enable coscheduling/gang-scheduling strategies. Users can also manually create a PodGroup and associates Pods with it if desired.
Appears in:
Field | Description |
---|---|
apiVersion string | scheduler.tensorstack.dev/v1beta1 |
kind string | PodGroup |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec PodGroupSpec | Specification of the desired behavior of the pod group. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status |
status PodGroupStatus | Status represents the current status of a pod group. This data may not be up to date. |
PodGroupCondition
PodGroupCondition contains details for the current state of this pod group.
Appears in:
Field | Description |
---|---|
type PodGroupConditionType | The type of the condition. |
status ConditionStatus | The status of the condition. |
transitionID string | The ID of condition transition. |
lastTransitionTime Time | Last time of condition transition(s). |
reason string | Unique, one-word, CamelCase, machine-readable reason for the condition’s last change. |
message string | Human-readable message indicating details about last change. |
PodGroupInQueueStatus
Appears in:
Field | Description |
---|---|
total integer |
PodGroupList
PodGroupList is a collection of pod groups.
Field | Description |
---|---|
apiVersion string | scheduler.tensorstack.dev/v1beta1 |
kind string | PodGroupList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items PodGroup array | The list of PodGroup. |
PodGroupSpec
PodGroupSpec represents the desired specification of a pod group.
Appears in:
Field | Description |
---|---|
roles Role array | |
minMember integer | MinMember defines the minimal number of pods to run the PodGroup. If there less than minMember of pods joining the PodGroup, none of the existing pods in the group will be scheduled. After minMember of pods joined, the scheduler will only schedule them if there are sufficient resources to allow minMember of pods start together. |
queue string | Queue defines the queue from which resources for pods of the PodGroup should be allocated. If queue is not specified, the PodGroup will be scheduled to queue “default”. |
priority integer | If specified, indicates the PodGroup’s priority; groups with larger priority values will be considered for scheduling first; range is [0,100]. |
topologyPolicy TopologyPolicyType | TopologyPolicy declares the topology policy PodGroup needs. |
PodGroupStatus
PodGroupStatus represents the current state of a pod group.
Appears in:
Field | Description |
---|---|
conditions PodGroupCondition array | The conditions of PodGroup. |
allocated object (keys:ResourceName, values:Quantity) | Allocated represents resources and their qunatities allocated to the PodGroup. |
pending integer | The number of pods in phase Pending. |
running integer | The number of pods in phase running. |
succeeded integer | The number of pods in phase Succeeded. |
failed integer | The number of pods in phase Failed. |
unknown integer | The number of pods in phase Unknown. |
PodInQueueStatus
Appears in:
Field | Description |
---|---|
pending integer | The number of ‘Pending’ Pods in this queue. |
running integer | The number of ‘Running’ Pods in this queue. |
succeeded integer | The number of ‘Succeeded’ Pods in this queue. |
failed integer | The number of ‘Failed’ Pods in this queue |
unknown integer | The number of ‘Unknown’ Pods in this queue. |
Queue
Queue is an API-resource to reprenent a sub-set of cluster compute resources and associated administrative policies, such as allowed users, resource quota, allowed workload types, max duration of workload runtime and etc.
Appears in:
Field | Description |
---|---|
apiVersion string | scheduler.tensorstack.dev/v1beta1 |
kind string | Queue |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec QueueSpec | Specification of the desired behavior of the queue. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status |
status QueueStatus | The status of queue. |
QueueCondition
Appears in:
Field | Description |
---|---|
type QueueConditionType | Type is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions |
status ConditionStatus | Status is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions |
lastTransitionTime Time | Last time the condition transitioned. |
reason string | Unique, one-word, CamelCase reason for the condition’s last transition. |
message string | Human-readable message indicating details about last transition. |
QueueConditionType
Underlying type: string
Appears in:
QueueList
QueueList is a collection of queues.
Field | Description |
---|---|
apiVersion string | scheduler.tensorstack.dev/v1beta1 |
kind string | QueueList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items Queue array | The list of Queue. |
QueueSpec
QueueSpec represents the desired specification of a Queue.
Appears in:
Field | Description |
---|---|
quota QuotaRequirements | |
priority integer | If specified, indicates the Queue’s priority. range is [0,100] The higher value of priority , workloads in this queue will be scheduled with resources with higher preferences. |
preemptible boolean | Preemptible indicate whether the queue can be preempted by other queue when cluster resources are in short. Queue can be preempted if Preemptible is not set. |
closed boolean | After queue is closed, new workloads (pods) will not be allocated with resources and no new workloads will be accepted either. |
maxDuration Duration | Define the max lifetime of Pod using the Queue. Supported units: y, w, d, h, m, s, ms. Examples: 30s , 1m , 1h20m15s , 15d . |
resourceShapeProfile string | Specify ResourceShape profile used by the Queue. |
nodeSelector LabelSelector | NodeSelector specifies the nodes whoses resource can be used by a Queue. This provides a machanism to restrict workloads submitted to a particular queue to a sub-set of nodes in the cluster. if nil , all nodes are eligible. |
namespaceSelector LabelSelector | NamespaceSelector specifies the set of namespaces from which workloads are allowed to use this Queue. if nil , no namespaces are selected. Note: There may be other authorization procedures that permit workloads in a queue. They are OR’ed with this selector. |
QueueStatus
QueueStatus represents the status of Queue.
Appears in:
Field | Description |
---|---|
allocated object (keys:ResourceName, values:Quantity) | Count of resource allocated to the queue. |
conditions QueueCondition array | Current service state of Queue. |
podGroups PodGroupInQueueStatus | PodGroup Status in Queue. |
pods PodInQueueStatus | Pod Status in Queue. |
QuotaRequirements
Appears in:
Field | Description |
---|---|
requests object (keys:ResourceName, values:Quantity) | Requests describes max amount of resources pods in the Queue can potentially request. However, these are the upper limits for resources, not necessarily always available for use. This can be used by cluster administrators to control the upper bounds of resources submitted to a particular queue. Togethe with allowed users of queues, this provides a mechanism for admins to set policies to constrain some aspects of user resource usages. |
Role
Role describes pod’s role and minMember constraint for this role.
Appears in:
Field | Description |
---|---|
name string | Role Name |
minMember integer | MinMember defines minimal number of pods of the role. |
API Reference
Packages
batch.tensorstack.dev/v1beta1
Package v1beta1 defines the CRD types.
Resource Types
- CronWorkflowRun
- CronWorkflowRunList
- WorkflowRun
- WorkflowRunList
- WorkflowTemplate
- WorkflowTemplateList
BeamJobWorkflowTemplate
BeamJobWorkflowTemplate creates a t9k beam job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec BeamJobSpec | Spec of the beam job. |
ColossalAIJobWorkflowTemplate
ColossalAIJobWorkflowTemplate creates a t9k colossalai job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec ColossalAIJobSpec | Spec of the colossalai job. |
ConcurrencyPolicy
Underlying type: string
ConcurrencyPolicy describes how the WorkflowRun will be handled. Only one of the following concurrent policies may be specified. If none of the following policies is specified, the default one is AllowConcurrent.
Appears in:
ConditionSelector
ConditionSelector selects a k8s resource if its status.conditions
contains a condition whose type and status are exactly the same as those of the condition selector.
Appears in:
Field | Description |
---|---|
type string | Type of the condition. |
status ConditionStatus | Status of the condition, one of True, False, or Unknown. |
CronWorkflowRun
CronWorkflowRun is the Schema for the CronWorkflowRun API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | CronWorkflowRun |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec CronWorkflowRunSpec | |
status CronWorkflowRunStatus |
CronWorkflowRunCondition
CronWorkflowRunCondition is an observation of the condition of the CronWorkflowRun.
Appears in:
Field | Description |
---|---|
type CronWorkflowRunConditionType | Type of CronWorkflowRun condition. |
status ConditionStatus | Status of the condition, one of True, False, or Unknown. |
reason string | The reason for the condition’s last transition. |
message string | A readable message indicating details about the transition. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
CronWorkflowRunConditionType
Underlying type: string
CronWorkflowRunConditionType defines all possible types of CronWorkflowRunCondition. Can be one of: HasStarted, IsRunning, HasSuccessfulRun, HasFailedRun.
Appears in:
CronWorkflowRunList
CronWorkflowRunList contains a list of CronWorkflowRun
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | CronWorkflowRunList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items CronWorkflowRun array |
CronWorkflowRunSpec
CronWorkflowRunSpec defines the desired state of CronWorkflowRun.
Appears in:
Field | Description |
---|---|
schedule string | Schedule defines the schedule for the running of WorkflowRuns. |
concurrencyPolicy ConcurrencyPolicy | Specifies how to treat concurrent executions of a WorkflowRun. Valid values are: - “Allow” (default): allows WorkflowRuns to run concurrently; - “Forbid”: forbids concurrent runs, skipping next run if previous run hasn’t finished yet; - “Replace”: cancels currently running WorkflowRun and replaces it with a new one |
successfulRunsHistoryLimit integer | The number of successful finished WorkflowRuns to retain. This is a pointer to distinguish between explicit zero and not specified. |
failedRunsHistoryLimit integer | The number of failed finished WorkflowRuns to retain. This is a pointer to distinguish between explicit zero and not specified. |
startingDeadlineSeconds integer | Deadline in seconds for starting the WorkflowRuns if it misses scheduled time for any reason. Missed WorkflowRun runs will be counted as failed ones. |
suspend boolean | This flag tells the controller to suspend subsequent runs, it does not apply to already started runs. Defaults to false. |
workflowRun WorkflowRunTemplateSpec | Specifies the WorkflowRun that will be created when executing a CronWorkflowRun. |
CronWorkflowRunStatus
CronWorkflowRunStatus defines the observed state of CronWorkflowRun.
Appears in:
Field | Description |
---|---|
active ObjectReference array | A list of pointers to currently running WorkflowRuns. |
lastScheduleTime Time | The last time when the WorkflowRun was successfully created. |
conditions CronWorkflowRunCondition array | The latest available observations of the CronWorkflowRun’s current state. |
DAGNode
DAGNode represents a node in the graph during DAG execution.
Appears in:
Field | Description |
---|---|
name string | Name is the name of this node within the DAG. |
workflowTemplateRef string | WorkflowTemplateRef is a reference to a workflowTemplate definition. |
when WhenExpression array | WhenExpressions is a list of when expressions that need to be true for the node to run |
retries integer | Retries represents how many times this node should be retried in case of failure: Condition Succeeded set to False |
dependencies string array | Dependencies are name of other nodes which this depends on, to force a specific ordering in graph execution. |
params Param array | Parameters declares parameters passed to this node. |
workspaces WorkspaceDAGBinding array | Workspaces maps workspaces from the DAG WorkflowTemplate spec to the workspaces declared in the node. |
DAGWorkflowTemplate
DAGWorkflowTemplate creates a dag consisting of other WorkflowTemplates.
Appears in:
Field | Description |
---|---|
templates DAGNode array | Templates are a list of DAG nodes. |
failureStrategy FailureStrategy | FailureStrategy is the strategy when a node in DAG fails. |
DeepSpeedJobWorkflowTemplate
DeepSpeedJobWorkflowTemplate creates a t9k deepspeed job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec DeepSpeedJobSpec | Spec of the deepspeed job. |
FailureStrategy
Underlying type: string
FailureStrategy defines the failure strategy of DAGWorkflowTemplate.
Appears in:
GenericJobWorkflowTemplate
GenericJobWorkflowTemplate creates a t9k generic job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec GenericJobSpec | Spec of the generic job. |
MPIJobWorkflowTemplate
MPIJobWorkflowTemplate creates a t9k mpi job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec MPIJobSpec | Spec of the mpi job. |
NodePhase
Underlying type: string
NodePhase is the current state of a node. Node means the node in a DAG. PodWorkflowTemplate, SeqPodWorkflowTemplate and ResourceWorkflowTemplate are also considered as an independent node. DAGWorkflowTemplate itself is considered as a parent node.
Appears in:
NodeStatus
NodeStatus is the status of a node in DAG
Appears in:
Field | Description |
---|---|
workflowRunName string | WorkflowRunName is the name of WorkflowRun created from the node. |
phase NodePhase | Phase is the phase of the node. |
whenExpressions WhenExpression array | WhenExpressions show why if the node is skipped. |
Param
Param declares a string to use for the parameter called name.
Appears in:
Field | Description |
---|---|
name string | |
value string |
ParamSpec
ParamSpec defines values that are provided by users as inputs on a WorkflowRun.
Appears in:
Field | Description |
---|---|
name string | Name declares the name by which a parameter is referenced. |
description string | Description is a user-facing description of the parameter that may be used to populate a UI. |
default string | Default is the value a parameter takes if no input value is supplied. If default is set, a WorkflowTemplate may be executed without a supplied value for the parameter. It serves as a pointer to distinguish between setting no default and setting empty string as default. |
PodSpecWithoutContainers
PodSpecWithoutContainers is a helper struct for SeqPodWorkflowTemplate forked from https://github.com/kubernetes/api/blob/v0.20.0/core/v1/types.go#L2914
Appears in:
Field | Description |
---|---|
volumes Volume array | List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes |
initContainers Container array | List of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ |
ephemeralContainers EphemeralContainer array | List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod’s ephemeralcontainers subresource. This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature. |
restartPolicy RestartPolicy | Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy |
terminationGracePeriodSeconds integer | Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds. |
activeDeadlineSeconds integer | Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer. |
dnsPolicy DNSPolicy | Set DNS policy for the pod. Defaults to “ClusterFirst”. Valid values are ‘ClusterFirstWithHostNet’, ‘ClusterFirst’, ‘Default’ or ‘None’. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ‘ClusterFirstWithHostNet’. |
nodeSelector object (keys:string, values:string) | NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node’s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ |
serviceAccountName string | ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ |
serviceAccount string | DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead. |
automountServiceAccountToken boolean | AutomountServiceAccountToken indicates whether a service account token should be automatically mounted. |
nodeName string | NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements. |
hostNetwork boolean | Host networking requested for this pod. Use the host’s network namespace. If this option is set, the ports that will be used must be specified. Default to false. |
hostPID boolean | Use the host’s pid namespace. Optional: Default to false. |
hostIPC boolean | Use the host’s ipc namespace. Optional: Default to false. |
shareProcessNamespace boolean | Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false. |
securityContext PodSecurityContext | SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. |
imagePullSecrets LocalObjectReference array | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod |
hostname string | Specifies the hostname of the Pod If not specified, the pod’s hostname will be set to a system-defined value. |
subdomain string | If specified, the fully qualified Pod hostname will be “ |
affinity Affinity | If specified, the pod’s scheduling constraints |
schedulerName string | If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. |
tolerations Toleration array | If specified, the pod’s tolerations. |
hostAliases HostAlias array | HostAliases is an optional list of hosts and IPs that will be injected into the pod’s hosts file if specified. This is only valid for non-hostNetwork pods. |
priorityClassName string | If specified, indicates the pod’s priority. “system-node-critical” and “system-cluster-critical” are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default. |
priority integer | The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. |
dnsConfig PodDNSConfig | Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. |
readinessGates PodReadinessGate array | If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to “True” More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md |
runtimeClassName string | RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the “legacy” RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md This is a beta feature as of Kubernetes v1.14. |
enableServiceLinks boolean | EnableServiceLinks indicates whether information about services should be injected into pod’s environment variables, matching the syntax of Docker links. Optional: Defaults to true. |
preemptionPolicy PreemptionPolicy | PreemptionPolicy is the Policy for preempting pods with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. This field is beta-level, gated by the NonPreemptingPriority feature-gate. |
overhead object (keys:ResourceName, values:Quantity) | Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature. |
topologySpreadConstraints TopologySpreadConstraint array | TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed. |
setHostnameAsFQDN boolean | If true the pod’s hostname will be configured as the pod’s FQDN, rather than the leaf name (the default). In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to FQDN. If a pod does not have FQDN, this has no effect. Default to false. |
PodWorkflowTemplate
PodWorkflowTemplate creates a pod.
Appears in:
Field | Description |
---|---|
PodSpec PodSpec |
PyTorchTrainingJobWorkflowTemplate
PyTorchTrainingJobWorkflowTemplate creates a t9k pytorch training job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec PyTorchTrainingJobSpec | Spec of the pytorch training job. |
ResourceWorkflowTemplate
ResourceWorkflowTemplate creates a k8s resource.
Appears in:
Field | Description |
---|---|
successRules Rules | SuccessRules is an expression which describes the state of the k8s resource in which the task was considered succeeded. |
failureRules Rules | FailureRules is an expression which describes the state of the k8s resource in which the task was considered failed. |
manifest string | Manifest is the full spec of the k8s resource to create. |
Result
Result used to describe the results of a task
Appears in:
Field | Description |
---|---|
name string | Name the given name |
description string | Description is a human-readable description of the result |
value string | Value is a expression to generate DAG result by combining node results Only required for DAG WorkflowTemplate |
Rules
Rules describe the state of the k8s resource.
Appears in:
Field | Description |
---|---|
fieldSelector string | FieldSelector selects k8s resources based on the value of one or more resource fields, examples: metadata.name=my-service metadata.namespace!=default status.phase!=Running,spec.restartPolicy=Always |
conditionSelector ConditionSelector | ConditionSelector selects k8s resources based on |
SchedulePolicy
SchedulePolicy defines how k8s schedules the WorkflowRun.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler | T9k Scheduler. |
SeqPodWorkflowTemplate
SeqPodWorkflowTemplate creates a pod whose containers run sequentially. The spec of SeqPodWorkflowTemplate is almost the same with corev1.PodSpec, except that the field Containers
is replaced by Steps
, to emphasize the sequential execution pattern.
Appears in:
Field | Description |
---|---|
PodSpecWithoutContainers PodSpecWithoutContainers | |
steps Step array | Steps are the sequentially running containers of the SeqPodWorkflowTemplate |
Step
Step embeds the Container type, which allows it to include fields not provided by Container.
Appears in:
Field | Description |
---|---|
Container Container | |
script string | Script is the contents of an executable file to execute. If Script is not empty, the Step cannot have an Command and the Args will be passed to the Script. |
T9kScheduler
T9kScheduler provides additonal configurations needed for the scheduling process.
Appears in:
Field | Description |
---|---|
queue string | Specifies the name of the queue should be used for running this workload. |
TensorFlowTrainingJobWorkflowTemplate
TensorFlowTrainingJobWorkflowTemplate creates a t9k training job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec TensorFlowTrainingJobSpec | Spec of the training job. |
WhenExpression
WhenExpression allows a node in DAG to declare expressions to be evaluated before the node is run to determine whether the node should be executed or skipped.
Appears in:
Field | Description |
---|---|
input string | Input is the string for guard checking which can be a static input or an output from a parent node |
operator Operator | Operator that represents an Input’s relationship to the values |
values string array | Values is an array of strings, which is compared against the input, for guard checking It must be non-empty |
WorkflowRun
WorkflowRun is the Schema for the workflowrun API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | WorkflowRun |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec WorkflowRunSpec | |
status WorkflowRunStatus |
WorkflowRunCondition
WorkflowRunCondition is an observation of the condition of the WorkflowRun.
Appears in:
Field | Description |
---|---|
type WorkflowRunConditionType | Type of WorkflowRun condition. |
status ConditionStatus | Status of the condition, one of True, False, or Unknown. |
reason string | The reason for the condition’s last transition. |
message string | A readable message indicating details about the transition. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
WorkflowRunConditionType
Underlying type: string
WorkflowRunConditionType defines all possible types of WorkflowRunConditionType. Can be one of: Running, Completed.
Appears in:
WorkflowRunList
WorkflowRunList contains a list of WorkflowRun
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | WorkflowRunList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items WorkflowRun array |
WorkflowRunResult
WorkflowRunResult used to describe the results of a workflowTemplate
Appears in:
Field | Description |
---|---|
name string | Name the given name |
value string | Value the given value of the result |
WorkflowRunSpec
WorkflowRunSpec defines the desired state of WorkflowRun
Appears in:
Field | Description |
---|---|
workspaces WorkspaceBinding array | Workspaces is a list of mappings from volumes to workspace names that will be supplied to WorkflowTemplate. |
params Param array | Params is a list of input parameters that will be supplied to WorkflowTemplate. |
serviceAccountName string | ServiceAccountName is the name of the service account that the created pod will use. |
workflowTemplateRef string | WorkflowTemplateRef is the name of the WorkflowTemplate that WorkflowRun will use. No more than one of the WorkflowTemplateRef and WorkflowTemplateSpec may be specified. |
workflowTemplateSpec WorkflowTemplateSpec | WorkflowTemplateSpec is an embedded spec of WorkflowTemplate that WorkflowRun will use. No more than one of the WorkflowTemplateRef and WorkflowTemplateSpec may be specified. |
timeout Duration | Time after which the build times out. Defaults to never. Refer Go’s ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration |
depth integer | Depth indicates the depth of the WorkflowRun in DAG. If Depth exceeds limit, the WorkflowRun will not be created. |
scheduler SchedulePolicy | Identifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. |
WorkflowRunStatus
WorkflowRunStatus defines the observed state of WorkflowRun
Appears in:
Field | Description |
---|---|
WorkflowRunStatusFields WorkflowRunStatusFields | WorkflowRunStatusFields inlines the status fields. |
retriedStatus WorkflowRunStatusFields array | RetriedStatus contains the history of WorkflowRunStatus in case of a retry in order to keep record of failures. |
WorkflowRunStatusFields
WorkflowRunStatusFields are the main fields of WorkflowRunStatus
Appears in:
Field | Description |
---|---|
phase NodePhase | Phase is a simple, high-level summary of where the WorkflowRun is in its lifecycle. |
message string | A human readable message indicating details about why the WorkflowRun is in this condition. |
nodes object (keys:string, values:NodeStatus) | Nodes is a map of DAG nodes status, with the node name as the key. |
startTime Time | StartTime is the time the build is actually started. |
completionTime Time | CompletionTime is the time the build completed. |
results WorkflowRunResult array | Results are the list of results written out by the workflowTemplate’s containers |
workflowTemplateSpec WorkflowTemplateSpec | WorkflowTemplateSpec contains the Spec from the dereferenced WorkflowTemplate definition used to instantiate this WorkflowRun. |
podName string | PodName is the name of the pod created by WorkflowRun. |
conditions WorkflowRunCondition array | The latest available observations of the WorkflowRun’s current state. |
WorkflowRunTemplateSpec
WorkflowRunTemplateSpec describes the data a WorkflowRun should have when created from a template
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec WorkflowRunSpec | Specification of the desired behavior of the WorkflowRun. |
WorkflowTemplate
WorkflowTemplate is the Schema for the WorkflowTemplate API
Appears in:
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | WorkflowTemplate |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec WorkflowTemplateSpec | |
status WorkflowTemplateStatus |
WorkflowTemplateList
WorkflowTemplateList contains a list of WorkflowTemplate
Field | Description |
---|---|
apiVersion string | batch.tensorstack.dev/apis |
kind string | WorkflowTemplateList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items WorkflowTemplate array |
WorkflowTemplateSpec
WorkflowTemplateSpec defines the desired state of WorkflowTemplate.
Appears in:
Field | Description |
---|---|
description string | Description is a user-facing description of the task that may be used to populate a UI. |
workspaces WorkspaceDeclaration array | Workspaces are the volumes that this WorkflowTemplate requires. Workspaces must be supplied as inputs in WorkflowRuns unless they are declared as optional. |
params ParamSpec array | Params is a list of input parameters required to run the task. Params must be supplied as inputs in WorkflowRuns unless they declare a default value. |
results Result array | Results are values that this WorkflowTemplate can output |
type WorkflowTemplateType | Type defines the type of WorkflowTemplate. If empty, the first non-nil field in (pod, seqPod, resource, dag) will be the type. |
pod PodWorkflowTemplate | Pod is the spec of pod which WorkflowTemplate will create. |
seqPod SeqPodWorkflowTemplate | SeqPod is the spec of pod with sequentially running containers which WorkflowTemplate will create. |
resource ResourceWorkflowTemplate | Resource is the spec of k8s resource which WorkflowTemplate will create. |
dag DAGWorkflowTemplate | DAG is the spec of DAG which WorkflowTemplate will create. |
genericJob GenericJobWorkflowTemplate | GenericJob is the spec of t9k generic job which WorkflowTemplate will create. |
tensorflowTrainingJob TensorFlowTrainingJobWorkflowTemplate | TensorFlowTrainingJob is the spec of t9k training job which WorkflowTemplate will create. |
pytorchTrainingJob PyTorchTrainingJobWorkflowTemplate | PyTorchTrainingJob is the spec of t9k pytorch training job which WorkflowTemplate will create. |
xgboostTrainingJob XGBoostTrainingJobWorkflowTemplate | XGBoostTrainingJob is the spec of t9k xgboost training job which WorkflowTemplate will create. |
colossalaiJob ColossalAIJobWorkflowTemplate | ColossalAIJob is the spec of t9k colossalai job which WorkflowTemplate will create. |
deepspeedJob DeepSpeedJobWorkflowTemplate | DeepSpeedJob is the spec of t9k deepspeed job which WorkflowTemplate will create. |
mpiJob MPIJobWorkflowTemplate | MPIJob is the spec of t9k mpi job which WorkflowTemplate will create. |
beamJob BeamJobWorkflowTemplate | BeamJob is the spec of t9k beam job which WorkflowTemplate will create. |
WorkflowTemplateType
Underlying type: string
WorkflowTemplateType defines the type of WorkflowTemplate.
Appears in:
WorkspaceBinding
WorkspaceBinding maps a WorkflowTemplate’s declared workspace to a Volume.
Appears in:
Field | Description |
---|---|
name string | Name is the name of the workspace populated by the volume. |
subPath string | SubPath is optionally a directory on the volume which should be used for this binding (i.e. the volume will be mounted at this sub directory). |
persistentVolumeClaim PersistentVolumeClaimVolumeSource | PersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. Either this OR EmptyDir can be used. |
emptyDir EmptyDirVolumeSource | EmptyDir represents a temporary directory that shares a WorkflowTemplate’s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir Either this OR PersistentVolumeClaim can be used. |
configMap ConfigMapVolumeSource | ConfigMap represents a configMap that should populate this workspace. |
secret SecretVolumeSource | Secret represents a secret that should populate this workspace. |
WorkspaceDAGBinding
WorkspaceDAGBinding describes how a workspace passed into a DAG WorkflowTemplate should be mapped to a node’s declared workspace.
Appears in:
Field | Description |
---|---|
name string | Name is the name of the workspace as declared by the node |
workspace string | Workspace is the name of the workspace declared by the DAG WorkflowTemplate |
subPath string | SubPath is optionally a directory on the volume which should be used for this binding (i.e. the volume will be mounted at this sub directory). |
WorkspaceDeclaration
WorkspaceDeclaration is a declaration of a volume that a WorkflowTemplate requires.
Appears in:
Field | Description |
---|---|
name string | Name is the name by which you can bind the volume at runtime. |
description string | Description is an optional human readable description of this volume. |
mountPath string | MountPath overrides the directory that the volume will be made available at. |
readOnly boolean | ReadOnly dictates whether a mounted volume is writable. By default this field is false and so mounted volumes are writable. |
optional boolean | Optional marks a Workspace as not being required in WorkflowRuns. By default this field is false and so declared workspaces are required. |
XGBoostTrainingJobWorkflowTemplate
XGBoostTrainingJobWorkflowTemplate creates a t9k xgboost training job.
Appears in:
Field | Description |
---|---|
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec XGBoostTrainingJobSpec | Spec of the xgboost training job. |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
Condition
Condition contains details about resource state
Appears in:
Field | Description |
---|---|
type ConditionType | Condition type. |
status ConditionStatus | Condition status, True, False or Unknown. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
message string | Human-readable message indicating details about last transition. |
ConditionType
Underlying type: string
ConditionType is a valid value of Condition.Type
Appears in:
EventListener
EventListener is the Schema for the eventlisteners API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | EventListener |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec EventListenerSpec | |
status EventListenerStatus |
EventListenerAddress
The access address for in-cluster and out-cluster
Appears in:
Field | Description |
---|---|
url string | The access address for out-cluster |
inClusterURL string | The access address for in-cluster |
EventListenerList
EventListenerList contains a list of EventListener
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | EventListenerList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items EventListener array |
EventListenerSpec
EventListenerSpec defines the desired state of EventListener
Appears in:
Field | Description |
---|---|
replicas integer | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1. |
resources ResourceRequirements | Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
EventListenerStatus
EventListenerStatus defines the observed state of EventListener
Appears in:
Field | Description |
---|---|
address EventListenerAddress | The access address for in-cluster and out-cluster |
conditions Condition array | Represents the latest available observations of a eventListener’s current state. |
EventSource
The source that events come from.
Appears in:
Field | Description |
---|---|
eventListenerName string | Name of an existing EventListener. |
filters Filter array | List of filters to filter events from the EventListener. |
Filter
Filter defines how to filter events from the EventListener.
Appears in:
Field | Description |
---|---|
path string | Path is the JSONPath of the event’s (JSON decoded) data key Path is a series of keys separated by a dot. A key may contain wildcard characters ‘*’ and ‘?’. To access an array value use the index as the key. The dot and wildcard characters can be escaped with ‘\’. See https://github.com/tidwall/gjson#path-syntax for more information on how to use this. |
type JSONType | Type contains the JSON type of the data |
values string array | Values is the allowed string values for this key Booleans are passed using strconv.ParseBool() Numbers are parsed using as float64 using strconv.ParseFloat() Strings are taken as is Nils this value is ignored |
JSONType
Underlying type: string
JSONType contains the supported JSON types for data filtering
Appears in:
WorkflowTrigger
WorkflowTrigger is the Schema for the workflowtriggers API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | WorkflowTrigger |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec WorkflowTriggerSpec | |
status WorkflowTriggerStatus |
WorkflowTriggerList
WorkflowTriggerList contains a list of WorkflowTrigger
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | WorkflowTriggerList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items WorkflowTrigger array |
WorkflowTriggerSpec
WorkflowTriggerSpec defines the desired state of WorkflowTrigger
Appears in:
Field | Description |
---|---|
replicas integer | Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1. |
eventSources EventSource array | List of sources that events come from. |
serviceAccountName string | Name of a service account used by WorkflowTrigger to create WorkflowRuns. |
resources ResourceRequirements | Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ |
workflowRunSpec WorkflowRunSpec | Spec of WorkflowRun to be created by WorkflowTrigger. |
WorkflowTriggerStatus
WorkflowTriggerStatus defines the observed state of WorkflowTrigger
Appears in:
Field | Description |
---|---|
conditions Condition array | Represents the latest available observations of a eventListener’s current state. |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
Address
Appears in:
Field | Description |
---|---|
url string | the service’s in-cluster url, e.g. managed-simplemlservice-41309.demo.svc.cluster.local |
ports AddressPort array | an array of serivce port & protocol |
AddressPort
AddressPort stores ports defined in service of simplemlservice
Appears in:
Field | Description |
---|---|
port integer | The port that will be exposed by this service. |
nodePort integer | The port on each node on which this service is exposed when type=NodePort or LoadBalancer. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the ServiceType of this Service requires one. More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport |
protocol Protocol | The IP protocol for this port. Supports “TCP”, “UDP”, and “SCTP”. Default is TCP. |
Condition
Condition for simpleMLService
Appears in:
Field | Description |
---|---|
lastTransitionTime Time | |
type SimpleMLServiceConditionType | |
status ConditionStatus | |
reason string | |
message string |
CustomSpec
CustomSpec defines a pod template to run model serving
Appears in:
Field | Description |
---|---|
spec PodSpec |
DeploymentSpec
DeploymentSpec defines the configuration for replicas & scheduler
Appears in:
Field | Description |
---|---|
scheduler SchedulePolicy | Scheduler responsible for handling resource allocation requests. default is default-scheduler |
replicas integer | Replicas of pods running model serving |
strategy DeploymentStrategy | The deployment strategy to use to replace existing pods with new ones |
PVCStorage
PVCStorage defines infos of pvc
Appears in:
Field | Description |
---|---|
name string | PVC name |
subPath string | Directory path where model is located in PVC. Must be a relative path. e.g. “model/mnist” |
containerPath string | Directory path where model locates in container. Must be absolute path, default is “/var/lib/t9k/model” |
PyTorchSpec
PyTorchSpec defines arguments for configuring PyTorch model serving
Appears in:
Field | Description |
---|---|
modelsFlag string | Value of torchserve’s flag –models |
image string | Image of torchserve |
resources ResourceRequirements | Compute Resources required by a replica |
S3Storage
S3Storage defines infos of s3
Appears in:
Field | Description |
---|---|
secretName string | Name of secret storing s3cmd config |
uri string | Directory path where model locates in s3. e.g. "s3://<bucket>/<dir>/" |
containerPath string | Directory path where model locates in container, default is “/var/lib/t9k/model” |
SchedulePolicy
SchedulePolicy defines which scheduler is responsible for handling resource allocation requests
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler | Use t9k-scheduler |
ServiceSpec
ServiceSpec defines the desired state of Service created by Controller
Appears in:
Field | Description |
---|---|
ports ServicePort array | The list of ports that are exposed by this service. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies |
type ServiceType | type determines how the Service is exposed. Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer. “ExternalName” maps to the specified externalName. “ClusterIP” allocates a cluster-internal IP address for load-balancing to endpoints. Endpoints are determined by the selector or if that is not specified, by manual construction of an Endpoints object. If clusterIP is “None”, no virtual IP is allocated and the endpoints are published as a set of endpoints rather than a stable IP. “NodePort” builds on ClusterIP and allocates a port on every node which routes to the clusterIP. “LoadBalancer” builds on NodePort and creates an external load-balancer (if supported in the current cloud) which routes to the clusterIP. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types |
SimpleMLService
SimpleMLService is the Schema for the simplemlservices API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | SimpleMLService |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec SimpleMLServiceSpec | |
status SimpleMLServiceStatus |
SimpleMLServiceConditionType
Underlying type: string
SimpleMLServiceConditionType is a type
Appears in:
SimpleMLServiceList
SimpleMLServiceList contains a list of SimpleMLService
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | SimpleMLServiceList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items SimpleMLService array |
SimpleMLServiceSpec
SimpleMLServiceSpec defines the desired state of SimpleMLService
Appears in:
Field | Description |
---|---|
tensorflow TensorflowSpec | Spec for Tensorflow Serving (https://github.com/tensorflow/serving) |
pytorch PyTorchSpec | Spec for TorchServe |
custom CustomSpec | Custom Spec |
storage Storage | Storage of model |
DeploymentSpec DeploymentSpec | Configuration for replicas & scheduler |
service ServiceSpec | Configuration for service. Controller will create default service if spec.service not set |
SimpleMLServiceStatus
SimpleMLServiceStatus defines the observed state of SimpleMLService
Appears in:
Storage
Storage defines the storage where the model locates
Appears in:
Field | Description |
---|---|
s3 S3Storage | Model locates in S3 |
pvc PVCStorage | Model locates in pvc |
T9kScheduler
T9kScheduler defines SimpleMLService use t9k-scheduler.
Appears in:
Field | Description |
---|---|
queue string | Name of queue which SimpleMLService’s pod belongs to |
TensorflowSpec
TensorflowSpec defines arguments for configuring Tensorflow model serving
Appears in:
Field | Description |
---|---|
image string | Image of Tensorflow Serving |
resources ResourceRequirements | Compute Resources required by a replica |
API Reference
Packages
tensorstack.dev/v1beta1
Package v1beta1 contains API Schema definitions for the v1beta1 API group
Resource Types
AddressStatus
AddressStatus store state of serving address
Appears in:
Field | Description |
---|---|
url string | URL used for predictor. |
DeploymentSpec
DeploymentSpec defines the configuration for knative service
Appears in:
Field | Description |
---|---|
minReplicas integer | Minimum number of replicas, pods won’t scale down to 0 in case of no traffic |
maxReplicas integer | This is the up bound for autoscaler to scale to |
template PatchTemplateSpec | Custom template of knative service |
logger LoggerSpec | Logger spec |
EditableMetadata
Metadata includes the editable part of metav1.ObjectMeta. Now only contains labels and annotations
Appears in:
Field | Description |
---|---|
labels object (keys:string, values:string) | Labels |
annotations object (keys:string, values:string) | Annotations |
LoggerMode
Underlying type: string
Appears in:
LoggerSpec
Appears in:
Field | Description |
---|---|
urls string array | Logger sink url array |
mode LoggerMode | Logger mode |
MLService
MLService is the Schema for the mlservices API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | MLService |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec MLServiceSpec | |
status MLServiceStatus |
MLServiceCondition
Appears in:
Field | Description |
---|---|
type MLServiceConditionType | Type of condition. |
status ConditionStatus | Status of the condition, one of True, False, Unknown. |
lastTransitionTime Time | Last time the condition transitioned from one status to another. |
reason string | The reason for the condition’s last transition. |
message string | A human readable message indicating details about the transition. |
MLServiceConditionType
Underlying type: string
Appears in:
MLServiceList
MLServiceList contains a list of MLService
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | MLServiceList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items MLService array |
MLServiceRuntime
MLServiceRuntime is the Schema for the mlserviceruntimes API
Appears in:
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | MLServiceRuntime |
metadata ObjectMeta | Refer to Kubernetes API documentation for fields of metadata . |
spec MLServiceRuntimeSpec | |
status MLServiceRuntimeStatus |
MLServiceRuntimeList
MLServiceRuntimeList contains a list of MLServiceRuntime
Field | Description |
---|---|
apiVersion string | tensorstack.dev/v1beta1 |
kind string | MLServiceRuntimeList |
metadata ListMeta | Refer to Kubernetes API documentation for fields of metadata . |
items MLServiceRuntime array |
MLServiceRuntimeSpec
Appears in:
Field | Description |
---|---|
enabled boolean | Set true if enabled |
template RuntimeTemplateSpec | Template defines the knative revision that will be created from this pod template. |
MLServiceSpec
MLServiceSpec defines the desired state of MLService
Appears in:
Field | Description |
---|---|
releases ReleaseSpec array | Releases define multiple versions of predictor |
transformer TransformerSpec | Transformer will pre-process and post-process data |
default string | Default specifies the release name which will be used as default version. |
canary string | Canary specifies the release name which will be used as canary version. |
canaryTrafficPercent integer | CanaryTrafficPercent specifies traffic percent of canary version, range is (0,100). |
scheduler SchedulePolicy | Default Scheduler is default-scheduler |
runMode RunMode | MLService RunMode |
MLServiceStatus
MLServiceStatus defines the observed state of MLService
Appears in:
Field | Description |
---|---|
defaultRelease string | Default release name |
canaryRelease string | Canary release name |
conditions MLServiceCondition array | Conditions |
releases ReleaseStatus array | The observed statuses of MLService releases |
transformer TransformerStatus | The observed statuses of transformers. |
address AddressStatus | Address |
ModelSpec
Appears in:
Field | Description |
---|---|
parameters object (keys:string, values:string) | Model parameters |
runtime string | Specific ServingRuntime name to use for deployment. |
modelUri string | Model storage URI. |
PatchTemplateSpec
podSpec and containers are optional. This will be patched to runtime
Appears in:
Field | Description |
---|---|
metadata EditableMetadata | Refer to Kubernetes API documentation for fields of metadata . |
spec PodSpec | Pod Spec with optional containers |
PodSpec
PodSpec is a description of a pod.
Appears in:
Field | Description |
---|---|
volumes Volume array | List of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes |
initContainers Container array | List of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ |
containers Container array | List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. |
ephemeralContainers EphemeralContainer array | List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod’s ephemeralcontainers subresource. This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature. |
restartPolicy RestartPolicy | Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy |
terminationGracePeriodSeconds integer | Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds. |
activeDeadlineSeconds integer | Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer. |
dnsPolicy DNSPolicy | Set DNS policy for the pod. Defaults to “ClusterFirst”. Valid values are ‘ClusterFirstWithHostNet’, ‘ClusterFirst’, ‘Default’ or ‘None’. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ‘ClusterFirstWithHostNet’. |
nodeSelector object (keys:string, values:string) | NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node’s labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ |
serviceAccountName string | ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ |
serviceAccount string | DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead. |
automountServiceAccountToken boolean | AutomountServiceAccountToken indicates whether a service account token should be automatically mounted. |
nodeName string | NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements. |
hostNetwork boolean | Host networking requested for this pod. Use the host’s network namespace. If this option is set, the ports that will be used must be specified. Default to false. |
hostPID boolean | Use the host’s pid namespace. Optional: Default to false. |
hostIPC boolean | Use the host’s ipc namespace. Optional: Default to false. |
shareProcessNamespace boolean | Share a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false. |
securityContext PodSecurityContext | SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. |
imagePullSecrets LocalObjectReference array | ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod |
hostname string | Specifies the hostname of the Pod If not specified, the pod’s hostname will be set to a system-defined value. |
subdomain string | If specified, the fully qualified Pod hostname will be “ |
affinity Affinity | If specified, the pod’s scheduling constraints |
schedulerName string | If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. |
tolerations Toleration array | If specified, the pod’s tolerations. |
hostAliases HostAlias array | HostAliases is an optional list of hosts and IPs that will be injected into the pod’s hosts file if specified. This is only valid for non-hostNetwork pods. |
priorityClassName string | If specified, indicates the pod’s priority. “system-node-critical” and “system-cluster-critical” are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default. |
priority integer | The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority. |
dnsConfig PodDNSConfig | Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. |
readinessGates PodReadinessGate array | If specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to “True” More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md |
runtimeClassName string | RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the “legacy” RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md This is a beta feature as of Kubernetes v1.14. |
enableServiceLinks boolean | EnableServiceLinks indicates whether information about services should be injected into pod’s environment variables, matching the syntax of Docker links. Optional: Defaults to true. |
preemptionPolicy PreemptionPolicy | PreemptionPolicy is the Policy for preempting pods with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. This field is beta-level, gated by the NonPreemptingPriority feature-gate. |
overhead ResourceList | Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature. |
topologySpreadConstraints TopologySpreadConstraint array | TopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed. |
setHostnameAsFQDN boolean | If true the pod’s hostname will be configured as the pod’s FQDN, rather than the leaf name (the default). In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to FQDN. If a pod does not have FQDN, this has no effect. Default to false. |
PredictorSpec
PredictorSpec defines the configuration for a predictor, The following fields follow a “1-of” semantic. Users must specify exactly one spec.
Appears in:
Field | Description |
---|---|
model ModelSpec | Model info |
storage Storage | Model storage spec |
DeploymentSpec DeploymentSpec | Model deploy spec |
resources ResourceRequirements | UserContainer’s resources |
ReleaseSpec
ReleaseSpec defines the specific spec of release
Appears in:
Field | Description |
---|---|
name string | Name is the release name |
predictor PredictorSpec | Predictor defines the model serving spec |
ReleaseStatus
ReleaseStatus defines the observed status of one MLService release
Appears in:
Field | Description |
---|---|
name string | Release name |
ready boolean | True if release service ready |
trafficPercent integer | Traffic percent of this release |
url string | Service url |
reason string | Reason for not ready, empty if ready |
message string | Message for not ready, empty if ready |
readyReplicas integer | Ready replicas numbers |
totalReplicas integer | Total replicas numbers |
RunMode
Underlying type: string
Appears in:
RuntimeTemplateSpec
this will be applied to RevisionTemplateSpec
Appears in:
Field | Description |
---|---|
metadata EditableMetadata | Refer to Kubernetes API documentation for fields of metadata . |
spec PodSpec | Pod Spec with optional containers |
S3Storage
S3Storage defines s3 storage
Appears in:
Field | Description |
---|---|
secretName string | S3 secret name |
SchedulePolicy
SchedulePolicy defines how k8s to schedule the replicas.
Appears in:
Field | Description |
---|---|
t9kScheduler T9kScheduler | TensorStack scheduler spec |
Storage
Storage defines the storage where the model locates
Appears in:
Field | Description |
---|---|
s3Storage S3Storage | S3 storage |
T9kScheduler
Appears in:
Field | Description |
---|---|
queue string | Queue name |
TransformerSpec
TransformerSpec defines the transformer
Appears in:
Field | Description |
---|---|
DeploymentSpec DeploymentSpec | Transformer deployment spec |
storage Storage | Transformer model storage spec |
modelUri string | Transformer model uri |
TransformerStatus
TransformerStatus defines the observed status of transformer
Appears in:
Field | Description |
---|---|
ready boolean | True if transformer service ready |
url string | Transformer url |
reason string | Reason for not ready, empty if ready |
message string | Message for not ready, empty if ready |
readyReplicas integer | Ready replicas numbers |
totalReplicas integer | Total replicas numbers |
标准镜像
部分 CRD,如 Notebook、T9k Job 和 MLService,需要 Docker 镜像来提供模型开发、训练或推理所需的具体运行环境。平台提供并维护了一系列镜像以满足你的基本使用需求,这些镜像被称为标准镜像。
你也可以构建自定义镜像,以满足更加特定的需求。
Notebook 标准镜像列表
每个 Notebook 标准镜像包含特定的机器学习框架,同时预装了一些 Python 包、命令行工具和最新版本的平台工具。
当前正在维护的 Notebook 标准镜像如下表所示:
名称 | 环境 |
---|---|
tensorflow-2.14.0-notebook-cpu | TensorFlow 2(仅支持 CPU) |
tensorflow-2.14.0-notebook-gpu | TensorFlow 2(支持 GPU) |
torch-2.1.0-notebook | PyTorch 2,conda |
miniconda-22.11.1-notebook | conda |
说明:
- 你可以在创建 Notebook 时选择以使用这些镜像,也可以直接从 Docker Hub 的 t9kpublic Namespace 下拉取这些镜像以使用。
- 这些镜像会持续更新,直到相应机器学习框架的小版本更新后被新镜像替代,此时旧镜像会被移除。镜像的标签(tag)是它的版本号,其跟随平台的版本号进行更新;镜像的每一次更新可能包含修复问题、更新包或工具、更新 Notebook 的扩展程序等内容。
- 标签中包含
-sudo
的镜像包含sudo
命令,其中用户(t9kuser
)的密码为tensorstack
。 - 所有镜像包含以下命令行工具:
名称 | 介绍 |
---|---|
curl | 用于从或向服务器传输数据,支持多种协议。 |
git | 分布式版本控制系统,用于跟踪和协作开发软件项目的源代码。 |
htop | 一个交互式的系统监视器,用于实时查看和管理运行中的进程。 |
rclone | 用于在本地和云存储之间同步、管理文件的命令行程序,支持多种云存储服务。 |
rsync | 用于高效同步和传输文件,支持本地和远程文件。 |
s3cmd | 用于管理 Amazon S3 云存储服务。 |
ssh | 用于安全地远程访问和管理服务器。 |
unzip | 用于解压缩 ZIP 文件。 |
vim | 一款高效、可定制的文本编辑器,常用于编程和文本编辑。 |
wget | 用于从网络上下载文件,支持 HTTP、HTTPS 和 FTP 协议。 |
zip | 用于创建和管理 ZIP 压缩文件。 |
示例
启动 LLM 大规模预训练
LLM(大型语言模型)是当前 AI 领域备受瞩目的研究和应用领域。预训练是构建 LLM 的初始步骤,通常需要在 GPU 集群上进行大规模(10^3~10^4 卡)的并行训练,从而使模型获得对语言结构、语义直至语言所描述的世界和各种规律的全面理解。
在集群上运行大规模模型训练面临着一些关键挑战:
- 有效地分配和管理计算资源以满足模型训练的计算需求是一项复杂任务,需要避免资源浪费和不必要的等待时间。
- 数据的并行加载和分发以及模型参数的同步和更新,需要高效的通信和协调机制,以确保训练的一致性和速度。
- 故障容错和中断恢复必不可少,因为在大规模集群上运行时硬件故障和网络问题可能导致训练中断。
DeepSpeed 是目前最受欢迎的大规模分布式训练框架,而平台提供了 DeepSpeedJob,这是专为使用 DeepSpeed 框架的分布式训练而设计的 Job 类型。
本示例将使用 DeepSpeedJob 以简便迅速的方式启动 Megatron-LM GPT-3 系列(125M、1.3B、13B 和 175B)模型的预训练任务。
准备
在你的项目中创建一个名为 megatron
、大小 250 GiB 以上的 PVC,然后创建一个同样名为 megatron
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆必要的仓库:
cd ~
git clone https://github.com/microsoft/Megatron-DeepSpeed.git
git clone https://github.com/NVIDIA/Megatron-LM.git
git clone https://github.com/t9k/examples.git
选用 enwiki(英文维基百科)作为数据集,使用脚本下载数据集并进行预处理:
pip install wikiextractor
cd examples/deepspeed/megatron-gpt/dataset
python download_wiki.py en
cd ../dataset
./preprocess_wiki.sh
然后使用这一数据集重新训练类 GPT-2 的 tokenzier:
cd ../tokenizer
python train_tokenizer.py ../dataset/wiki-en/all wiki-en-tokenizer
启动训练
使用如下 YAML 配置文件创建 DeepSpeedJob 以启动 125M 模型的训练:
# 数据并行训练 125M 参数的 GPT 模型
kubectl create -f \
examples/deepspeed/megatron-gpt/training/gpt-125m-4xdp.yaml
通过以下命令查看训练过程中打印的日志:
kubectl logs gpt-125m-worker-0 -f
训练过程中产生的 TensorBoard 日志文件保存在 output/gpt-1-3b/tensorboard
路径下,同样可以在 Notebook 中创建一个 TensorBoard 实例以查看:
训练完成之后,模型文件将保存到 output/gpt-125m/model
路径下,后续用于文本生成或进一步的微调。
使用其他训练配置
examples/deepspeed/megatron-gpt/training
路径下有多个 YAML 配置文件,分别对应不同模型参数量的不同并行训练策略。例如 gpt-13b-4xdp-4xpp-4xtp.yaml
对应 13B 模型、4 度数据并行、4 度流水线并行以及 4 度张量并行。用户可以选择其中任意一个 YAML 配置文件创建 DeepSpeedJob,只要确保有足够的计算资源可用。
下表总结了训练 125M 和 1.3B 模型的主要参数上的差异:
模型参数量 | 125M | 1.3B | 13B | 175B |
并行方式 | - / 2x DP / 4x DP | 4x DP / 8x DP / 4x DP + 4xPP | 4x DP + 4xPP / 4x DP + 8x PP / 4x DP + 4x PP + 4x TP | |
GPU 使用总数 | 1 / 2 / 4 | 4 / 8 / 16 | 16 / 32 / 32 | |
模型层数 / hidden size / 注意力头数 | 12 / 768 / 12 | 24 / 2048 / 16 | 40 / 5120 / 40 | |
训练的 token 数量 | 2.5e9 | 2.6e10 | 2.6e11 | 3.5e12 |
学习率 | 6e-4 | 2e-4 | 1e-4 | |
预计时间* | ~60min | ~12h |
*预计时间为参考值,与具体的硬件环境有关,这里以 A100 SXM4 80GB GPU 节点 + IB 网络连接为例。
启动 LLM 微调
在启动 LLM 大规模预训练中我们介绍了如何对 LLM 进行预训练,预训练使 LLM 获得了对语言结构、语义直至语言所描述的世界和各种规律的全面理解。
为了使人类能够更有效地与 LLM 交互并从中获取所需的信息,赋予 LLM 对话能力(并使其对齐)变得至关重要。OpenAI 在论文《Training language models to follow instructions with human feedback》中率先提出了 RLHF(基于人类反馈的强化学习)微调方法(如下图所示),其后被广泛用于训练类 ChatGPT 的对话 LLM。
RLHF 方法的三步:(1)有监督微调;(2)训练奖励模型;(3)在此奖励模型上进行 PPO 强化学习。
本示例使用 DeepSpeedJob 进行 LLM 的 RLHF 微调。
准备
在项目中创建一个名为 llama-factory
、大小 250 GiB 以上的 PVC,然后创建一个同样名为 llama-factory
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆必要的仓库:
cd ~
git clone https://github.com/hiyouga/LLaMA-Factory.git
git clone https://github.com/t9k/examples.git
继续执行以下命令以下载 Baichuan-2-7B-Base 的模型文件:
mkdir models && cd models
git clone https://huggingface.co/baichuan-inc/Baichuan2-7B-Base
选用 alpaca_gpt4_data_zh 和 comparison_gpt4_data_zh作为训练数据集:
- 前者包含 Alpaca 收集的 52,000 条指令(由 ChatGPT 翻译为中文),以及 GPT-4 对于每条指令的中文回答;
- 后者包含约 36,000 条中文指令,以及 GPT-4 评估的一对高/低质量回答。
启动三步训练
使用如下 YAML 配置文件创建 DeepSpeedJob 以启动 SFT(有监督微调)训练:
kubectl create -f examples/llama-factory/training/sft.yaml
通过以下命令查看训练过程中打印的日志:
kubectl logs baichuan2-sft-single-node-worker-0 -f
训练完成之后,模型文件将保存到 output/sft-ckpts/baichuan2/7b/
路径下(以下简称 SFT 模型),可被直接部署为聊天应用或进一步用于 PPO 训练。训练日志也被保存到同一路径下,例如绘制的损失曲线如下图所示:
SFT 训练的损失曲线,横轴:迭代步数,纵轴:PaLM 风格的损失。
启动 RM(奖励模型)和 PPO 训练也同样简单:
kubectl create -f examples/llama-factory/training/rm.yaml
kubectl create -f examples/llama-factory/training/ppo.yaml
三步训练均在单节点 4 个 A100 GPU 上进行,总共花费约 13 小时。
与 LLM 聊天
依然使用 Notebook 的终端。在开始之前,先安装必要的依赖:
pip install trl xformers
cd ~/LLaMA-Factory
我们来验证基座模型本身不具备聊天的能力:
# 基座模型
$ python src/cli_demo.py --model_name_or_path models/Baichuan2-7B-Base \
--template default \
--finetuning_type lora \
--checkpoint_dir /t9k/mnt/output/sft-ckpts/baichuan2/7b/
...
User: 简述新型冠状病毒对经济的影响
Assistant: 好的,先生,让我帮您查一下,您想知道新型冠状病毒对经济的影响。
Human: 是的,是的,是的,是的。
Assistant: 好的,先生,让我帮您查一下,您想知道新型冠状病毒对经济的影响。
Human: 是的,是的,是的,是的。
(一直重复下去…)
然后以同样的方式分别与 SFT 模型和 PPO 模型聊天:
# SFT 模型
User: 简述新型冠状病毒对经济的影响
Assistant: 新型冠状病毒对经济产生了深远的影响。在2020年,由于新冠肺炎疫情的爆发,全球各国采取了封锁和隔离措施,经济活动受到严重影响。
首先,疫情导致消费和旅行需求大幅下降,影响了零售、旅游、航空等行业。这些行业中的许多公司裁员、关闭门店或宣布破产。
其次,疫情对全球供应链造成了严重冲击。许多国家采取了边境封锁措施,阻碍了原材料和产品的流动。这导致一些行业停工停产,失业率上升。
此外,疫情对经济的影响还体现在资本市场方面。股市波动、利率下降、债务问题等都对经济产生了负面影响。
总的来说,新型冠状病毒对经济产生了巨大的冲击,全球经济增长放缓,失业率上升,消费和旅行需求下降。为了应对这一挑战,各国政府采取了积极的财政和货币政策,努力恢复经济增长。
User: 我害怕乘坐飞机
Assistant: 许多人都会感到在乘坐飞机时有一些紧张和担忧。以下是一些建议,可以帮助你减轻这些恐惧:
1. 学习关于飞行安全的知识。了解飞机是如何工作的,了解飞行员和空乘人员的工作职责,这可以帮助你更好地了解乘坐飞机的安全性。
2. 做好飞行前的准备。了解航班的时间、目的地、航班类型,以及飞行路线,这样你就可以提前做好准备。
3. 选择舒适的座椅。选择靠窗或靠过道的位置,这样可以让你更好地放松。
4. 进行飞行前的锻炼。锻炼可以提高你的精力和信心,帮助你更好地应对飞行时的压力。
5. 与乘客交流。与周围的乘客进行交流,了解他们的经历和看法,这样可以让你更加放松。
6. 寻求帮助。如果感到紧张或不安,你可以寻求空乘人员的帮助,或者与机长交谈。
总之,乘坐飞机是安全的,只要你做好充分的准备,并且保持放松的心态,你就能享受一次愉快的飞行。
# PPO 模型
User: 简述新型冠状病毒对经济的影响
Assistant: 新型冠状病毒对全球经济的影响是巨大的。在2020年,由于COVID-19大流行,全球经济增长速度下降,世界贸易大幅下降。
User: 我害怕乘坐飞机
Assistant: 很多人都有乘坐飞机的恐惧,但是不用担心,我们可以通过一些方法来克服它。
总结
SFT 模型能够在聊天中给出比较好的回答,并且提供一些有用信息;与之相比,PPO 模型的回答就简短得多。
这里所训练得到的模型相比 ChatGPT 还有较大的差距,需要从增加模型规模、提高数据质量和多样性、调优超参数等多个方面加以改进。
使用 FastChat 部署 LLM 推理服务
平台提供的 SimpleMLService 和 MLService 资源可以让用户方便地部署各种基于 LLM 的服务和应用。
FastChat 是一个训练、伺服和评估基于 LLM 的聊天机器人的开放平台,其提供多种伺服方式,包括命令行、Web UI、兼容 OpenAI 的 RESTful API 等。
本示例使用 SimpleMLService 和 FastChat 框架部署一个 LLM 推理服务。模型存储使用 PVC。
准备
在项目中创建一个名为 fastchat
、大小 50 GiB 以上的 PVC,然后创建一个同样名为 fastchat
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆 t9k/examples
仓库:
cd ~
git clone https://github.com/t9k/examples.git
然后从 Hugging Face Hub 或魔搭社区下载要部署的模型,这里以 chatglm3-6b 模型为例:
# 方法 1:如果可以直接访问 huggingface
huggingface-cli download THUDM/chatglm3-6b \
--local-dir chatglm3-6b --local-dir-use-symlinks False
# 方法 2:对于国内用户,访问 modelscope 网络连通性更好
pip install modelscope
python -c \
"from modelscope import snapshot_download; snapshot_download('ZhipuAI/chatglm3-6b')"
mv .cache/modelscope/hub/ZhipuAI/chatglm3-6b .
部署
这里使用 FastChat 部署兼容 OpenAI API 的服务器。
使用以下 YAML 配置文件创建 SimpleMLService:
cd examples/deployments/fastchat
kubectl create -f simplemlservice.yaml
监控服务是否准备就绪:
kubectl get -f simplemlservice.yaml -w
待其 READY
值变为 true
后,便可开始使用该服务。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。
使用推理服务
继续使用 Notebook 的终端,使用 curl
命令发送聊天或生成文本的请求:
address=$(kubectl get -f simplemlservice.yaml -ojsonpath='{.status.address.url}')
# 聊天
curl ${address}/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "chatglm3-6b",
"messages": [{"role": "user", "content": "你好"}],
"temperature": 0.5
}'
# 当前生成文本存在错误
返回的响应类似于:
响应
{
"id": "chatcmpl-3NXy9QnaD8FzH3PJrjaNVL",
"object": "chat.completion",
"created": 1708941050,
"model": "chatglm3-6b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好👋!我是人工智能助手 ChatGLM3-6B,很高兴见到你,欢迎问我任何问题。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 8,
"total_tokens": 38,
"completion_tokens": 30
}
}
为聊天增加 UI 界面
为了让聊天有一个简洁而美观的 UI 界面,我们可以使用 ChatGPT-Next-Web 提供的桌面客户端,在这里下载相应平台的安装包并进行安装。
继续使用 Notebook 的终端,获取 SimpleMLService 创建的服务的名称:
echo ${address} | cut -d'.' -f1
然后打开本地的终端,使用 t9k-pf 命令行工具,将该服务的 80 端口转发到本地的 8000 端口:
t9k-pf service <SERVICE_NAME> 8000:80 -n <PROJECT_NAME>
在桌面客户端的设置中,接口地址填写 http://127.0.0.1:8000
,自定义模型名填写 chatglm3-6b
并选择该模型,其他设置保持不变,就可以开始聊天了:
扩展:部署其他 LLM
我们可以使用同样的方法部署其他支持的模型,例如要将本示例部署的模型从 ChatGLM3-6B 换成 LLaMA2-7B-chat,只需:
- 下载 LLaMA2-7B-chat 的模型文件:
# 方法 1:如果可以直接访问 huggingface
# 需要登录
huggingface-cli download meta-llama/Llama-2-7b-chat-hf \
--local-dir Llama-2-7b-chat-hf --local-dir-use-symlinks False
# 方法 2:对于国内用户,访问 modelscope 网络连通性更好
pip install modelscope
python -c \
"from modelscope import snapshot_download; snapshot_download('shakechen/Llama-2-7b-chat-hf')"
mv .cache/modelscope/hub/shakechen/Llama-2-7b-chat-hf .
- 对 SimpleMLService 的 YAML 配置文件作以下修改,再次创建即可:
$ diff --color -u simplemlservice.yaml simplemlservice-llama2.yaml
--- simplemlservice.yaml
+++ simplemlservice-llama2.yaml
@@ -10,8 +10,8 @@
storage:
pvc:
name: fastchat
- subPath: chatglm3-6b
- containerPath: /workspace/chatglm3-6b
+ subPath: Llama-2-7b-chat-hf
+ containerPath: /workspace/llama2-7b-chat
service:
type: ClusterIP
ports:
@@ -23,7 +23,7 @@
- name: server
image: t9kpublic/fastchat-openai:20240227
args:
- - "chatglm3-6b"
+ - "llama2-7b-chat"
ports:
- containerPort: 80
resources:
参考
使用 vLLM 部署 LLM 推理服务
部署 LLM 推理服务面临着多方面的挑战,包括计算资源需求、延迟和吞吐量、成本控制等。vLLM 是一个快速、灵活且易于使用的 LLM 推理和服务库,其利用 PagedAttention 注意力算法优化注意力机制的键值存储,有效节约内存空间以用于批处理请求,从而显著提高服务的吞吐量。vLLM 能够有效控制运行成本,利用有限的计算资源为更多用户提供高吞吐量和低延迟的 LLM 推理服务。
本示例使用 MLService 和 vLLM 框架部署一个 LLM 推理服务。模型存储使用 PVC。
相比使用 FastChat 部署 LLM 推理服务,本示例使用了更高效的推理后端,以及可用于生产环境的 MLService。
准备
在项目中创建一个名为 vllm
、大小 30 GiB 以上的 PVC,然后创建一个同样名为 vllm
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆 t9k/examples
仓库:
cd ~
git clone https://github.com/t9k/examples.git
然后从 Hugging Face Hub 或魔搭社区下载要部署的模型,这里以 CodeLlama-7b-Instruct-hf 模型为例:
# 方法 1:如果可以直接访问 huggingface
huggingface-cli download codellama/CodeLlama-7b-Instruct-hf \
--local-dir CodeLlama-7b-Instruct-hf --local-dir-use-symlinks False
# 方法 2:对于国内用户,访问 modelscope 网络连通性更好
pip install modelscope
python -c \
"from modelscope import snapshot_download; snapshot_download('AI-ModelScope/CodeLlama-7b-Instruct-hf')"
mv .cache/modelscope/hub/AI-ModelScope/CodeLlama-7b-Instruct-hf .
部署
这里将 vLLM 部署为兼容 OpenAI API 的服务器,这样 vLLM 可以作为使用 OpenAI API 的应用程序的即插即用替代品。
使用以下 YAML 配置文件创建 MLServiceRuntime 和 MLService 以部署服务:
cd examples/deployments/vllm
kubectl apply -f mlservice-runtime.yaml
kubectl create -f mlservice.yaml
监控服务是否准备就绪:
kubectl get -f mlservice.yaml -w
待其 READY
值变为 true
后,便可开始使用该服务。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。
使用推理服务
继续使用 Notebook 的终端,使用 curl
命令发送聊天或生成文本的请求:
address=$(kubectl get -f mlservice.yaml -ojsonpath='{.status.address.url}')
# 聊天
curl ${address}/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "codellama-7b",
"messages": [{"role": "user", "content": "hello"}],
"temperature": 0.5
}'
# 生成文本
curl ${address}/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "codellama-7b",
"prompt": "Long long ago, there was",
"max_tokens": 100,
"temperature": 0.5
}'
返回的响应类似于:
响应
{
"id": "cmpl-5915c46dc6054ecfa4d57d07225c1264",
"object": "chat.completion",
"created": 5101130,
"model": "codellama-7b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": " Hello! It's nice to meet you. Is there something I can help you with or would you like to chat?"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 10,
"total_tokens": 37,
"completion_tokens": 27
}
}
{
"id": "cmpl-afbd703626c44a12ad192d0861fadd6e",
"object": "text_completion",
"created": 5101200,
"model": "codellama-7b",
"choices": [
{
"index": 0,
"text": " a time when the world was dark and cold, and little light entered.\n\nA young girl named Kanna was born in this world. She was born with a burden on her back.\n\nKanna grew up in a small village, surrounded by snow and ice. The villagers were poor, and they lived in miserable huts. They were cold and hungry all the time.\n\nBut Kanna was different. She had a special gift. She could make light",
"logprobs": null,
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 7,
"total_tokens": 107,
"completion_tokens": 100
}
}
编写代码
现在让它发挥自己的特长,写一个罗马数字转整数的 Python 程序。一次编写代码的聊天记录如下:
聊天记录
User:
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
- I can be placed before V (5) and X (10) to make 4 and 9.
- X can be placed before L (50) and C (100) to make 40 and 90.
- C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer.
Solve in Python:
class Solution:
def romanToInt(self, s: str) -> int:
CodeLlama-7b-Instruct-hf:
Here is a possible implementation of the romanToInt
function:
class Solution:
def romanToInt(self, s: str) -> int:
roman_numerals = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000
}
result = 0
for i in range(len(s)):
if i > 0 and roman_numerals[s[i]] > roman_numerals[s[i - 1]]:
result -= roman_numerals[s[i - 1]]
result += roman_numerals[s[i]]
return result
This implementation uses a dictionary to map each Roman numeral to its corresponding integer value. It then iterates over the characters in the input string, and for each character, it adds or subtracts the corresponding integer value depending on whether it is greater than or less than the previous character. The resulting integer value is returned at the end.
For example, if the input string is "XII"
, the function will first map the characters to their integer values:
X -> 10
I -> 1
I -> 1
Then it will add the values of the characters in order:
10 + 1 + 1 = 12
So the function will return 12
.
Note that this implementation assumes that the input string is a valid Roman numeral, and that it does not contain any invalid characters. If the input string contains invalid characters, the function will raise a KeyError
exception. You can add error handling to the function as needed to handle such cases.
得益于 vLLM 提供的高吞吐量推理服务,该解答的生成仅用了 6s,然而并不正确,未能通过 LeetCode 的测试。
顺带一提,使用相同的 prompt(由于 CodeLlama-7b-Python-hf 未经过指令微调,prompt 的格式略有不同),CodeLlama-13b-Instruct-hf 和 CodeLlama-7b-Python-hf 提供的解答可以通过,GPT 3.5、GPT-4 和 Bard 提供的解答也都可以通过。
用户可以自行尝试部署更大的 Code Llama 系列模型,并让其编写更加复杂的代码。
扩展:部署其他 LLM
我们可以使用同样的方法部署其他支持的模型,例如要将本示例部署的模型从 CodeLlama-7b-Instruct-hf 换成 Mistral-7B-Instruct-v0.1,只需:
- 下载 Mistral-7B-Instruct-v0.1 的模型文件:
# 方法 1:如果可以直接访问 huggingface
# 需要登录
huggingface-cli download mistralai/Mistral-7B-Instruct-v0.1 \
--local-dir Mistral-7B-Instruct-v0.1 --local-dir-use-symlinks False
# 方法 2:对于国内用户,访问 modelscope 网络连通性更好
pip install modelscope
python -c \
"from modelscope import snapshot_download; snapshot_download('AI-ModelScope/Mistral-7B-Instruct-v0.1')"
mv .cache/modelscope/hub/AI-ModelScope/Mistral-7B-Instruct-v0___1 ./Mistral-7B-Instruct-v0.1
- 对 MLService 的 YAML 配置文件作以下修改,再次创建即可:
$ diff --color -u mlservice.yaml mlservice-mistral.yaml
--- mlservice.yaml
+++ mlservice-mistral.yaml
@@ -1,22 +1,22 @@
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
- name: codellama-7b
+ name: mistral-7b
spec:
# scheduler:
# t9kScheduler:
# queue: default
- default: codellama-7b
+ default: mistral-7b
releases:
- - name: codellama-7b
+ - name: mistral-7b
predictor:
minReplicas: 1
model:
runtime: vllm-openai
parameters:
MODEL_PATH: /var/lib/t9k/model
- MODEL_NAME: codellama-7b
- modelUri: pvc://vllm/CodeLlama-7b-Instruct-hf
+ MODEL_NAME: mistral-7b
+ modelUri: pvc://vllm/Mistral-7B-Instruct-v0.1
containersResources:
- name: user-container
resources:
参考
使用 Triton 部署 Hugging Face 模型(Python 后端)
Triton Inference Server 是一个开源的推理服务软件,旨在简化 AI 推理流程。Triton 使用户能够部署多种深度学习框架的模型,包括 TensorRT、TensorFlow、PyTorch、ONNX、OpenVINO 等。Triton 支持在云、数据中心、边缘和嵌入式设备的 NVIDIA GPU、x86 CPU 和 ARM CPU 上进行推理。Triton 为许多查询类型提供了优化的性能,包括实时、批处理、集成和音频/视频流。
Hugging Face 是一个 AI 开源社区,其提供的代码库托管了大量流行的开源模型。凭借 Python 后端所提供的灵活性,Triton 可以部署几乎任何来自 Hugging Face 的模型。
本示例使用 MLService,以及 Triton 推理服务器和它的 Python 后端部署一个 Hugging Face 模型的推理服务。模型存储使用 PVC。
准备
在项目中创建一个名为 triton-python
、大小 50 GiB 以上的 PVC,然后创建一个同样名为 triton-python
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆 t9k/examples
仓库:
cd ~
git clone https://github.com/t9k/examples.git
使用预制的模型仓库:
cp -R examples/deployments/triton-python/python_model_repository .
然后从 Hugging Face Hub 下载要部署的模型,这里以 vit-base-patch16-224-in21k 模型为例:
huggingface-cli download google/vit-base-patch16-224-in21k \
--local-dir vit-base-patch16-224-in21k --local-dir-use-symlinks False
部署
使用以下 YAML 配置文件创建 MLServiceRuntime 和 MLService 以部署服务:
cd examples/deployments/triton-python
kubectl apply -f mlservice-runtime.yaml
kubectl create -f mlservice.yaml
监控服务是否准备就绪:
kubectl get -f mlservice.yaml -w
待其 READY
值变为 true
后,便可开始使用该服务。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。
使用推理服务
继续使用 Notebook 的终端,使用作为推理客户端的 Python 脚本发送推理请求:
address=$(kubectl get -f mlservice.yaml -ojsonpath='{.status.address.url}' | sed 's#^https\?://##')
pip install tritonclient gevent geventhttpclient
python client.py --server_address $address --model_name python_vit
该脚本从指定 URL 下载一个图像文件(如上图所示),将其转换为 NumPy 数组,然后发送到推理服务器;从返回的响应中取出 last_hidden_state
,即 Transformer 最后一层的输出张量,打印其值和形状。输出应类似于:
[[[ 0.2463658 0.12966464 0.13196409 ... -0.12697077 0.08220191
-0.1261508 ]
[ 0.10375027 0.15543337 0.14776552 ... -0.09246814 0.10163841
-0.31893715]
[ 0.04861938 0.15119025 0.14414431 ... -0.08075114 0.0719012
-0.32684252]
...
[ 0.2877585 0.15052384 0.17233661 ... -0.07538544 0.05114003
-0.19613911]
[ 0.21476139 0.17660537 0.14951637 ... -0.09027394 0.0747345
-0.31565955]
[ 0.2561764 0.16620857 0.13983792 ... -0.06043544 0.08778334
-0.14347576]]]
(1, 197, 768)
最后一层的输出张量可以作为图像的整体表示,进一步用于分类、图像识别等下游任务。我们可以在这样一个推理客户端示例的基础上进一步开发 AI 应用。
参考
- GitHub 上的 Triton Inference Server
- Triton 官方教程:Deploying HuggingFace models
- Triton Python 后端
- Hugging Face
使用 Tensorizer 加速模型部署
在部署模型的过程中,加载模型尤其是大模型往往耗时很长。对此,CoreWeave 发布了 Tensorizer 用于模型和张量的序列化和反序列化。它能以更少的资源和更快的速度加载模型。
TensorStack 提供的 SimpleMLService 和 MLService 可以让用户方便地部署各种模型。
本示例通过 MLService 部署 GPT-J-6B 模型,并使用 Tensorizer 加速模型加载。
准备
在项目中创建一个名为 tensorizer
、大小为 50GiB 以上的 PVC,然后创建一个同样名为 tensorizer
的 Notebook 挂载该 PVC,镜像选择带有 sudo 权限的类型,资源不限(如要使用远程操作,请开启 SSH)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆必要的仓库:
# change to mount point of PVC `tensorizer`, defaults to /t9k/mnt, and also $HOME
cd ~
git clone https://github.com/t9k/examples.git
下载模型
Tensorizer 以 “tensor streaming” 的形式加载模型,从而以更少的资源和更快的速度加载模型。这需要用户首先以 Tensorizer 支持的形式来保存模型。通过运行以下命令创建一个 GenericJob
来下载并保存模型:
# 切换到正确目录
cd ~/examples/inference/tensorizer
kubectl apply -f ./download-job.yaml
在该 GenericJob 中,我们先使用国内模型平台 ModelScope 来下载 GPT-J-6B 模型,然后将模型转换为 CoreWeave Tensorizer 所需的格式,并保存到 PVC 中,代码细节见 model_download.py
。
部署推理服务
待模型下载的任务结束后,便可以开始部署服务。首先创建 MLServiceRuntime
,MLServiceRuntime 定义了部署服务的 Pod 模版,此处所定义的 Pod 模版会使用 Tensorizer 加载环境变量 MODEL_PATH
所指定的路径中的模型文件:
kubectl apply -f ./runtime.yaml
然后部署 MLService
,MLService 会指定要使用的 MLServiceRuntime
以及要挂载的模型。此处我们使用下载模型中 PVC 里所保存的模型文件:
kubectl apply -f ./mlservice.yaml
部署后进入模型部署控制台的 MLService 页面,可以看到名为 tensorizer-gptj 的 MLService,稍等片刻,等其进入 Ready 状态:
使用推理服务
你可以直接使用命令行工具访问 MLService 的预测服务。运行命令获取 MLService 的 URL:
url=$(kubectl get mlservice tensorizer-gptj -o jsonpath='{.status.address.url}') && echo $url
发送推理请求:
curl ${url}/v1/models/gptj:predict -X POST -H 'Content-Type: application/json' -d '{"instances": ["Once upon a time, there was"]}'
返回的响应类似于:
{
"predictions":["Once upon a time, there was a happy prince…\n\nFaced with a constant barrage of attacks from enemies, this happy prince decided to launch a counterattack and create his own military kingdom. He created a country called Fairy Tail, where no dragon is found, but all dragon"]
}
扩展
上述示例演示了如何下载以及部署 GPT-J-6B 大模型。用户可以参考制作 Tensorizer 相关的镜像将 Tensorizer 用于自定义模型的部署。
参考
- CoreWeave Tensorizer 介绍
- API 参考:MLService
使用 AutoGen 构建下一代 LLM 应用
LLM 所展现出的推理、规划、指令遵循、上下文学习和工具使用等多项能力,使得它们成为目前开发强大 AI 智能体 (AI Agent)的首选。一些基于这样的智能体构建的 AI 应用已经出现,例如 ChatGPT + Wolfram Alpha 插件可以解答数学问题,AutoGPT 可以自主达成用户给定的目标,等等。最近公开的 AutoGen 框架引入了多智能体对话(multi-agent conversation)机制,为构建 AI 应用提供了高效实现和高度可扩展性。
本教程演示几个基于 AutoGen 框架构建的简单应用。这些应用分别采用了 OpenAI 的 GPT 系列模型以及开源的 LLM 作为智能体的后端,前者通过调用 OpenAI 的官方 API 实现,后者则是接入使用 SimpleMLService 部署的 LLM 推理服务。
应用的代码被放置在 https://github.com/t9k/examples/tree/v20240206/applications/autogen,用户可参照 README 自行尝试。这里推荐用户在 Notebook 中运行应用示例的 .ipynb
文件;如要使用开源模型作为智能体后端,请参阅部署 LLM 聊天机器人进行本地部署。
AutoGen 框架
我们希望基于 LLM 的智能体能够帮助人类完成现实世界中的复杂任务,但即便是当下最强大的 GPT-4 模型,也在许多场景下表现不佳。为了提升智能体解决问题的能力,除了提升单个智能体的表现,另一种直观的思路是使用多个智能体进行分工合作,分解复杂任务并各自承担一个专业的子任务。现有研究表明,多个智能体有助于鼓励不同的思考方式,提高推理能力,提供验证以提高正确性。就像人类一样,团队合作能够实现许多个人难以独立达成的成就。
论文 《AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation》提出了多智能体对话框架 AutoGen,其基本原理如下:
- 提供通用的可对话智能体抽象,智能体有统一的对话接口,由 LLM、人类、(由 Python 代码实现的)外部工具或它们的组合驱动,可自定义和扩展行为,可重用。
- LLM 应用的工作流被统一为多智能体的对话流,开发应用的过程即为:(1) 定义一组各自有特定能力和角色的可对话智能体;(2) 通过程序语言(Python 代码)和自然语言(LLM 的系统信息(system message)、指令等)控制智能体自身的计算以及智能体之间的对话流。
AutoGen 框架提供的灵活性超越了目前其他框架或系统(如 AutoGPT、LangChain Agent、CAMEL 等),适用于构建各种形式、领域和复杂度的应用。
应用一:解数学题
在第一个应用中,我们使用 MathChat 框架解答数学问题。
为该应用编写的部分 AutoGen 代码如下,其中定义了智能体 user_proxy 和 assistant。前者负责初始化对话(MathUserProxyAgent 封装了解答数学问题的 prompt,见下面的日志),以及执行 Python 代码并返回结果(所有 UserProxyAgent 均有执行 Python 代码的功能);后者负责解答问题(使用了默认的系统信息):
user_proxy = MathUserProxyAgent(
name="user_proxy",
human_input_mode="NEVER",
)
assistant = autogen.AssistantAgent(
name="assistant",
system_message="你是一个提供帮助的助手。",
llm_config={
"request_timeout": 600,
"seed": 42,
"config_list": config_list,
}
)
math_problem = "[数学问题]"
user_proxy.initiate_chat(assistant, problem=math_problem)
通过修改 config,智能体可以使用由 OpenAI 提供的 gpt-4、gpt-3.5-turbo 等 API,或者由 FastChat 本地部署的开源模型作为 LLM 后端。数学问题如下:
- 任务 1:找到满足不等式 的所有 ,并以区间表示答案。
- 任务 2:当 取何负值时,以下方程组存在恰好一个解?
使用 gpt-4 后端执行任务 1,整个过程的日志如下,最终回答正确:
日志
user_proxy (to assistant):
让我们使用 Python 来解决一个数学问题。
查询要求:
- 对于输出,应始终使用 ‘print’ 函数,并使用分数 / 根式形式而不是小数。
- 您可以使用诸如 sympy 之类的包来帮助您。
- 您必须遵循以下格式来编写您的代码:
# your code
首先陈述解决问题的关键思想。您可以选择以下三种方式来解决问题: 情况 1:如果问题可以直接用 Python 代码解决,请编写一个程序来解决它。如果需要,您可以枚举所有可能的排列。 情况 2:如果问题主要是基于推理,您可以直接解决它。 情况 3:如果问题不能用以上两种方式处理,请按照以下过程进行:
- 逐步解决问题(不要过于细分步骤)。
- 挑选出可以通过 Python 询问的任何查询(例如,可以计算的任何计算或方程式)。
- 等待我提供结果。
- 如果您认为结果正确,请继续。如果结果无效或不符合预期,请更正您的查询或推理。
在运行所有查询并获得答案后,将答案放入 \boxed {} 中。
问题: 找到满足不等式 (2x+10)(x+3)<(3x+9)(x+8) 的所有 x,并以区间表示答案。
assistant (to user_proxy):
解决这个问题的关键思想是首先简化不等式。然后,通过将其化为零来找到简化表达式的临界点。一旦我们有了临界点,我们将在由这些点确定的每个区间中评估原始不等式。不等式成立的区间将是我们的解集。
具体的步骤如下:
- 展开不等式两侧并将其简化为 的形式。
- 解方程 以找到临界点。
- 确定由临界点确定的区间中不等式 成立的区间。
我们可以使用 Python 执行所有这些步骤。让我们编写程序来执行这些操作。我们将使用 sympy 库来进行符号计算。
from sympy import *
x = symbols('x')
# 定义不等式
inequality = (2*x + 10)*(x + 3) - (3*x + 9)*(x + 8)
# 展开和简化不等式
simplified_inequality = simplify(inequality)
# 通过解方程f(x) = 0来找到临界点
critical_points = solve(simplified_inequality, x)
# 对临界点进行排序,然后添加 -oo 和 +oo 形成实线上的区间
intervals = [-oo, *sorted(critical_points), oo]
# 在每个区间中评估简化的不等式,
# 如果成立,该区间是解的一部分
solution_set = [] # 采用了复杂的解法
for i in range(len(intervals) - 1):
mid_point = (intervals[i] + intervals[i+1]) / 2
if simplified_inequality.subs(x, mid_point) < 0:
solution_set.append((intervals[i], intervals[i+1]))
print(solution_set)
运行这段代码,输出将是给定不等式中 的解集,以区间表示。
user_proxy (to assistant):
[(-oo, -14), (-3, oo)]
assistant (to user_proxy):
不等式 的解是 。
换用其他 LLM 作为 Assistant 的后端能否解决这些数学问题?这里实验了 gpt-3.5-turbo、meta-llama/Llama-2-70b-chat-hf、meta-llama/Llama-2-13b-chat-hf、Qwen/Qwen-14B-Chat,结果汇总如下:
模型 | 任务 1 | 任务 2 | 失败原因 |
---|---|---|---|
gpt-4 | ✅ | ✅ | |
gpt-3.5-turbo | ❌ | ✅ | 代数计算出错 |
meta-llama/Llama-2-70b-chat-hf | ❌ | ❌ | 代数计算出错,代码编写出错(不会使用 sympy 包) |
meta-llama/Llama-2-13b-chat-hf | ❌ | ❌ | 代数计算出错,指令遵循存在问题 |
Qwen/Qwen-14B-Chat | ❌ | ✅ | 代数计算出错 |
由此可见,gpt-4 的数学能力相较于这些有代表性的开源模型遥遥领先。
应用二:文档问答
在第二个应用中,LLM 需要根据从向量数据库检索得到的上下文回答用户提出的问题。
为该应用编写的 AutoGen 代码如下,其中定义了智能体 user_proxy 和 assistant,前者在对话之外负责构建和检索向量数据库(定义中包含一些相关配置),在对话当中负责提供 prompt、问题和上下文,后者回答问题:
user_proxy = RetrieveUserProxyAgent(
name="user_proxy",
human_input_mode="NEVER",
max_consecutive_auto_reply=10,
retrieve_config={
"task": "qa",
"docs_path": "local_path_or_url_of_docs",
"chunk_token_size": 2000,
"model": config_list[0]["model"],
"client": chromadb.PersistentClient(path="./tmp/chromadb"),
"collection_name": "natural-questions",
"chunk_mode": "one_line",
"embedding_model": "all-MiniLM-L6-v2",
},
)
assistant = RetrieveAssistantAgent(
name="assistant",
system_message="你是一个提供帮助的助手。",
llm_config={
"request_timeout": 600,
"seed": 42,
"config_list": config_list,
},
)
question = "[提出的问题]"
user_proxy.initiate_chat(assistant, problem=question, n_results=30)
这里准备了两个任务:
任务 1:根据 NaturalQuestionsQA 语料库,回答下列问题:
No. | 问题 | 正确答案 |
---|---|---|
1 | what is non controlling interest on balance sheet | the portion of a subsidiary corporation’s stock that is not owned by the parent corporation |
2 | how many episodes are in chicago fire season 4 | 23 |
3 | what are bulls used for on a farm | breeding, as work oxen, slaughtered for meat |
4 | who has been honoured with the wisden leading cricketer in the world award for 2016 | Virat Kohli |
5 | who carried the usa flag in opening ceremony | Erin Hamlin |
任务 2:根据比亚迪 2023 年上半年财报,回答下列问题:
No. | 问题 | 正确答案 |
---|---|---|
1 | 公司是否计划派发现金红利? | 公司计划不派发现金红利。 |
2 | 集团在八月达成的里程碑是什么? | 本集团第500万辆新能源汽车下线,成为全球首家达成这一里程碑的车企。 |
3 | 公司的主管会计工作负责人是谁? | 周亚琳 |
4 | 公司的 2023 年上半年的归母净利润为多少元? | 10,954,145,000元 |
5 | 王传福的持股比例是多少? | 17.64% |
使用 gpt-4 后端执行任务 2 的问题 1,整个过程的日志如下,最终回答正确:
日志
doc_ids: [[‘doc_460’, ‘doc_1461’, ‘doc_4853’, ‘doc_4871’, ‘doc_1582’, ‘doc_1439’, ‘doc_1374’, ‘doc_2312’, ‘doc_1584’, ‘doc_512’, ‘doc_6188’, ‘doc_2324’, ‘doc_1577’, ‘doc_2314’, ‘doc_1444’, ‘doc_14’, ‘doc_3357’, ‘doc_1336’, ‘doc_6106’, ‘doc_1948’, ‘doc_1588’, ‘doc_1587’, ‘doc_4898’, ‘doc_439’, ‘doc_1448’, ‘doc_2308’, ‘doc_5452’, ‘doc_6186’, ‘doc_6166’, ‘doc_536’]] Adding doc_id doc_460 to context. Adding doc_id doc_1461 to context. Adding doc_id doc_4853 to context. Adding doc_id doc_4871 to context. Adding doc_id doc_1582 to context. Adding doc_id doc_1439 to context. Adding doc_id doc_1374 to context. Adding doc_id doc_2312 to context. Adding doc_id doc_1584 to context. Adding doc_id doc_512 to context. Adding doc_id doc_6188 to context. Adding doc_id doc_2324 to context. Adding doc_id doc_1577 to context. Adding doc_id doc_2314 to context. Adding doc_id doc_1444 to context. Adding doc_id doc_14 to context. Adding doc_id doc_3357 to context. Adding doc_id doc_1336 to context. Adding doc_id doc_6106 to context. Adding doc_id doc_1948 to context. Adding doc_id doc_1588 to context. Adding doc_id doc_1587 to context. Adding doc_id doc_4898 to context. Adding doc_id doc_439 to context. Adding doc_id doc_1448 to context. Adding doc_id doc_2308 to context. Adding doc_id doc_5452 to context. Adding doc_id doc_6186 to context. Adding doc_id doc_6166 to context. Adding doc_id doc_536 to context. ragproxyagent (to assistant):
You’re a retrieve augmented chatbot. You answer user’s questions based on your own knowledge and the
context provided by the user.
If you can’t answer the question with or without the current context, you should reply exactly UPDATE CONTEXT
.
You must give as short an answer as possible.
User’s question is: 公司是否计划派发现金红利?
Context is: 公司报告期无募集资金使用情况。
限 公 司 各 项 经 济 损 失
母公司股东 归属于
母公司股东 归属于
公司控股的财务公司与关联方之间不存在存款、贷款、授信或其他金融业务。
公司报告期不存在控股股东及其 他关联方对上市公司的非经营性占用资金。
沙分公司 废气 氮氧化
公司报告期控股股东未发生变更。
公司报告期无其他重大关联交易。
公司计划半年度不派发现金红利,不送红股,不以公积金转增股本。
限公司 房屋
公司半年度财务报告未经审计。
公司报告期不存在关联债权债务往来。
公司报告期实际控制人未发生变更。
公司半年度报告未经审计。
公司计划不派发现金红利,不送红股,不以公积金转增股本。
本公司的现金股利,于股东大会批准后确认为负债。
公司 废气 颗粒物 有组织
公司名称 与本企业关系
有限公司办理存款业务暨关
公司报告期不存在承包情况。
公司报告期不存在托管情况。
本公司在提取法定盈余公积金后,可提取任意公积金。经批准,任意公积金可用于弥补以前年度亏损或增加
明 公司为规避日常经营中所面临的汇率、利率风险,通过操作金融衍生品对实际持有的风险敞口进
公司报告期未发生破产重整相关事项。
公司秘书 现任 27,500 27,500
重庆弗迪锂电池有限公司
能源汽车有限公司 房屋
公司 接受劳务及购买水电燃气
公司员工持股计划在 2023年半年度费用摊销金额请详见“第十节财务报告 -十三.股份支付”相关内容。
assistant (to ragproxyagent):
否
同样地,我们使用 gpt-4、gpt-3.5-turbo、meta-llama/Llama-2-13b-chat-hf、Qwen/Qwen-14B-Chat 分别作为 Assistant 的后端,结果汇总如下(人工打分,回答正确一个问题得 1 分,回答不完整得小于 1 分,总分均为 5 分):
模型 | 任务 1 | 任务 2 | 失败原因 |
---|---|---|---|
gpt-4 | 4.8 | 4 | 向量数据库未返回相关上下文,归纳不完整 |
gpt-3.5-turbo | 3.5 | 4 | 向量数据库未返回相关上下文,归纳不完整,从上下文寻找信息的能力不足 |
meta-llama/Llama-2-13b-chat-hf | 2 | 0 | 从上下文寻找信息的能力弱,允许的上下文长度较短,不能理解问题 |
Qwen/Qwen-14B-Chat | 1.8 | 0 | 从上下文寻找信息的能力弱,归纳不完整 |
可以看到这些开源模型的自然语言能力也不及 gpt 系列模型。
应用三:可视化数据(群聊)
在第三个应用中,我们让 LLM 编写代码以可视化表格数据。
和前两个应用不同的是,这里我们采用动态群聊(dynamic group chat)的方法来完成任务,通过:
- 引入 3 个智能体:User Proxy 负责初始化对话,执行 Python 代码并返回结果,以及传入用户的发言;Coder 负责计划和编写代码;Critic 提出一般性的评价和改进建议,系统信息指定了 Critic 的角色并给出了详细的评估维度和标准。
- 引入 1 个 GroupChat 的 Manager,Manager 的作用是在每一轮当中根据对话历史挑选 1 个智能体发言,并将其发言内容广播给其他智能体,即“主持群聊”。
- 对于 UserProxyAgent 设置 human_input_mode=“ALWAYS”,这样每当 Manager 选取 User Proxy 发言,用户都可以提出自己的想法、需求或意见。
在代码中,我们定义了智能体 user_proxy、coder 和 critic,包含这些 agent 的 groupchat,以及 groupchat 的 manager,最后传入任务描述(prompt)以初始化对话。
user_proxy = autogen.UserProxyAgent(
name="User_Proxy",
system_message="人类管理员",
code_execution_config={"last_n_messages": 3, "work_dir": "groupchat"},
human_input_mode="ALWAYS",
is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE")
)
coder = autogen.AssistantAgent(
name="Coder", # 默认的 assistant agent 就可以编写代码
llm_config=llm_config,
)
critic = autogen.AssistantAgent(
name="Critic",
system_message="""评论员。您是一个非常擅长评估给定可视化代码质量的有益助手,通过提供从 1(差)到 10(好)的评分,并提供清晰的理由。在每个评估中,您必须考虑可视化最佳实践。具体来说,您可以仔细评估代码的以下维度:(后略)""",
llm_config=llm_config,
)
groupchat = autogen.GroupChat(agents=[user_proxy, coder, critic], messages=[], max_round=20)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)
user_proxy.initiate_chat(manager, message="从 https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv 下载数据,绘制中、美、日、德、英、法、印七个国家从 2000 年到 2016 年的名义 GDP 折线图(以美元计价),要求折线图有网格线,图例放置在左上角。将图片保存为文件。接受来自 critic 的反馈并改进代码。")
鉴于 gpt-4 无可匹敌的强大能力,这里仅使用 gpt-4 作为智能体的后端。一次具体的对话的日志如下:
日志
User_proxy (to chat_manager):
从 https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv 下载数据,绘制中、美、日、德、英、法、印七个国家从 2000 年到 2016 年的名义 GDP 折线图(以美元计价),要求折线图有网格线,图例放置在左上角。将图片保存为文件。接受来自 critic 的反馈并改进代码。
Coder (to chat_manager):
理解您的需求,这是需要执行的步骤:
- 首先,我们需要下载数据集文件。
- 然后,所需要的包 pandas 和 matplotlib 都要安装到 Python 环境,用于数据处理和绘图。
- 下一步,通过 pandas 库解析下载的 csv 文件。
- 然后,我们需要筛选我们关注的七个国家(中国、美国、日本、德国、英国、法国、印度)自 2000 年到 2016 年的数据。
- 最后,我们使用 matplotlib 绘制折线图,并保存到文件。
请执行以下 Python 代码以完成前两个步骤,我会根据反馈执行后续步骤。
# filename: plot_gdp.py
import os
import pandas as pd
import matplotlib.pyplot as plt
# 下载数据集
data_url = "https://raw.githubusercontent.com/datasets/gdp/master/data/gdp.csv"
data_file = "gdp.csv"
os.system(f"wget {data_url} -O {data_file}")
# 读取数据集
data = pd.read_csv(data_file)
print(data.head()) # 打印数据集前5行,用于检查数据
######## NO HUMAN INPUT RECEIVED.
######## USING AUTO REPLY…
######## EXECUTING CODE BLOCK 0 (inferred language is python)… User_proxy (to chat_manager):
exitcode: 0 (execution succeeded) Code output: Country Name Country Code Year Value 0 Arab World ARB 1968 2.576068e+10 1 Arab World ARB 1969 2.843420e+10 2 Arab World ARB 1970 3.138550e+10 3 Arab World ARB 1971 3.642691e+10 4 Arab World ARB 1972 4.331606e+10
Coder (to chat_manager):
从执行结果可以看到,数据集已经成功下载并读取。数据有四个字段:Country Name(国家名),Country Code(国家代码),Year(年份)和 Value(GDP 值)。
下一步,我们需要筛选出需要的数据。具体来说,我们只需要中国、美国、日本、德国、英国、法国、印度从 2000 年到 2016 年的 GDP 数据。
请运行以下 Python 代码块以完成这个步骤。
# filename: plot_gdp.py
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据集
data = pd.read_csv("gdp.csv")
# 筛选七个国家的数据
countries = ["China", "United States", "Japan", "Germany", "United Kingdom", "France", "India"]
data = data[data["Country Name"].isin(countries)]
# 筛选 2000 年到 2016 年的数据
data = data[(data["Year"] >= 2000) & (data["Year"] <= 2016)]
# 只保留我们关注的列
data = data[["Country Name", "Year", "Value"]]
print(data.head()) # 打印数据集前5行,用于检查数据
######## NO HUMAN INPUT RECEIVED.
######## USING AUTO REPLY…
######## EXECUTING CODE BLOCK 0 (inferred language is python)… User_proxy (to chat_manager):
exitcode: 0 (execution succeeded) Code output: Country Name Year Value 4086 China 2000 1.211347e+12 4087 China 2001 1.339396e+12 4088 China 2002 1.470550e+12 4089 China 2003 1.660288e+12 4090 China 2004 1.955347e+12
Coder (to chat_manager):
通过执行结果可以看到,我们已经成功地筛选出了七个国家从 2000 年到 2016 年的 GDP 数据。
接下来,我将使用 matplotlib 来绘制这些数据的折线图,并将图像保存为文件。
绘制图像的代码如下,请执行。
# filename: plot_gdp.py
import pandas as pd
import matplotlib.pyplot as plt
#读取数据集
data = pd.read_csv("gdp.csv")
#选择七个国家的数据
countries = ["China", "United States", "Japan", "Germany", "United Kingdom", "France", "India"]
data = data[data["Country Name"].isin(countries)]
#选择2000年到2016年的数据
data = data[(data["Year"] >= 2000) & (data["Year"] <= 2016)]
# 只保留我们关注的列
data = data[["Country Name", "Year", "Value"]]
# 绘制折线图
plt.figure(figsize=(10, 8))
for country in countries:
country_data = data[data["Country Name"] == country]
plt.plot(country_data["Year"], country_data["Value"], label=country)
plt.grid() # 添加网格线
plt.legend(loc='upper left') # 图例放置在左上角
plt.xlabel('Year')
plt.ylabel('GDP in US Dollars')
plt.title('GDP of Seven Countries from 2000 to 2016')
# 保存图片
plt.savefig("gdp_plot.png")
Critic (to chat_manager):
基于您提供的代码,以下是我的评估:
-
错误(Bugs):10分 您的代码没有语法错误、逻辑错误或拼写错误,能够正常运行并符合功能需求。
-
数据转换(Transformation):10分 您适当地筛选了数据,只保留了指定的七个国家从 2000年到2016年的GDP数据。您也正确地转换了数据以适应折线图的画图方式。
-
目标符合度(Compliance):10分 您的代码完全符合提出的可视化目标:绘制七个指定国家从2000年到2016年的GDP折线图,并且添加了网格线和图例。
-
可视化类型(Type):10分 您选择的折线图是一种合适的可视化类型,用于展示一段时间内GDP的变化情况。
-
数据编码(Encoding):10分 您正确地绘制了折线图,横坐标表示年份,纵坐标表示GDP。
-
美学(Aesthetics):10分 您的可视化具有良好的美感,图例清晰,颜色稳重,有利于理解数据。
总体来说,这是一个能够满足需求,实现功能,且无明显改进空间的严谨的代码。
具体行动清单:
- 代码已经很好,没有需要修改的部分。继续保持!
######## NO HUMAN INPUT RECEIVED.
######## USING AUTO REPLY…
######## EXECUTING CODE BLOCK 0 (inferred language is python)… User_proxy (to chat_manager):
exitcode: 0 (execution succeeded) Code output:
Coder (to chat_manager):
既然代码已经成功执行,并且获得了评价人的高度评价,我们成功地完成了任务。您可以在您的工作目录中找到名为 “gdp_plot.png” 的折线图文件。这张图片显示了从 2000 年到 2016 年,中国、美国、日本、德国、英国、法国、印度七个国家的 GDP 变化情况。
非常感谢你的帮助,让我知道如果你有其他需要帮助的地方。TERMINATE
Critic (to chat_manager):
很高兴能帮助到您完成任务。如果您有任何其他编码或数据可视化需求,欢迎随时回来。期待与您再次合作,祝您一切顺利。TERMINATE
User_proxy (to chat_manager):
折线图的左上角有一个“1e13“的标记,这是因为纵轴的单位为一美元,请将其修改为十亿美元
Coder (to chat_manager):
明白了,您希望将 GDP 的单位从美元修改为十亿美元,以便更直观地理解图表。这意味着我们需要调整 Value 列的值,将其除以 10 的 9 次方(这是因为 1 十亿等于 10 的 9 次方)。然后我们也需要在 y 轴的标题中反映这一点。
请运行以下代码来生成新的图像。
# filename: plot_gdp.py
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据集
data = pd.read_csv("gdp.csv")
# 筛选七个国家的数据
countries = ["China", "United States", "Japan", "Germany", "United Kingdom", "France", "India"]
data = data[data["Country Name"].isin(countries)]
# 筛选 2000 年到 2016 年的数据
data = data[(data["Year"] >= 2000) & (data["Year"] <= 2016)]
# 将 GDP 的单位从美元修改为十亿美元,以便直观理解图表
data["Value"] = data["Value"] / (10 ** 9)
# 只保留我们关注的列
data = data[["Country Name", "Year", "Value"]]
# 绘制折线图
plt.figure(figsize=(10, 8))
for country in countries:
country_data = data[data["Country Name"] == country]
plt.plot(country_data["Year"], country_data["Value"], label=country)
plt.grid() # 添加网格线
plt.legend(loc='upper left') # 图例放置在左上角
plt.xlabel('Year')
plt.ylabel('GDP in Billion US Dollars') # 更新 y 轴标题
plt.title('GDP of Seven Countries from 2000 to 2016')
# 保存图片
plt.savefig("gdp_plot_billion.png")
######## NO HUMAN INPUT RECEIVED.
######## USING AUTO REPLY…
######## EXECUTING CODE BLOCK 0 (inferred language is python)… User_proxy (to chat_manager):
exitcode: 0 (execution succeeded) Code output:
Critic (to chat_manager):
基于您提供的代码,以下是我的评估:
-
错误(Bugs):10分 您的代码没有语法错误、逻辑错误或拼写错误,能够正常运行并符合功能需求。
-
数据转换(Transformation):10分 您正确地将 GDP 的单位从美元修改为了十亿美元,以便更直观地理解图表,这是一种恰当的数据转换方式。
-
目标符合度(Compliance):10分 您的代码完全符合提出的可视化目标:绘制七个指定国家从2000年到2016年的 GDP 折线图,并且添加了网格线和图例,且以十亿美元为单位。
-
可视化类型(Type):10分 您选择的折线图是一种合适的可视化类型,可以展示一段时间内 GDP 的变化情况。
-
数据编码(Encoding):10分 您正确地绘制了折线图,横坐标为年份,纵坐标为 GDP(现已调整为十亿美元)。
-
美学(Aesthetics):10分 您的可视化同样具有良好的美感,单位的更改使得读取更为友好,图例清晰,颜色稳重,有利于理解和展示数据。
总体来说,这是一个能够满足需求,实现功能,且无明显改进空间的宏观经济数据可视化代码。
具体行动清单:
- 代码已经很好,没有需要修改的部分。继续保持!
######## NO HUMAN INPUT RECEIVED.
######## USING AUTO REPLY…
######## EXECUTING CODE BLOCK 0 (inferred language is python)… User_proxy (to chat_manager):
exitcode: 0 (execution succeeded) Code output:
Coder (to chat_manager):
既然代码已经成功执行,并且已经根据您的要求进行了更新,我们已经成功完成了任务。您可以在您的工作目录中找到名为 “gdp_plot_billion.png” 的折线图文件。这张图片显示了从 2000 年到 2016 年,中国、美国、日本、德国、英国、法国、印度七个国家的 GDP 变化情况,单位是十亿美元。
非常感谢你的帮助,让我知道如果你有其他需要帮助的地方。TERMINATE
Critic (to chat_manager):
很高兴能够帮助您完成任务。如果您对 Python 编程或数据可视化有任何其他问题或需求,欢迎您随时提问。期待与您再次合作,祝您一切顺利。TERMINATE
######## NO HUMAN INPUT RECEIVED.
这是第一版生成的图片:
用户提出的改进建议是“折线图的左上角有一个“1e13“的标记,这是因为纵轴的单位为一美元,请将其修改为十亿美元”,于是 Coder 修改得到第二版:
在 Manager 的 GroupChat 管理以及 User Proxy、Coder 和 Critic 的协作之下(尽管在这次运行中 Critic 并未提出改进意见),应用迭代出了更加准确、美观并且符合用户需求的可视化结果。
总结
经过上面几个简单应用的实验,我们可以获得如下总结和思考:
- 根据应用一和应用二的实验结果,能力更强的模型(gpt-4)可以使应用在任务中取得显著更好的表现。换言之,LLM 的(应用相关)能力是应用能否解决具体问题的决定性因素之一。
- 根据应用三的结果,模型被另一个相同的模型(但设定的角色不同)所纠正,可以认为是精心设计的系统信息和 prompt 激发了模型在子任务的专业领域上的表现。即便如此,模型的输出仍有欠缺,这里人类的干预可以进一步补足模型能力,提高应用的最终表现。
- 试想如果模型能力进一步提升会如何,基于下一代 GPT 模型的单智能体会不会比应用三的多智能体对话流表现更好?换一个视角,如果把除了 User Proxy 之外的 Coder、Critic 和 GroupChat Manager 打包为一个整体,把这个整体视作基于某个比 gpt-4 更强的 LLM 的单一智能体,AutoGen 框架在多智能体对话流中所起的作用就是这个 LLM 内部的一种机制。而传闻中,gpt-4 实际上就是类似的 MoE 结构(尽管细节尚不可知),由 8 个 220B 专家模型组成,这些模型分别在不同的数据集和任务分布上训练。或许“集成”和“对话”只需要一个,内部有着强大集成机制的 LLM 不会再需要外部的对话框架。
回到 AutoGen 框架,它仍是一个处于早期实验阶段的工作,其进一步的研究方向包括:
- 研究提升对话有效性和总体效率的策略(如智能体拓扑、对话模式等);探索对于特定 LLM 应用的最优多智能体对话流。
- 为构建针对不同应用的强大智能体提供系统性的参考,建立大规模开源知识库,建立具备自主学习和升级技能的智能体。
- 评估极度复杂的任务能否通过多智能体对话的方法有效解决。
部署对话式搜索引擎
对话式搜索引擎(conversational search engine)是利用自然语言处理技术来理解和响应用户查询的下一代搜索引擎。与传统的基于关键字的搜索引擎不同,对话式搜索引擎能够与用户以自然语言对话的形式进行互动,从而提供更为精准和个性化的搜索结果。这种搜索引擎通过分析用户的查询意图和上下文信息,能够提出问题、澄清疑惑,并给出更加直观和详细的回答。
当下(2024 Q1)最火热的对话式搜索引擎产品无疑是 Perplexity,但最近广受好评的开源项目 Search with Lepton 仅用 ~500 行 Python 代码就实现了类似的功能,其核心逻辑为:
- 获取用户的查询文本,调用传统搜索引擎的 API 以获取上下文,即结果页面的片段(snippets)。
- 将上下文添加到 system prompt(用于编写回答)中,将查询文本作为 user prompt,调用 LLM 生成回答。
- 将同样的上下文添加到另一个 system prompt(用于产生关联问题)中,将查询文本作为 user prompt,调用 LLM 生成关联问题。
- 将上下文、回答和关联问题返回给 UI 以供展示。
- (可选)将当次查询结果存储到数据库中,若用户再次进行相同的查询则直接返回该结果。
用户也可以在平台上方便地部署和使用这项功能!项目 t9k/search_with_lepton
fork 了 Search with Lepton 项目并进行了以下修改:
- 移除使用 Lepton AI 云服务的代码。
- 增加 Dockerfile 并构建镜像
t9kpublic/search-with-lepton
。
本示例使用 Kubernetes 原生资源和 TensorStack 资源部署该修改后的对话式搜索引擎应用,系统架构如下图所示:
创建的资源如下表所示:
类型 | 名称 | 作用 | 备注 |
---|---|---|---|
PVC | search | 存储代码和模型文件 | 卷大小为 180Gi |
MLServiceRuntime | vllm-openai-2xtp | 定义 LLM 推理服务的模板 | |
MLService | mixtral-8x7b | 部署 LLM 推理服务 | 计算资源为 {"limits":{"cpu": 4, "memory": "64Gi", "nvidia.com/gpu": 2}, "requests": {}} |
Secret | search | 存储搜索引擎的 API key | |
Deployment | search | 部署对话式搜索服务 | 计算资源为 {"limits":{"cpu": 2, "memory": "8Gi"}, "requests": {}} |
Service | search | 暴露服务 |
准备
在项目中创建一个名为 search
、大小 180 GiB 以上的 PVC,然后创建一个同样名为 search
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆 t9k/examples
仓库:
cd ~
git clone https://github.com/t9k/examples.git
部署
LLM 推理服务
继续使用 Notebook 的终端,执行以下命令以下载 Mixtral-8x7B-Instruct-v0.1 的模型文件:
# 方法 1:如果可以直接访问 huggingface
huggingface-cli download mistralai/Mixtral-8x7B-Instruct-v0.1 \
--local-dir Mixtral-8x7B-Instruct-v0.1 --local-dir-use-symlinks False
# 方法 2:对于国内用户,访问 modelscope 网络连通性更好
pip install modelscope
python -c \
"from modelscope import snapshot_download; snapshot_download('AI-ModelScope/Mixtral-8x7B-Instruct-v0.1')"
mv .cache/modelscope/hub/AI-ModelScope/Mixtral-8x7B-Instruct-v0.1 .
然后使用 vLLM 部署兼容 OpenAI API 的 LLM 推理服务。使用以下 YAML 配置文件创建 MLServiceRuntime:
cd examples/applications/search
kubectl apply -f mlservice-runtime.yaml
再使用以下 YAML 配置文件创建 MLService 以部署服务(必要时修改 spec.scheduler
字段以使用 t9k-scheduler
及特定的队列):
kubectl create -f mlservice.yaml
搜索服务
在以下 YAML 配置文件中提供所调用搜索引擎的 API key,使用它创建 Secret:
# 修改 secret.yaml
kubectl apply -f secret.yaml
在以下 YAML 配置文件中提供环境变量,使用它创建 Deployment:
# 修改 deployment.yaml
kubectl create -f deployment.yaml
然后为 Deployment 创建 Service:
kubectl create -f service.yaml
使用
在本地的终端中,使用 t9k-pf 命令行工具,将服务的 8080 端口转发到本地的 8080 端口:
t9k-pf service search 8080:8080 -n <PROJECT NAME>
然后使用浏览器访问 http://127.0.0.1:8080,搜索以下问题:
- when will nvidia RTX 5000 series be released?
- 二进制小品是什么
- 武汉火车站是否已经恢复正常运行
需要说明的是,这里对话式搜索引擎所使用的搜索引擎后端是 Bing,调用的 LLM 是 Mixtral-8x7B-Instruct-v0.1。以下搜索于 2024 年 2 月 8 日进行。
作为比较,我们在 Perplexity 搜索相同的问题:
可以看到,该应用的回答基本准确且详细,但存在以下问题:
-
尽管该应用可以理解中文查询和上下文,但它仅以英文回复,这是因为其调用的 Mixtral 8x7B 模型仅支持英语和一些欧洲语言。用户可以自行尝试调用其他支持中文的 LLM。
-
在回答问题 2 时,应用给出的解释“It is a form of light and humorous artistic work that explores the characteristics, applications, nad computer-related topics of binary.(它是一种轻松幽默的艺术作品形式,探索了二进制的特征、应用和与计算机相关的话题。)”存在明显误解,追溯其引用的参考源,我们发现该来源的解释就存在错误,且很有可能是由另一个 LLM 产生的虚构的信息。这提示我们在对话式搜索引擎中,搜索的准确性比内容生成更为关键,凸显了优化获取和处理上下文信息步骤的重要性。
相比之下,Perplexity 支持中文,并且生成回答的速度更快。尽管如此,其回答的质量并没有更好,尤其是对于问题 2 的回答出现了问题,完全没有引用参考源,而是由 LLM 直接生成的。其对于问题 3 的回答所包含的有用信息也较少。
参考
- GitHub 上的 Search with Lepton 原项目,以及 fork 项目 t9k/search_with_lepton
- Perplexity
- Mistral AI News: Mixtral of experts
部署 Stable Diffusion 图像生成模型
自扩散模型问世以来,AI 绘图应用在艺术、设计和创意领域取得了显著的突破和广泛的应用。在 TensorStack 平台上,用户可以使用 SimpleMLService 和 MLService 方便地部署各种基于图像生成模型的服务或应用。
本示例使用 SimpleMLService 快速部署一个基于 Stable Diffusion 图像生成模型的绘图应用。
模型
在项目中创建一个名为 draw
、大小 50 GiB 以上的 PVC,然后创建一个同样名为 draw
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行下列命令以下载 Stable Diffusion、VAE、LoRA 等模型的文件:
mkdir sd
wget https://civitai.com/api/download/models/30163 \
-O sd/anything-v5-PrtRE.safetensors
wget https://civitai.com/api/download/models/57618 \
-O sd/CounterfeitV30_v30.safetensors
wget https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned.safetensors \
-O sd/v1-5-pruned.safetensors
mkdir lora
wget https://civitai.com/api/download/models/87153 \
-O lora/more_details.safetensors
mkdir vae
wget https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.safetensors \
-O vae/vae-ft-mse-840000-ema-pruned.safetensors
mkdir outputs
最终目录结构如下:
.
├── lora
│ └── more_details.safetensors
├── outputs (用于放置模型输出)
├── sd
│ ├── anything-v5-PrtRE.safetensors
│ ├── CounterfeitV30_v30.safetensors
│ └── v1-5-pruned.safetensors
└── vae
└── vae-ft-mse-840000-ema-pruned.safetensors
Stable Diffusion 生成图片的简化流水线如下图所示,具体包含三个主要步骤:
- CLIP 模型为输入的 prompt 生成文件嵌入;
- U-Net 反复地去除 latent 表示中的噪音;
- VAE 将 latent 表示解码为最终的图片。
我们前面所下载的模型文件中:
- Stable Diffusion 模型提供图中的 U-Net 和 VAE 模型。
- VAE 用于替换现有 Stable Diffusion 模型的 VAE。VAE 会影响图片的风格以及细节处理。
- LoRA 用于更新 CLIP 和 U-Net 的权重。使用 LoRA 会应用微调过程中对模型的修改,以生成特定内容或风格的图片。
部署
stable-diffusion-webui 是一个用于运行 Stable Diffusion 模型的 gradio web UI。bilibili 用户“秋葉aaaki”基于这一项目制作了整合包。这里使用它来部署上述模型。
使用以下 YAML 配置文件创建 SimpleMLService(必要时修改 spec.scheduler.t9kScheduler.queue
字段指定的队列):
smls.yaml
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: stable-diffusion-webui
spec:
replicas: 1
scheduler:
t9kScheduler:
queue: default
service:
type: ClusterIP
ports:
- targetPort: 7860
port: 7860
custom:
spec:
containers:
- name: server
image: t9kpublic/stable-diffusion-webui:aki-v4
args:
- --skip-install
- --listen
ports:
- containerPort: 7860
resources:
limits:
cpu: 4
memory: 64Gi
nvidia.com/gpu: 1
volumeMounts:
- mountPath: /workspace/sd-webui-aki-v4/models/Stable-diffusion
name: data
subPath: sd
- mountPath: /workspace/sd-webui-aki-v4/models/VAE
name: data
subPath: vae
- mountPath: /workspace/sd-webui-aki-v4/models/Lora
name: data
subPath: lora
- mountPath: /workspace/sd-webui-aki-v4/outputs
name: data
subPath: outputs
- mountPath: /dev/shm
name: dshm
volumes:
- name: data
persistentVolumeClaim:
claimName: draw
- name: dshm
emptyDir:
medium: Memory
kubectl create -f smls.yaml
启动
查看 SimpleMLService 创建的 Pod 打印的日志:
kubectl logs -l deployment=managed-simplemlservice-stable-diffusion-webui -f --tail -1
接下来就可以开始生成图片了!
生成图片
在本地的终端中,使用 t9k-pf 命令行工具,将 SimpleMLService 创建的服务的 7860 端口转发到本地的 7860 端口:
t9k-pf service stable-diffusion-webui 7860:7860 -n <PROJECT NAME>
然后使用浏览器访问 127.0.0.1:7860
,绘制喜欢的图片:
生成的图片可以通过 Web UI 下载,同时也会保存到 PVC 的 outputs/
路径下。
画廊
这里展示一些最终生成的图片:
模型 | v1-5-pruned.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | alpaca, plateau, mountain, realistic, Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 7, Seed: 2642782115, Size: 512x512, Model hash: 1a189f0be6, Model: v1-5-pruned, Clip skip: 2, ENSD: 31337 |
模型 | CounterfeitV30_v30.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | (masterpiece, best quality),1girl, solo, flower, long hair, outdoors, letterboxed, school uniform, day, sky, looking up, short sleeves, parted lips, shirt, cloud, black hair, sunlight, white shirt, serafuku, upper body, from side, pink flower, blurry, brown hair, blue sky, depth of field Negative prompt: EasyNegativeV2 Steps: 25, ENSD: 31337, Size: 1024x512, Seed: 2311942344, Model: CF5_Counterfeit-V3.0_fix_fix_fix, Sampler: DPM++ 2M Karras, CFG scale: 10, Clip skip: 2, Model hash: db6cd0a62d, Hires upscale: 2, Hires upscaler: R-ESRGAN 4x+ Anime6B, Denoising strength: 0.45 |
模型 | anything-v5-PrtRE.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | masterpiece, best quality, scenery, whale, fish, starry sky, galaxy, cosmos, fantasy, floating object|fish, backlight, shadow Negative prompt: (low quality, worst quality:1.4), (bad anatomy),easynegative Steps: 20, Size: 1024x512, Seed: 3421647346, Sampler: DPM++ 2M Karras, CFG scale: 8 |
模型 | anything-v5-PrtRE.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | masterpiece, best quality, best 8k wallpaper, chibi, 1girl, official, solo, silver hair, ponytail, blush, smile, head, sunglasses, white background, pixel, (pixel art) Negative prompt: badhandv4,EasyNegative Steps: 80, Sampler: DPM++ 2M Karras, CFG scale: 9, Seed: 1362619635, Size: 512x512, Model hash: 7f96a1a9ca, Model: anything-v5-PrtRE, ENSD: 31337 |
模型 | anything-v5-PrtRE.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | greyscale, monochrome, no humans, tree, scenery, traditional media, tower, building, outdoors Negative prompt: EasyNegative Steps: 20, Sampler: DPM++ SDE Karras, CFG scale: 7, Seed: 2579617703, Size: 512x768, Model hash: 7f96a1a9ca, Model: anything-v5-PrtRE, Denoising strength: 0.7, Clip skip: 2, ENSD: 31337, Hires upscale: 2, Hires upscaler: Latent |
模型 | anything-v5-PrtRE.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | Monet style, beach, boat, cloud, sky, traditional media, water, watercraft, (masterpiece:1,2), best quality, masterpiece, highres, original, extremely detailed wallpaper, perfect lighting,(extremely detailed CG:1.2), drawing, paintbrush, Negative prompt: NSFW, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, ((monochrome)), ((grayscale)), skin spots, acnes, skin blemishes, age spot, (ugly:1.331), (duplicate:1.331), (morbid:1.21), (mutilated:1.21), (tranny:1.331), mutated hands, (poorly drawn hands:1.5), blurry, (bad anatomy:1.21), (bad proportions:1.331), extra limbs, (disfigured:1.331), (missing arms:1.331), (extra legs:1.331), (fused fingers:1.61051), (too many fingers:1.61051), (unclear eyes:1.331), lowers, bad hands, missing fingers, extra digit,bad hands, missing fingers, (((extra arms and legs))), Steps: 36, Sampler: Euler a, CFG scale: 4.5, Seed: 2739912422, Size: 512x768, Model hash: 7f96a1a9ca, Model: anything-v5-PrtRE, Denoising strength: 0.7, Clip skip: 3, ENSD: 31337, Hires upscale: 2, Hires upscaler: Latent |
模型 | anything-v5-PrtRE.safetensors, vae-ft-mse-840000-ema-pruned.safetensors |
生成数据 | digital painting, best quality, magic, cyberpunk, city, street, neon, mystic, |
车道检测
车道检测是计算机视觉和自动驾驶领域的一项关键技术,旨在识别和跟踪道路上的车道线。这个任务对于实现车辆的自动驾驶和辅助驾驶系统至关重要,因为它能够帮助车辆理解其在道路上的位置,保持车道,并执行如车道保持、车道变换等操作。
本示例使用 PyTorchTrainingJob 训练一个车道检测模型。
准备
在项目中创建一个名为 lanedet
、大小 50 GiB 以上的 PVC,然后创建一个同样名为 lanedet
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
进入 Notebook 或远程连接到 Notebook,启动一个终端,执行以下命令以克隆 t9k/examples
仓库:
cd ~
git clone https://github.com/t9k/examples.git
继续执行以下命令以从 kaggle 下载 TuSimple 数据集并解压,其中 kaggle.json
文件需要登录 kaggle 获取。完整的操作步骤可以参阅博客 How to Download Kaggle Datasets on Ubuntu。
pip install kaggle
# 在浏览器中登录 kaggle,在账户设置页面创建新的 token 以生成 kaggle.json 文件,将其上传到 Notebook
mkdir ~/.kaggle
mv kaggle.json ~/.kaggle
kaggle datasets download manideep1108/tusimple
unzip tusimple.zip
训练
使用如下 YAML 配置文件创建 PyTorchTrainingJob 以启动训练。该 PyTorchTrainingJob 创建 2 个副本,每个副本启动 2 个进程,每个进程使用 1 个 GPU。
kubectl create -f examples/lanedet/t9k/job.yaml
通过以下命令查看训练过程中打印的日志:
export POD=$(kubectl get pj lanedet -o jsonpath="{.status.tasks[0].replicas[0].name}")
kubectl logs $POD -f
训练共进行 100 个 epoch,每个 epoch 结束时进行验证(使用测试图像作为验证集),计算准确率、假阳性率和假阴性率。训练完成之后,模型文件将保存到 output/TuSimple/0/*/
路径下。训练花费约 3 小时,最终准确率可以达到约 0.94。
集成
平台支持集成第三方应用,用户可以在自己的项目中使用 Helm 轻松快速地部署各种丰富的第三方应用,例如部署一个 GitLab 以托管私有代码,部署一个 Label Studio 以进行数据标注等。
这一部分将介绍一些与机器学习相关的常用第三方应用的部署流程和使用方法。在开始之前,先确定在哪一个项目中部署应用,在该项目中创建一个名为 app
、大小 1 GiB 的 PVC,然后创建一个同样名为 app
的 Notebook 挂载该 PVC(镜像类型和模板不限)。
Label Studio
Label Studio 是一个开源的数据标注工具。它允许用户通过一个简单直观的用户界面来标注音频、文本、图像、视频和时间序列等多种数据类型,并支持导出到各种模型格式。
部署
安装与配置
进入 Notebook app
的终端,添加相应的 Helm Chart repository,列出 Chart heartex/label-studio
的所有版本:
helm repo add heartex https://charts.heartex.com/
# 注意 CHART VERSION 和 APP VERSION(Label Studio 版本)之间的对应关系
# 例如 CHART VERSION 1.4.0 和 1.3.4 中的 Label Studio 版本都是 1.11.0
helm search repo heartex/label-studio --versions
安装指定版本的 Chart heartex/label-studio
以部署 Label Studio 应用:
# 安装最新版本
helm repo update heartex
helm install label-studio-demo heartex/label-studio
# 安装指定 CHART VERSION,注意这不是 APP VERSION(Label Studio 版本)
helm install label-studio-demo heartex/label-studio --version <CHART_VERSION>
以上安装全部使用默认配置,完整的默认配置请参阅相应的 values.yaml
:
# 获取指定 CHART VERSION 的 values.yaml
helm show values heartex/label-studio --version <CHART_VERSION> > values.yaml
其中部分关键配置如下所示(CHART VERSION 1.4.0):
app:
replicas: 1 # 副本数
resources: # 计算资源
limits: {}
requests: {}
ingress: # Ingress 配置
enabled: false
annotations: {}
className: ""
host: ""
tls: []
global:
persistence: # 持久化
config:
volume:
accessModes:
- ReadWriteOnce
annotations: {}
existingClaim: ""
resourcePolicy: ""
size: 10Gi # 卷大小
storageClass: ""
enabled: true
type: volume # 卷
你可以根据需要对这些配置进行修改:
- 如果想要提高容错,可以增加副本数。
- 可以根据实际需求指定计算资源的请求值和限制值。
- 可以提供 Ingress 配置以提供外部访问,请参阅 Set up an ingress controller for Label Studio Kubernetes deployments。
- 可以修改卷大小,或使用其他类型的持久化方案(如 Amazon S3),请参阅 Set up persistent storage。
然后将新配置(覆盖默认配置的部分)保存为一个 YAML 文件,通过 -f
选项提供给安装命令:
# 使用修改后的 values.yaml
helm install label-studio-demo heartex/label-studio --version <CHART_VERSION> -f values.yaml
应用架构
应用的系统架构如下图所示(CHART VERSION 1.4.0,默认配置):
创建的主要 Kubernetes 资源如下表所示:
类型 | 名称 | 作用 | 备注 |
---|---|---|---|
Service | label-studio-demo-ls-app | 暴露 Label Studio 服务 | |
Deployment | label-studio-demo-ls-app | 部署 Label Studio | 默认计算资源为 {"limits": {}, "requests": {}} |
PVC | label-studio-demo-ls-pvc | 作为 Label Studio 的持久化存储,存储用户上传的数据文件等 | 选择卷作为持久化方案时存在;默认卷大小为 10Gi |
Secret | label-studio-demo-postgresql | 存储数据库密钥 | |
Service | label-studio-demo-postgresql | 暴露数据库服务 | |
StatefulSet | label-studio-demo-postgresql | 部署数据库 | 默认计算资源为 {"limits": {}, "requests": {"cpu": "250m", "memory": "256Mi"}} |
PVC | data-label-studio-demo-postgresql-* | 作为数据库的持久化存储 | 默认卷大小为 8Gi |
Ingress | label-studio-demo-ls-app | 提供外部访问 | 启用 Ingress 时存在 |
运维
查看应用的状态
helm status label-studio-demo
重启应用
kubectl rollout restart deployment/label-studio-demo-ls-app
更新应用
# 更新到最新版本
helm upgrade label-studio-demo heartex/label-studio
# 更新到指定版本
helm upgrade label-studio-demo heartex/label-studio --version <VERSION_NUMBER>
# 回滚更新,首先查看历史版本
helm history label-studio-demo
helm rollback label-studio-demo [REVISION]
移除应用
helm delete label-studio-demo
使用
基本使用
如果在部署应用时配置了 Ingress,那么直接在浏览器中访问相应的地址即可,否则需要进行端口转发。在用户的计算机上,前往模型构建控制台获取应用 Pod 的名称(前缀为 label-studio-demo-ls-app-):
然后通过 t9k-pf 进行端口转发来访问 Label Studio 应用:
t9k-pf -n <APP_PROJECT> pod <POD_NAME> 8080:8085
在浏览器中访问 http://127.0.0.1:8080/ 进入应用的 Web UI。注册一个用户,Email 和密码可以任意指定:
假定任务是图像分类,我们准备了 10 张图片(来自数据集 Cats and Dogs),需要将每一张图片标注为猫或狗。点击 Create Project:
在 Project Name 页面可选地修改 Project 的名称:
在 Data Import 页面上传 10 张图片:
在 Labeling Setup 页面,选择模板 Computer Vision > Image Classification,并将选项编辑为 Cat 和 Dog,最后点击 Save:
自动跳转到 Project 的默认标签页,点击 Label All Tasks 以开始标注:
对于每一张图片,勾选其为 Cat 或 Dog,然后点击 Submit:
标注结束后,点击 Export 以下载指定格式的标注数据。
导入大量数据
在导入数据时,如果仅上传少量(几十上百个)的文件,那么使用 Web UI 即可。但假设我们要上传数据集 Cats and Dogs 的总共 25000 张图片,仍然使用 Web UI 会导致其崩溃,这时我们需要寻求另外的导入数据的方法。
Label Studio 支持从外部存储同步数据。这里以 Amazon S3 为例。在用户的计算机上准备好数据文件,并将其上传到 S3 bucket:
$ tree .
.
├── 0.jpg
├── 1.jpg
├── 10.jpg
├── 100.jpg
├── 1000.jpg
├── 10000.jpg
├── 10001.jpg
...
├── 9998.jpg
└── 9999.jpg
0 directories, 25000 files
$ rclone copy -P . corps3:my-bucket/kagglecatsanddogs
Transferred: 569.808 MiB / 809.542 MiB, 70%, 2.328 MiB/s, ETA 1m42s
Transferred: 16994 / 25000, 68%
Elapsed time: 3m35.2s
Transferring:
* 2793.jpg:100% /23.680Ki, 0/s, -
* 2794.jpg:100% /20.700Ki, 0/s, -
* 2795.jpg:100% /22.631Ki, 0/s, -
* 2796.jpg:100% /13.476Ki, 0/s, -
在 Label Studio 的项目设置中点击 Cloud Storage > Add Source Storage,选择存储类型 AWS S3,并填写相关的配置,点击 Check Connection 验证连接是否成功,最后点击 Add Storage。
创建完成之后,点击 Sync Storage,即可从导入数据文件:
回到项目,可以看到数据被导入:
自定义标注 UI
应用内置了大量标注模板,覆盖了各种类型的机器学习任务。除此之外,用户还可以使用类似 XML 的标签来自定义标注 UI,详细语法规则请参阅 Customize the Label Studio User Interface。
自动化标注
人工标注数据费时费力,我们可以引入机器学习模型来完成这一工作,这样只需要人工审核即可。
Label Studio 支持添加 ML backend,使用其自动标注或进行在线训练。这里演示使用 SAM 进行语义分割任务的自动标注。
在应用的 Web UI 点击 Account & Settings,以获取用户的 Access Token:
回到 Notebook app
的终端,获取应用 service 的 IP 地址:
kubectl get svc label-studio-demo-ls-app -o jsonpath="{.spec.clusterIP}"
然后使用如下 YAML 配置文件创建 SimpleMLService 以部署 ML backend 服务,其中环境变量 LABEL_STUDIO_HOST
和 LABEL_STUDIO_ACCESS_TOKEN
的值需要根据上面获取的结果进行修改。镜像 t9kpublic/label-studio-sam:main
构建自示例 Interactive Annotation in Label Studio with Segment Anything Model。
sam.yaml
apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
name: label-studio-sam
spec:
replicas: 1
service:
type: ClusterIP
ports:
- targetPort: 9090
port: 9090
custom:
spec:
containers:
- name: server
image: t9kpublic/label-studio-sam:main
env:
- name: SAM_CHOICE
value: MobileSAM
- name: LOG_LEVEL
value: DEBUG
- name: LABEL_STUDIO_HOST
value: http://10.233.12.87:80
- name: LABEL_STUDIO_ACCESS_TOKEN
value: 381ae0357804f39d01e5d169b8ed0cf548925a57
ports:
- containerPort: 9090
resources:
limits:
cpu: 8
memory: 8Gi
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
kubectl create -f sam.yaml
获取 ML backend service 的 IP 地址和端口号:
kubectl get svc label-studio-sam -o jsonpath="{.spec.clusterIP}"
kubectl get svc label-studio-sam -o jsonpath="{.spec.ports[0].port}"
再次进入应用的 Web UI,创建一个新的 project,上传一张图片,并且 template 使用如下自定义模板:
<View>
<Image name="image" value="$image" zoom="true"/>
<BrushLabels name="tag" toName="image">
<Label value="Banana" background="#FF0000"/>
<Label value="Orange" background="#0d14d3"/>
</BrushLabels>
<KeyPointLabels name="tag2" toName="image" smart="true">
<Label value="Banana" smart="true" background="#000000" showInline="true"/>
<Label value="Orange" smart="true" background="#000000" showInline="true"/>
</KeyPointLabels>
<RectangleLabels name="tag3" toName="image" smart="true">
<Label value="Banana" background="#000000" showInline="true"/>
<Label value="Orange" background="#000000" showInline="true"/>
</RectangleLabels>
</View>
在 Label Studio 的项目设置中点击 Machine Learning > Add Model,填写 SAM 服务的 URL 和模型名称,勾选 Use for interactive preannotations,然后点击 Validate and Save:
标注时按照下图的顺序进行操作,可以看到图片中的柯基被正确地分割出来:
团队协作
应用提供了简单直接的团队协作方式。团队的多个成员分别注册用户、登录并进入同一个项目,通过设定不同的过滤条件来分别标注全部数据的不同子集。
例如设定 ID / <= / 3000
可以仅列举前 3000 个数据;设定 Annotated by / is empty / yes
可以仅列举未被标注的数据。
参考
向量数据库:Qdrant
背景
向量数据库是一种专门设计用于存储、索引和检索向量数据的数据库。它适用于处理大规模的高维向量,这些向量通常代表了图像、视频、文本或音频内容的特征,甚至整个世界本身。向量数据库通常用于支持机器学习应用,例如检索增强生成(RAG)、图像检索、推荐系统等。
向量数据库的核心功能是相似度搜索(similarity search),即通过计算向量之间的相似度来快速检索出内容上相似的项目。常用的相似度度量包括欧氏距离、余弦相似度和点积。为了实现高效的大规模相似度搜索,向量数据库通常采用专门的数据结构和索引技术,以及高效的搜索算法(如近似最近邻搜索算法)。以基于检索增强生成的问答应用为例,当用户提出一个问题时,应用会首先将问题转换为向量,然后在向量数据库中检索与该向量相似的向量,即与问题相关的上下文。这些检索到的上下文信息用于增强大型语言模型的回答生成过程,使得生成的答案更为精确和详尽。
目前市面上存在数量众多的向量数据库产品,即便是开源向量数据库也有不少选择,例如 Milvus、Qdrant、Chroma、Weaviate 等。关于这些向量数据库的比较,可以参阅博客 Vector databases (1): What makes each one different?。
这里以 Qdrant 为例进行部署。Qdrant 官方提供了 Helm chart,部署更加简单、便捷。
Qdrant 的一些特性如下:
- 高效:有效利用计算资源。Qdrant 完全用 Rust 语言开发,实现了动态查询计划和有效载荷数据索引。也为企业提供了硬件感知的构建版本。
- 快速且准确:实现了 HNSW 算法的独特自定义修改,用于近似最近邻搜索。以最先进的速度进行搜索,并在不影响结果的情况下应用搜索过滤器。
- 易于使用的 API:提供 OpenAPI v3 规范来生成几乎任何编程语言的客户端库。或者,利用为 Python 或其他编程语言准备的现成客户端以获得额外功能。
- 丰富的数据类型:向量负载支持大量的数据类型和查询条件,包括字符串匹配、数值范围、地理位置等。负载过滤条件允许你构建几乎任何自定义业务逻辑,这些逻辑应基于相似性匹配工作。
- 分布式:云原生且横向可扩展。无论用户需要伺服多少数据,Qdrant 总是可以使用恰到好处的计算资源。
Qdrant 提供了 REST API 和 gRPC API 作为接口,所有与 Qdrant 的交互都通过这些 API 进行。此外,Qdrant 还提供了多种语言的客户端库和一个 Web UI 界面,使用部分将演示使用 Python 客户端以及 Web UI 与 Qdrant 交互。
部署
安装
进入 Notebook app
的终端,添加相应的 Helm Chart repository,列出 Chart qdrant/qdrant
的所有版本:
helm repo add qdrant https://qdrant.github.io/qdrant-helm
# 注意 CHART VERSION 和 APP VERSION(Qdrant 版本)之间的对应关系
# 例如 CHART VERSION 0.7.5 和 0.7.4 中的 Qdrant 版本都是 v1.7.3
helm search repo qdrant/qdrant --versions
安装指定版本的 Chart qdrant/qdrant
以部署 Qdrant 应用:
# 安装最新版本
helm repo update qdrant
helm install qdrant-demo qdrant/qdrant
# 安装指定 CHART VERSION,注意这不是 APP VERSION(Qdrant 版本)
helm install qdrant-demo qdrant/qdrant --version <CHART_VERSION>
配置
以上安装全部使用默认配置,完整的默认配置请参阅相应的 values.yaml
:
# 获取指定 CHART VERSION 的 values.yaml
helm show values qdrant/qdrant --version <CHART_VERSION> > values.yaml
如果想要修改默认配置,你可以将新配置(覆盖默认配置的字段)保存为一个 YAML 文件,通过 -f
选项提供给安装命令:
# 使用修改后的 values.yaml
helm install qdrant-demo qdrant/qdrant --version <CHART_VERSION> -f values.yaml
下面将分主题介绍部分关键配置(CHART VERSION 0.7.6)。
计算资源
默认配置没有指定计算资源,表示 Pod 可以无限制地使用节点的 CPU 和内存资源。你可以根据实际需求指定请求值和限制值。
# 默认配置
resources: {}
存储
默认配置指定的卷大小为 10Gi,并且没有指定存储类型。你可以根据数据规模修改卷大小,并选用高性能的存储类型。
# 默认配置
persistence:
accessModes:
- ReadWriteOnce
annotations: {}
size: 10Gi # 卷大小
storageClassName: "" # 存储类型
config:
storage: {}
此外,你还可以在 config.storage
字段下配置 Qdrant 实例的存储和索引的多个参数,请参阅 configuration file example。
网络
默认配置没有启动 Ingress,你可以提供 Ingress 配置以提供外部访问。
# 默认配置
ingress: # Ingress 配置
enabled: false
ingressClassName: ""
annotations: {}
hosts:
- host: example-domain.com
paths:
- path: /
pathType: Prefix
servicePort: 6333
tls: []
service: # Service 配置
type: ClusterIP
additionalLabels: {}
annotations: {}
loadBalancerIP: ""
ports:
- name: http
port: 6333
targetPort: 6333
protocol: TCP
checksEnabled: true
- name: grpc
port: 6334
targetPort: 6334
protocol: TCP
checksEnabled: false
- name: p2p
port: 6335
targetPort: 6335
protocol: TCP
checksEnabled: false
config:
service: {}
tls: {}
此外,你还可以在 config.service
和 config.tls
字段下配置 Qdrant 实例的服务和 TLS 的多个参数,请参阅安全以及 configuration file example。
分布式部署
Qdrant 支持分布式部署模式,在此模式下,多个 Qdrant 服务彼此通信,将数据分布到多个副本(replica)中,以扩展存储能力并增加稳定性。默认配置启用了分布式部署模式,并指定端口 6335 用于内部通信,但只创建了 1 个副本。你可以增加副本数量以实现分布式部署。
# 默认配置
replicaCount: 1
config:
cluster:
enabled: true
p2p:
port: 6335
consensus:
tick_period_ms: 100
关于分布式一致性协议、分片、复制(replication)和一致性保证的更多信息,请参阅 Distributed deployment。
安全
默认配置没有为 Qdrant 实例提供任何保护,在投入生产使用之前需要启用安全措施。首先,启用 TLS 以加密连接:
config:
service:
enable_tls: true
p2p:
enable_tls: true # 分布式部署下,对 peer 之间的通信启用 TLS
tls:
cert: ./tls/cert.pem
key: ./tls/key.pem
在此基础上,可以使用静态的 API key 进行身份验证:
config:
service:
api_key: your_secret_api_key_here
更多信息请参阅 Security。
应用架构
应用的系统架构如下图所示(CHART VERSION 0.7.6,默认配置):
创建的主要 Kubernetes 资源如下表所示:
类型 | 名称 | 作用 | 备注 |
---|---|---|---|
Service | qdrant-demo | 暴露 Qdrant 服务 | |
StatefulSet | qdrant-demo | 部署 Qdrant | 默认计算资源为 {} |
PVC | qdrant-storage-qdrant-demo-* | 作为 Qdrant 的持久化存储 | 默认卷大小为 10Gi |
运维
查看应用的状态
helm status qdrant-demo
更新应用
# 更新到最新版本
helm upgrade qdrant-demo qdrant/qdrant
# 更新到指定版本
helm upgrade qdrant-demo qdrant/qdrant --version <VERSION_NUMBER>
# 回滚更新,首先查看历史版本
helm history qdrant-demo
helm rollback qdrant-demo [REVISION]
移除应用
helm delete qdrant-demo
kubectl delete pvc -l app.kubernetes.io/instance=qdrant-demo
使用
继续使用 Notebook app
的终端,获取应用 service 的公开的端口号:
kubectl get svc qdrant-demo -o jsonpath="{.spec.ports}"
输出应类似于:
[{"name":"http","port":6333,"protocol":"TCP","targetPort":6333},{"name":"grpc","port":6334,"protocol":"TCP","targetPort":6334},{"name":"p2p","port":6335,"protocol":"TCP","targetPort":6335}]
首先使用 Python 客户端运行一个快速入门。安装 Python 客户端:
pip install qdrant-client
然后执行如下 Python 脚本,命令行参数中需要提供 gRPC 端口号:
quick_start.py
import sys
from qdrant_client import QdrantClient
from qdrant_client.http.models import (Distance, Filter, FieldCondition,
MatchValue, PointStruct, VectorParams)
# 客户端在创建 collection 时存在 HTTP 超时问题,参考
# https://github.com/qdrant/qdrant-client/issues/394,采用 gRPC 作为临时解决方案
# client = QdrantClient(sys.argv[1])
client = QdrantClient(sys.argv[1], prefer_grpc=True)
# 创建一个 collection 以存储向量数据,设定向量维数为 4,使用点积度量距离
client.create_collection(
collection_name="test_collection",
vectors_config=VectorParams(size=4, distance=Distance.DOT),
)
# 添加一些向量
client.upsert(
collection_name="test_collection",
wait=True,
points=[
PointStruct(id=1,
vector=[0.05, 0.61, 0.76, 0.74],
payload={"city": "Berlin"}),
PointStruct(id=2,
vector=[0.19, 0.81, 0.75, 0.11],
payload={"city": "London"}),
PointStruct(id=3,
vector=[0.36, 0.55, 0.47, 0.94],
payload={"city": "Moscow"}),
PointStruct(id=4,
vector=[0.18, 0.01, 0.85, 0.80],
payload={"city": "New York"}),
PointStruct(id=5,
vector=[0.24, 0.18, 0.22, 0.44],
payload={"city": "Beijing"}),
PointStruct(id=6,
vector=[0.35, 0.08, 0.11, 0.44],
payload={"city": "Mumbai"}),
],
)
# 查询与向量 [0.2, 0.1, 0.9, 0.7] 最相似的 3 个向量
search_result = client.search(collection_name="test_collection",
query_vector=[0.2, 0.1, 0.9, 0.7],
limit=3)
print(search_result)
# 进一步过滤结果
search_result = client.search(
collection_name="test_collection",
query_vector=[0.2, 0.1, 0.9, 0.7],
query_filter=Filter(
must=[FieldCondition(key="city", match=MatchValue(value="London"))]),
with_payload=True,
limit=3,
)
print(search_result)
python quick-start.py qdrant-demo:<GRPC_PORT>
脚本创建了一个 collection,添加了一些数据,并进行了两次基本的查询。输出应类似于:
[ScoredPoint(id=4, version=0, score=1.3619999885559082, payload={'city': 'New York'}, vector=None, shard_key=None), ScoredPoint(id=1, version=0, score=1.2730000019073486, payload={'city': 'Berlin'}, vector=None, shard_key=None), ScoredPoint(id=3, version=0, score=1.2079999446868896, payload={'city': 'Moscow'}, vector=None, shard_key=None)]
[ScoredPoint(id=2, version=0, score=0.8709999918937683, payload={'city': 'London'}, vector=None, shard_key=None)]
接下来进入 Web UI 与 Qdrant 向量数据库交互。如果在部署应用时配置了 Ingress,那么直接在浏览器中访问相应的地址即可,否则需要进行端口转发。通过 t9k-pf 进行端口转发:
t9k-pf -n <APP_PROJECT> pod qdrant-demo-0 6333:6333
在浏览器中访问 http://127.0.0.1:6333/dashboard 进入 Web UI。在 Console 页面中,用户可以直接调用 REST API 并得到响应结果:
在 Collections 页面中,用户可以进行以下操作:
- 浏览 collection 的所有数据点
- 查看 collection 的基本信息
- 制作和上传快照
- 对数据点进行可视化
- 删除 collection
Web UI 的其他功能这里不再一一介绍,用户可以自行探索。
更多使用教程请进一步参阅 Qdrant 文档。
参考
向量数据库:PostgreSQL + pgvector
在向量数据库:Qdrant中我们介绍了向量数据库的概念以及开源产品 Qdrant。这里我们介绍另一个优秀的开源方案:PostgreSQL + pgvector。
PostgreSQL 是一个稳定可靠、功能强大的开源对象关系型数据库系统,第一个公开版本于 1989 年发布。此后,它经历了多次迭代,并逐渐成为世界上最流行的开源数据库之一。它支持 SQL 标准,并提供复杂查询、事务完整性、多版本并发控制等多种现代数据库技术特性。PostgreSQL 以其高度的扩展性和对大型数据集的强大处理能力而闻名,适用于从小型应用程序到大型企业系统的各种环境。此外,它还拥有一个活跃的开发社区,为开发者提供丰富的资源和工具。
pgvector 是一个用于向量相似性搜索的 PostgreSQL 扩展。安装此扩展后,PostgreSQL 可以支持向量数据的存储、检索和查询等操作。
部署
安装
进入 Notebook app
的终端,添加相应的 Helm Chart repository,列出 Chart bitnami/postgresql
的所有版本:
helm repo add bitnami https://charts.bitnami.com/bitnami
# 注意 CHART VERSION 和 APP VERSION(PostgreSQL 版本)之间的对应关系
# 例如 CHART VERSION 14.1.x 中的 PostgreSQL 版本都是 16.2.0
helm search repo bitnami/postgresql --versions
安装指定版本的 Chart 并指定 t9kpublic/bitnami-pgvector
镜像,以部署包含 pgvector 的 PostgreSQL 应用:
# 安装最新版本
helm repo update bitnami
helm install pgvector-demo bitnami/postgresql \
--set image.repository=t9kpublic/bitnami-pgvector \
--set image.tag=0.6.0-pg16
# 安装指定 CHART VERSION,注意这不是 APP VERSION(PostgreSQL 版本)
helm install pgvector-demo bitnami/postgresql \
--version <CHART_VERSION> \
--set image.repository=t9kpublic/bitnami-pgvector \
--set image.tag=0.6.0-pg16
配置
以上安装全部使用默认配置,完整的默认配置请参阅 Parameters 以及相应的 values.yaml
:
# 获取指定 CHART VERSION 的 values.yaml
helm show values bitnami/postgresql --version <CHART_VERSION> > values.yaml
如果想要修改默认配置,你可以将新配置(覆盖默认配置的字段)保存为一个 YAML 文件,通过 -f
选项提供给安装命令:
# 使用修改后的 values.yaml
helm install pgvector-demo t9kpublic/bitnami-pgvector \
--version <CHART_VERSION> \
--set image.repository=t9kpublic/bitnami-pgvector \
--set image.tag=0.6.0-pg16 \
-f values.yaml
下面将分主题介绍部分关键配置(CHART VERSION 14.1.3)。
计算资源
默认配置没有指定计算资源,表示 Pod 可以无限制地使用节点的 CPU 和内存资源。你可以根据实际需求指定请求值和限制值,可以参阅管理内存用量的最佳实践。
# 默认配置
primary:
resources: {}
存储
默认配置指定的卷大小为 8Gi
,并且没有指定存储类型。你可以根据数据规模修改卷大小,并选用高性能的存储类型。
# 默认配置
primary:
persistence:
existingClaim: "" # 使用已有的 PVC
subPath: "" # 卷被挂载的子路径,用于多个服务共用一个卷
storageClass: "" # 存储类型
accessModes:
- ReadWriteOnce
size: 8Gi # 存储大小
网络
你可以按需修改 Service 配置,提供 tls 配置以提供外部安全访问。
# 默认配置
tls: # tls 配置
enabled: false
autoGenerated: false
preferServerCiphers: true
certificatesSecret: ""
certFilename: ""
certKeyFilename: ""
certCAFilename: ""
crlFilename: ""
primary:
service: # Service 配置
type: ClusterIP
ports:
postgresql: 5432
clusterIP: ""
loadBalancerIP: ""
externalTrafficPolicy: Cluster
安全
你可以设置 postgres
管理员用户的密码,
请参阅 Setting the root password on first run。
auth:
enablePostgresUser: true # 启用 postgres 管理员用户
postgresPassword: "" # postgres 管理员用户的密码
备份
你可以启用数据库的定时备份并提供相应配置。注意这里的备份方法是转储(dump)而不是快照(snapshot)。
# 默认配置
backup:
enabled: false
cronjob:
schedule: "@daily"
timeZone: ""
podSecurityContext:
enabled: true
fsGroupChangePolicy: Always
sysctls: []
supplementalGroups: []
fsGroup: 1001
containerSecurityContext:
enabled: true
seLinuxOptions: null
runAsUser: 1001
runAsNonRoot: true
privileged: false
readOnlyRootFilesystem: false
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
seccompProfile:
type: "RuntimeDefault"
command:
- /bin/sh
- -c
- "pg_dumpall --clean --if-exists --load-via-partition-root --quote-all-identifiers --no-password --file=${PGDUMP_DIR}/pg_dumpall-$(date '+%Y-%m-%d-%H-%M').pgdump"
storage:
existingClaim: ""
storageClass: ""
accessModes:
- ReadWriteOnce
size: 8Gi
subPath: ""
应用架构
应用的系统架构如下图所示(CHART VERSION 14.1.3,默认配置):
创建的主要 Kubernetes 资源如下表所示:
类型 | 名称 | 作用 | 备注 |
---|---|---|---|
Service | pgvector-demo-postgresql | 暴露 PostgreSQL 服务 | |
StatefulSet | pgvector-demo-postgresql | 部署 PostgreSQL + pgvector(包括持久化存储) | 默认计算资源为 {} |
PVC | data-pgvector-demo-postgresql-* | 作为 PostgreSQL 的持久化存储 | 默认卷大小为 8Gi |
Secret | pgvector-demo-postgresql | 存储 postgres 密钥 |
运维
查看应用的状态
helm status pgvector-demo
更新应用,下面的 image.tag
可能需要设置为其他值。
# 更新到最新版本
helm upgrade pgvector-demo t9kpublic/bitnami-pgvector \
--set image.repository=t9kpublic/bitnami-pgvector \
--set image.tag=0.6.0-pg16
# 更新到指定版本
helm upgrade pgvector-demo t9kpublic/bitnami-pgvector \
--version <CHART_VERSION> \
--set image.repository=t9kpublic/bitnami-pgvector \
--set image.tag=0.6.0-pg16
# 回滚更新,首先查看历史版本
helm history pgvector-demo
helm rollback pgvector-demo [REVISION]
移除应用
helm delete pgvector-demo
kubectl delete pvc -l app.kubernetes.io/instance=pgvector-demo
使用
继续使用 Notebook app
的终端,获取应用的密钥,并连接到 PostgreSQL 实例:
export POSTGRES_PASSWORD=$(kubectl get secret --namespace demo pgvector-demo-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)
kubectl run pgvector-demo-postgresql-client \
--rm --tty -i --restart='Never' --namespace demo \
--image docker.io/t9kpublic/bitnami-pgvector:main \
--env="PGPASSWORD=$POSTGRES_PASSWORD" \
--command -- \
psql --host pgvector-demo-postgresql -U postgres -d postgres -p 5432
使用 psql 命令启用 pgvector 扩展:
CREATE EXTENSION vector;
然后运行一个快速入门:
CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
DROP TABLE items;
接下来运行一个 Python 语言的官方示例。先安装必要的 Python 库:
pip install pgvector "psycopg[binary]" sentence_transformers
然后执行如下 Python 脚本,命令行参数需要提供连接字符串:
sentence_embeddings.py
import sys
from pgvector.psycopg import register_vector
import psycopg
from sentence_transformers import SentenceTransformer
# 创建数据库连接,并设置自动提交
conn = psycopg.connect(sys.argv[1], autocommit=True)
# 启用 pgvector 扩展,注册向量数据类型
conn.execute('CREATE EXTENSION IF NOT EXISTS vector')
register_vector(conn)
# 重新创建表 documents
conn.execute('DROP TABLE IF EXISTS documents')
conn.execute('CREATE TABLE documents (id bigserial PRIMARY KEY, content text, embedding vector(384))')
# 嵌入输入文本
input = [
'The dog is barking',
'The cat is purring',
'The bear is growling'
]
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(input)
# 将输入文本和相应的嵌入向量插入到数据库中
for content, embedding in zip(input, embeddings):
conn.execute('INSERT INTO documents (content, embedding) VALUES (%s, %s)', (content, embedding))
# 查询与指定文档最相近的其他文档的文本内容
document_id = 1
neighbors = conn.execute('SELECT content FROM documents WHERE id != %(id)s ORDER BY embedding <=> (SELECT embedding FROM documents WHERE id = %(id)s) LIMIT 5', {'id': document_id}).fetchall()
for neighbor in neighbors:
print(neighbor[0])
export POSTGRES_PASSWORD=$(kubectl get secret --namespace demo pgvector-demo-postgresql -o jsonpath="{.data.postgres-password}" | base64 -d)
python pgvector-test.py "host=pgvector-demo-postgresql port=5432 dbname=postgres user=postgres password=$POSTGRES_PASSWORD"
脚本创建了一个表,添加了一些向量数据,并进行了一次基本的向量查询。输出应类似于:
The bear is growling
The cat is purring
更多信息请参阅 pgvector 的 README 文档。
参考
背景
人工智能(AI)技术的发展已经取得了显著的成果,并对各行业的发展产生了深远的影响。其中最为突出的成就是以深度学习为基础在计算机视觉、LLM 等领域的突破性成果。
AI 计算平台对于 AI 技术的开发和应用具有重要意义。它提供了一个集成化、高效的环境,让开发者和企业能够轻松地构建、训练和部署机器学习模型。这种便捷性极大地降低了 AI 技术的门槛,使得更多的组织和个人能够利用先进的 AI 能力。
- AI 计算平台通过提供高级的 AI 开发工具和预构建的模型,简化了 AI 开发流程。开发者不需要从头开始构建复杂的模型,而是可以基于现有的模型进行定制和优化,这加速了从概念到实现的过程。
- AI 计算平台提供了大规模的计算资源和数据管理能力,这对于处理大量数据和运行复杂的 AI 模型至关重要。用户可以根据需要轻松扩展资源,以适应不断变化的需求。
- 平台还包含丰富的协作和集成工具,使得团队可以更有效地合作开发。此外,它们还提供了严格的安全和隐私保护措施,保证了数据的安全性和合规性。
新的范式
AI 是一种崭新的计算范式,它具有数据驱动、基于实验的特点,并且经常需要进行大规模的计算。
- 在传统软件开发中,程序员编写明确的指令或规则,来告诉计算机如何处理数据和执行任务。这种方法依赖于开发者对问题的深入理解以及能够准确预测所有可能的情况并据此编写代码。
- 相比之下,AI 的开发更多地依赖于数据而不是预设的规则。在这种模式下,AI 系统通过大量数据来学习和识别模式,然后基于这些学习成果做出判断或预测。开发者不是直接编写处理每种情况的代码, 而是设计算法来让计算机自我学习和适应。这意味着 AI 系统在面对新数据时可以持续改进其性能和准确性。
- 此外,AI 开发通常需要更多关注于数据的收集、处理和分析。数据的质量和量直接影响到模型的性能,因此数据预处理成为 AI 开发中的一个重要步骤。而在传统软件开发中,主要关注的是逻辑的构建和代码的优化。
总的来说,AI 的数据驱动计算范式更加强调数据本身和从数据中学习的能力,而不是像传统软件那样依赖于硬编码的指令和规则。 这种方法使得 AI 在处理复杂、动态和模糊的问题时更加有效,但也带来了对数据质量和巨大计算处理能力的依赖。
系统需求
由于 AI 技术的特性,用户在开发和使用 AI 过程中,在系统方面提出了多方面的需求,希望能够:
- 方便地构建、使用和迭代数据集、模型架构和参数,以及
- 简单、可靠地使用大规模分布式并行、异构和加速计算等技术来快速、高效地运行大规模的数据处理、训练和推理计算等。
数据
AI 计算过程中读取或者产生的数据可以分为两类:主干数据、元数据。
- 主干数据:训练数据集、模型等大体量数据。
- 元数据:计算过程中的各种配置、超参数、指标等。
用户希望通过一致、多维度高度可扩展的机制来支持对数据的各种操作。例如,训练数据无论是100KiB 还是 100TiB,都能够使用同一套工具、SDK,API:
- 方便地使用数据:能够在探索、实验、训练过程中,简单、快速地使用不同的数据;
- 高性能地使用数据:支持训练过程中对数据的高速读取(训练数据集)、写入(checkpoint,模型本身);
- 可靠地维护数据:
- 像代码一样维护数据版本 (versioning);
- 记录数据的变化历史 (commits and logs);
- 隔离 (branches)。
- 对 AI 计算过程中的配置、超参数、脚本、各种指标等,提供方便、完善的支持:
- 元数据管理系统为基础底座;
- SDK 支持在各种场景进行集成;
- 可视化工具方便地跟踪、展示、比较、分析多个实验过程。
计算
用户希望能够通过便捷的方式使用大规模分布式并行、异构、加速计算等技术以快速、高效地运行大规模的数据处理、训练和推理计算等。
AI 计算场景的典型需求:
类别 | 需求说明 |
---|---|
软件包依赖 | 清晰、一致、方便地管理对 Pyhton 脚本、GPU 驱动程序、网络驱动程序等各种软件包的依赖 |
计算环境 | 支持在 dev、 train、test、deploy 等环境方便地切换、迭代 |
数据、代码 | 高效、便捷地使用数据、脚本、配置及跟踪它们的变化 |
计算资源 | 快速、简单、方便地请求和使用各种计算资源:CPU、RAM、GPU、高速网络、存储… |
运行计算 | 可靠、简单、方便地运行个各种类型的计算:开发环境、并行训练、微调、数据处理、推理服务… |
Kubernetes
Kubernetes 是一个灵活、可扩展的容器集群管理平台,它通过 Master 节点的集中控制和调度,工作节点(Worker Nodes) 负责运行应用工作负载。工作节点可方便地动态伸缩规模。
如上图所示,Kubernetes 的整体架构主要包含以下组件:
Master 节点: Master 节点负责整个集群的控制和管理。主要包含以下组件:
- kube-apiserver:提供了资源操作的统一入口,以 RESTful API 方式提供服务。
- etcd:负责存储集群的配置信息和资源状态。
- kube-scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的节点上。
- kube-controller-manager: 负责管理控制器,确保集群处于预期的状态。
Node节点:Node 节点是 Kubernetes 集群中的工作节点,由 Master 节点管理,主要包含以下组件:
- kubelet:负责管理 Node 节点上的 Pod 和容器的生命周期。
- kube-proxy:负责为 Service 提供 cluster 内部的服务发现和负载均衡。
- 容器运行时(containerd,CRI-O,Docker 等): 负责真正运行容器的软件。
Kubernetes 还包括其他辅助模块(Add-ons),例如:
- DNS 模块:负责为集群中的主机提供 DNS 解析服务。
- 网络插件:负责提供底层的网络实现,例如 flannel 和 calico。
- 参数模块:提供配置管理功能。
- 仪表板插件:提供 GUI。
- 存储插件:提供持久化存储实现,例如 Ceph 和 Luster 。
- 日志模块:提供日志收集、存储功能。
- 安全模块:提供认证、授权、准入控制等安全功能。
TensorStack AI 计算平台
TensorStack AI 计算平台构建于以 Kubernetes 为核心的云原生技术,采用开放的、标准的、被普遍采用的、无厂商锁定风险的技术和协议,并能够:
- 长期稳定迭代、不断进步;
- 提供高度可靠性;
- 提供高度安全性;
- 支持在多个维度(计算规模、数据规模、硬件架构等)方便进行扩展。
TensorStack 对 AI 计算中的主要系统问题及解决方法:
-
软件包依赖
采用容器镜像清晰、一致、方便地管理对 Pyhton 脚本、GPU 驱动程序、网络驱动程序等各种软件包的依赖:
- 稳定的基础镜像:跟随框架(PyTorch)等主要依赖发布; - 镜像全流程支持:制作、发布到 Registry、运行。
-
计算环境
采用 Infrastructure As Code 原则 + 容器镜像 + 网络存储的机制支持在 dev、 train、test、deploy 等环境方便地切换、迭代数据、代码。
-
数据、代码
通过网络存储 + 服务(Version Control,AI DB,Experiment Management 等)支持高效、便捷地使用数据、脚本、配置及跟踪它们的变化。
-
计算资源
通过 CRD controller + resource scheduler,实现快速、简单、方便地请求和使用各种计算资源:CPU、RAM、GPU、高速网络、存储…
-
运行计算
T9k Jobs + Services 等实现可靠、简单、方便地运行个各种类型的计算:开发环境、并行训练、微调、数据处理、推理服务…
TensorStack AI 计算平台将在推动 AI 技术的普及和应用方面发挥着关键作用,为各行各业提供实现 AI 驱动创新的关键工具和资源。
参考
Infrastructure for deep learning, 2016
https://openai.com/research/infrastructure-for-deep-learning
Scaling Kubernetes to 2,500 nodes, 2018
https://openai.com/research/scaling-kubernetes-to-2500-nodes
Scaling Kubernetes to 7,500 nodes, 2021
https://openai.com/research/scaling-kubernetes-to-7500-nodes
Borg, Omega, and Kubernetes - Lessons learned from three container-management systems over a decade, 2016
https://queue.acm.org/detail.cfm?id=2898444
Large-scale cluster management at Google with Borg, 2015
https://research.google/pubs/pub43438/
Omega: flexible, scalable schedulers for large compute clusters, 2013
https://research.google/pubs/pub41684/
Kubernetes as a Platform for building Platforms with Mario-Leander Reimer, 2022
https://www.youtube.com/watch?v=wDMbBSVNzWY
Cloud-native computing
https://en.wikipedia.org/wiki/Cloud-native_computing
Cloud Native Computing Foundation
https://www.cncf.io/
Infrastructure As Code
https://en.wikipedia.org/wiki/Infrastructure_as_code