nirs4all.pipeline.bundle.generator module
Bundle Generator - Export trained pipelines as standalone bundles.
This module provides the BundleGenerator class for exporting trained pipelines to various bundle formats (.n4a, .n4a.py) for deployment, sharing, or archival.
- Bundle Formats:
- .n4a: Full nirs4all bundle (ZIP archive) containing:
manifest.json: Bundle metadata and version info
pipeline.json: Minimal pipeline configuration / chain.json
trace.json: Execution trace for deterministic replay
artifacts/: Directory with artifact binaries
fold_weights.json: CV fold weights (if applicable)
- .n4a.py: Portable Python script with:
Embedded artifacts (base64 encoded)
Standalone predict() function
No nirs4all dependency (only numpy, joblib required)
Supports two export paths:
Store-based (preferred):
export_from_chain(chain_id, output_path)loads the chain fromWorkspaceStoreand packages it into a bundle.Resolver-based:
export(source, output_path)resolves from a prediction dict / folder / bundle and packages artifacts.
Example
>>> from nirs4all.pipeline.bundle import BundleGenerator
>>>
>>> # Store-based export (preferred)
>>> generator = BundleGenerator(workspace_path)
>>> bundle_path = generator.export_from_chain("abc123", "exports/model.n4a")
>>>
>>> # Resolver-based export
>>> bundle_path = generator.export(best_prediction, "exports/model.n4a")
- class nirs4all.pipeline.bundle.generator.BundleFormat(value)[source]
Bases:
StrEnumSupported bundle export formats.
- Variables:
N4A – Full ZIP bundle with all artifacts and metadata
N4A_PY – Portable Python script with embedded artifacts
- N4A = 'n4a'
- N4A_PY = 'n4a.py'
- class nirs4all.pipeline.bundle.generator.BundleGenerator(workspace_path: str | Path, verbose: int = 0, store: Any | None = None)[source]
Bases:
objectGenerate standalone prediction bundles from trained pipelines.
This class exports trained pipelines to bundle formats that can be used for deployment, sharing, or archival without requiring the original workspace or full nirs4all installation.
- Variables:
workspace_path – Path to the workspace root
resolver – PredictionResolver for resolving prediction sources
verbose – Verbosity level for logging
Example
>>> generator = BundleGenerator(workspace_path) >>> generator.export(best_prediction, "model.n4a") >>> >>> # Export to portable script >>> generator.export(best_prediction, "model.n4a.py", format="n4a.py")
- export(source: dict[str, Any] | str | Path, output_path: str | Path, format: str | BundleFormat = BundleFormat.N4A, include_metadata: bool = True, compress: bool = True) Path[source]
Export a prediction source to a bundle.
- Parameters:
source – Prediction source (prediction dict, folder path, etc.)
output_path – Path for the output bundle
format – Bundle format (‘n4a’ or ‘n4a.py’)
include_metadata – Whether to include full metadata in bundle
compress – Whether to compress artifacts (for .n4a format)
- Returns:
Path to the created bundle
- Raises:
ValueError – If format is not supported
FileNotFoundError – If source cannot be resolved
- export_from_chain(chain_id: str, output_path: str | Path, fmt: str | BundleFormat = 'n4a') Path[source]
Export a chain from WorkspaceStore as a standalone bundle.
This is the preferred export path. It reads the chain directly from the workspace store, collects all referenced artifacts, and packages them into the requested format.
- Parameters:
chain_id – Chain identifier stored in WorkspaceStore.
output_path – Destination file path.
fmt – Export format (
"n4a"or"n4a.py").
- Returns:
Path to the created bundle file.
- Raises:
RuntimeError – If no store was provided at construction time.
KeyError – If the chain does not exist.
- nirs4all.pipeline.bundle.generator.write_single_model_bundle(model: Any, output_path: str | Path, *, model_label: str = 'model', pipeline_uid: str = '', preprocessing_chain: str = '', provenance: dict[str, Any] | None = None, extra_members: dict[str, bytes] | None = None, train_steps: list[Any] | None = None, compress: bool = True) Path[source]
Write a minimal, valid
.n4aZIP bundle whose sole step is one predict-capable model.Unlike
BundleGenerator(which packages a workspace chain of per-step / per-fold artifacts resolved from aPredictionResolver), this writes a SELF-CONTAINED single-model bundle from one in-hand object: the bundle’s only step ismodel, whosepredict(X)already performs the entire forward pass (feature transforms → estimator → optional y-inverse). It is the bundle-format counterpart of a barejoblib.dump(model)and needs NO workspace, store, resolver, or trace.Its purpose is the dag-ml NATIVE
.n4aexport: a single-model dag-ml run captures its refit model as exactly such a predict-capable object (_DagmlExportedModel), and this packages it into a portable bundle WITHOUT re-fitting the pipeline on the legacy engine.The output conforms to the EXISTING
.n4aformat (bundle_format_versionBUNDLE_FORMAT_VERSION): amanifest.jsonwithmodel_step_index == 1, apipeline.jsoncarrying a singlemodelstep, and oneartifacts/step_1_foldfinal_<label>.joblibpayload. An unmodifiedBundleLoaderreads it through the no-trace index path and predicts by loading that single refit artifact and callingmodel.predict(X)directly — so the bundle reload-predict reproducesmodel.predictexactly. Directory-backed host estimators add individually hashedhost_artifacts/files to the manifest and ZIP; older inline joblib archives remain readable.- Parameters:
model – A predict-capable object (
predict(X) -> np.ndarray). Must be joblib-serializable and importable by its module path at load time (e.g. a module-level wrapper class).output_path – Destination bundle path; a
.n4asuffix is enforced.model_label – Human-readable model name used only for the manifest/pipeline label and the artifact filename. The loader keys on the step index, not this label, so it is cosmetic (sanitized to
[A-Za-z0-9_]).pipeline_uid – Optional source-run identifier recorded in the manifest.
preprocessing_chain – Optional preprocessing-chain summary string for the manifest.
provenance – Optional ADDITIVE manifest fields recording the export origin (e.g. the dag-ml run / plan / variant ids and an
export_pathmarker). Older loaders ignore unknown manifest keys (BundleMetadata.from_dict()), so this never breaks bundle reads.extra_members – Optional additional named ZIP members supplied by the caller. Names must be plain root-level files distinct from the bundle’s standard members.
train_steps – Optional REPLAYABLE training pipeline steps (the JSON-serialized form produced by
serialize_component(), one entry per original run step). When given they are written as an ADDITIVEtrain_pipeline.jsonmember soretrain(mode="full")can re-train the ORIGINAL pipeline structure from scratch. The predict path is untouched:pipeline.jsonkeeps the single cosmetic model step the loader keys on, and older loaders ignore the extra member. Without it the bundle stays predict-only (itspipeline.jsonmodel label is cosmetic, not an importable component reference).compress –
ZIP_DEFLATEDwhenTrue(default), elseZIP_STORED.
- Returns:
The written bundle path (with the enforced
.n4asuffix).