Enterprise LLM Studio API Quickstart Guide
This notebook shows how to use the Enterprise LLM Studio API to manage projects, datasets, data generation, experiments, and deployments.
What you’ll do:
- List/create/update projects
- Upload and manage datasets
- Run data generation
- Validate, start, and monitor experiments
- Get next-best-experiment suggestions (KGM)
- Create and manage deployments
- Run AutoML to explore configurations
Generate Your API Key​
To authenticate with the API, you’ll need to generate a personal API key:
- Log in to your H2O Enterprise LLM Studio environment.
- Click on your name in the top-right corner, then select API Keys.
- If no key has been generated yet, click Generate New API Key.
- You’ll be shown the key only once — make sure to copy it to a safe location immediately.
Note
Lost it? Just generate a new one — this will invalidate any existing key.
- After generation, you’ll see your key listed (e.g.
<your name>'s API Key
) with usage status and timestamp.
Before you begin​
First import the required packages.
# import required packages
import os
import requests
from pathlib import Path
import json
# Config
BASE_URL = os.getenv("LLM_STUDIO_BASE_URL")
TOKEN = os.getenv("LLM_STUDIO_TOKEN")
if not TOKEN:
raise SystemExit("Set LLM_STUDIO_TOKEN")
headers = {
"Accept": "application/json",
"Authorization": f"Bearer {TOKEN}",
}
1. Projects​
List all projects available to your token in the workspace.
resp = requests.get(BASE_URL+"/api2/api/projects", headers=headers, timeout=60)
resp.raise_for_status()
projects = resp.json()
print("Projects:")
for i, p in enumerate(projects, 1):
pid = p.get("project_id")
name = p.get("name")
print(f"{i}. {name} -> {pid}")
Create new project​
payload = {
"name": "New Project",
"description": "Created via API",
"visibility": "private",
}
resp = requests.post(BASE_URL + "/api2/api/projects", headers=headers, json=payload, timeout=60)
resp.raise_for_status()
project = resp.json()
print("Created Project:")
pid = project.get("project_id")
name = project.get("name")
print(f"{name} -> {pid}")
Fetch project details using project ID​
project_id = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
resp = requests.get(f"{BASE_URL}/api2/api/projects/{project_id}", headers=headers, timeout=60)
resp.raise_for_status()
project = resp.json()
print("Project:")
pid = project.get("project_id")
name = project.get("name")
description = project.get("description")
visibility = project.get("visibility")
print(f"""Name : {name}
ID : {pid}
Description: {description}
Visibility : {visibility}""")
Update project settings​
Update the name, description and visibility.
project_id = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
payload = {
"name": "Project Name Updated",
"description": "Updated Description",
"visibility": "private", # or "public"
}
resp = requests.put(f"{BASE_URL}/api2/api/projects/{project_id}", headers=headers, json=payload, timeout=60)
resp.raise_for_status()
project = resp.json()
name = project.get("name", "")
pid = project.get("project_id")
description = project.get("description", "")
visibility = project.get("visibility", "")
print(f"""Name : {name}
ID : {pid}
Description: {description}
Visibility : {visibility}""")
2. Data Generation​
Start a data generation job​
Start a synthetic data generation job with prompts, seeds, and generator settings.
project_id = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
datagen_payload = {
"datagen_name": "generate customer review v5", #datagen name
"problem_type": "datagen_generate_rows",
"dataset": {"n_rows": 10},
"transform": {
"llm_model_name": "gpt-4o-mini",
"max_new_tokens": 512,
"temperature": 0.2,
"suggestion": "Make the config better",
#####-------
"seed_data_dict": "{ \"aspects\": [\"network_connectivity\", \"billing_payment\", \"account_access\"], \"resolution_status\": [\"resolved\", \"unresolved\"] }"
,
"system_prompt_template": "You are a customer-service telco call summary generator that produces concise, realistic synthetic summaries in 3–6 factual, neutral, and specific sentences using active voice",
"user_prompt_template": "Please write a telco customer-care call summary in a factual, neutral, and specific tone that focuses on one or more of these {aspects}, with a {resolution_status}.",
######-------
"parse_these_columns_from_response": ""
},
"logging": {},
"project_id": project_id
}
resp = requests.post(f"{BASE_URL}/api2/api/datagen", headers=headers, json=datagen_payload, timeout=60)
resp.raise_for_status()
out = resp.json()
datagen_id = out.get("datagen_id")
status = out.get("status")
message = out.get("message", "")
print(f"Started datagen -> {datagen_id} [{status}]")
List data generation jobs​
project_id = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
resp = requests.get(
f"{BASE_URL}/api2/api/datagens",
params={"project_id": project_id},
headers=headers,
timeout=60,
)
resp.raise_for_status()
datagens = resp.json()
print("Datagens (newest first):")
for i, d in enumerate(datagens, 1):
did = d.get("datagen_id")
name = d.get("datagen_name")
status = d.get("status")
created = d.get("created_at")
print(f"{did} [{status}] created: {created}")
3. Datasets​
Upload, view, and delete datasets.
Upload data​
# Local file to upload
FILE_PATH = "feedback.csv" #replace with your file path
DATASET_NAME = "feedback_snowflake" #replace with your dataset name
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
form = {
"project_id": PROJECT_ID,
"name": DATASET_NAME,
}
file_path = Path(FILE_PATH)
if not file_path.exists():
raise SystemExit(f"File not found: {file_path}")
with open(file_path, "rb") as f:
files = {
"file": (file_path.name, f, "application/octet-stream"),
}
print(f"POST {BASE_URL} -> uploading {file_path.name} to project {PROJECT_ID}")
resp = requests.post(f"{BASE_URL}/api2/api/datasets/upload", headers=headers, data=form, files=files, timeout=600)
print("Status:", resp.status_code)
if resp.headers.get("content-type", "").startswith("application/json"):
print(json.dumps(resp.json(), indent=2))
else:
print(resp.text)
List the datasets​
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
resp = requests.get(f"{BASE_URL}/api2/api/datasets?project_id={PROJECT_ID}", headers=headers, timeout=60)
if resp.status_code == 200:
data = resp.json()
print("Datasets:")
if not data:
print(" (none)")
else:
for i, ds in enumerate(data, 1):
did = ds.get("dataset_id")
name = ds.get("name")
created = ds.get("created_at")
print(f"{i}. Name : {name}")
print(f" ID : {did}")
print(f" Created : {created}\n")
extras = {k: v for k, v in ds.items() if k not in {"dataset_id","id","name","dataset_name","status","created_at","created_on","size","row_count","num_rows"}}
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/roles and project permissions.")
print(resp.text)
else:
print(f"Error {resp.status_code}: {resp.text}")
Get dataset by ID​
DATASET_ID = "f653e0f6-ab3a-4843-8033-e1d2964cc9f2" #replace with your dataset ID
resp = requests.get(f"{BASE_URL}/api2/api/datasets/{DATASET_ID}", headers=headers, timeout=60)
if resp.status_code == 200:
data = resp.json()
print("Dataset:")
fields = ["dataset_id", "project_id", "name", "file_type", "size_bytes",
"created_at", "row_count", "columns", "file_url"]
for k in fields:
if k in data:
print(f"- {k}: {data[k]}")
elif resp.status_code == 404:
print("Dataset not found (404). Check DATASET_ID.")
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/permissions for this dataset/project.")
elif resp.status_code == 422:
print("Validation error (422). Ensure dataset_id format is correct.")
else:
print(f"Error {resp.status_code}: {resp.text[:1000]}")
Delete dataset by ID​
DATASET_ID = "f653e0f6-ab3a-4843-8033-e1d2964cc9f2" #replace with your dataset ID
resp = requests.delete(f"{BASE_URL}/api2/api/datasets/{DATASET_ID}", headers=headers, timeout=60)
if resp.status_code == 200:
print("Deleted:", resp.json())
elif resp.status_code == 404:
print("Dataset not found (404).")
elif resp.status_code == 403:
print("Access denied (403). Check permissions.")
elif resp.status_code == 422:
print("Validation error (422). Check dataset_id format.")
else:
print(f"Error {resp.status_code}: {resp.text[:1000]}")
4. Experiments​
Validate the experiment config and create, list, and delete experiments.
List experiments​
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
LIMIT = 20 # optional
params = {"project_id": PROJECT_ID}
if LIMIT is not None:
params["limit"] = LIMIT
try:
resp = requests.get(f"{BASE_URL}/api2/api/datasets/", headers=headers, params=params, timeout=60)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
print(f"HTTP {resp.status_code} error:\n" + json.dumps(resp.json(), indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
experiments = resp.json()
print("Experiments (newest first):")
if not experiments:
print(" (none)")
else:
for i, exp in enumerate(experiments, 1):
eid = exp.get("experiment_id")
name = exp.get("name")
status = exp.get("status")
created = exp.get("created_at")
train_ds = exp.get("train_dataset_name")
val_ds = exp.get("validation_dataset_name")
error = (exp.get("error") or "").strip()
print(f"{i}. Name : {name}")
print(f" ID : {eid}")
print(f" Status : {status}")
print(f" Created : {created}")
print(f" Train DS : {train_ds}")
print(f" Val DS : {val_ds}")
if error:
print(f" Error : {error[:300]}")
Check experiment config​
Experiment config:​
- TRAINING_MODE (training_mode)
- Options: 'lora' | 'qlora' | 'full'
- Default: 'lora'
- Notes: LoRA = fastest; QLoRA = least VRAM; Full = most compute/memory.
- DATA_SAMPLE_FRACTION (dataset.data_sample)
- Type: float in 0, 1 ; Default: 1
- DATASET_ID (dataset.train_dataset_id)
- Type: str (UUID)
- Notes: Required. Must match an uploaded dataset ID.
- PROMPT_COLUMN (dataset.prompt_column)
- Type: str; Default: "instruction"
- Notes: Input text column in your dataset (e.g., "input").
- ANSWER_COLUMNS (dataset.answer_column)
- Type: list[str] | str | None; Default: "output"
- Notes: Use list for multi-target; single string for single target.
- VALIDATION_STRATEGY (dataset.validation_strategy)
- Options: 'automatic' | 'custom'
- Default: 'automatic'
- Notes: 'automatic' splits train by
validation_size
; 'custom' expects separate validation data/id.
- VALIDATION_SIZE (dataset.validation_size)
- Type: float in (0,1); Default: 0.2
- Notes: Used only when
validation_strategy='automatic'
.
- MAX_SEQ_LENGTH (tokenizer.max_length)
- Type: int; Default: 512
- Notes: Truncation/padding length; lower to save memory.
- PREDICTION_METRICS (prediction.metrics)
- Type: list[str]; Default: []
- Classification examples: "AUC", "Accuracy".
- Language Modeling: "BLEU", "Perplexity"
- EXPERIMENT_NAME (experiment_name)
- Type: str; Default: "experiment"
- Notes: Display name for the run.
- PROJECT_ID (project_id)
- Type: str (UUID)
- Notes: Target project container for all resources.
- LLM_BACKBONE (llm_backbone)
- Type: str (Hugging Face model id); Default: "h2oai/h2o-danube3-500m-chat"
- PROBLEM_TYPE (problem_type)
- Options: 'text_causal_language_modeling' | 'text_causal_classification_modeling'
- Default: 'text_causal_language_modeling'
- Notes: Use classification for tasks like sentiment/topic classification.
Multi-target classification experiment setup​
# === Editable knobs ===
TRAINING_MODE = "lora" # training_mode
DATA_SAMPLE_FRACTION = 1.0 # data_sample (1.0 = use all data)
DATASET_ID = "7cb76178-6907-4610-a882-a766e4d84fdf" # dataset id
PROMPT_COLUMN = "input" # prompt_column
ANSWER_COLUMNS = [ # answer_column (multi-target) or (single-target)
"question_is_billing_issue",
"question_was_issue_resolved",
"question_is_technical_issue",
]
VALIDATION_STRATEGY = "automatic" # validation_strategy
VALIDATION_SIZE = 0.2 # validation_size
MAX_SEQ_LENGTH = 512 # tokenizer.max_length
TRAIN_BATCH_SIZE = 1 # training.batch_size
NUM_EPOCHS = 1 # training.epochs
LEARNING_RATE = 1e-4 # training.learning_rate
PREDICTION_METRICS = ["AUC","Accuracy"] # prediction.metrics
EXPERIMENT_NAME = "telco_v3_test" # experiment_id
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" # project_id
LLM_BACKBONE = "h2oai/h2o-danube3-500m-chat" # llm_backbone
PROBLEM_TYPE = "text_causal_classification_modeling" # text_causal_classification_modeling
# ======================
payload = {
"architecture": {
"training_mode": TRAINING_MODE,
"gradient_checkpointing": True,
"intermediate_dropout": 0,
"backbone_kwargs": "{}"
},
"dataset": {
"data_sample_choice": ["Train", "Validation"],
"data_sample": DATA_SAMPLE_FRACTION,
"prompt_column": PROMPT_COLUMN,
"answer_column": ANSWER_COLUMNS,
"train_dataset_id": DATASET_ID,
"validation_strategy": VALIDATION_STRATEGY,
"validation_size": VALIDATION_SIZE,
"unroll_conversations": False
},
"environment": {
"find_unused_parameters": False,
"huggingface_branch": "main",
"mixed_precision": True,
"use_fsdp": False,
"use_fsdp_cpu_offload": False,
"seed": -1,
"trust_remote_code": True
},
"tokenizer": {
"max_length": MAX_SEQ_LENGTH,
"padding_quantile": 1,
"tokenizer_kwargs": "{\"use_fast\": true, \"add_prefix_space\": false}"
},
"training": {
"attention_implementation": "auto",
"batch_size": TRAIN_BATCH_SIZE,
"differential_learning_rate_layers": [],
"differential_learning_rate": 1e-5,
"epochs": NUM_EPOCHS,
"evaluate_before_training": True,
"evaluation_epochs": 1,
"grad_accumulation": 1,
"gradient_clip": 0,
"learning_rate": LEARNING_RATE,
"lora_alpha": 16,
"lora_dropout": 0.05,
"lora_rank": 4,
"lora_target_modules": "",
"min_learning_rate_ratio": 0,
"optimizer": "AdamW",
"schedule": "Cosine",
"train_validation_data": False,
"use_length_based_sampler": True,
"warmup_epochs": 0,
"weight_decay": 0
},
"logging": {},
"prediction": {
"batch_size_inference": 0,
"max_length_inference": 128,
"metrics": PREDICTION_METRICS,
"min_length_inference": 2,
"num_beams": 1,
"repetition_penalty": 1,
"temperature": 0,
"top_k": 0,
"top_p": 1
},
"experiment_name": EXPERIMENT_NAME,
"project_id": PROJECT_ID,
"reference_experiment_ids": [],
"llm_backbone": LLM_BACKBONE,
"problem_type": PROBLEM_TYPE
}
try:
resp = requests.post(f"{BASE_URL}/api2/api/train/validate", headers=headers, json=payload, timeout=120)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
print(f"HTTP {resp.status_code} error:\n" + json.dumps(resp.json(), indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
result = resp.json()
valid = result.get("valid")
errors = result.get("errors")
warnings = result.get("warnings")
print("Validation result:")
print(f" valid : {valid}")
if errors:
print(" errors :")
for e in errors:
print(f" - {e}")
if warnings:
print(" warnings:")
for w in warnings:
print(f" - {w}")
Start experiment​
try:
resp = requests.post(f"{BASE_URL}/api2/api/train", headers=headers, json=payload, timeout=120)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
print(f"HTTP {resp.status_code} error:\n" + json.dumps(resp.json(), indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
out = resp.json()
exp_id = out.get("experiment_id")
status = out.get("status")
message = out.get("message", "")
print("Training started:")
print(f" experiment_id : {exp_id}")
print(f" status : {status}")
if message:
print(f" message : {message}")
Check experiment status​
EXPERIMENT_ID = "9619dfb4-b298-4ea6-b409-c7c3606087fa" #replace with your experiment ID
try:
resp = requests.get(f"{BASE_URL}/api2/api/experiments/{EXPERIMENT_ID}/status", headers=headers, timeout=60)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
err = resp.json()
print(f"HTTP {resp.status_code} error:\n" + json.dumps(err, indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
status = resp.json()
fields = {
"ETA": status.get("eta", "N/A"),
"HF Repo ID": status.get("hf_repo_id"),
"Num GPUs": status.get("num_gpus"),
"Price per GPU hour": status.get("price_per_gpu_hour"),
"Runtime": status.get("runtime"),
"Status": status.get("status"),
}
print("Experiment Status Summary")
print("-------------------------")
print(f"ETA : {fields['ETA']}")
print(f"Num GPUs : {fields['Num GPUs']}")
print(f"Price per GPU hour : {fields['Price per GPU hour']}")
print(f"Runtime : {fields['Runtime']}")
print(f"Status : {fields['Status']}")
Ask KGM​
EXPERIMENT_ID = "9619dfb4-b298-4ea6-b409-c7c3606087fa" # the reference experiment's ID to base suggestions on
try:
resp = requests.post(f"{BASE_URL}/api2/api/agents/next-best-experiment/{EXPERIMENT_ID}", headers=headers, timeout=120)
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
if resp.status_code == 200:
try:
data = resp.json()
except ValueError:
raise SystemExit(f"Unexpected response format:\n{resp.text[:1000]}")
print("Next-Best-Experiment Recommendation:")
print(json.dumps(data, indent=2))
cfg = data.get("config") or data.get("payload") or {}
for k in [
("llm_backbone", cfg.get("llm_backbone")),
("training.learning_rate", cfg.get("training", {}).get("learning_rate") if isinstance(cfg.get("training"), dict) else None),
("training.batch_size", cfg.get("training", {}).get("batch_size") if isinstance(cfg.get("training"), dict) else None),
("training.epochs", cfg.get("training", {}).get("epochs") if isinstance(cfg.get("training"), dict) else None),
("architecture.training_mode", cfg.get("architecture", {}).get("training_mode") if isinstance(cfg.get("architecture"), dict) else None),
]:
if k[1] is not None:
print(f" - {k[0]}: {k[1]}")
else:
print(f"Error {resp.status_code}")
try:
print(json.dumps(resp.json(), indent=2))
except ValueError:
print(resp.text[:2000])
Delete experiment​
EXPERIMENT_ID = "9619dfb4-b298-4ea6-b409-c7c3606087fa" #replace with your experiment ID
try:
resp = requests.delete(f"{BASE_URL}/api2/api/experiments/{EXPERIMENT_ID}", headers=headers, timeout=60)
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
if resp.status_code == 200:
try:
data = resp.json()
except ValueError:
data = {"message": resp.text.strip() or "Deleted"}
print("Deleted experiment:")
print(json.dumps(data, indent=2))
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/roles and project permissions.")
print(resp.text[:1000])
elif resp.status_code == 404:
print("Experiment not found (404). Verify EXPERIMENT_ID.")
print(resp.text[:1000])
elif resp.status_code == 422:
print("Validation error (422). The EXPERIMENT_ID format may be invalid.")
else:
print(f"Error {resp.status_code}:")
5. Deployments​
Create a deployment, check the live status of a deployment, and list deployments.
Create a deployment​
EXPERIMENT_ID = "6decfbe4-3e2f-4909-a195-83d7586cebcb" # from a completed training run <replace>
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" # the project to attach the deployment to <replace>
DEPLOYMENT_NAME = "my-deployment-v2"
params = {
"project_id": PROJECT_ID,
"experiment_id": EXPERIMENT_ID,
"name" : DEPLOYMENT_NAME
}
try:
resp = requests.post(f"{BASE_URL}/api2/api/deployments/create_deployment/{EXPERIMENT_ID}", headers=headers, params=params, timeout=120)
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
if resp.status_code == 200:
try:
data = resp.json()
except ValueError:
raise SystemExit(f"Unexpected response format: {resp.text[:1000]}")
print("Deployment created:")
print(json.dumps(data, indent=2))
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/roles and project permissions.")
print(resp.text[:1000])
elif resp.status_code == 404:
print("Not found (404). The experiment_id may not exist or is not visible in this project.")
print(resp.text[:1000])
elif resp.status_code == 422:
print("Validation error (422). Verify experiment_id format and required params.")
else:
print(f"Error {resp.status_code}:")
List existing deployments​
PROJECT_ID = "6b62cd37-3080-490f-ba00-af911bb15981" #replace with your project ID
params = {"project_id": PROJECT_ID}
try:
resp = requests.get(f"{BASE_URL}/api2/api/deployments", headers=headers, params=params, timeout=60)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
print(f"HTTP {resp.status_code} error:\n" + json.dumps(resp.json(), indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
deployments = resp.json()
if deployments:
print("\nSummary:")
for d in deployments:
print("-" * 60)
print(f"deployment_id : {d.get('deployment_id')}")
print(f"name : {d.get('name')}")
print(f"project_id : {d.get('project_id')}")
print(f"experiment_id : {d.get('experiment_id')}")
print(f"status : {d.get('status')}")
print(f"url : {d.get('url')}")
print(f"url_internal : {d.get('url_internal')}")
print(f"created_at : {d.get('created_at')}")
print(f"started_at : {d.get('started_at')}")
print(f"updated_at : {d.get('updated_at')}\n")
else:
print("No deployments found for this project.")
Check the status of the deployment​
DEPLOYMENT_ID = "5bd560ec-bdd1-4a42-bcda-3ea8a4e48e80" #replace with your deployment ID
try:
resp = requests.get(f"{BASE_URL}/api2/api/deployments/{DEPLOYMENT_ID}", headers=headers, timeout=60)
resp.raise_for_status()
except requests.exceptions.HTTPError:
try:
print(f"HTTP {resp.status_code} error:\n" + json.dumps(resp.json(), indent=2))
except Exception:
print(f"HTTP {resp.status_code} error:\n{resp.text[:2000]}")
raise
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
status = resp.json()
# Nice summary
print("Deployment Status")
print("-----------------")
print(f"deployment_id : {status.get('deployment_id')}")
print(f"project_id : {status.get('project_id')}")
print(f"name : {status.get('name')}")
print(f"experiment_id : {status.get('experiment_id')}")
print(f"status : {status.get('status')}")
print(f"url : {status.get('url')}")
print(f"url_internal : {status.get('url_internal')}")
print(f"created_at : {status.get('created_at')}")
print(f"started_at : {status.get('started_at')}")
print(f"updated_at : {status.get('updated_at')}\n")
Delete deployment​
DEPLOYMENT_ID = "5bd560ec-bdd1-4a42-bcda-3ea8a4e48e80" #replace with your deployment ID
try:
resp = requests.delete(f"{BASE_URL}/api2/api/deployments/{DEPLOYMENT_ID}", headers=headers, timeout=60)
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
if resp.status_code == 200:
try:
data = resp.json()
except ValueError:
data = {"message": resp.text.strip() or "Deleted"}
print("Deletion successful:")
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/roles and project permissions.")
elif resp.status_code == 404:
print("Deployment not found (404). Verify DEPLOYMENT_ID.")
elif resp.status_code == 422:
print("Validation error (422). The DEPLOYMENT_ID format may be invalid.")
else:
print(f"Error {resp.status_code}:")
6. AutoML​
Create an AutoML job to explore multiple experiment configurations automatically.
automl_payload = {
"name": "my-automlv2", # AutoML job display name
"total_experiments": 1, # how many experiments AutoML should launch
"request": { # baseline experiment config to start from
"architecture": {
"training_mode": "lora",
"gradient_checkpointing": True,
"intermediate_dropout": 0,
"backbone_kwargs": "{}"
},
"dataset": {
"data_sample_choice": ["Train", "Validation"],
"data_sample": 1,
"prompt_column": "input",
"answer_column": [ # answer_column (multi-target) or (single-target)
"question_is_billing_issue",
"question_was_issue_resolved",
"question_is_technical_issue",
],
"train_dataset_id": "ed7e88a7-d459-4b97-bbc4-50e07a63fd5b",
"validation_strategy": "automatic",
"validation_size": 0.2,
"unroll_conversations": False
},
"environment": {
"find_unused_parameters": False,
"huggingface_branch": "main",
"mixed_precision": True,
"use_fsdp": False,
"use_fsdp_cpu_offload": False,
"seed": -1,
"trust_remote_code": True
},
"tokenizer": {
"max_length": 512,
"padding_quantile": 1,
"tokenizer_kwargs": "{\"use_fast\": true, \"add_prefix_space\": false}"
},
"training": {
"attention_implementation": "auto",
"batch_size": 1,
"differential_learning_rate_layers": [],
"differential_learning_rate": 1e-5,
"epochs": 1,
"evaluate_before_training": True,
"evaluation_epochs": 1,
"grad_accumulation": 1,
"gradient_clip": 0,
"learning_rate": 1e-4,
"lora_alpha": 16,
"lora_dropout": 0.05,
"lora_rank": 4,
"lora_target_modules": "",
"min_learning_rate_ratio": 0,
"optimizer": "AdamW",
"schedule": "Cosine",
"train_validation_data": False,
"use_length_based_sampler": True,
"warmup_epochs": 0,
"weight_decay": 0
},
"logging": {},
"prediction": {
"batch_size_inference": 0,
"max_length_inference": 128,
"metrics": [],
"min_length_inference": 2,
"num_beams": 1,
"repetition_penalty": 1,
"temperature": 0,
"top_k": 0,
"top_p": 1
},
"experiment_name": "experiment",
"experiment_id": "string",
"project_id": "1234",
"reference_experiment_ids": [],
"llm_backbone": "h2oai/h2o-danube3-500m-chat",
"problem_type": "text_causal_classification_modeling"
},
"project_id": "6b62cd37-3080-490f-ba00-af911bb15981", # project where AutoML will create experiments
"llm_backbones": ["string"]
}
try:
resp = requests.post(f"{BASE_URL}/api2/api/automl", headers=headers, data=json.dumps(automl_payload), timeout=180)
except requests.exceptions.RequestException as e:
raise SystemExit(f"Request failed: {e}")
if resp.status_code == 200:
try:
data = resp.json()
except ValueError:
raise SystemExit(f"Unexpected response format:\n{resp.text[:1000]}")
print("AutoML job created:")
print(json.dumps(data, indent=2))
elif resp.status_code == 403:
print("Access denied (403). Check token scopes/roles and project permissions.")
print(resp.text[:1000])
elif resp.status_code == 422:
print("Validation error (422). Check required fields and value types.")
try:
print(json.dumps(resp.json(), indent=2))
except ValueError:
print(resp.text[:1000])
else:
print(f"Error {resp.status_code}")
try:
print(json.dumps(resp.json(), indent=2))
except ValueError:
print(resp.text[:2000])
- Submit and view feedback for this page
- Send feedback about H2O Enterprise LLM Studio to cloud-feedback@h2o.ai