Skip to main content

AfriLink SDK

Version: 0.9.2

One-line access to GPUs for training, finetuning, and inference — from any notebook.

pip install afrilink-sdk

Works in: Google Colab · Kaggle · Jupyter · VS Code · any Python 3.8+ environment


Contents

  1. 60-second quickstart
  2. Authentication
  3. Which method should I use?
  4. Backend (k3s)
  5. Guides by taskPretrain · Finetune · Generate · Custom containers
  6. Working with your output model
  7. API reference
  8. Hardware & billing
  9. Model & dataset registry
  10. Troubleshooting
  11. Built-in help

60-second quickstart

This example uses the default k3s backend — no environment variable needed.

from afrilink import AfriLinkClient

client = AfriLinkClient()
client.authenticate(api_key="afk_live_…")  # or set AFRILINK_API_KEY

job = client.pretrain(
    kind="image-classify",
    model="resnet18",
    data="./images/",
    params={"epochs": 5, "num_classes": 2},
    gpus=1,
)
result = job.run(wait=True)
print(result["status"])

Every other capability (finetune, generate, custom containers) follows this same client → job → job.run() pattern. See Guides by task.


Authentication

Auth is a single stateless API key — no passwords, no certificate refresh, no SSH key management on your side.

Get a key

  1. Sign up at dataspires.com.
  2. Profile → AfriLink SDK keys → Create new key. Copy the afk_live_… value — it's shown once.
  3. Store it as AFRILINK_API_KEY.

Set the key

Environment How
Google Colab 🔑 sidebar → Add secret → name AFRILINK_API_KEY → enable for notebook
Kaggle Add-ons → Secrets → name AFRILINK_API_KEY → attach to notebook
Local Jupyter / VS Code os.environ["AFRILINK_API_KEY"] = "afk_live_…" before authenticate()
Anywhere client.authenticate(api_key="afk_live_…")
client = AfriLinkClient()
client.authenticate()   # resolves from secret / env / argument, in that order

What happens at auth time

Your API key is exchanged at api.dataspires.com for a short-lived Supabase JWT used for billing writes. The JWT lives in memory for the kernel lifetime — nothing is written to disk. Rotate a key by revoking it on the dashboard and minting a new one.


Which method should I use?

Your goal Call You provide
Train a YOLO / CNN / transformer from scratch client.pretrain(kind=…) kind, data, optional weights= / scratch=
Fine-tune an LLM / VLM foundation model client.finetune() model, training_mode, data, optional task=
Run a model without changing weights client.generate() model, prompts / image+question manifest
Need a custom framework/version not curated client.build_and_train() image spec + script

Rule of thumb: train from zero → pretrain(). Adapt existing weights → finetune(). Frozen answers → generate(). Need a bespoke environment → build_and_train().

client.train(), adapt(), and initialize() are deprecated in 0.9 and will be removed in 1.0.0.


Backend (k3s)

The pilot and student path uses the DataSpires K3s GPU cluster (default). You do not need to set AFRILINK_BACKEND.

k3s (default)
How to select Default — nothing to set
What it targets DataSpires K3s GPU cluster (multi-node, multi-GPU capable)
Job model Async by default — submit, then poll or list jobs, even from a new session
File I/O S3-compatible presigned URLs
Output retrieval Sync from /workspace/job/output/ — see K3s output retrieval
Billing Not yet wired (billing: None in result)
Multi-GPU Supported by the cluster

Guides by task

Pretrain

(train from scratch — YOLO, CNN, or transformer)

Image classification:

job = client.pretrain(
    kind="image-classify",
    model="resnet18",
    data="./images/",
    params={"epochs": 5, "num_classes": 2},
    gpus=1,
)
result = job.run(wait=True)

YOLO detection:

job = client.pretrain(
    kind="yolo-detect",
    weights="yolo11n.pt",       # or scratch=True for random init
    data="./dataset/",
    data_config="data.yaml",
    gpus=1,
    time_limit="02:00:00",
)
result = job.run(wait=True)

Curated containers resolved from kind=:

kind prefix Container Frameworks
yolo-* afrilink-yolo Ultralytics, PyTorch, torchvision
image-classify afrilink-vision PyTorch, torchvision
transformer/ViT afrilink-pretrain Transformers, accelerate

Need a stack outside these? → Custom containers.

K3s output retrieval

On k3s, your script writes to /workspace/job/output/; the orchestrator syncs it to S3 on completion.

from pathlib import Path
job.k8s_runner.download_output(job.job_id, Path("./my-outputs"))

Requires a deployed orchestrator exposing GET /api/v1/jobs. Full spec: dataspires.com/docs.

Finetune

(LoRA/QLoRA adaptation of an LLM/VLM — runs in the afrilink-finetune container)

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 — see table below
    data=data,
    gpus=1,
    time_limit="01:00:00",
)
result = job.run(wait=True)
if result["status"] == "completed":
    client.download_model(result["job_id"], "./my-model")
Mode Strategy Quantization
low QLoRA (rank 8) 4-bit
medium LoRA (rank 16) 8-bit / none
high Full LoRA (rank 64) none

For VLMs, pass task= (e.g. captioning / VQA) with image+text data. See afrilink/finetune in the built-in help.

Generate

(frozen inference — no weight updates)

job = client.generate(
    model="smolvlm-256m",
    data="./manifest_dir/",
    outputs=["text", "confidence"],   # add "hidden_states" for analysis
    max_new_tokens=64,
    temperature=0.0,
)
result = job.run(wait=True)

Custom containers

For frameworks or model versions the curated containers don't cover.

spec = dict(
    base_image="pytorch",       # preset — see table below
    pip_packages=["transformers>=4.45", "accelerate>=0.34", "peft>=0.13"],
    apt_packages=["git"],
    model_source={"kind": "huggingface", "id": "Qwen/Qwen2.5-0.5B-Instruct"},
)

# check cache first — avoids a ~5 min rebuild for a spec you've already built
hit = client.find_existing_image(**spec)

result = client.build_and_train(
    **spec,
    script="my_train.py",
    gpus=1,
    time_limit_hours=0.5,
    reuse_existing_image=True,   # default
)
client.download_model(result["run"]["job_id"], "./output")

base_image presets:

Preset Resolves to Notes
pytorch pytorch/pytorch:2.5.0-cuda12.4-cudnn9-runtime GPU default
pytorch-2.4 pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime
pytorch-cpu pytorch/pytorch:2.5.0-cpu-runtime CPU-only, smaller
cuda-12.4 nvidia/cuda:12.4.0-runtime-ubuntu22.04 bring-your-own-Python
ultralytics ultralytics/ultralytics:latest YOLOv8 ready

model_source kinds: huggingface (id, optional revision/subfolder), url, git, gs, s3, or omit to load the model yourself in-script. Models are fetched at runtime, not baked into the image — keeps images ~2GB instead of 7+GB. Gated HF models (Llama, Gemma) work automatically if you add HUGGINGFACE_TOKEN as a notebook secret.

Cache key includes base_image, pip_packages, apt_packages, index URLs, and model_source. It excludes script, env, extra_files, and job/user IDs — so two runs with an identical environment spec but different training scripts share a cached image.

Lifecycle: the built image lives permanently in Artifact Registry (that's what cache hits read from); the local copy on the compute node is deleted at the end of each build_and_train() call unless cleanup_image_after=False.


Working with your model

Convert to GGUF for Ollama / llama.cpp

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")

# python convert_hf_to_gguf.py ./my-model-merged --outfile my-model.gguf --outtype f16
# ./llama-quantize my-model.gguf my-model-q4.gguf Q4_K_M
# ollama create my-model -f Modelfile && ollama run my-model

Publish to Hugging Face Hub

from huggingface_hub import HfApi

api = HfApi(token="hf_...")
api.create_repo("your-username/my-finetuned-model", exist_ok=True)
api.upload_folder(folder_path="./my-model", repo_id="your-username/my-finetuned-model")  # adapter only

API reference

AfriLinkClient

Method Description
authenticate(api_key=None) Resolve key (arg / env / Colab / Kaggle secrets), exchange for session
pretrain(kind, data, gpus, ...) From-scratch / recipe training job
finetune(model, training_mode, data, gpus, ...) LoRA/QLoRA job in afrilink-finetune
generate(model, data, outputs, ...) Frozen inference job
find_existing_image(...) Check cache before a custom build
build_image(...) Build a custom image only
build_and_train(...) Cache-check → build (or skip) → run → cleanup
delete_built_image(job_id_or_image) Remove image from the compute node's local cache
download_model(job_id, local_dir) Download output/ directory
upload_dataset(local_path, dataset_name) Upload to job-scoped staging
list_containers() / list_available_models() / list_available_datasets() Registry lookups
get_model_requirements(model, training_mode) GPU/memory recommendation
cancel_job(job_id) Stop and remove a job
list_jobs(include_completed=False) List your jobs
get_job_status(job_id) Poll by ID — works across sessions on k3s
get_job(job_id) In-session job object, if still tracked

TrainJob / FinetuneJob / GenerateJob

Returned by pretrain() / finetune() / generate() / build_and_train().

Member Description
run(wait=True, poll_interval=30) Submit; wait=True polls to completion
cancel() Stop the job
get_logs(tail=100) Recent log lines
estimated_cost_usd() Estimate from GPUs × time limit
status, job_id Current state / 8-char job ID
k8s_runner Use for download_output() on k3s

Result shape — k3s:

{"job_id": "a1b2c3d4", "status": "completed", "billing": null}

On failure, also includes "error": "<last 200 log lines>".

Async job discovery:

result = job.run(wait=False)
for entry in client.list_jobs():
    print(entry["job_id"], entry["state"], entry.get("reason"))

status = client.get_job_status(result["job_id"])  # works even after a notebook restart

list_jobs(include_completed=True) includes completed jobs for up to 3 days.


Hardware & billing

Jobs run on the DataSpires k3s GPU cluster. Prefer small models and training_mode="low" (QLoRA) for workshop / assignment budgets.

Model size Mode Fits on 1 GPU?
0.5B – 3B low / medium yes
3B – 7B low (QLoRA 4-bit) yes
7B medium (LoRA 8-bit) yes
13B low (QLoRA 4-bit) tight
30B+ low (QLoRA 4-bit) unlikely (OOM risk)

Billing: wall-clock GPU usage is charged against your DataSpires balance when billing is enabled for the job path. Invoices: dataspires.com/dashboard/billing. Cloud Build time for custom images is absorbed by the platform — you only pay for GPU time. k3s result objects currently return billing: null until cluster billing is fully wired.


Model & dataset registry

client.list_available_models()                # all
client.list_available_models(size="tiny")      # tiny | small | medium | large
client.list_available_datasets()
client.get_model_requirements("qwen2.5-0.5b", "low")
ID Type Params Min VRAM
qwen2.5-0.5b text 0.5B 4 GB
gemma-3-270m text 0.27B 2 GB
llama-3.2-1b text 1.0B 4 GB
deepseek-r1-1.5b text 1.5B 6 GB
ministral-3b text 3.3B 8 GB
florence-2-base vision 0.23B 4 GB
smolvlm-256m vision 0.26B 2 GB
moondream2 vision 1.9B 8 GB
internvl2-1b vision 1.0B 4 GB
llava-1.5-7b vision 7.0B 16 GB

Anything else → custom containers with model_source=.


Troubleshooting

Symptom Likely cause Fix
Job stuck in queued Cluster at capacity client.list_jobs() to check state; jobs auto-clear after 3 days if abandoned
Fresh build every time despite unchanged deps A field outside the cache key changed (e.g. script) — this is expected Only base_image, pip_packages, apt_packages, index URLs, and model_source are hashed
Gated HF model fails to download Missing HUGGINGFACE_TOKEN Add it as a notebook secret
download_model() / output empty Script didn't write to /workspace/job/output/ Confirm output path in your training script; use k8s_runner.download_output()

Built-in help

Query the inline reference manual from any cell — no internet required:

import afrilink

afrilink/help          # index
afrilink/quickstart
afrilink/auth
afrilink/choose
afrilink/finetune
afrilink/pretrain
afrilink/generate
afrilink/training      # deprecated train() notes
afrilink/specs
afrilink/datasets
afrilink/billing

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

afrilink_sdk-0.9.2.tar.gz (164.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

afrilink_sdk-0.9.2-py3-none-any.whl (173.7 kB view details)

Uploaded Python 3

Release history Release notifications | RSS feed

0.9.4

2 files

0.9.3

2 files

This release

0.9.2 This release

2 files

0.9.1

2 files

0.9.0

2 files

0.8.28

2 files

0.8.27

2 files

0.8.26

2 files

0.8.25

2 files

0.8.24

2 files

0.8.23

2 files

0.8.22

2 files

0.8.21

2 files

0.8.20

2 files

0.8.19

2 files

0.8.18

2 files

0.8.17

2 files

0.8.16

2 files

0.8.15

2 files

0.8.14

2 files

0.8.13

2 files

0.8.12

2 files

0.8.11

2 files

0.8.10

2 files

0.8.9

2 files

0.8.8

2 files

0.8.7

2 files

0.8.6

2 files

0.8.5

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.5

2 files

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.0

2 files

0.5.9

2 files

0.5.8

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.3

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page