Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ No build step, no dependency install, no backend process. Pyodide and its packag

The whole app pivots around three files. Understanding the contract between them is the key to being productive here.

- **`frontend/py/learner.py`** — pure Python module. Every former HTTP endpoint is a top-level function (`upload_csv`, `load_sample`, `train`, `train_all`, `predictions`, `scatter_data`, `export_model`, `bulk_zip`, `comparison`, etc.) that takes JSON-serializable args and returns a `dict` (or raw `bytes` for downloads). Module-level `current_data` dict holds session state — dataframe, trained models, task type. Each browser tab is its own Pyodide instance, so global state is fine.
- **`frontend/py/learner.py`** — pure Python module. Every former HTTP endpoint is a top-level function (`upload_csv`, `load_sample`, `train`, `predictions`, `scatter_data`, `export_model`, `bulk_zip`, `comparison`, etc.) that takes JSON-serializable args and returns a `dict` (or raw `bytes` for downloads). Module-level `current_data` dict holds session state — dataframe, trained models, task type. Each browser tab is its own Pyodide instance, so global state is fine.
- **`frontend/js/pyodide-bridge.js`** — boots Pyodide, loads packages, copies `data/airfoil.csv` into the Pyodide MEMFS at `/data/airfoil.csv`, executes `learner.py`, then exposes a tiny surface on `window`:
- `pyCall(fnName, [primitiveArgs])` — for JSON-able calls. Builds a Python expression string and runs it via `runPython`. Result is converted with `toJs({dict_converter: Object.fromEntries})`.
- `pyCallBinary(fnName, Uint8Array, extraArgs)` — passes a binary buffer via a `globals.set('__bridge_buf', ...)` shim (used by `upload_csv`).
Expand Down
3 changes: 0 additions & 3 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,6 @@ <h2>📈 Scikit-Learner</h2>
<button class="btn btn-outline-primary btn-sm" onclick="trainSelectedModels()" id="trainBtn" disabled>
<i class="bi bi-play-fill"></i> Train Selected
</button>
<button class="btn btn-outline-primary btn-sm" onclick="trainAllModels()" id="trainAllBtn" disabled>
<i class="bi bi-lightning"></i> Train All
</button>
</div>
<div class="vr"></div>
<div class="btn-group" role="group">
Expand Down
10 changes: 0 additions & 10 deletions frontend/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,6 @@ function updateTrainButtons() {
const hasSelectedModels = state.selectedModelsToTrain.size > 0;

document.getElementById('trainBtn').disabled = !(hasData && hasTarget && hasFeatures && hasSelectedModels);
document.getElementById('trainAllBtn').disabled = !(hasData && hasTarget && hasFeatures);
}

// Show new data modal (unified)
Expand Down Expand Up @@ -722,15 +721,6 @@ async function trainSelectedModels() {
await trainModels(modelsToTrain);
}

// Train all available models
async function trainAllModels() {
const allModels = [];
for (const models of Object.values(state.availableModels)) {
models.forEach(m => allModels.push(m.key));
}
await trainModels(allModels);
}

// Train models
async function trainModels(modelKeys) {
showLoading();
Expand Down
15 changes: 0 additions & 15 deletions frontend/py/learner.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,21 +467,6 @@ def train(
"n_features": len(features),
}


def train_all(features: list, target: str, cv_folds: int = 5, task_type: str = "regression") -> dict:
"""Train every model in the active dictionary, reporting per-model success."""
if hasattr(features, "to_py"):
features = list(features.to_py())
src = AVAILABLE_CLASSIFICATION_MODELS if task_type == "classification" else AVAILABLE_MODELS
results = []
for key in src:
try:
results.append(train(key, features, target, cv_folds, task_type))
except Exception as e:
results.append({"success": False, "model_type": key, "error": str(e)})
return {"results": results}


def get_model(model_id: str) -> dict:
if model_id not in current_data["models"]:
raise ValueError("Model not found")
Expand Down