Skip to content

Train models from the web UI and streamline the train command - #111

Merged
cpmpercussion merged 2 commits into
mainfrom
remote-training
Sep 26, 2026
Merged

cpmpercussion merged 2 commits into
mainfrom
remote-training

Conversation

@cpmpercussion

Copy link
Copy Markdown
Owner

Part of #97 (option 2 from the discussion).

Web UI

  • Train page: you pick a dataset (its dimension is shown), a model size, max epochs and patience. Training runs in a background thread, one job at a time. The page polls progress every 2 s (epoch, loss, val loss, elapsed time). Stop and Save ends the run early and still writes the model. .tflite/.keras download buttons appear when it's done.
  • Logs page: takes one or more .log files as uploads, so logs from IMPSYpi, the AUv3 app or IMPSY Web can be trained on. It rejects names that don't end in -{N}d-mdrnn.log, since dataset would skip them.
  • Datasets page: shows each dataset's dimension and has a Train button.

The web UI runs on the user's own device, e.g. a laptop running the Docker image or a Raspberry Pi. A Pi 4 or 5 should be able to train small models; the docs recommend against training on a Pi Zero 2 W.

impsy train

  • impsy train datasets/foo.npz works: the dimension is read from the dataset. -D is optional and gives an error if it doesn't match the dataset. With no arguments, it uses the only .npz in datasets/.
  • Ctrl-C during training saves the .keras and .tflite with the latest weights.
  • train_mdrnn() and PredictiveMusicMDRNN.train() accept extra Keras callbacks. The web UI uses this for progress and stopping.

Fixes

  • generate_dataset now creates its destination folder. Before this, generating a dataset in the web UI failed on a fresh workspace.
  • train_mdrnn(save_model=False, save_tflite=True) no longer crashes with an undefined model_keras_file.

Docs

  • README training section: updated the training-time estimate (minutes on a CPU, not hours) and documented the new command and the Train page.
  • Workshop page: replaced the "can't train from the web UI (yet!)" line.

Testing

  • Full suite passes locally (205 tests). New tests cover dimension detection, stopped and interrupted training, the CLI dataset argument, log upload, train form validation, and a real background training job, including stopping one.
  • Ran impsy webui on a fresh workspace: uploaded 6 logs, made a 4d dataset, trained xs for 30 epochs (~25 s), downloaded the .tflite, checked that a second job is refused, and stopped a large run, which saved a model after 4 epochs.
  • The pages haven't been checked visually in a browser.

Open questions

  • A stopped run saves the latest weights. Should it convert the best -ckpt.keras checkpoint instead?
  • A Colab notebook (option 1) will follow in a separate PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_016oUxTsghWZWfnCnnkKcuNv

Adds a Train page to the web UI that trains a model from a dataset in a
background thread, shows progress, can be stopped early, and offers the
.keras/.tflite files for download. The Logs page now accepts log uploads
so data from IMPSYpi, the AUv3 app or IMPSY Web can be trained on.

`impsy train` now takes a .npz file as an argument and reads the
dimension from it, and Ctrl-C (or a stopping callback) still saves the
model with its latest weights. generate_dataset creates its destination
folder so dataset generation works in a fresh workspace.

Part of #97.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016oUxTsghWZWfnCnnkKcuNv
Copilot AI lite review requested due to automatic review settings September 26, 2026 08:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical and moderate issues remain in the web training workflow.

Review effort: Lite
Findings: 1 High severity · 2 Medium severity

Open (3)
What changed in this PR

Adds web-based model training, improved CLI dataset handling, interruption support, and related documentation/tests.

Changes:

  • Added log uploads, dataset dimensions, background training, progress polling, stopping, and downloads.
  • Added dataset autodetection, callback support, and interrupted-training saves.
  • Updated dataset generation, documentation, and test coverage.

Open findings include one critical stop-state race, four moderate validation/performance issues, and one minor patience-validation issue.

File Reviewed changes
tests/​test_webui.py Web UI and background training tests
tests/​test_trained_model.py Training and CLI tests
tests/​test_data.py Dataset destination creation test
README.md Updated training documentation
impsy/​web_interface.py Uploads, dataset metadata, validation, and training jobs
impsy/​train.py Dataset resolution and callback-aware training
impsy/​templates/​train.html Training controls and progress display
impsy/​templates/​models.html Training page navigation
impsy/​templates/​logs.html Log upload interface
impsy/​templates/​datasets.html Dataset dimensions and Train links
impsy/​templates/​base.html Training navigation
impsy/​mdrnn.py Additional Keras callback support
impsy/​dataset.py Automatic destination directory creation
docs/​impsypi-workshop.md Updated workshop guidance

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread impsy/web_interface.py Outdated
Comment on lines +384 to +387
def stop(self):
if self.running:
self._stop_requested = True
self.status = "stopping"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 204866b: stop() now takes the lock and only moves running → stopping, and the thread sets its final status/files/error under the same lock. Added a test that stopping a finished job leaves it finished.

Comment thread impsy/web_interface.py Outdated
Comment on lines +309 to +312
if not name.endswith("d-mdrnn.log"):
return None
dim = name[: -len("d-mdrnn.log")].rsplit("-", 1)[-1]
return int(dim) if dim.isdigit() else None

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 204866b: log_file_dimension now uses -(\d+)d-mdrnn\.log$, matching generate_dataset, with a regression case for 2d-mdrnn.log.

Comment thread impsy/web_interface.py
Comment on lines +315 to +323
def get_dataset_file_info(filepath):
"""Get metadata for a dataset file, including the dimension of its data."""
info = get_file_info(filepath)
try:
from impsy.train import dataset_dimension

info["dimension"] = dataset_dimension(filepath)
except Exception:
info["dimension"] = None

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 204866b: the dimension now comes from standard training-dataset-{N}d.npz names without loading the file, and only other names get loaded. Tested with a fake file that couldn't be loaded.

- Make stopping a training job and finishing it atomic so a late stop
  can't leave a finished job stuck as "stopping".
- Require the "-" in -{dimension}d-mdrnn.log when checking uploads,
  matching what generate_dataset accepts.
- Read dataset dimensions from standard training-dataset-{N}d.npz names
  instead of decompressing every dataset on each page load.
- Give patience its own error message.
- Explain when no performance is long enough to train on, instead of
  failing inside Keras.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_016oUxTsghWZWfnCnnkKcuNv
@cpmpercussion
cpmpercussion merged commit 5be00b7 into main Sep 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants