modulearn 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modulearn/__init__.py +16 -0
- modulearn/cli.py +88 -0
- modulearn/compiler.py +238 -0
- modulearn/demo.py +81 -0
- modulearn/registry.py +283 -0
- modulearn/server.py +195 -0
- modulearn/static/graph-engine.js +623 -0
- modulearn/static/graph.html +170 -0
- modulearn/static/graph.js +1003 -0
- modulearn-0.1.0.dist-info/METADATA +163 -0
- modulearn-0.1.0.dist-info/RECORD +14 -0
- modulearn-0.1.0.dist-info/WHEEL +4 -0
- modulearn-0.1.0.dist-info/entry_points.txt +2 -0
- modulearn-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: modulearn
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A visual, Unreal-Blueprints-style node-graph editor for building and launching ML training runs.
|
|
5
|
+
Project-URL: Homepage, https://github.com/IsaiahKoamalu/modulearn
|
|
6
|
+
Project-URL: Source, https://github.com/IsaiahKoamalu/modulearn
|
|
7
|
+
Author: Isaiah Broderson
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: fastapi,machine-learning,node-graph,training,visual-programming
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: fastapi>=0.110
|
|
18
|
+
Requires-Dist: pydantic>=2.0
|
|
19
|
+
Requires-Dist: uvicorn>=0.29
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: build; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
23
|
+
Requires-Dist: twine; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# ModuLearn
|
|
27
|
+
|
|
28
|
+
A visual, [Unreal-Blueprints](https://dev.epicgames.com/documentation/en-us/unreal-engine/blueprints-visual-scripting-in-unreal-engine)-style
|
|
29
|
+
node-graph editor for building and launching machine-learning training runs.
|
|
30
|
+
Drop **Dataset → Model → Train** nodes on a canvas, wire **hyperparameters**,
|
|
31
|
+
**loss** and **feature transforms** into them, hit ▶ Train, and watch the learning
|
|
32
|
+
curve live on the graph. No forms, no drift between the UI and the code it runs.
|
|
33
|
+
|
|
34
|
+
> **ModuLearn** is a working name — you assemble training runs from modular nodes and
|
|
35
|
+
> learn from the live curve. Rename the package/repo freely; nothing depends on the name.
|
|
36
|
+
|
|
37
|
+
<!-- A screenshot or GIF of the editor goes well here. -->
|
|
38
|
+
|
|
39
|
+
## Why
|
|
40
|
+
|
|
41
|
+
Most training UIs are flat forms that slowly rot out of sync with the code behind
|
|
42
|
+
them. ModuLearn inverts that: your Python is the single source of truth. You *declare*
|
|
43
|
+
what you can train once, in a `Registry`, and the entire editor — palette, typed
|
|
44
|
+
wiring rules, live validation, launch — is generated from it. Wire something the
|
|
45
|
+
backend can't accept and it simply won't connect.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install -e . # fastapi + uvicorn + pydantic
|
|
51
|
+
modulearn demo # serve the bundled editor at http://localhost:8000
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`modulearn demo` is a complete, **dependency-free** editor (its "trainer" is a toy
|
|
55
|
+
loss curve) so you can click around immediately. Once you've built your own app,
|
|
56
|
+
serve it the same way:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
modulearn run myproject.py # serves the `app` you built with create_app
|
|
60
|
+
modulearn run myproject.py:editor # ...or a differently-named app / factory
|
|
61
|
+
modulearn --help
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Swap `on_train` for your real training loop and nothing else changes. (The
|
|
65
|
+
equivalent source file lives at [`examples/quickstart.py`](examples/quickstart.py)
|
|
66
|
+
if you'd rather run it directly with `python`.)
|
|
67
|
+
|
|
68
|
+
## The whole integration is two things
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from modulearn import Registry, Param, create_app
|
|
72
|
+
|
|
73
|
+
reg = Registry()
|
|
74
|
+
|
|
75
|
+
reg.add_dataset("iris", title="Iris", kind="tabular",
|
|
76
|
+
features=[...], targets=["species"])
|
|
77
|
+
reg.add_model("mlp", title="MLP", requires_kind="tabular",
|
|
78
|
+
params=[Param("hidden", "hidden layers", "int_list", [64, 32])])
|
|
79
|
+
reg.add_hyperparameter("lr", label="learning rate", default=1e-3, min=1e-6, max=1)
|
|
80
|
+
reg.add_loss([Param("loss", "kind", "enum", "mse", choices=["mse", "cross_entropy"])])
|
|
81
|
+
|
|
82
|
+
def on_train(compiled, reporter):
|
|
83
|
+
# compiled.dataset, .model, .model_params, .hyperparameters, .loss_params, .transforms
|
|
84
|
+
reporter.state(epochs=100)
|
|
85
|
+
for e in range(100):
|
|
86
|
+
reporter.metric(epoch=e, train=..., val=...) # drives the live chart
|
|
87
|
+
reporter.state(epoch=e, best_val=...)
|
|
88
|
+
reporter.state(phase="done", test_score=...)
|
|
89
|
+
|
|
90
|
+
app = create_app(reg, on_train, title="My Project")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
1. **A `Registry`** — declare datasets, models, hyperparameters, a loss, and
|
|
94
|
+
optional feature transforms. Each hyperparameter you add automatically grows a
|
|
95
|
+
matching, type-checked input on the Train sink.
|
|
96
|
+
2. **`on_train(compiled, reporter)`** — your training loop. `compiled` is a
|
|
97
|
+
fully-validated [`CompiledGraph`](modulearn/compiler.py); `reporter` publishes
|
|
98
|
+
progress the editor polls (see the state contract below).
|
|
99
|
+
|
|
100
|
+
## How it fits together
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
registry.py ── you declare nodes ──► catalog (GET /api/nodes)
|
|
104
|
+
│ │
|
|
105
|
+
▼ ▼
|
|
106
|
+
compiler.py ◄── canvas JSON ──────── static/ (custom canvas engine)
|
|
107
|
+
│ type-checks every wire, runs semantic checks
|
|
108
|
+
▼
|
|
109
|
+
CompiledGraph ──► your on_train(compiled, reporter) ──► runs/<id>/{state,metrics}.json
|
|
110
|
+
│
|
|
111
|
+
editor polls ◄─┘ (live panel + chart)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- **Typed ports.** Links carry a family (`dataset`, `model`, `loss`, `run`) or a
|
|
115
|
+
field-specific scalar subtype (`scalar/lr`), so a learning-rate value fits the
|
|
116
|
+
`lr` input and *never* `epochs` — enforced both client-side and in the compiler.
|
|
117
|
+
- **All-or-nothing compile.** `compile_graph` collects every structural, type and
|
|
118
|
+
semantic error and raises them together, so the UI flags all bad wires at once.
|
|
119
|
+
- **Composable transforms.** Chain `Dataset → Transform → … → Model`; the compiler
|
|
120
|
+
walks the chain into `compiled.transforms`. Mark a transform `live=False` to show
|
|
121
|
+
it in the palette but have the compiler refuse it until your backend is ready.
|
|
122
|
+
- **Stateless live window.** Training runs in a background thread and persists to
|
|
123
|
+
`runs/<id>/`. Closing the browser never stops a run; reopening shows true state.
|
|
124
|
+
|
|
125
|
+
## The state contract
|
|
126
|
+
|
|
127
|
+
Your `on_train` reports through `reporter`, and the editor reads these keys:
|
|
128
|
+
|
|
129
|
+
| call | keys the UI understands |
|
|
130
|
+
|------|-------------------------|
|
|
131
|
+
| `reporter.state(**kw)` | `phase` (`running`/`done`/`error`), `epoch`, `epochs`, `best_val`, `test_score`, `error` |
|
|
132
|
+
| `reporter.metric(**row)` | `epoch`, `train`, `val` → the live learning curve |
|
|
133
|
+
|
|
134
|
+
Anything else you write is stored and returned by the API, just not charted.
|
|
135
|
+
|
|
136
|
+
## Editor niceties
|
|
137
|
+
|
|
138
|
+
- Searchable palette with collapsible category dropdowns; `⌘K` / `/` to focus,
|
|
139
|
+
Enter to drop the first match.
|
|
140
|
+
- Wires colored by type, with flowing pulses that speed up on the edges feeding a
|
|
141
|
+
running Train node; ports glow while you drag a compatible connection.
|
|
142
|
+
- Canvas persists to `localStorage`; reload/fork any past run's blueprint.
|
|
143
|
+
- All motion respects `prefers-reduced-motion`.
|
|
144
|
+
|
|
145
|
+
## Layout
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
modulearn/
|
|
149
|
+
registry.py the declarative surface your app fills in
|
|
150
|
+
compiler.py graph JSON -> validated CompiledGraph (pure, unit-testable)
|
|
151
|
+
server.py create_app(): FastAPI factory + background job runner
|
|
152
|
+
cli.py the `modulearn` command (demo / run)
|
|
153
|
+
demo.py the app `modulearn demo` serves
|
|
154
|
+
static/ graph.html, graph.js (app), graph-engine.js (canvas engine)
|
|
155
|
+
examples/
|
|
156
|
+
quickstart.py a complete, dependency-free editor
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT (see [LICENSE](LICENSE)). The canvas node-graph engine
|
|
162
|
+
(`static/graph-engine.js`) is our own, built from scratch — no third-party
|
|
163
|
+
graph library.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
modulearn/__init__.py,sha256=6EN58AT7BZPRsO1b_oOZUQt0jcQfa6-zxOTlgDSJ_KE,744
|
|
2
|
+
modulearn/cli.py,sha256=87Nlkrh8vMLtzhFZgHw_cLy5T8x5Fxfb1R1KnoH5i2k,3292
|
|
3
|
+
modulearn/compiler.py,sha256=H0_J6zvhM465IsfSJpf7b01s61rfweUu9ui3O4wtwSg,9918
|
|
4
|
+
modulearn/demo.py,sha256=CAYKeJ474K2mYeCIEDeIzzNddaWKq80JCt0_5yf9_Ms,3625
|
|
5
|
+
modulearn/registry.py,sha256=ZrNig7_f_KNJttPAAy_RDUOzfzKBA7Y9mrCjUZWd5ck,12279
|
|
6
|
+
modulearn/server.py,sha256=2LboJ7Fa0TMwuPOruW3CXT-IwDAzHbF1Qys4DZD9mHs,7306
|
|
7
|
+
modulearn/static/graph-engine.js,sha256=2S20jl-BRhbPqp-NGmeOIOHB8Ul6_L0XloBKMzzf_gY,23894
|
|
8
|
+
modulearn/static/graph.html,sha256=cGi-SRTbGN2p83uHG_Rnh37xwkk3XjEDRIf3Temp1PE,9376
|
|
9
|
+
modulearn/static/graph.js,sha256=pk6CoKANOvrjnKiKE_EkWtplM4rlEN91vdl49kqS0ow,42798
|
|
10
|
+
modulearn-0.1.0.dist-info/METADATA,sha256=FyRzqa_1IYQUFF0go6VtaffgdBlI25UKihZTwF3_IYw,7181
|
|
11
|
+
modulearn-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
12
|
+
modulearn-0.1.0.dist-info/entry_points.txt,sha256=M2Tgfyoyj6rZKM1yzsQr8_2K2irYMeVnp4enUNH2kRg,49
|
|
13
|
+
modulearn-0.1.0.dist-info/licenses/LICENSE,sha256=D_c18RFRF53oxJo1eTGDelamr2ZMRaL-Ti4vvwmCDrI,1073
|
|
14
|
+
modulearn-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Isaiah Broderson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|