Skip to main content

latentplant

ci license

Learned world models for industrial process time series. An action-conditioned model of process dynamics that can be rolled forward in imagination, carries calibrated uncertainty, and supports what-if queries, planning and regime-change detection.

What a world model is here, and why it is not a forecaster

A forecaster maps history to a future. A world model maps history and a proposed action sequence to a distribution over futures:

rollout(obs_ctx, act_ctx, exo_ctx, act_fut, exo_fut, n_samples=64)

act_fut is an argument. That single difference is what makes counterfactual questions expressible ("what if we raise the amine dose for the next four hours") and what makes planning possible at all. A model that ignores its action input is a forecaster wearing a costume, so the test suite asserts direction-of-effect on a system with known gain.

The disciplines baked in

Rollout-first evaluation. One-step teacher-forced error is not a world-model metric: on any autocorrelated process series it flatters a model that has learned nothing. Everything in latentplant.metrics is indexed by horizon, and break_even_horizon reports where the model stops beating persistence. That integer belongs next to every headline number.

Two uncertainties, reported separately. uncertainty_split returns aleatoric (process and sensor noise, irreducible) and epistemic (the model does not know this region) as different arrays. A noisy tag and an unfamiliar operating point look identical in a single band and mean completely different things; the epistemic band is what a regime-change alarm should watch.

Cadence is declared, not guessed. An hourly lab assay carried on 20-second rows repeats about 180 times. A model trained without masking those repeats learns to copy the previous row and scores beautifully. PlantSchema takes update_seconds per tag and stale_mask marks the repeats so the loss can ignore them.

Leakage-safe by construction. Episodes never cross an acquisition gap, windows never cross an episode, splits are chronological, and standardization is fitted on train only.

Install

pip install latentplant                 # core: numpy + torch
pip install "latentplant[onnx]"         # ONNX export for a browser inference lane
pip install "latentplant[baselines]"    # sysidentpy / pysindy baseline adapters

Quick start

import numpy as np
from latentplant import (PlantSchema, TagSpec, ProbabilisticEnsemble,
                         split_on_gaps, make_windows, chronological_split)
from latentplant.metrics import rollout_report

schema = PlantSchema(
    tags=(
        TagSpec("silica_conc", "target", "pct", 0.0, 10.0, update_seconds=3600.0),
        TagSpec("pulp_level", "observation", "pct", 0.0, 100.0),
        TagSpec("amina_flow", "action", "m3/h", 0.0, 800.0),
        TagSpec("iron_feed", "exogenous", "pct"),
    ),
    row_seconds=20.0,
)

episodes = split_on_gaps(schema, values, timestamps)      # a plant stop ends an episode
windows = make_windows(schema, episodes, context=24, horizon=12)
train, val, test = chronological_split(windows)

wm = ProbabilisticEnsemble(n_obs=2, n_act=1, n_exo=1, n_members=5)
wm.fit(train, epochs=60, seed=0)

roll = wm.rollout(test.obs_ctx, test.act_ctx, test.exo_ctx,
                  test.act_fut, test.exo_fut, n_samples=64, seed=0)
lo, hi = roll.interval(0.9)
print(rollout_report(roll.samples, test.obs_fut, test.obs_ctx, test.mask_fut))

Counterfactual A/B from the same anchor:

more, less = wm.counterfactual(ctx_obs, ctx_act, ctx_exo, action_a, action_b, exo_fut)
lift = more.mean - less.mean

On real plant data this supports direction-of-effect claims only: logged actions come from a closed loop, so observational data does not identify interventions without assumptions. On a simulator the ground truth exists and the imagination-to-reality gap is measured instead.

Plan against the model, and measure what the plan was worth:

from latentplant import Planner, cvar_cost, target_tracking_cost, imagination_gap

planner = Planner(model=wm, bounds=action_bounds, horizon=24, method="cem")
plan = planner.plan(obs_ctx[:1], act_ctx[:1], exo_ctx[:1], exo_fut[:1],
                    cvar_cost(target_tracking_cost(target), alpha=0.2),
                    action_rate_penalty=2.0)

realized = env.execute(plan.actions)          # only possible where truth exists
print(imagination_gap(plan, realized, persistence_from=obs_ctx[0]))

Fix an overconfident model's intervals without retraining it:

from latentplant import fit_conformal, calibration_report

conf = fit_conformal(cal_roll, cal.obs_fut, level=0.9, mask=cal.mask_fut)
print(calibration_report(conf, test_roll, test.obs_fut, mask=test.mask_fut))

Documentation

Full docs in docs/: concepts (what a world model is, the plant contract, windows and leakage), models (probabilistic ensemble, RSSM, ensembled RSSM), evaluation (rollout metrics, conformal calibration) and planning (imagination, the imagination-to-reality gap).

Status

0.03.000, alpha. Shipping now: the ingestion contract with the multi-rate observation operator, episodes/windows/leakage-safe splits, the probabilistic ensemble (PETS-class, TS-inf propagation), the vector RSSM, the ensembled RSSM with the aleatoric/epistemic split, the rollout metric suite, split-conformal interval calibration, and CEM/MPPI planning with the imagination-to-reality gap. On the roadmap: ONNX export for a browser inference lane, a Gymnasium imagination env, and baseline adapters.

Cite

Santibañez-Leal, F. (2026). Action-Conditioned Latent Dynamics for Mineral Processing: A World-Model Engine, and a Measured Account of Where It Earns Its Cost. Preprint v0.01, CC BY 4.0. 10.5281/zenodo.22135521 (concept DOI, always latest: 10.5281/zenodo.22135520).

The paper reports what this engine actually achieves on mineral-processing data, in three directions: a recurrent latent tracks a PDE concentration field it never observes and is overconfident doing it, a linear model wins on a near-linear grinding circuit, and on a real flotation historian the whole class fails for a reason that is a property of the record rather than of the method. Source in manuscripts/.

Not to be confused with

phenoforge, the sibling engine, which fits and ensembles closed-form phenomenological equations. latentplant learns latent dynamics from data. Same industry, different object.

References

The design follows: Chua et al. 2018, Deep RL in a Handful of Trials with Probabilistic Dynamics Models, arXiv:1805.12114 (probabilistic ensembles, TS-inf); Lakshminarayanan et al. 2017, Simple and Scalable Predictive Uncertainty Estimation using Deep Ensembles, arXiv:1612.01474; Hafner et al. 2019, Learning Latent Dynamics for Planning from Pixels, arXiv:1811.04551 (RSSM); Hafner et al. 2023, Mastering Diverse Domains through World Models, arXiv:2301.04104; Janner et al. 2019, When to Trust Your Model, arXiv:1906.08253 (rollout horizon and compounding error); Che et al. 2016, Recurrent Neural Networks for Multivariate Time Series with Missing Values, arXiv:1606.01865 (cadence and masking); Romano et al. 2019, Conformalized Quantile Regression, arXiv:1905.03222 (interval calibration); Williams et al. 2017, Information Theoretic Model Predictive Control, arXiv:1707.02342 (MPPI); Levine et al. 2020, Offline Reinforcement Learning: Tutorial, Review, and Perspectives, arXiv:2005.01643 (why the planner refuses to issue setpoints).

Developed by Felipe Santibanez-Leal. MIT licensed.

Release files for latentplant 0.11.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for latentplant 0.11.0
File Size Uploaded
latentplant-0.11.0.tar.gz 158.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for latentplant 0.11.0
File Interpreter ABI Platform
latentplant-0.11.0-py3-none-any.whl Python 3 none any Details

Total release size: 276.7 kB

Release files / latentplant-0.11.0.tar.gz

Download URL latentplant-0.11.0.tar.gz
Size 158.3 kB
Tags Source
SHA-256 checksum
How to use checksums
885d1b2d29537fd7b6e5ccf0822f9fdbf0c9d7e447a150eb897761096b941b8e
BLAKE2b-256 checksum
How to use checksums
0dc4007213f6860eec0649be628bfa9aeaecaa23aea4e9cb03b151d47c18eaf1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release files / latentplant-0.11.0-py3-none-any.whl

Download URL latentplant-0.11.0-py3-none-any.whl
Size 118.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2361f080041944e76860d22159ead10886346dddc9227cbb36e7f7ec4c99f752
BLAKE2b-256 checksum
How to use checksums
52d70e837be9a4e9a248ec672ce8f4130defe8862ffcfdd7ee3fac22791a0766
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.

Transparency log

Release history Release notifications | RSS feed

0.11.1

2 release files

This release

0.11.0 This release

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page