Skip to main content

GPU Training Nodes

GPU Training Nodes

Provision a raw GPU VM (a DigitalOcean droplet), run a training or fine-tuning job on it, then destroy it. Unlike Dedicated GPU Deployments, which serve a model steady-state, a training node is burst compute you spin up, train on, and tear down.

Base path: /api/v1/public/deployments/gpu-training


Inference vs Training — which do I want?

Dedicated DeploymentGPU Training Node
PurposeServe a modelTrain / fine-tune a model
Mental modelKept warm, latency-optimizedSpin up → train → tear down
You interact viachat/completions proxySSH or cloud-init on a raw VM
BackingDO dedicated inferenceDO GPU droplet
Best forProduction / low-latency servingFine-tunes, experiments, batch jobs

Rule of thumb: if you want to send requests to it, use a Dedicated Deployment. If you want to run python train.py on it, use a GPU Training Node.


Endpoints

MethodPathAuthDescription
GET/deployments/gpu-training/sizesNoList GPU droplet sizes + live pricing
POST/deployments/gpu-trainingYesProvision a node
GET/deployments/gpu-training/{droplet_id}YesGet status + public IP
DELETE/deployments/gpu-training/{droplet_id}YesDestroy the node (stops billing)

List GPU sizes

No authentication required.

curl https://api.ainative.studio/api/v1/public/deployments/gpu-training/sizes

Response (200):

{
"sizes": [
{ "slug": "gpu-mi300x8-1536gb", "label": "AMD MI300X ×8 (1536GB VRAM)", "hourly_cost_usd": 15.92, "vram_gb": 1536 },
{ "slug": "gpu-h100x8-640gb", "label": "NVIDIA H100 ×8 (640GB VRAM)", "hourly_cost_usd": 23.92, "vram_gb": 640 },
{ "slug": "gpu-mi300x1-192gb", "label": "AMD MI300X ×1 (192GB VRAM)", "hourly_cost_usd": 1.99, "vram_gb": 192 },
{ "slug": "gpu-h100x1-80gb", "label": "NVIDIA H100 ×1 (80GB VRAM)", "hourly_cost_usd": 3.39, "vram_gb": 80 }
]
}

Prices come from DigitalOcean's live catalog at request time. The gpu-mi300x8-1536gb node (1,536 GB VRAM) is large enough to fine-tune GLM-5-class models.


Provision a node

import requests

API_KEY = "sk_your_key"
BASE = "https://api.ainative.studio/api/v1/public"
H = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

node = requests.post(
f"{BASE}/deployments/gpu-training",
headers=H,
json={
"name": "glm5-finetune",
"size_slug": "gpu-mi300x8-1536gb", # default
"region": "atl1", # default
"ssh_key_ids": [12345678], # OR user_data — at least one required
},
).json()

print(node["droplet_id"], node["hourly_cost_usd"])

Request body:

FieldTypeRequiredDefaultDescription
namestringYesNode name
size_slugstringNogpu-mi300x8-1536gbGPU droplet size
regionstringNoatl1DigitalOcean region
ssh_key_idslist[int]No*DO SSH key IDs to inject (interactive access)
user_datastringNo*cloud-init script run on first boot (hands-off jobs)
At least one access method is required

You must supply ssh_key_ids, user_data, or both. A node with neither would be unreachable and would bill idle — the API rejects it with 400.

Response (201):

{
"droplet_id": 987654321,
"name": "glm5-finetune",
"status": "new",
"size_slug": "gpu-mi300x8-1536gb",
"hourly_cost_usd": 15.92
}

Check status

curl https://api.ainative.studio/api/v1/public/deployments/gpu-training/987654321 \
-H "Authorization: Bearer $TOKEN"

Response (200):

{ "droplet_id": 987654321, "status": "active", "public_ip": "203.0.113.42" }

Poll until status is active and public_ip is populated before connecting.


Destroy the node

curl -X DELETE https://api.ainative.studio/api/v1/public/deployments/gpu-training/987654321 \
-H "Authorization: Bearer $TOKEN"

Response (200):

{ "destroyed": true, "droplet_id": 987654321 }

Billing stops the moment the node is destroyed.


Cost model

Billing runs from boot (POST) to destroy (DELETE) — the whole wall-clock window, including boot, model download, and weight load, not just the training loop. On large 8×GPU nodes, cold-start is a real fraction of the bill.

Batch experiments on one hot node to amortize cold-start: pull weights once, then iterate, rather than provisioning a fresh node per run.


Hands-off pattern with cloud-init

Pass a cloud-init script as user_data to run a fully unattended job. A robust pattern is: train → merge → push the adapter → self-destruct. The node destroys itself on completion by calling the same DELETE /gpu-training/{id} endpoint with a short-lived AINative bearer token, so it never bills idle after the job finishes.

cloud_init = """#!/bin/bash
set -euo pipefail

# 1. train + merge + push the adapter to Hugging Face
python train.py && python merge_and_push.py

# 2. self-destruct — stop billing immediately on completion
curl -X DELETE \
"https://api.ainative.studio/api/v1/public/deployments/gpu-training/${DROPLET_ID}" \
-H "Authorization: Bearer ${AINATIVE_TOKEN}"
"""

node = requests.post(
f"{BASE}/deployments/gpu-training",
headers=H,
json={"name": "unattended-finetune", "user_data": cloud_init},
).json()
Self-destruct guarantee

When the job finishes (success or failure), the node calls DELETE /deployments/gpu-training/{droplet_id} on itself. Combined with the ainative-gpu-training tag applied to every node on DigitalOcean, this makes idle spend easy to prevent and orphaned nodes easy to find and clean up.

Only a scoped AINative token needs to reach the node — you never place a raw DigitalOcean API key on the VM.


Next steps