Distributing MLFFs: sidecar and catalog (draft 2026-09-18)#
Status: draft for discussion (Paul, Sina). Nothing here is implemented yet.
Why#
Trained checkpoints are megabytes to gigabytes, so they do not belong in a
plug-in’s data/ directory on GitHub. Publishing each model on Zenodo gives
it a DOI (a concept DOI that always resolves to the newest version, plus one
DOI per version), long-term storage, and a citation. SEAMM then needs three
things: a way to describe a model (the sidecar), a way to find the models we
recommend (the catalog), and rules for caching, updating and citing them.
Requirements gathered so far#
The curated catalog must be easy to update by hand, several times a day if needed – the packaging workflow depends on it. This rules out putting the catalog itself in a Zenodo record (every edit would be a new immutable version). The big files go on Zenodo; the small catalog lives in a Git repo and is fetched as a raw file.
Offline and secure sites: a model fetched on one machine, or from the Zenodo web page by hand, must be fully usable (and citable) when copied to a machine without Internet access. Hence the sidecar travels with the checkpoint.
The model-chemistry name stays the plain model name (
xnn:MLFF@water); which version and which source were used are reported and cited, not encoded in the name, so a retrain does not change anyone’s flowchart.xnn checkpoints already carry some of this internally (
{"model": state_dict, "cfg": Config}: model family, cutoff, architecture, the species list incfg.model.extra, the training paths and property keys). Whatever can be derived from the checkpoint should be derived, not retyped; the sidecar adds what the checkpoint cannot know (DOI, provenance, conventions, licence). Open question for Sina: iscfgstable enough to read from outside the trainer, and can xnn write the sidecar itself atsavetime?
The sidecar#
One JSON file next to each checkpoint, same stem, extension .mlff.json
(water_mace_les.pt + water_mace_les.mlff.json). It is what SEAMM reads;
the checkpoint is opaque to SEAMM. Fields marked derivable can be filled from
the checkpoint by the publishing utility; the rest are supplied by the author.
{
"schema": "seamm-mlff-sidecar/1",
"name": "water_mace_les",
"title": "Water MACE-LES, run 56 + trimers",
"description": "MACE with long-range electrostatics (LES) trained on ...",
"version": "2026.09.15",
"created": "2026-09-15T19:37:00Z",
"authors": [
{"name": "Sina Mostafanejad", "affiliation": "MolSSI", "orcid": "0000-..."}
],
"license": "CC-BY-4.0",
"doi": "10.5281/zenodo.1234567",
"concept_doi": "10.5281/zenodo.1234566",
"zenodo_record": 1234567,
"files": {
"water_mace_les.pt": {"sha256": "…", "size": 3653832}
},
"engine": {
"code": "xnn",
"min_version": "0.1.0",
"family": "mace",
"dtype": "float32",
"cutoff": 6.0,
"cutoff_units": "Å",
"checkpoint_format": "xnn-trainer/1"
},
"applicability": {
"elements": ["H", "O"],
"periodic": true,
"charges": [0],
"spin_multiplicities": [1],
"phases": ["gas-phase clusters", "liquid water"],
"notes": "Trained on 1- to 3-mers plus liquid snapshots; not for ions."
},
"conventions": {
"energy_units": "eV",
"length_units": "Å",
"energy_reference": "formation energy, isolated-atom reference, E0 = 0",
"reference_model_chemistry": "ORCA:DFT@revDSD-PBEP86-D4/def2-TZVPPD",
"counterpoise": "SSFC",
"stress_sign": "pressure (MDI convention)"
},
"training": {
"data_doi": "10.5281/zenodo.7654321",
"n_structures": 8666,
"energy_mae": {"value": 0.4, "units": "meV/atom"},
"force_mae": {"value": 12.0, "units": "meV/Å"},
"test_set": "held-out 10 %"
},
"citations": [
{"doi": "10.5281/zenodo.1234567", "note": "This model."},
{"doi": "10.48550/arXiv.2206.07697", "note": "MACE architecture."}
]
}
Field notes#
schemalets the reader reject or upgrade old sidecars.nameis the model-chemistry method token; it must avoid: @ / |and should be stable across versions.versionis free text but a date is recommended, matching SEAMM’s CalVer habit.doi/concept_doi/zenodo_record: the version DOI is what a job cites; the concept DOI is what the update check follows. All three are absent for a private, unpublished model – the sidecar is still useful.fileswithsha256: integrity after a manual copy, and detection of a model that changed without a version bump.engine: everything the launcher and the driver need to know without loading torch – the family, dtype (mps needs float32), cutoff, and the minimum xnn that can unpickle it. Derivable fromcfgexceptmin_version.applicability: what the Model Chemistry step can filter on (elements, periodic) and what the Energy step should warn about at run time (a charged or open-shell configuration for a model trained on neutral singlets).elementsis derivable from the species list incfg.model.extra.conventions: the campaign decisions a consumer must know to compare with QM – units, and above all the energy reference (per-atom formation energy with E0 = 0, per the water/electrolyte plan). Without this a REF_energy from the model and one from ORCA cannot be put on the same axis.training: provenance and headline accuracy; thedata_doicloses the loop to the training set on Zenodo.citations: whatself.references.citeshould add when the model is used, beyond the plug-in’s own reference.
The catalog#
A single JSON file in a small Git repository (proposed
molssi-seamm/mlff-catalog, file catalog.json on main), fetched by
raw URL. Editing it is a commit – by hand or by the publishing utility – so
it can change as often as needed, with history and review if wanted. Zenodo
holds the files; the catalog holds pointers plus a copy of each model’s sidecar
so the Model Chemistry dialog can list and filter models without touching
Zenodo at all.
{
"schema": "seamm-mlff-catalog/1",
"updated": "2026-09-18T21:00:00Z",
"models": {
"water_mace_les": {
"concept_doi": "10.5281/zenodo.1234566",
"latest": "2026.09.15",
"versions": {
"2026.09.15": {
"doi": "10.5281/zenodo.1234567",
"zenodo_record": 1234567,
"files": {"water_mace_les.pt": {"sha256": "…", "size": 3653832}},
"sidecar": { "...the full sidecar above..." }
},
"2026.08.08": {
"doi": "10.5281/zenodo.1234500",
"zenodo_record": 1234500,
"files": {"water_mace_les.pt": {"sha256": "…", "size": 3653832}},
"sidecar": { "..." },
"deprecated": "Superseded by 2026.09.15 (trimer data added)."
}
}
}
}
}
Keyed by model name;
latestnames the version the plug-in offers by default; older versions remain resolvable for reproducibility, optionally markeddeprecatedwith a reason.The embedded
sidecaris a copy: the authoritative one is the file on Zenodo. The utility that adds a version to the catalog copies it in, so the two cannot drift by hand-editing unless someone edits the copy on purpose.The plug-in caches the catalog at
~/.seamm.d/xnn/catalog.jsonwith the HTTP ETag, refreshing at most once an hour when online and silently keeping the cached copy when not. A user can also pointcataloginxnn.iniat a file or a different URL (a site mirror behind a firewall).
Resolution and caching#
Model directories keep today’s order (personal:xnn, local:xnn, extra
directories), and the catalog is appended as a further, remote source. When a
model chemistry xnn:MLFF@<name> is used:
Look for
<name>.ptin the model directories. If found, read its sidecar (if present) and use it. A checkpoint without a sidecar is still usable, reported as unpublished/local, and not citable.Otherwise look the name up in the catalog and download the
latestversion’s files and sidecar intolocal:xnn(machine-wide) – orpersonal:xnniflocalis not writable – verifying the sha256. Downloading happens at run time, once; the job then proceeds as with a local file. Model Chemistry shows catalog-only models with a marker such as “(download)”.Report and cite: the output names the file used and its version DOI, and
self.references.citeadds the model’s citations.
Update policy: default use what is cached. When online and the catalog says
a newer version exists, print a one-line notice; never swap under a running
campaign. Explicit actions: fetch --update to take the newest, or pin a
version in xnn.ini (water_mace_les = 2026.08.08) for a study that must
not move.
Utility (offline and secure sites)#
Subcommands of xnn-step-installer (or a seamm-mlff script if this
becomes shared with other MLFF providers):
models list [--catalog URL|FILE]– what the catalog offers, with version, elements and whether it is cached.models fetch <name> [--version V] [--to DIR]– download checkpoint + sidecar, verify sha256. Run on a connected machine, copy the two files to the inside machine’slocal:xnnorpersonal:xnn; nothing else is needed.models check– compare cached versions with the catalog.models publish <checkpoint> --sidecar X.json [--sandbox]– upload to Zenodo (viaseamm_util.Zenodo, which already handles deposits, versions and publishing), then add the version to the catalog file for commit. Fills the derivable sidecar fields from the checkpoint.
Open questions#
Sina: what exactly does
cfgexpose (species list location, units assumptions), and would xnn write the sidecar atTrainer.save?Zenodo community for the models (
seammexists for flowcharts?) and the licence to standardise on.Whether the catalog repository should also carry the training-set records, or those stay per-model via
training.data_doionly.Generalise now or later: the sidecar and catalog are engine-agnostic (only
engine.codediffers); a MACE-native or other provider could share them, which argues for the code living in a small shared package rather than inxnn_step.