Skip to content

model deployment

github-actions[bot] edited this page Sep 15, 2026 · 2 revisions

Model deployment: bundles and modules

A trained checkpoint (.pt, under SPIKEFORGE_MODEL_DIR) is a training-time artifact — weights plus a topology spec, meant for spikeforge itself to load and keep training. A deployment bundle (.spkf) is the portable version: everything a runtime needs to load and run the model, and nothing else. A module is one of those bundles installed under a name, so it runs as its own standalone command.

Bundling a trained model

From the dashboard: Model & Data → Model → Bundle, pick a saved checkpoint, and click Download .spkf. The browser downloads a real file — GET /api/bundle/<name> builds it server-side from the checkpoint via spikeforge.serving.bundle.build and streams it back.

From Python:

from spikeforge.serving.bundle import build

build("my_model", out="my_model.spkf")

A .spkf is a zip with a fixed entry set — manifest.json (topology, encode config, label map, provenance), weights.pt, and a SHA256SUMS integrity file — documented in full in spikeforge/serving/bundle_manifest.py. It carries no training code, no optimizer state, and no dataset.

Running a bundle

spikeforge-serve (a separate distribution: pip install spikeforge-serve) loads a .spkf and runs it two ways:

# As an HTTP/WebSocket service (predict / stream / metrics):
spikeforge-serve serve --bundle my_model.spkf --port 8899

# One-shot, no server: read a JSON request, print a JSON response, exit.
echo '{"frames": [[...]], "encoded": true}' | spikeforge-serve run my_model.spkf

The one-shot run path and the HTTP /v1/predict route go through the same ServingService, so a bundle behaves identically served or run standalone.

Installing a bundle as a module

Think of a module the way a small Unix tool or a Linux kernel module works: one name, one job, a plain input and a plain output. spikeforge-serve install registers a bundle under ~/.local/share/spikeforge/modules/<name>/ and writes an executable <name> wrapper to ~/.local/bin/:

spikeforge-serve install my_model.spkf --name digit-classifier
# installed 'digit-classifier' -> ~/.local/share/spikeforge/modules/digit-classifier

echo '{"frames": [[...]], "encoded": true}' | digit-classifier

spikeforge-serve list shows every installed module; spikeforge-serve uninstall <name> removes one. Running by name (spikeforge-serve run digit-classifier) resolves the installed copy first and falls back to treating the argument as a literal .spkf path, so a bundle works whether or not it has been installed.

Because each module reads one JSON object from stdin and writes one JSON object to stdout, several installed models chain into a pipeline the same way any Unix tools do — reshape between them with jq, no shared code required:

cat frame.json \
  | digit-classifier \
  | jq '{frames: [.predictions[0].mean_logits.values]}' \
  | risk-scorer

Neither module needs to know the other exists; the contract is just the JSON shape on the pipe.

Chaining checkpoints visually: the Pipeline tab

The shell-pipe chaining above works from a terminal; the dashboard's Pipeline tab is the same idea as a visual, in-app DAG editor. Each node is a saved checkpoint (the same list the Load/Bundle tabs show); each edge picks one of three fixed ways to shape the source node's output into the target's next input — mean_logits (the full readout vector, the common case), predicted_class (a single scalar), or one_hot (sized to the target's own num_classes). There's no custom mapping expression and no fan-in (a node with two incoming edges is refused) — see spikeforge_serve/pipeline.py for the exact rules.

A pipeline is a DAG, not a state machine: nodes run once each, in topological order, with no conditional branching and no loops. Running one spawns a background worker (mirroring how training runs — see server/pipeline_service.py) that streams a pipeline_node_result message as each node finishes, so the canvas shows live idle → running → done/error status per node. Under the hood it's the same ServingService every other serving path uses, built on demand from each node's checkpoint via spikeforge.serving.bundle.build — no install step, no bundle file ever touches disk.

Saved pipelines live server-side (SPIKEFORGE_DATA_DIR/pipelines/, overridable via SPIKEFORGE_PIPELINES_DIR), alongside saved checkpoints.

What a module does and does not give you

  • No physical install in the sense of a compiled binary — a module is a .spkf file plus a small shell wrapper that invokes python -m spikeforge_serve run. spikeforge-serve (and by extension spikeforge core, i.e. PyTorch) must be installed wherever the module runs.
  • No sandboxing — an installed module runs with the invoking user's permissions, same as any other local script.
  • No network step — run/install/list/uninstall are all local; the HTTP path (serve) is the only one that talks over a socket.

Clone this wiki locally