DataSpires SDK
Version: 0.1.1
Train, fine-tune, and run models on DataSpires GPUs from any notebook.
pip install dataspires
Works in: Google Colab · Kaggle · Jupyter · VS Code · any Python 3.9+ environment
Contents
- Quickstart
- Authentication
- Which method should I use?
- Models & data sources
- Resource guide
- Jobs
- Guides by task — Pretrain · Finetune · Generate — Checkpointing · Long-running jobs
- Working with your model
- API reference
- Hardware & billing
- Model & dataset registry
- Troubleshooting
- Built-in help
Quickstart
Fine-tune a model on a Hugging Face dataset in a few lines:
from dataspires import DataSpiresClient
client = DataSpiresClient()
client.authenticate()
job = client.finetune(
model="qwen2.5-0.5b",
training_mode="low",
data="tatsu-lab/alpaca",
gpus=1,
)
result = job.run(wait=True)
if result["status"] == "completed":
job.download("./my-model")
else:
print(result.get("error") or result.get("reason"))
pretrain() and generate() follow the same pattern: create a job, then call job.run().
Authentication
Get an API key
- Sign in at dataspires.com.
- Go to Profile → SDK keys → Create new key, then copy the
afk_live_…value. It is shown only once. - Save it as
DATASPIRES_API_KEY.
Set the key
| Environment | How |
|---|---|
| Google Colab | Secrets → DATASPIRES_API_KEY |
| Kaggle | Add-ons → Secrets → DATASPIRES_API_KEY |
| Terminal | export DATASPIRES_API_KEY=afk_live_… |
| In code | client.authenticate(api_key="afk_live_…") |
client = DataSpiresClient()
client.authenticate()
authenticate() raises an error if the key is invalid or revoked. To rotate a key, revoke it in the dashboard and create a new one.
To use gated Hugging Face models or datasets, also set HUGGINGFACE_TOKEN.
Which method should I use?
| Your goal | Method | You provide |
|---|---|---|
| Train a detector, CNN, or transformer from scratch | client.pretrain() |
architecture, kind, data, optional init, config, tokenizer |
| Adapt an existing LLM or vision-language model | client.finetune() |
model, training_mode, data, optional task |
| Run a model without changing its weights | client.generate() |
model, prompts or an image manifest |
Models & data sources
Pass a registry name, a Hugging Face ID, a URL, a Google Drive file, or local data. Remote sources are downloaded directly by the job, so large datasets never pass through your notebook. Local files and DataFrames are uploaded for you.
model=
| Input | Example |
|---|---|
| Registry name | qwen2.5-0.5b, llama-3.2-1b |
| Hugging Face ID (optional revision) | Qwen/Qwen2.5-0.5B, Qwen/Qwen2.5-0.5B@main |
| Hugging Face URL | https://huggingface.co/Qwen/Qwen2.5-0.5B |
| Google Drive file | gdrive:FILE_ID or a Drive share link |
data=
| Input | Example |
|---|---|
| In-memory | Python list, pandas DataFrame, Hugging Face Dataset |
| Local file or folder | ./train.jsonl, ./corpus/ |
| Hugging Face dataset | tatsu-lab/alpaca |
| Dataset with config | Salesforce/wikitext#wikitext-2-raw-v1 |
| HTTPS file | https://example.com/train.jsonl (jsonl, csv, parquet, txt, zip) |
| Google Drive file | gdrive:FILE_ID or a Drive share link |
tokenizer= (transformer pretraining)
Accepts gpt2, any Hugging Face tokenizer ID (optionally with @revision), a Hugging Face URL, or a Google Drive file containing tokenizer files.
Preview how a source resolves
from dataspires import resolve_model, resolve_data, resolve_tokenizer
resolve_model(model="Qwen/Qwen2.5-0.5B")
resolve_data(data="Salesforce/wikitext#wikitext-2-raw-v1")
resolve_tokenizer("gpt2")
Dataset format (finetune)
A single text column works best. These common layouts are converted automatically:
| Columns | Converted to |
|---|---|
messages (chat format) |
text |
user + final (optional analysis) |
Instruction-style text |
instruction + output, or prompt + completion |
Instruction-style text |
Google Drive
Pass a Drive file the same way as any other source:
job = client.finetune(
model="qwen2.5-0.5b",
training_mode="low",
data="gdrive:FILE_ID",
gpus=1,
)
- Shared files (“Anyone with the link”) work immediately.
- Private files open a Google sign-in window the first time. After you approve read-only access, the job continues and future jobs reuse your sign-in.
For headless environments, set GOOGLE_DRIVE_TOKEN instead. To turn off the sign-in prompt, set DATASPIRES_GDRIVE_AUTO_CONNECT=0. To sign out, call client.disconnect_google_drive().
To check a file before submitting a job:
client.inspect_source("gdrive:FILE_ID")
Current limitations
| Feature | Status |
|---|---|
| Google Drive folders | Share a .zip of the folder |
| Resume from a Hub, HTTPS, or Drive checkpoint | Coming soon — resume from a previous job today |
Custom YOLO/CNN weights= from Hub or Drive |
Coming soon — built-in weight names are supported |
Resource guide
Check whether a model fits before you start a run:
est = client.estimate_model("qwen2.5-0.5b", training_mode="low", gpus=1)
print(est["fits"], est["min_vram_gb"], est["parameters_b"])
fits |
Meaning |
|---|---|
True |
Expected to fit with this mode and GPU count |
False |
Likely too large — try training_mode="low" or more GPUs |
"unknown" |
Model size not known — start with low on 1 GPU |
If a configuration is unlikely to fit, the SDK shows a warning before submitting.
Jobs
Jobs run asynchronously on the DataSpires GPU cluster.
| Lifecycle | Submit, then wait or poll with list_jobs() |
| Outputs | job.download() or client.download_model() |
| Multi-GPU | Available on request with gpus= |
| Maximum duration | Set per workspace or cohort. Pass time_limit="HH:MM:SS" within that limit. |
status and state
| Returned by | Field | Values |
|---|---|---|
job.run() |
status |
submitted, completed, failed, timeout, cancelled |
client.list_jobs(), client.get_job_status() |
state |
The same values, plus queued and running |
result = job.run(wait=True)
print(result["status"])
for entry in client.list_jobs():
print(entry["job_id"], entry["state"])
Guides by task
Pretrain
Image classification (CNN):
job = client.pretrain(
architecture="cnn",
kind="resnet18",
init="pretrained",
data="./images/",
config={"n_epoch": 5, "num_classes": 2, "batch_size": 32, "seed": 42},
gpus=1,
time_limit="02:00:00",
)
result = job.run(wait=True)
job.export_metrics("./run.csv")
Object detection:
job = client.pretrain(
architecture="detector",
kind="detect", # or "segment", "pose"
init="pretrained",
weights="yolo11n.pt",
data="./dataset/",
data_config="data.yaml",
config={"n_epoch": 100, "imgsz": 640, "batch_size": 16, "seed": 42},
)
Detector runs report training loss.
Language model from scratch:
job = client.pretrain(
architecture="transformer",
kind="gpt-decoder-tiny",
init="scratch",
tokenizer="gpt2",
data="roneneldan/TinyStories", # or a local folder such as "./corpus/"
config={"max_steps": 200, "n_epoch": 1, "batch_size": 2, "seed": 42},
)
print(job.estimate())
architecture |
kind |
|---|---|
detector |
detect, segment, pose |
cnn |
resnet18, resnet50 |
transformer |
gpt-decoder-tiny, qwen-decoder-tiny, llama-3-decoder-tiny, vit-tiny |
Download results:
job.download("./my-outputs")
job.download("./checkpoints", include="checkpoints")
Finetune
import pandas as pd
data = pd.DataFrame({"text": ["Below is an instruction...\n\n### Response:\n..."]})
job = client.finetune(
model="qwen2.5-0.5b",
training_mode="low", # low | medium | high | custom
data=data,
gpus=1,
time_limit="01:00:00",
)
result = job.run(wait=True)
if result["status"] == "completed":
job.download("./my-model")
| Mode | Strategy | Precision |
|---|---|---|
low |
QLoRA (rank 8) | 4-bit |
medium |
LoRA (rank 16) | 8-bit on 1 GPU, bf16 on more |
high |
LoRA (rank 64) | bf16 |
custom |
Your settings via config= |
bf16, fp16, 4bit, or 8bit |
For full control, use training_mode="custom" with a config:
job = client.finetune(
model="qwen2.5-0.5b",
training_mode="custom",
data=data,
config={
"batch_size": 2,
"learning_rate": 2e-4,
"scheduler": "cosine",
"n_epoch": 3,
"precision": "bf16",
"lora": {"r": 16, "alpha": 32, "dropout": 0.05},
"max_seq_length": 2048,
"optimizer": "adamw_torch",
"n_checkpoint": 100,
"n_evals": 0,
"seed": 42,
},
)
gpus and time_limit are passed as arguments, not inside config. Reported accuracy is token-level accuracy. Setting n_evals above 0 requires an evaluation split.
For vision-language models, pass task="captioning" or task="vqa" with image-text data. See dataspires.docs("finetune").
Checkpointing and resuming
Save checkpoints during a run, then continue from a previous job:
job = client.finetune(
model="qwen2.5-0.5b",
training_mode="low",
data=data,
time_limit="08:00:00",
checkpoint={"every": 200, "keep": 2},
)
result = job.run(wait=True)
if result["status"] != "completed":
resumed = client.finetune(
model="qwen2.5-0.5b",
training_mode="low",
data=data,
resume_from=job, # or a job ID
)
resumed.run(wait=True)
| Path | Contents |
|---|---|
output/checkpoints/checkpoint-N/ |
Snapshots saved during training |
output/final/ |
Final weights |
List checkpoints with client.list_checkpoints(job_id). See dataspires.docs("checkpoints").
Generate
Run a model without changing its weights:
job = client.generate(
model="Qwen/Qwen2.5-0.5B",
data=[{"text": "Write one short sentence about GPUs."}],
max_new_tokens=48,
gpus=1,
)
result = job.run(wait=True)
if result["status"] == "completed":
job.download("./generate-output")
Generated text is saved to the output folder. Use job.get_logs() to view progress while the job runs.
With a vision-language model and a local image manifest:
job = client.generate(
model="smolvlm-256m",
data="./manifest_dir/",
outputs=["text", "confidence"],
max_new_tokens=64,
temperature=0.0,
)
result = job.run(wait=True)
if result["status"] == "completed":
job.download("./vlm-output")
Long-running jobs
Notebook sessions can end before a long job finishes. Submit without waiting, save the job ID, and check back later:
job.run(wait=False)
job_id = job.job_id
# Later, in the same or a new session
status = client.get_job_status(job_id)
print(status["state"])
if status["state"] == "completed":
client.download_model(job_id, "./my-model")
Jobs keep running on the cluster after your notebook disconnects.
Handling failures
job.run(wait=True) returns a result instead of raising when a job fails. Check result["status"] before downloading. Authentication and validation errors raise immediately.
Working with your model
The steps below apply to finetune() outputs. Fine-tuning produces a LoRA adapter, which is loaded on top of the base model.
Convert to GGUF for Ollama or llama.cpp
Merge the adapter into the base model first:
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B")
model = PeftModel.from_pretrained(base, "./my-model")
merged = model.merge_and_unload()
merged.save_pretrained("./my-model-merged")
AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B").save_pretrained("./my-model-merged")
Then convert ./my-model-merged with llama.cpp's convert_hf_to_gguf.py.
Publish to Hugging Face Hub
from huggingface_hub import HfApi
api = HfApi()
# Publish the adapter
api.upload_folder(folder_path="./my-model", repo_id="you/my-adapter", repo_type="model")
# Or publish full merged weights
api.upload_folder(folder_path="./my-model-merged", repo_id="you/my-model", repo_type="model")
API reference
DataSpiresClient
| Method | Description |
|---|---|
authenticate(api_key=None) |
Authenticate with your API key |
pretrain(architecture, kind, init, config, …) |
Create a pretraining job |
finetune(model, training_mode, data, config, …) |
Create a fine-tuning job |
generate(model, data, outputs, …) |
Create an inference job |
estimate_model(model, training_mode, gpus) |
Estimate memory and fit |
inspect_source(ref) |
Check how a source resolves and whether it is accessible |
connect_google_drive() / disconnect_google_drive() |
Sign in to or out of Google Drive |
download_model(job_id, local_dir, include=("final",)) |
Download job outputs |
list_checkpoints(job_id) |
List saved checkpoints |
upload_dataset(local_path, dataset_name=None) |
Upload a dataset ahead of time |
list_available_models() / list_available_datasets() |
Browse the registry |
get_model_requirements(model, training_mode) |
Recommended GPUs and memory |
cancel_job(job_id) |
Cancel a job |
list_jobs(include_completed=False) |
List your jobs |
get_job_status(job_id) |
Get the status of a job |
Job objects
| Member | Description |
|---|---|
run(wait=True, poll_interval=30) |
Submit the job; with wait=True, block until it finishes |
cancel() |
Cancel the job |
get_logs(tail=100) |
Recent log lines |
get_metrics() |
Training metrics |
export_metrics(path) |
Save metrics as .csv or .json |
download(local_dir, include=("final",)) |
Download outputs |
checkpoints() |
List saved checkpoints |
estimated_cost_usd() |
Maximum cost based on gpus and time_limit |
job_id, status |
Job ID and current status |
Fine-tuning jobs also provide validate(). Pretraining jobs provide estimate().
Source helpers
| Helper | Description |
|---|---|
resolve_model |
Resolve a model reference |
resolve_data |
Resolve a data reference |
resolve_tokenizer |
Resolve a tokenizer reference |
estimate_model |
Same as client.estimate_model |
Hardware & billing
Start with a small model and training_mode="low", and use estimate_model before trying larger models.
| Model size | Mode | Single GPU |
|---|---|---|
| 0.5B – 3B | low, medium | Yes |
| 3B – 7B | low | Yes |
| 7B | medium | Yes |
| 13B | low | Tight |
| 30B+ | low | Unlikely |
Jobs can use up to 32 GPUs. Maximum duration is set per workspace or cohort.
GPU time is billed at $0.60 per GPU-hour (NVIDIA L4). View invoices at dataspires.com/dashboard/billing. job.estimated_cost_usd() shows the maximum cost for a job's time_limit; you are billed for actual usage.
Model & dataset registry
Browse curated models and datasets:
client.list_available_models()
client.list_available_models(size="tiny")
client.list_available_datasets()
client.get_model_requirements("qwen2.5-0.5b", "low")
Any public Hugging Face model or dataset also works. See Models & data sources.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
API key auth failed |
Invalid or revoked key | Create a new key and update DATASPIRES_API_KEY |
Job stays queued |
Cluster at capacity | The job starts automatically when capacity is available |
KeyError: 'status' from list_jobs() |
Different field name | Use entry["state"] |
KeyError: 'state' from job.run() |
Different field name | Use result["status"] |
Dataset has no 'text' column |
Unsupported format | Add a text column or use a supported layout |
| Drive file not accessible | File is private or not shared with you | Sign in when prompted, or share the file as “Anyone with the link” |
| Drive folder link rejected | Folders are not supported | Share a .zip of the folder |
| Google sign-in unavailable | Drive sign-in is not configured in this environment | Set GOOGLE_DRIVE_TOKEN, or see Google Drive setup |
| HTTPS download fails | URL is not publicly reachable | Use a public https:// URL |
| Gated Hugging Face model fails | Missing token | Set HUGGINGFACE_TOKEN |
download_model() returns nothing |
Job did not finish | Check the status, or download with include="checkpoints" |
Job ends with DeadlineExceeded |
Reached time_limit |
Resume with resume_from=job |
Notebook disconnected during wait=True |
Session ended | See Long-running jobs |
Built-in help
import dataspires
dataspires.docs("help")
dataspires.docs("finetune")
dataspires.docs("pretrain")
dataspires.docs("checkpoints")
Metadata
Release files for dataspires 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dataspires-0.1.1.tar.gz | 210.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dataspires-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 429.1 kB
Release files / dataspires-0.1.1.tar.gz
| Download URL | dataspires-0.1.1.tar.gz |
|---|---|
| Size | 210.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1a2d85c2cf28a2e075ba463be295a19d398cc6e77c272f695a99868a9089e26f
|
|
BLAKE2b-256 checksum How to use checksums |
8571867ae4a78dade3d211c24261f9e5a704648a70c2408b97ddca58f02c613c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.11
|
Release files / dataspires-0.1.1-py3-none-any.whl
| Download URL | dataspires-0.1.1-py3-none-any.whl |
|---|---|
| Size | 219.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1f2db0a125e1adf6dddc43b0a0f8bb777a95de9fb4edf23a109646f348aff856
|
|
BLAKE2b-256 checksum How to use checksums |
3fb1b212a899cfb2480d17aa751e2eba882f03f724257b5cb11e7cf4f9e4399f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.11
|