Skip to main content
Nimbus middleware is the product wedge: a Bayesian personalization head for frozen neural / foundation embeddings. Encoders stay external. Apps consume thin BrainState outputs. One-liner: anything that maps trials to embeddings plugs in; Nimbus owns personalization, uncertainty gating, and cheap online updates — not the trunk.
Product takeaway (Paper 1): ship one Personalizer; treat fine-tune as a priced escape hatch, not the default integration path. Use the head where embedding capacity exists; stay cal-only when clean already wins.
One API across many trunks: frozen trunk epochs to embeddings, Personalizer Bayesian head, app state intent + uncertainty One Personalizer API across trunks — from the Universal Personalizer manuscript (Paper 1). Core: L0 / Bayesian head / linear probe / full FT (severe · n=40) Why the hatch stays priced: across classical trunks, stream Personalizer (L1) recovers most of the L0→L3 gain and usually beats a matched linear probe — details on Evidence.

Ladder legend (plain language)

Blue rec % on the figure = how much of the L0→L3 accuracy gain L1 recovers: (acc_L1 − acc_L0) / (acc_L3 − acc_L0). ≥FT means L1 matches or beats L3. How the Paper 1 / 1b numbers were produced (datasets, bandpass, session split, synthetic stress): Evidence → How the experiments work.
Classical CSP / bandpower / Riemann features still work. Use Personalizer.for_features(...) or the standalone heads (NimbusLDA, …) documented under Models. Upgrading from 0.5? See Migration to 0.6.

Start here

Encoder contract

wrap → Personalizer → save/load rules.

BrainState

App-facing intents, presets, and bridges.

Evidence

Head vs probe vs FT, LDA/QDA/Softmax, REVE, transfer map.

Paradigms & profiles

MI / P300 / Riemann recipes and day-2 profiles.

Transforms

Embedding-space alignment before the head.

Python Quickstart

Fit a Personalizer in a few minutes.

Minimal example

Other factories: for_research (permissive + knobs), for_features (no trunk), for_riemann / for_p300 (nimbus-bci[riemann]), for_balora (nimbus-bci[train]). Paradigm recipes and day-2 profiles: Paradigms & profiles.

Integrator checklist

  1. When to adapt — prefer the adaptation gateway, or the thin mean-shift helper with a user-supplied threshold:
Policy: stay on the current head when clean; stream-update when shift clears tau; full fine-tune stays a manual escape hatch. Portable day-2 warm-start: export_profile() → from_profile(...). See Evidence.
  1. Trial gate (different signal) — preset="strict" / "permissive" (0.6 rename; was research / consumer); inspect BrainState.rejected, need_more_data, uncertainty. See BrainState.
  2. Head stability — after online updates, use calibration_sufficient / calibration_status on an unlabeled pool.
  3. Encoder swap — freeze trunk; match embedding_dim; never pass logits as embeddings; keep model_id consistent across save / load / profiles. See Encoder contract.

Next read

Encoder contract

Wrap rules and save/load.

BrainState

App-facing intents and presets.

API Reference

Personalizer and middleware symbols.

Heads / Models

LDA, QDA, Softmax, STS.