Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

<!-- What this changes, and why. Say what you rejected when the choice wasn't obvious. -->

Closes #<!-- the issue number; you should be its assignee (CONTRIBUTING.md, "Picking up an issue") -->

## Checklist (CONTRIBUTING.md)

- [ ] I was assigned the issue before opening this (or it's a maintainer change)
- [ ] `make lint` and `make test` pass (CI runs both); `make test-gpu` too if training code changed
- [ ] The engine (`src/slmkit/`) doesn't reference any project (rule 2); a Project API change has an ADR
- [ ] Docs in the same change: the concept page and runbook for what was built, with real output
Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ interfaces; each entry says what moved. Milestones (M0, M1, …) are described i
`info` says `"engine": "browser"`; project viewers work unchanged (ADR 0011).
- `slm runs list --project NAME` lists one project's runs (#8, thanks @KeuqS).
- `abc-folk` on the Hugging Face Hub ([m87techlabs/abc-folk](https://huggingface.co/m87techlabs/abc-folk)),
and a runbook for publishing an export there (`docs/runbooks/hf-hub.md`).
with a [live demo](https://huggingface.co/spaces/m87techlabs/abc-folk) that runs the model in the
browser, and a runbook for publishing an export there (`docs/runbooks/hf-hub.md`).
- `CONTRIBUTING.md`: how to pick up an issue (comment, get assigned, then open a pull request).

## [0.1.0] - 2026-10-13

Expand Down
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ uv run slm pretrain abc_music/micro_v1 --set train.lr=6e-4
uv run slm eval <run_id>
uv run slm runs list # tokens done/target, GPU-hours, last checkpoint
uv run slm runs list --project abc_music # only runs for one project
uv run slm runs list --json # the same, as JSON for scripts; accepts --project
uv run slm runs compare <run_a> <run_b>
uv run slm export <run_id> --name <model> --version <n>
uv run slm serve --model <model>:<n>
Expand Down Expand Up @@ -193,6 +194,25 @@ part of the current milestone — implement it rather than inventing a different
- **No co-author or generated-by trailers.** Commits carry the repository author only.
- Never commit anything under `$SLM_HOME`; artifacts stay out of git by design.

## Picking up an issue

New here? Issues labelled
[`good first issue`](https://github.com/m87techlabs/slmkit/labels/good%20first%20issue) each say what
to change, which files, and when it's done.

1. **Comment on the issue first**, with a short plan, and **wait to be assigned** before opening a pull
request. An issue with an assignee is taken. This keeps two people from doing the same work: two pull
requests for one issue means one of them gets closed.
2. Maintainers reply to requests within a few days. If an assigned issue sees no activity for two
weeks, ask on it and it can be freed up.
3. Open the pull request from a branch, with `Closes #N` in its description. The pull-request template's
checklist mirrors this file.
4. **Run `make lint` and `make test` before opening it.** The music grader tests need `abc2midi`
(`sudo apt install abcmidi`). CI runs both again; for a first contribution, a maintainer has to
approve the CI run, so expect a short wait.
5. Using an AI assistant is fine. Say so in the pull request, and make sure you understand and have
run what you submit; you're answering for it in review.

## Workflow expectations

- **Changes arrive as pull requests** from a branch; CI (`.github/workflows/ci.yml`) runs `make lint`
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
**A framework for building small language models from scratch on a single consumer GPU — and a
guided way to learn how language models actually work.**

**[Try it in your browser →](https://huggingface.co/spaces/m87techlabs/abc-folk)** A folk-tune model
trained with slmkit (864K parameters, under a minute of GPU time) writes a tune on request, draws it as
sheet music and plays it. The model runs in your browser; there is no server
([how](docs/concepts/browser-inference.md)).

```
ingest → prepare → tokenizer → pack → pretrain → SFT → eval → export → serve
```
Expand Down Expand Up @@ -111,7 +116,7 @@ uv run slm studio start # "See it in action": everything you built, in your br
| [`docs/DESIGN.md`](docs/DESIGN.md) | Architecture, contracts, and the rules the code enforces |
| [`docs/ROADMAP.md`](docs/ROADMAP.md) | Milestones and their exit criteria |
| [`docs/decisions/`](docs/decisions/) | ADRs — what was decided, and what was rejected |
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | The rules every change follows: hard rules, conventions, commits |
| [`CONTRIBUTING.md`](CONTRIBUTING.md) | The rules every change follows: hard rules, conventions, commits. **Want to help?** Start with a [`good first issue`](https://github.com/m87techlabs/slmkit/labels/good%20first%20issue), and see "Picking up an issue" there |
| [`CHANGELOG.md`](CHANGELOG.md) | What changed in each release |

## Status
Expand Down
5 changes: 3 additions & 2 deletions docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ Goal: a public repo a newcomer can evaluate in a minute and contribute to withou

---

## Hugging Face Hub: the folk-tune model and a live demo ◐
## Hugging Face Hub: the folk-tune model and a live demo ☑

Goal: anyone can load `abc-folk` with `transformers`, or try it in a browser, without installing
anything. *No GPU.* Decisions: ADR 0010. Runbook: `runbooks/hf-hub.md`.
Expand All @@ -176,7 +176,8 @@ anything. *No GPU.* Decisions: ADR 0010. Runbook: `runbooks/hf-hub.md`.
anonymously with `transformers` (runbook H.4).
- [x] `slm site`: the model runs in the browser from static files, parity-tested against PyTorch in
headless Chrome (ADR 0011). Docker Spaces turned out to need a paid plan; static Spaces are free.
- [ ] The static Space is live, and the README links to it.
- [x] The static Space is live (huggingface.co/spaces/m87techlabs/abc-folk), and the README links
to it (runbook H.5).

---

Expand Down
2 changes: 1 addition & 1 deletion docs/runbooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ must match exactly and which are only ballpark figures.
| [`m1-engine.md`](m1-engine.md) | M1 | ☑ |
| [`m2-abc-music.md`](m2-abc-music.md) | M2 | ☑ |
| [`studio.md`](studio.md) | Studio | ◐ phases 1–3 done; last criterion proved by M3 |
| [`hf-hub.md`](hf-hub.md) | Publishing on the Hugging Face Hub, and `slm site` | ◐ model live; static Space next |
| [`hf-hub.md`](hf-hub.md) | Publishing on the Hugging Face Hub, and `slm site` | ☑ model and Space live |

**In `slm studio`.** The studio lists each project's runbooks next to its runs. A runbook that belongs
to one project says so near its top with `<!-- slm-studio: projects=abc_music -->` (a comma-separated
Expand Down
37 changes: 35 additions & 2 deletions docs/runbooks/hf-hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,39 @@ hf upload m87techlabs/abc-folk <the Space's README.md> README.md --type space \
A model and a Space can share a name: they are different repository types. A static Space has no build
step; it is live within a minute.

**Check the live Space**, from anywhere, with no token: the Space's metadata, the page's `info` file,
and the weights it serves (the same SHA-256 as the export, H.4):

```bash
curl -s https://huggingface.co/api/spaces/m87techlabs/abc-folk | python3 -c "
import json, sys
d = json.load(sys.stdin)
print(d['id'], d['sdk'], d['runtime']['stage'], 'model:', ', '.join(d['models']))"
curl -s https://m87techlabs-abc-folk.static.hf.space/info | python3 -c "
import json, sys
d = json.load(sys.stdin)
print(d['model'], d['engine'], d['device'])"
curl -sL https://m87techlabs-abc-folk.static.hf.space/model/model.safetensors | sha256sum | cut -d' ' -f1
```

```
m87techlabs/abc-folk static RUNNING model: m87techlabs/abc-folk
abc-folk:3 browser your browser
0ff22be8daed1a48fc80205f4fe484774a95e2f23762e2e9ed86b2cb99024af9
```

Then open the Space, click **jig-G** and **Generate**. Measured from here in Chrome: seed 3 gives the same
jig as the local site, 189 tokens in 0.11 s.

**Two things the Hub does to a static Space**, both harmless:

- It serves large files (the weights) by redirecting to its file storage, on another domain. `fetch`
follows the redirect, and the storage allows cross-origin reads, so the page loads the model as it
does locally.
- It adds one `<script>` line to `index.html` (the Space's ID). Creating the Space also commits its
template's `style.css`; the page doesn't use it, and
`hf repos delete-files m87techlabs/abc-folk style.css --type space` removes it.

**Why it's built this way.**

- **No server:** a Docker Space needs a paid plan (H.1), and a server is more than a 3.5 MB model needs.
Expand Down Expand Up @@ -299,6 +332,6 @@ step; it is live within a minute.
- [x] The Hub's weights are byte-identical to the export, and `transformers` loads them anonymously and
generates the expected tune (H.4).
- [x] `slm site` builds the static site, and `model.js` matches PyTorch in Chrome (H.5).
- [ ] The static Space is live; the playground draws and plays a tune there (H.5).
- [ ] The README links to the Space.
- [x] The static Space is live; the playground draws and plays a tune there (H.5).
- [x] The README links to the Space.
- [ ] **You** have run H.4 and opened both pages.
Loading