feat: remote training over SSH (no HF Jobs/account required)#76
Open
ZouzouWP wants to merge 1 commit into
Open
feat: remote training over SSH (no HF Jobs/account required)#76ZouzouWP wants to merge 1 commit into
ZouzouWP wants to merge 1 commit into
Conversation
The only non-local training option was HF Jobs — cloud, paid, and tied to a Hugging Face account. This adds a way to train on any machine you can already SSH into (a spare GPU box, a rented cloud instance), with no account or extra service involved.
## What changed
- New `ssh_remote` job target, alongside `local` and `hf_cloud`. The connection form asks for host/port/username, an optional private key path (falls back to the local ssh-agent/default identity — LeLab never handles or stores a password), a remote working directory, and a free-form "remote Python command" (e.g. `python`, or `source ~/venv/bin/activate && python`), since LeLab has no way to know how the remote server is set up.
- New `lelab/runners/ssh_remote.py` (`SshRemoteJobRunner`): stages the dataset via `scp`, launches training over `ssh`, and tracks the local `ssh` client's PID as `process_pid`.
- Checkpoints are pulled back with a rate-limited `scp` (at most once every 30s, since the frontend polls checkpoints roughly every 5s) into the same local `output_dir` a local job would use — so checkpoint listing and inference reuse the exact same local code path, no separate "remote checkpoint" representation needed anywhere.
```mermaid
sequenceDiagram
participant U as User
participant T as TargetCard (Training page)
participant API as LeLab backend
participant R as SshRemoteJobRunner
participant S as Remote server
U->>T: Fill host/user/key/workdir/python cmd, start training
T->>API: POST /jobs/training {target: {runner: ssh_remote, ssh: {...}}}
API->>R: start()
R->>S: scp dataset -> remote_workdir
R->>S: ssh: run training command
loop every ~30s at most (rate-limited)
API->>S: scp checkpoints/ -> local output_dir
end
API-->>T: same checkpoint/metrics UI as a local job
```
## Testing
Implemented and exercised locally (dataset staging, command construction, checkpoint-pull rate limiting), but **not yet run end-to-end against a real remote host** — needs a pass against a reachable GPU box before merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The only non-local training option was HF Jobs — cloud, paid, and tied to a Hugging Face account. This adds a way to train on any machine you can already SSH into (a spare GPU box, a rented cloud instance), with no account or extra service involved.
What changed
ssh_remotejob target, alongsidelocalandhf_cloud. The connection form asks for host/port/username, an optional private key path (falls back to the local ssh-agent/default identity — LeLab never handles or stores a password), a remote working directory, and a free-form "remote Python command" (e.g.python, orsource ~/venv/bin/activate && python), since LeLab has no way to know how the remote server is set up.lelab/runners/ssh_remote.py(SshRemoteJobRunner): stages the dataset viascp, launches training overssh, and tracks the localsshclient's PID asprocess_pid.scp(at most once every 30s, since the frontend polls checkpoints roughly every 5s) into the same localoutput_dira local job would use — so checkpoint listing and inference reuse the exact same local code path, no separate "remote checkpoint" representation needed anywhere.sequenceDiagram participant U as User participant T as TargetCard (Training page) participant API as LeLab backend participant R as SshRemoteJobRunner participant S as Remote server U->>T: Fill host/user/key/workdir/python cmd, start training T->>API: POST /jobs/training {target: {runner: ssh_remote, ssh: {...}}} API->>R: start() R->>S: scp dataset -> remote_workdir R->>S: ssh: run training command loop every ~30s at most (rate-limited) API->>S: scp checkpoints/ -> local output_dir end API-->>T: same checkpoint/metrics UI as a local jobTesting
Implemented and exercised locally (dataset staging, command construction, checkpoint-pull rate limiting), but not yet run end-to-end against a real remote host — needs a pass against a reachable GPU box before merge.