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 Deployment | GPU Training Node | |
|---|---|---|
| Purpose | Serve a model | Train / fine-tune a model |
| Mental model | Kept warm, latency-optimized | Spin up → train → tear down |
| You interact via | chat/completions proxy | SSH or cloud-init on a raw VM |
| Backing | DO dedicated inference | DO GPU droplet |
| Best for | Production / low-latency serving | Fine-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
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /deployments/gpu-training/sizes | No | List GPU droplet sizes + live pricing |
POST | /deployments/gpu-training | Yes | Provision a node |
GET | /deployments/gpu-training/{droplet_id} | Yes | Get status + public IP |
DELETE | /deployments/gpu-training/{droplet_id} | Yes | Destroy 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:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | — | Node name |
size_slug | string | No | gpu-mi300x8-1536gb | GPU droplet size |
region | string | No | atl1 | DigitalOcean region |
ssh_key_ids | list[int] | No* | — | DO SSH key IDs to inject (interactive access) |
user_data | string | No* | — | cloud-init script run on first boot (hands-off jobs) |
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()
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
- Dedicated GPU Deployments — serve a model on reserved GPU capacity
- Inference Overview — chat completions, embeddings, rerank, audio
- Authentication — API keys and bearer tokens