Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modellen Tools & Services
Oplossingen
Organisaties Ontwikkelaars Internet Service Providers Managed Service Providers AI-in-a-Box
Kenniscentrum
Ondersteuning Documentation Blog Downloads
Bedrijf
Over ons Onderzoek Vacatures Investeren Contact
Inloggen

Uploading a model

The full path from "nothing" to a downloadable version, with the Python SDK.

Prerequisites#

  • Write access to the namespace (role member or higher — see Authentication).
  • The files you want to publish, locally.

1. Make sure the model exists#

Models are created once; versions are added over time. type is required.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from scaiatlas import ScaiAtlas
client = ScaiAtlas.from_env()

client.models.create(
    "poolnoodle", "noodletron",
    type="llm",                       # required; see the model-types reference
    display_name="Noodletron",
    description="A demo language model.",
    license="apache-2.0",
    tags=["demo", "8b"],
)

If it already exists you'll get a ConflictError — safe to ignore or catch.

2. Upload a version#

The upload session creates the version in uploading state, streams each file in checksum-verified chunks, and finalizes it on complete():

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
with client.upload.version(
    "poolnoodle", "noodletron", "1.0.0",
    format="safetensors",
    release_notes="Initial release.",
    requirements={"transformers": ">=4.40"},
) as up:
    up.add_file("model.safetensors")
    up.add_file("config.json")
    up.add_file("tokenizer.json")
    version = up.complete()

print(version.full_name, version.status)   # poolnoodle/noodletron:1.0.0 ready

Add a whole directory instead of listing files:

python
1
2
3
4
with client.upload.version("poolnoodle", "noodletron", "1.0.0",
                           format="safetensors") as up:
    up.add_directory("./noodletron/", pattern="*", recursive=True)
    up.complete()

Progress reporting#

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from scaiatlas.resources.upload import UploadProgress

def on_progress(p: UploadProgress):
    print(f"{p.file_name}: {p.percent_complete:.1f}%")

with client.upload.version("poolnoodle", "noodletron", "1.0.0",
                           format="safetensors",
                           progress_callback=on_progress) as up:
    up.add_file("model.safetensors")
    up.complete()

If something goes wrong#

The session is a context manager: if an exception propagates out of the with block before complete(), the upload is aborted and server-side state is cleaned up automatically. You can also call up.abort() explicitly.

  • version string must be semver (1.0.0, 2.1.0-beta.1) or you'll get a ValidationError.
  • format must be a supported format (GET /api/v1/options/formats) or the create step returns 400.
  • Re-using an existing version string returns a ConflictError.

Async note: upload and download are synchronous-only helpers. AsyncScaiAtlas exposes namespaces, models, versions, variants, and search, but not upload/download. Run transfers with the sync client (e.g. in a thread executor).

3. Add format variants (optional)#

Request an alternative representation of the version — e.g. a GGUF quantization:

python
1
2
3
4
5
6
client.variants.create(
    "poolnoodle", "noodletron", "1.0.0",
    variant_name="gguf-q4_k_m",
    format="gguf",
    quantization="Q4_K_M",
)

This returns immediately (the server accepts the request and converts asynchronously: pending → converting → available). List variants to check status:

python
1
2
for v in client.variants.list_all("poolnoodle", "noodletron", "1.0.0"):
    print(v.variant_name, v.status, v.is_primary)

4. Manage the version later#

python
1
2
3
4
5
6
7
# Update release notes or lifecycle status
client.versions.update("poolnoodle", "noodletron", "1.0.0",
                       release_notes="Patched tokenizer.", status="ready")

# Deprecate or delete
client.versions.update("poolnoodle", "noodletron", "1.0.0", status="deprecated")
client.versions.delete("poolnoodle", "noodletron", "1.0.0")

Under the hood (REST)#

The session maps onto these calls, which you can drive directly in any language:

  1. POST /api/v1/namespaces/{ns}/models/{model}/versions — create (status uploading).
  2. POST …/versions/{version}/upload/init — per file: returns upload_id, part_size, part_count.
  3. PUT …/upload/{upload_id}/parts/{n} — push each chunk, collect etags.
  4. POST …/upload/{upload_id}/complete — assemble and verify.

See the REST API reference for exact schemas.

Updated 2026-07-16 01:40:59 View source (.md) rev 1