-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
120 lines (99 loc) · 4.87 KB
/
Copy pathMakefile
File metadata and controls
120 lines (99 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
.PHONY: setup lint format test test-network smoke train evaluate ac2 pilot-lr pilot-steps baselines \
curve oos-ablation verify-logits report clean-checkpoints
CONFIG ?= configs/bert-base.yaml
SEED ?= 42
# Load HF_TOKEN / ANTHROPIC_API_KEY from a gitignored .env if one exists.
ENV_FILE := $(wildcard .env)
UV_ENV := $(if $(ENV_FILE),--env-file $(ENV_FILE),)
# The workspace lives inside iCloud Drive. iCloud never syncs a path ending
# in `.nosync`, so the virtualenv and checkpoints live in `*.nosync`
# directories and the conventional names are symlinks to them. Without
# this, iCloud tries to upload a multi-GB torch install and every
# checkpoint, and can evict files mid-training. See README "iCloud".
NOSYNC_LINKS := .venv checkpoints
# No default target. On 2026-09-23 a zsh loop ran `make $t` with
# t="curve MODEL=bert"; make got one argument, read it as a variable
# assignment, ran the first target (setup) and exited 0, and two curves
# were reported done with no point run. A bare `make` (or only variable
# assignments) now fails instead of silently running setup.
# tests/test_makefile.py pins this.
ifeq ($(strip $(MAKECMDGOALS)),)
$(error no target given; a quoted "curve MODEL=bert" is one variable assignment, not a target)
endif
setup:
@for name in $(NOSYNC_LINKS); do \
if [ -L "$$name" ]; then continue; fi; \
if [ -e "$$name" ]; then \
echo "error: $$name exists and is not a symlink; move it to $$name.nosync and rerun make setup"; \
exit 1; \
fi; \
mkdir -p "$$name.nosync" && ln -s "$$name.nosync" "$$name" && echo "linked $$name -> $$name.nosync"; \
done
uv sync --locked
lint:
uv run ruff check .
uv run ruff format --check .
uv run python scripts/check_em_dash.py
format:
uv run ruff check --fix .
uv run ruff format .
# Offline unit tests. Tests that download from the Hugging Face Hub carry
# the `network` marker and are excluded by pyproject's addopts.
test:
uv run pytest
test-network:
uv run pytest -m network
# End to end on real data with a ~1 MB random BERT: download CLINC150
# (checksum verified), train one step on a few dozen rows on CPU, evaluate.
# Writes under the system temp dir, not checkpoints/.
smoke:
uv run $(UV_ENV) python -m tinyrouter.smoke --config configs/smoke.yaml
train:
uv run $(UV_ENV) python -m tinyrouter.train --config $(CONFIG) --seed $(SEED)
evaluate:
uv run $(UV_ENV) python -m tinyrouter.evaluate --config $(CONFIG) --seed $(SEED)
# AC2: bert-base-uncased, full data, seeds 42/43/44 -> results/ac2.json; exit 1 on FAIL.
# Resumes: seeds already scored and archived are skipped. FORCE=1 reruns all.
# Weights of seeds 43 and 44 are deleted after their logits are archived.
# FORCE=1 also deletes seed 42's kept weights before retraining. After
# `make clean-checkpoints`, seed 42's weights are not rebuilt by a plain
# `make ac2` (its results already exist); getting them back takes FORCE=1,
# which retrains all three seeds.
ac2:
uv run $(UV_ENV) python -m tinyrouter.ac2 --config configs/bert-base.yaml $(if $(filter 1,$(FORCE)),--force,)
# Step 3 (docs/PLAN.md section 4, hyperparameter protocol). Order:
# make pilot-lr then copy each model's selected lr into configs/curve.yaml
# make pilot-steps then copy the selected S_min into configs/curve.yaml
# make curve MODEL=bert ; make curve MODEL=modernbert ; make oos-ablation
# Pilots read and write validation numbers only (results/pilots/*.json) and
# never edit configs/curve.yaml. Curves and the ablation resume like ac2 and
# keep no weights, only logits. `curve` runs the cheap baselines first.
# `make baselines` runs them alone.
# Completion: each command's last line is `completed N/N ...` only after its
# index passed the checks in src/tinyrouter/completeness.py. `make curve`
# prints `completed 36/36 baseline points` before the curve starts, so a
# curve that fails later still has one completed line in its output. To
# decide a curve is done, match the whole line
# `completed 18/18 encoder points (<model>)` (the ablation:
# `completed 3/3 ablation points`), never just `completed`.
pilot-lr:
uv run $(UV_ENV) python -m tinyrouter.pilots lr
pilot-steps:
uv run $(UV_ENV) python -m tinyrouter.pilots steps
# Majority-class and TF-IDF centroid baselines on every (k, seed) sample; seconds.
baselines:
uv run python -m tinyrouter.baselines
# Checks configs/curve.yaml is filled in, then runs the baselines, then the curve.
curve:
@case "$(MODEL)" in bert|modernbert) ;; *) echo "usage: make curve MODEL=bert|modernbert"; exit 2;; esac
uv run $(UV_ENV) python -m tinyrouter.curves --model $(MODEL)
oos-ablation:
uv run $(UV_ENV) python -m tinyrouter.curves --ablation
# Every archive listed in results/logits-manifest.json is present and matches its SHA-256.
verify-logits:
uv run python -m tinyrouter.archive
report:
uv run python -m tinyrouter.report
# Removes every trained model. Disk is tight (see docs/PLAN.md section 6).
clean-checkpoints:
rm -rf checkpoints.nosync/*