Public Interfaces and Runtime
NIRS4ALL has one portable workflow contract and several user surfaces around it.
The portable contract is:
dataset.yaml or dataset.json
pipeline.yaml or pipeline.json
The public Python API runs the supported pipeline/dataset contracts. The CLI provides workflow run/predict/retrain/export/load, results and tuning in addition to dataset/config/workspace/artifact management; it has no general top-level nirs4all run. Start with the common interface matrix and task guide to select the correct product and profile.
Python API
Function/class |
Purpose |
Typical input |
Typical output |
|---|---|---|---|
|
Train/evaluate one or many pipelines on one or many datasets |
Pipeline spec + dataset spec |
|
|
Bounded scientific-library callable for Studio’s Rust-owned CPython stdio host |
Closed, already-resolved JSON value |
Bounded JSON-native scientific summary |
|
General scientific callable with library workspace persistence |
Canonical pipeline/dataset and Rust-authorized workspace |
Bounded summary, run IDs and native result paths |
|
Predict from a stored chain or exported bundle |
|
|
|
Run native HPO with an explicitly supplied host optimizer and controller |
DSL, signed envelope, manifests, HPO request and callbacks |
Native trial evidence, selection and checkpoint dictionary |
|
Execute a signed native DAG request with an explicitly supplied controller |
Named envelopes, relations, training influence and callbacks |
Native DAG-ML |
|
Transport captured portable Package V2 artifacts into Core |
Native training outcome, package and archive identity |
Archive identity and SHA-256 |
|
Validate storage and native portable payload semantics |
Core Archive V2 path |
DAG-ML |
|
Replay a signed current cohort through explicitly trusted controller callbacks |
Core archive, signed request/envelopes, trust manifests and read-only callbacks |
Native DAG-ML replay outcome |
|
Fit split-conformal intervals from explicit calibration evidence |
Replayed calibration predictions or selected calibration cohort + prediction ids |
|
|
Discover conformal method and exchangeability-unit vocabularies |
None |
Tuples aligned with runtime validation and registry schema |
|
Discover reserved and currently executable multi-target policies |
None |
Tuples aligned with runtime validation and registry schema |
|
Discover optimizer engines and objective directions accepted by the strict native tuning contract |
None |
Tuples aligned with |
|
Separate deterministic tuning-contract keys, optimizer persistence keys, and |
None |
Tuples for validators, bindings, CLIs and Studio forms |
|
Warm-start native HPO with an explicit first trial |
Public decoded parameter values keyed by |
Deterministic contract entry that can change trial order and selected predictor |
|
Resume the supported native HPO lanes |
Matching workspace result, Optuna storage, or n4m file checkpoint plus the same search-space contract |
Validated completed evidence followed by only the remaining work; |
|
Inspect canonical ordered tuning-space patches for forms, bindings and Studio |
|
JSON-native |
|
Publish the ordered tuning-space JSON Schema |
None or optional JSON indentation |
Stable schema for bindings, CLI validators and Studio tuning forms |
|
Publish a lightweight HPO summary for CI, release indexes, bindings and Studio cards |
|
|
|
Discover conformal-aware objective metrics that require |
None |
Tuple aligned with |
|
Discover registry-level model-local |
None |
Tuples aligned with keyword registry aliases |
|
Discover Optuna model-local HPO controls |
None |
Tuples aligned with |
|
Discover native n4m model-local HPO controls |
None |
Tuples aligned with |
|
Discover deterministic DAG-ML |
None |
Tuples aligned with native DAG-ML lowering validation |
|
Apply a stored conformal calibrator to new point predictions |
Calibrated result/store/bundle + |
|
|
Load a workspace conformal result through the public prediction surface |
Workspace path + conformal id/fingerprint |
|
|
Publish a public prediction result through the workspace prediction store |
Workspace path + |
Stored prediction id, with arrays and result metadata reloadable by the workspace prediction helpers |
|
Load a workspace prediction row through the public prediction surface |
Workspace path + prediction id |
|
|
Load workspace prediction rows through the public prediction surface |
Workspace path + optional dataset name |
|
|
Compute empirical conformal diagnostics |
Calibrated result or conformal |
|
|
Produce an audit-only robustness/generalization report |
Replayed predictions + observed targets + scenarios/slices |
|
|
Compute robustness directly from one stored prediction row |
Workspace path + prediction id + observed targets |
|
|
Discover reserved robustness modes and the subset executable today |
None |
Tuples aligned with runtime validation and registry schema |
|
Discover the ordered public robustness scenario |
None |
Tuple aligned with report metadata and registry enum |
|
Discover which scenarios accept |
None |
Tuples aligned with runtime validation and registry schema |
|
Convenience method equivalent to |
Result object + observed targets + optional scenarios/slices/workspace |
|
|
Publish/reload a verified robustness artifact directory |
|
Manifested JSON/summary/Markdown/HTML/Parquet bundle or verified |
|
Persist/reload verified robustness reports in a workspace |
Workspace path + |
Robustness id or |
|
Run the native single-estimator/linear tuning lane |
Estimator or linear pipeline + explicit score data |
|
|
Inspect the calibrated result returned by native tuning+calibration without reaching into nested fields |
|
Materialized interval, conformal metrics, or |
|
Return the machine-readable keyword/effect registry |
None |
JSON-compatible registry dict |
|
Serialize the keyword/effect registry deterministically |
Optional JSON indentation |
Registry JSON text |
|
Return the registry JSON Schema for static consumers |
None |
JSON Schema dict |
|
Serialize the registry JSON Schema deterministically |
Optional JSON indentation |
Schema JSON text |
|
Return the JSON Schema for |
None |
JSON Schema dict |
|
Serialize the robustness summary JSON Schema deterministically |
Optional JSON indentation |
Schema JSON text |
|
Return the JSON Schema for |
None |
JSON Schema dict |
|
Serialize the tuning summary JSON Schema deterministically |
Optional JSON indentation |
Schema JSON text |
|
Return the JSON Schema for |
None |
JSON Schema dict |
|
Serialize the ordered tuning-space JSON Schema deterministically |
Optional JSON indentation |
Schema JSON text |
|
Generate SHAP explanations |
Model/bundle + data |
|
|
Retrain from an existing result or bundle |
Source + new data |
|
|
Reuse a selected execution session and workspace across calls |
Optional pipeline and execution kwargs |
|
|
Load an exported |
Bundle path |
|
|
Generate synthetic NIRS data |
Synthetic parameters |
|
|
Export a trained pipeline bundle |
Output path |
|
Explicit portable RolePipeline archive transport
The three portable archive functions preserve the complete captured Package V2,
including a four-source numeric projection graph with five RAW
methods_role_pipeline artifacts: four branches and the OOF-trained meta-model.
The storage profile is dagml_methods_role_pipeline_raw_sha256; payloads remain
at their relative artifacts/<sha256>.json paths. Core validates the bounded
archive container and exact member inventory. DAG-ML validates package/outcome
links, controller contracts, artifact fingerprints and the complete union of
RAW payloads. The SDK delegates both layers and supplies no ZIP reader, model
deserializer or numerical implementation.
Use the captured native outcome and package produced by DAG-ML CV/SELECT/REFIT:
import nirs4all
reference = nirs4all.write_portable_predictor_archive_v2(
"five_models.n4a",
archive_id="archive:five-models",
outcome=captured_outcome,
package=captured_package,
)
package = nirs4all.read_portable_predictor_archive_v2("five_models.n4a")
replayed = nirs4all.replay_portable_predictor_archive_v2(
"five_models.n4a",
signed_predict_request,
current_source_envelopes,
trusted_controller_manifests,
controller.predict_callback,
outcome_id="outcome:heldout",
run_id="run:heldout",
artifact_callback=controller.artifact_callback,
)
signed_predict_request and current_source_envelopes are the native DAG-ML
contracts for the new, explicitly identified, target-free cohort. The trusted
manifests are supplied by the caller, independently of archive contents.
DAG-ML verifies them before callbacks. A read-only Methods controller hydrates
the saved RolePipeline N4ME states, predicts from the named numeric source rows
and releases every state, including when prediction fails. Before calling
Methods prediction, the controller must compare the saved feature names and
their order with features independently resolved from current sources and
upstream prediction inputs. Replay does not fit or request targets. Matching
Core and DAG-ML wheels providing the portable payload reader/validator and
trusted callback replay are required.
This is an explicit callback profile. Existing nirs4all.predict,
load_session and native N4MM APIs keep their separately qualified closed
PLS/Ridge contracts; RolePipeline bytes are not converted to N4MM or silently
routed into that lane. The numeric projection transport does not establish
the canonical U07 N-D encoders, its interlanguage controllers or other HPO
profiles. The deterministic five-model test capture and its provenance live
under tests/fixtures/portable_role_pipeline/.
The public run_host_hpo_search and execute_training entry points also expose
the native scheduling path for caller-supplied Python, R and Octave controllers.
They lazily load DAG-ML and preserve its arguments, advanced callbacks, native
errors and result objects. HPO executes FIT_CV trials and does not REFIT;
execute_training runs the signed request’s CV, SELECT and optional REFIT.
Capture a portable package while the native TrainingResult is attached, then
call detach() after export. These functions do not lower a high-level pipeline
or implement numerical models. The runnable
Octave models in a Python multimodal workflow example calls both SDK functions before
capturing all five models and replaying the archive in a fresh Octave process.
Train from Config Files
import nirs4all
result = nirs4all.run(
pipeline="pipeline.yaml",
dataset="dataset.yaml",
name="run_from_files",
random_state=42,
)
print(result.best_score)
result.export("exports/model.n4a")
library(reticulate)
nirs4all <- import("nirs4all")
result <- nirs4all$run(
pipeline = "pipeline.yaml",
dataset = "dataset.yaml",
name = "run_from_files",
random_state = 42L
)
result$export("exports/model.n4a")
using PythonCall
nirs4all = pyimport("nirs4all")
result = nirs4all.run(
pipeline="pipeline.yaml",
dataset="dataset.yaml",
name="run_from_files",
random_state=42,
)
result.export("exports/model.n4a")
import { spawnSync } from "node:child_process";
const code = `
import nirs4all
r = nirs4all.run("pipeline.yaml", "dataset.yaml", name="run_from_files", random_state=42)
print(r.best_score)
r.export("exports/model.n4a")
`;
const run = spawnSync("python", ["-c", code], { stdio: "inherit" });
if (run.status !== 0) process.exit(run.status);
Predict from an Exported Bundle
import nirs4all
pred = nirs4all.predict(
model="exports/model.n4a",
data="new_dataset.yaml",
)
df = pred.to_dataframe()
print(df.head())
library(reticulate)
nirs4all <- import("nirs4all")
pred <- nirs4all$predict(
model = "exports/model.n4a",
data = "new_dataset.yaml"
)
print(pred$to_dataframe())
using PythonCall
nirs4all = pyimport("nirs4all")
pred = nirs4all.predict(
model="exports/model.n4a",
data="new_dataset.yaml",
)
println(pred.to_dataframe())
import { spawnSync } from "node:child_process";
const code = `
import nirs4all
pred = nirs4all.predict(model="exports/model.n4a", data="new_dataset.yaml")
print(pred.to_dataframe())
`;
const run = spawnSync("python", ["-c", code], { stdio: "inherit" });
if (run.status !== 0) process.exit(run.status);
Runtime Engine
nirs4all.run() accepts an engine selector:
Engine |
Meaning |
|---|---|
|
Use the package default, |
|
Explicitly use the in-process Python compatibility orchestrator outside Studio during the ADR-24 rollback window. |
|
Request the dag-ml backend for covered shapes. Unsupported or unavailable native execution fails closed by default. |
|
Produce a portable Methods Archive V2 for the strict supported training subset; install |
|
Run the bounded native-first parity oracle for exact array/KFold/PLS regression; unsupported shapes fail before execution and the temporary legacy workspace is removed. |
The pipeline language is broader than current dag-ml native coverage. Requesting
engine="dag-ml" is fail-closed by default: unsupported shapes and unavailable
native dependencies raise structured errors. Direct Python callers may opt into
the ADR-24 rollback path only with engine="legacy" explicitly.
allow_fallback=True is no longer an execution route and is refused for native
selectors; genuine native runtime or operator failures always propagate.
Studio cannot select the compatibility route.
The frozen public nirs4all.run(...) signature deliberately has no product
execution-profile parameter. It remains the rollback-capable Python API through
the R4 removal decision. Product integrations use a private strict boundary
inside the package instead of widening or weakening that public contract.
The strict Archive V2 path is available in the base V1 installation; the
nirs4all[native] compatibility extra repeats the Core/Methods constraints for
existing deployment commands. Release 1.0.1 is qualified against
dag-ml==0.3.25, dag-ml-data==0.2.11, nirs4all-io==0.1.18,
nirs4all-core==0.3.30, and nirs4all-methods==1.0.18. The package metadata
admits only the corresponding compatibility families and their next breaking
version boundaries.
The native archive training compiler accepts only KFold followed by either a
terminal PLSRegression or the exact
StandardNormalVariate -> SavitzkyGolay -> PLSRegression sequence. SNV is
row-wise with ddof=0; Savitzky-Golay is smoothing-only (deriv=0,
delta=1.0) with native mode="interp" and defaults window_length=11,
polyorder=3; PLS keeps scale=True and its other public defaults. Raw PLS is
serialized as N4MM format 1 and the embedded pipeline as format 2. Both scalar
and multi-target regression are supported when target names are explicit.
Anything outside this profile is refused before execution, with no legacy,
pickle, plugin, or Python preprocessing fallback.
The explicit dual oracle returns the native RunResult after comparing its
winner, OOF identities/predictions, validation scores, and split evidence with
a temporary engine="legacy" oracle under the packaged compatibility ledger.
It never enables allow_fallback and does not expose the legacy workspace.
Native Methods lane of the general profile
Under the general DAG profile, a campaign whose steps are all generic n4m role
estimators (n4m.roles instances or n4m:<method_id> tokens) runs on DAG-ML’s
callback-free Methods lane: every node fits, transforms and predicts inside
libn4m through DAG-ML’s native estimator controllers, while the fold set,
envelope views, variant selection and scoring are those of the host-callback
lane. A campaign takes this lane when:
N4A_DAGML_NATIVE_METHODSis not0/false/off, the in-process DAG-ML mechanism is selected and the installeddag-mlexposes the lane;the dataset is one single-source 2D block without augmented rows, repetition grouping, held-out test partition, or samples excluded inside the OOF universe (
excludesteps resolved before the split are supported);the steps are n4m transformers or selectors followed by one
{"model": <n4m regressor or classifier>}(optionally named), the model role matching the task (a classifier has one integral class column), after any splitter;no method requires a fit input a DAG node cannot supply or retains training rows in its fitted state, and every parameter and model
_range_/_log_range_sweep produces exact native values.
Any other campaign keeps the host-callback lane. result.execution_lane
reports "native_methods", "host_callback" or "mixed", and a callback
campaign records its reason in per_dataset[...]["execution_lane_reason"].
Both lanes produce the same scores, predictions, selected variant and captured
joblib model, so exported archives are unchanged.
Every explicit engine="legacy" or engine="dual" request emits a
LegacyEngineUsageWarning. Its message is stable compact JSON with
schema_version, code, engine, and operation fields. Support counting is
separate and opt-in: set N4A_LEGACY_USAGE_COUNTER=1, then read the current
process snapshot with
nirs4all.pipeline.engine.get_legacy_engine_usage_counts(). The snapshot has
legacy, dual, and total counts only; it performs no network access, writes
nothing persistently, and records no paths, request inputs, or scientific data.
Counts exist only for the lifetime of the current Python process.
result = nirs4all.run(
pipeline="pipeline.yaml",
dataset="dataset.yaml",
engine="dag-ml",
random_state=42,
)
Native lifecycle capability matrix
engine="native" is a fail-closed portable Methods lane, distinct from the
general engine="dag-ml" host runtime. The authoritative machine-readable
contract is nirs4all.api.native_capabilities.get_native_capability_matrix().
It records each lifecycle form as native, plugin, or refused, with every
implicit fallback forbidden. The compatibility ledger remains
parity-tolerance context only; it is not semantic authority for capability
selection.
The native lifecycle covers portable training, identity-bound prediction,
Archive V2/V3 replay and explicit native sessions. Nested PLS-to-Ridge stacking
requires partitioned outer CV so every sample has exactly one outer OOF row.
Unsupported transfer, finetune, explanation, generation, archive, or workspace
forms fail before execution and never instantiate a legacy PipelineRunner.
Live Methods execution observation
native_execution_claim and native_execution_is_live expose an audit-only,
process-local observation of the exact strict Methods call while its owner is
open. It is not a portable attestation: result.close() or result.detach(),
and NativeMethodsSession.close(), invalidate the live observation. The signed
outcome and portable package remain authoritative, so
result.export("model.n4a") may still write the Core Archive V2 after the live
façade has been released.
Supported strict terminal form
run(..., terminal_predict={"X", "sample_ids"}, engine="native") is the
supported callback-free DAG-ML CV→REFIT→terminal-PREDICT facade. It requires
finite prediction arrays and explicit stable identities. The opaque frozen
receipt is process-local; Archive V2 never archives, reloads, or forges that
terminal receipt. Unsupported shapes fail before native data execution and do
not retry through the Python compatibility runner.
Studio Scientific CPython Host Boundary
The additive studio_scientific_job_v2(request) general contract uses schema
nirs4all.studio-scientific-job.v2, operation run, job_id, a canonical
pipeline list (as emitted by serialize_component), a library dataset path or
configuration, and options containing an absolute workspace_path authorized
by Rust. Optional engine and allow_fallback must be dag-ml and false.
Inline JSON X/y arrays and batches are supported. Options use the public run
semantics; unsupported execution capabilities fail without a legacy retry.
V2 persists the library’s exact scored predictions and captured model artifacts.
Its bounded response uses schema nirs4all.studio-scientific-job-result.v2 and
contains job_id, actual engine, and a result object with run_ids,
workspace_path, native_results_dirs, metric, nullable validation_score,
prediction_count, model_names, dataset_names, and
native_score_sets_available. The latter must not be treated as true for
host-only paths lacking native evidence. Missing CV is represented by null,
not an invented validation score. No full prediction arrays cross this seam.
Requests are limited to 8 MiB and nesting depth 64; responses to 256 KiB. Canonical operators are trusted scientific code, not sandboxed code. Imports are limited to the installed scientific package allowlist; custom packages require separate explicit authorization and are not enabled by arbitrary module names. Rust remains the authority for paths, jobs, cancellation, HTTP and events. Library workspace writes are not a Python scheduling backend. The narrow V1 callable below remains unchanged; V2 is an explicit versioned contract, not an automatic widening of V1.
nirs4all.studio_scientific_job_v1(request) is a library callable, not an
HTTP backend. It never opens a socket or caller-supplied path, reads a
workspace, owns a scheduler/job/event/cancellation transition, or writes a
durable result. The Studio sidecar must keep all of those responsibilities and
invoke this callable in a fresh, isolated CPython process over bounded JSON
stdio.
Before the public runner can prepare a session, inspect its pipeline or dataset,
write a result, or construct a PipelineRunner, the callable enters that private
strict boundary. The boundary rejects direct or environment-selected legacy,
the dual legacy oracle, and allow_fallback=True. The profile itself is fixed
in package code and is not selectable through the Studio request or an
environment variable. Public request/result contract refusals are reported as
the exported nirs4all.StudioScientificJobError with a stable code.
The v1 callable accepts exactly this minimal resolved contract (unknown keys are refused):
{
"schema": "nirs4all.studio-scientific-job.v1",
"operation": "run",
"job_id": "training_0001",
"engine": "dag-ml",
"allow_fallback": false,
"dataset": {
"name": "protein",
"task_type": "regression",
"X": [[1.0, 2.0], [2.0, 3.0], [3.0, 5.0], [4.0, 7.0]],
"y": [1.1, 2.2, 3.3, 4.4]
},
"pipeline": {
"kind": "pls_regression",
"n_components": 1,
"scale": true,
"cross_validation": {"kind": "kfold", "n_splits": 2, "shuffle": false}
},
"options": {"name": "protein_pls", "random_state": 17}
}
Only plain JSON is accepted. The engine is always dag-ml, fallback is always
disabled, and v1 is limited to bounded single-target regression with K-fold
PLS. legacy, dual, native, Python objects, non-finite values, arbitrary
class/import names, paths/workspaces, and ambient CLI or result-persistence
overrides are refused before scientific execution. The result contains no job
status; it reports only the selected metric and bounded counts for Rust to
interpret and persist.
Studio owns HTTP, jobs, WebSocket events, persistence, scheduling, and terminal
state in Rust. CPython is a bounded, explicit stdio library/plugin host for the
scientific call only. The Studio contract cannot request engine="legacy" or
allow_fallback=True: native refusal is returned to Rust, with no product
fallback. This keeps the ADR-24 legacy rollback surface available to direct
Python callers without making it reachable from Studio.
Environment switches:
Variable |
Effect |
|---|---|
|
Select a native engine for calls that do not pass |
|
Opt into the data-free, process-local explicit legacy/dual support counter. |
See Native Capability Preflight for the limitation-to-preflight matrix.
| N4A_NATIVE_RESULTS=/path/to/results | For dag-ml runs, request native result output. |
CLI Commands
Use nirs4all <group> <command> --help for exact options.
Group |
Command |
Purpose |
|---|---|---|
root |
|
Print dependency/install diagnostics. |
root |
|
Run the packaged integration smoke test. |
root |
|
Print installed package version. |
root |
|
Export the keyword/effect registry or its JSON Schema for docs, CI, Studio/Web, forms, and bindings. |
root |
|
Export the JSON Schema for |
root |
|
Export the JSON Schema for |
root |
|
Republish a verified |
workspace |
|
Compute a |
|
|
Validate a pipeline or dataset config. |
|
`schema pipeline |
dataset` |
|
|
Validate a dataset config/folder. |
|
|
Show sources, task type, aggregation, and optional detected file parameters. |
|
|
Normalize a dataset config to YAML or JSON. |
|
|
Compare two dataset configs. |
|
|
Create workspace directories and store. |
|
|
List recorded runs. |
|
|
Republish a verified persisted |
|
|
Query top predictions by metric. |
|
|
Filter prediction rows by dataset and scores. |
|
|
Show workspace score statistics. |
|
|
List saved templates/library items. |
|
|
Inspect or export persisted robustness reports by id or fingerprint. |
|
|
List artifacts not referenced by manifests. |
|
|
Dry-run or delete orphaned artifacts. |
|
|
Show artifact storage statistics. |
|
|
Delete all artifacts for a dataset when forced. |
Example:
nirs4all dataset validate dataset.yaml
nirs4all dataset inspect dataset.yaml --detect
nirs4all config validate pipeline.yaml --type pipeline --check-imports
nirs4all workspace init workspace
nirs4all workspace query-best --workspace workspace --metric test_score -n 5
Result Objects
RunResult exposes:
Accessor |
Purpose |
|---|---|
|
Best/final prediction entries. |
|
Convenience score fields. |
|
Top prediction rows. |
|
Filter prediction rows. |
|
Per-model refit result handles when available. |
|
Export the selected model bundle. |
See also Session API Reference, Predictions API Reference, and Module-Level API.
Conformal and Robustness Artifact Contracts
Conformal calibration artifacts and robustness reports are separate contracts.
The conformal artifact stores the fitted split-conformal calibrator, calibrated
coverage, physical sample identity, fingerprints, and guarantee-status payload.
Calibrated result metadata also exposes calibration_replay_source, copied into
conformal_guarantee_status, so downstream tools can display whether the
calibration predictions were provided arrays, a PredictResult, dataset-backed
y_pred, an in-memory predictor, a saved predictor_bundle, a
predictor_result, or a workspace predictor_chain_id. The block is
provenance only; its route is one of provided_arrays, predictor.predict,
or nirs4all.predict, and it does not authorize refit, recalibration, or replay
outside the original Python execution context. Reloaded results fail closed if
both locations carry calibration_replay_source but disagree, so bindings,
Studio, CLIs and notebooks cannot observe contradictory replay provenance.
Workspace conformal rows enforce the same physical prediction identity contract
as filesystem stores and .n4a sidecars. A corrupted conformal_results
workspace row with the same missing prediction identity is rejected. A stored
calibrated_result.json whose non-empty prediction cohort lacks
canonical physical sample_ids fails reload instead of becoming a partial public
PredictResult.
The robustness report stores audit diagnostics computed after predictions are
available. A robustness report can include conformal diagnostics, but it does not
modify or refresh the conformal calibrator.
The recommended publication layout for a robustness audit is:
report = nirs4all.robustness(
pred,
y_true=y_observed,
scenarios=[
{"kind": "observed", "severity": 0.0},
{"kind": "prediction_noise", "severity": 0.02, "distribution": "normal"},
],
slice_by=["Instrument"],
)
paths = report.save_artifacts("artifacts/robustness/run-001")
save_artifacts() writes a verified bundle. By default the bundle includes:
File |
Consumer |
Purpose |
|---|---|---|
|
Python/API/reload |
Full verified |
|
CI, bindings, Studio/Web, dashboards |
Stable compact summary rows plus optional fail-loud guarantee and replay-provenance blocks. |
Markdown/HTML |
Human review |
Release notes and audit reports. |
Parquet directory |
Data analysis |
Tabular report rows when Parquet support is installed. |
summary.json is intentionally smaller than the full report. Its schema is
available from both Python and CLI:
summary = report.summary_artifact()
schema = nirs4all.get_robustness_summary_schema()
schema_json = nirs4all.robustness_summary_schema_json()
nirs4all robustness-summary-schema --output robustness-summary.schema.json
The summary payload has:
format="nirs4all.robustness.summary";schema_version=1;fingerprint, matching the full report fingerprint;mode, one ofclean_frozen,matched_recalibration,structural_refit;report_version;slice_by;optional
conformal_guarantee_status, carrying fail-loud guarantee metadata for calibrated reports;optional
spectral_replay, carrying metadata-only provenance for spectral robustness scenarios:source,route,sample_ids_forwarded, and when applicable the savedpredictor_bundlepath andall_predictions=Falsereplay mode;summary, an array of scenario rows.
Each row reports the scenario label, severity, sample count, point metrics,
deltas from the reference scenario, worst slice metadata, nullable conformal
diagnostics when intervals are present, and an execution-scope hint. The
execution_scope value is baseline, prediction_replay, or
spectral_replay; requires_spectral_replay=true marks rows that came from
explicit-X spectral/OOD replay through a frozen predictor. Static consumers
should validate format, schema_version, and fingerprint before rendering a
card or making a release assertion.
spectral_replay is publication provenance, not an execution contract for
downstream products. Bindings, Studio/Web dashboards, and CI cards may display
that a Python robustness report replayed spectra through a frozen predictor or
predictor_bundle, but they must not infer permission or capability to replay
spectral/OOD perturbations locally from this metadata alone.
Prediction objects expose the same boundary through
PredictResult.robustness_evidence and
PredictResult.spectral_replay_evidence_status. The first accessor returns the
published evidence metadata when present, including the Studio/store shape under
result_metadata.robustness_evidence; the second accessor is a fail-closed
diagnostic that reports ready_for_spectral_replay only when an executable
row-aligned X/spectra matrix and a saved predictor_bundle/model_path are
present. It keeps publication markers separate from executable arrays through
has_X_or_spectra and has_executable_X_or_spectra; the executable flag also
requires the matrix row count to match the prediction row count.
Consumers should use that diagnostic before enabling spectral/OOD robustness
actions, while still delegating the actual report to nirs4all.robustness().
When a PredictResult carries the actual X/spectra matrix in metadata,
nirs4all.robustness() can consume that matrix and the published bundle path as
defaults; provenance-only strings remain non-executable metadata.
Workspace-loaded prediction records use the same boundary. Load them with arrays and convert them explicitly before invoking native conformal or robustness helpers:
from nirs4all.data.predictions import Predictions
predictions = Predictions.from_workspace("workspace/", load_arrays=True)
prediction = predictions.get_predict_result_by_id("pred-001")
record = predictions.get_prediction_by_id("pred-001", load_arrays=True)
# Direct public one-record shortcut:
prediction = nirs4all.load_workspace_predict_result("workspace/", "pred-001")
# Direct public bulk shortcut:
all_predictions = nirs4all.load_workspace_predict_results("workspace/")
# Direct public publisher shortcut:
prediction_id = nirs4all.save_workspace_predict_result(
"workspace/",
prediction,
dataset_name="wheat",
X=X_new,
result_metadata={"robustness_evidence": {"predictor_bundle": "model.n4a"}},
)
For the common stored-prediction audit path, call
nirs4all.robustness_from_workspace_prediction("workspace/", "pred-001", ...).
It performs the same array-preserving load/convert step, delegates to
nirs4all.robustness(), uses stored executable X/spectra and
predictor_bundle evidence as spectral/OOD defaults, and with
save_to_workspace=True persists the report linked to the same prediction_id.
nirs4all.save_workspace_predict_result(...),
nirs4all.load_workspace_predict_result(...),
nirs4all.load_workspace_predict_results(...),
Predictions.get_predict_result_by_id() and
Predictions.to_predict_results() use PredictResult.from_prediction_record()
internally. The conversion preserves result_metadata, robustness_evidence,
actual X/spectra arrays, sample indices, model name, preprocessing
metadata, calibration_replay_source and tuning_calibration_source. If
records were loaded without arrays, conversion fails explicitly instead of
creating a partial result with unverifiable replay status.
Workspace persistence keeps the same separation:
robustness_id = nirs4all.save_workspace_robustness_report(
"workspace/",
report,
robustness_id="run-001-robustness",
run_id="run-001",
chain_id="chain-001",
conformal_id="run-001-conformal",
)
restored = nirs4all.load_workspace_robustness_report("workspace/", robustness_id)
Python-side publishers should write executable spectral evidence through the
store-backed Predictions.add_prediction(..., X=..., spectra=..., result_metadata=...) path. X and spectra are stored in the Parquet sidecar,
result_metadata.robustness_evidence records the replay bundle or model path,
and Predictions.merge_stores(...) preserves those sidecar fields when
consolidating workspaces.
Studio and other products should consume summary.json or
RobustnessReport.summary_artifact() for cards and tables, then link to the
full report for audit. They must not recompute statistical meaning from partial
metrics.