Typed, provenance-aware configuration for ML runs: drafts, interpolation, one validation boundary. Powered by Pydantic.
Project description
nshconfig
Typed, provenance-aware configuration for ML runs, powered by Pydantic.
One verb family and one value:
Cls.config_draft()gives a mutable draft: plain Python assignment, nested configs auto-create, validation deferred.C.interp(lambda c: ...)is a value that resolves against the config tree at validation. It is legal anywhere a value sits: assigned on a draft, inside amodel_validatedict, or as a class default. This is Hydra-style interpolation, in Python, mostly type-checked.draft.config_finalize()resolves interpolation, validates once, and returns a frozen, hashable, fully-concrete config.
Plus provenance: final.config_explain("optim.lr") answers "why did this run use that value?" down
to file, line, function, source text, and the interpolation's "because" chain.
Install
pip install nshconfig # pydantic>=2.13, Python>=3.10
pip install nshconfig[treescope] # optional rich notebook rendering
Quickstart
import nshconfig as C
class LNConfig(C.Config):
dim: int = 32 # plain default; leaf classes need no interpolation
eps: float = 1e-5
class EncoderConfig(C.Config):
ln: LNConfig
class HeadConfig(C.Config):
# class-level interpolation: a value sitting in the default slot
dim: int = C.interp(lambda c: c.nearest(ModelConfig).dim)
class ModelConfig(C.Config):
dim: int = 768
encoder: EncoderConfig
head: HeadConfig
class TrainConfig(C.Config):
batch: int = 8
model: ModelConfig
# compose in a notebook; helpers are plain functions (your "config groups")
def large(cfg: TrainConfig) -> None:
cfg.model.dim = 1024
cfg = TrainConfig.config_draft()
large(cfg)
# instance-level interpolation: wire THIS tree only, at composition time
cfg.model.encoder.ln.dim = C.interp(lambda c: c.nearest(ModelConfig).dim)
final = cfg.config_finalize() # the one validation boundary
assert final.model.encoder.ln.dim == 1024 # followed the knob
assert final.model.head.dim == 1024 # class-default rule, same machinery
final.model_dump_json() # concrete values only: the run record
# why did this run use that value?
print(final.config_explain("model.head.dim"))
# model.head.dim = 1024
# interpolated to 1024 by <lambda> @ configs.py:11 (class default)
# because model.dim = 1024
# class-default rule: interp(<<lambda> @ configs.py:11>) (active)
Explicit always beats interpolation (presence in the input slot beats the default slot; last
write wins; del re-arms). Nothing pending can reach a final, a dump, an f-string, or an if
without a loud error naming the dotted path and the source line. Drafts cloudpickle to clusters
mid-composition and finalize on the far side, provenance included.
The Ctx API (what the lambda sees)
| Accessor | Hydra equivalent | Sees |
|---|---|---|
c.data |
same level | own fields, earlier markers already resolved |
c.parent |
${..x} |
one level up, resolved |
c.root |
${a.b} |
the validation root, incl. sibling subtrees |
c.nearest(Cls) |
(none: better) | nearest enclosing Cls; survives restructuring |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nshconfig-2.0.0a1.tar.gz.
File metadata
- Download URL: nshconfig-2.0.0a1.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5ede94b3965c4d0367a0c2a3968770c7af4c2899b1ac0b764ea291e249f7664
|
|
| MD5 |
514a7c8837f46674484e0edc1470cb25
|
|
| BLAKE2b-256 |
930c8765b91427fe92145fa07e788025c4a19b0b77fc8bfa852bf0bf61794cc4
|
File details
Details for the file nshconfig-2.0.0a1-py3-none-any.whl.
File metadata
- Download URL: nshconfig-2.0.0a1-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e23cb3773f43e8bb4950ba3240517a97b0445da85cb3bcf3cbd624d1437b931b
|
|
| MD5 |
5e0a3a907fb443c4f4fe8beb42f789cd
|
|
| BLAKE2b-256 |
cf4754db59a0c6ef5345fb094b3e8d9b647a999b33614945ab4250573e068f64
|