Skip to main content
A PRISM submission is a two-script bundle: a .zip archive (or a directory snapshot) containing a model architecture.py and a training training.py. The miner owns the model and the training loop; the challenge owns the dataset and the scoring. A single combined module no longer satisfies the contract. Source: docs/submissions.md:1-10; src/prism_challenge/evaluator/components.py:99-103.

The two-script contract

A bundle must contain two distinct scripts. architecture.py exposes a model factory:
def build_model(ctx):
    return MyModel(ctx.vocab_size)
build_model(ctx) must return a torch.nn.Module. It must not read data, open files, touch the network, or reference the dataset. training.py exposes the miner-owned training loop:
def train(ctx):
    model = ctx.build_model()
    # build the optimizer/schedule, read the locked train split from ctx.data_dir,
    # tokenize, run the loop, handle multi-GPU, write only under ctx.artifacts_dir.
    ...
The default entrypoints are architecture.py and training.py, and the default symbols are build_model and train. Source: docs/submissions.md:12-54; src/prism_challenge/evaluator/interface.py:11-14.

The prism.yaml manifest

An optional prism.yaml (or prism.yml) declares the entrypoints, the tokenizer, and the submit mode. When the manifest is absent, PRISM uses the default entrypoints and symbols. When it is present, declared entrypoints are honored exactly, with no silent fallback. Source: src/prism_challenge/evaluator/components.py:20, :54-105.

Manifest fields

FieldMeaningSource
kindSubmit mode: full, architecture_only, or training_for_arch (default full)src/prism_challenge/evaluator/components.py:21-22, :76-78
architecture_idOptional id linking the submission to an existing architecturesrc/prism_challenge/evaluator/components.py:79-81
architecture.entrypointPath to the architecture script (default architecture.py)src/prism_challenge/evaluator/components.py:85-87
training.entrypointPath to the training script (default training.py)src/prism_challenge/evaluator/components.py:88-90
<role>.factory / <role>.function / <role>.entryOverride the role’s symbol name (the entrypoint may also use an entrypoint.py::symbol suffix)src/prism_challenge/evaluator/components.py:131-141
<role>.filesExtra files (string or list) to include in the role’s fingerprintsrc/prism_challenge/evaluator/components.py:242-259
tokenizerThe chosen tokenizer, e.g. gpt2docs/submissions.md:43-49; examples/tiny-1m/prism.yaml:5
A minimal manifest:
architecture:
  entrypoint: architecture.py
training:
  entrypoint: training.py
tokenizer: gpt2
Source: examples/tiny-1m/prism.yaml:1-5.

Submit modes

The kind field selects one of three submit modes. The set of valid kinds is fixed in source, and an unsupported kind is rejected with a contract error. Source: src/prism_challenge/evaluator/components.py:21-22, :76-78.
The default mode (kind: full, also used when prism.yaml is absent). The bundle carries both roles — a complete architecture and its training recipe — and both are fingerprinted from the bundle.
kind: full
architecture:
  entrypoint: architecture.py
training:
  entrypoint: training.py
tokenizer: gpt2
Source: src/prism_challenge/evaluator/components.py:22, :67-90.

Architecture-vs-training ownership and attribution

The submit mode declares intent about which role a submission contributes — an architecture, a training recipe for an existing architecture, or both. PRISM records this as the kind plus the optional architecture_id, and the SQLite schema keeps architecture_families and training_variants tables that the family- and variant-listing routes expose. However, the live score and weights do not split rewards by role. get_weights keeps, per hotkey, the best final_score and normalizes the survivors; the v1-NAS architecture/training ownership reward pools are retired from the score, and the component-attribution holds and ownership-event machinery have been decommissioned.
The GET /v1/architectures and GET /v1/training-variants routes are retained as legacy endpoints for API compatibility. They do not drive the live weighting.
Source: src/prism_challenge/evaluator/components.py:21-22, :79-81; src/prism_challenge/db.py:100-131; src/prism_challenge/weights.py:21-31; docs/scoring.md:89; docs/architecture.md:162.

The challenge owns the data and the score

PRISM re-executes the miner’s training.py under a forced random init and a fixed seed, and records the online loss stream itself. Any value the miner reports is ignored, and the challenge authors the run manifest. See How PRISM works for the forced-init re-execution flow and Scoring for the bits-per-byte math. Source: docs/submissions.md:76-81.

ZIP safety rules

ZIP submissions are extracted defensively: no path traversal, no symlinks, a limited file count, limited total bytes, and only approved text or code suffixes. Unsupported or unsafe archives are rejected before evaluation. Source: docs/submissions.md:173-183.