aetherscan 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aetherscan/__init__.py +45 -0
- aetherscan/benchmark.py +179 -0
- aetherscan/candidate_figures.py +328 -0
- aetherscan/cli.py +3032 -0
- aetherscan/config.py +1002 -0
- aetherscan/dashboard.py +709 -0
- aetherscan/dashboard_cli.py +51 -0
- aetherscan/dashboard_launcher.py +194 -0
- aetherscan/data_generation.py +1448 -0
- aetherscan/db/__init__.py +21 -0
- aetherscan/db/db.py +2789 -0
- aetherscan/hf_hub.py +547 -0
- aetherscan/inference.py +912 -0
- aetherscan/inference_viz.py +1494 -0
- aetherscan/latent_gif.py +512 -0
- aetherscan/latent_variants.py +352 -0
- aetherscan/logger/__init__.py +21 -0
- aetherscan/logger/logger.py +467 -0
- aetherscan/logger/slack_handler.py +760 -0
- aetherscan/main.py +1269 -0
- aetherscan/manager/__init__.py +21 -0
- aetherscan/manager/manager.py +781 -0
- aetherscan/models/__init__.py +21 -0
- aetherscan/models/random_forest.py +171 -0
- aetherscan/models/vae.py +849 -0
- aetherscan/monitor/__init__.py +19 -0
- aetherscan/monitor/monitor.py +935 -0
- aetherscan/pfb.py +161 -0
- aetherscan/preprocessing.py +2718 -0
- aetherscan/rf_metrics.py +100 -0
- aetherscan/round_data.py +932 -0
- aetherscan/run_state.py +277 -0
- aetherscan/seeding.py +160 -0
- aetherscan/shap_parallel.py +238 -0
- aetherscan/tag_guards.py +206 -0
- aetherscan/train.py +7681 -0
- aetherscan-1.0.0.dist-info/METADATA +1187 -0
- aetherscan-1.0.0.dist-info/RECORD +41 -0
- aetherscan-1.0.0.dist-info/WHEEL +4 -0
- aetherscan-1.0.0.dist-info/entry_points.txt +2 -0
- aetherscan-1.0.0.dist-info/licenses/LICENSE +13 -0
aetherscan/tag_guards.py
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Fail-early save-tag dedup guards.
|
|
3
|
+
|
|
4
|
+
Reusing a save_tag silently mixes a new run's artifacts, config JSON, and DB rows with a
|
|
5
|
+
previous run's — the stale-artifact confusion the cluster runbook used to work around by
|
|
6
|
+
manually incrementing test_vNN tags. These guards hard-stop a run at startup (before any
|
|
7
|
+
expensive work or writes) when its resolved save-tag collides with a completed run's state,
|
|
8
|
+
while staying out of the way of the two legitimate same-tag flows:
|
|
9
|
+
|
|
10
|
+
- Training retries/relaunches: a run-state manifest (run_state_{tag}.json) marks the tag as
|
|
11
|
+
an in-progress resumable run, so the guard is skipped entirely (PR-04's supersede
|
|
12
|
+
semantics are what make same-tag retries safe).
|
|
13
|
+
- Inference resume: manifest rows in the inference_cadences DB table mark an in-progress
|
|
14
|
+
streaming run. Only a completed run — evidenced by its saved config_{tag}.json, written at
|
|
15
|
+
the very end of a successful pass — or stale legacy-path DB rows count as collisions.
|
|
16
|
+
|
|
17
|
+
Because every resolved save-tag carries a fresh second-resolution {command}_{datetime} stamp,
|
|
18
|
+
a fresh run can't collide by construction; the guards bite only if a completed run's tag is
|
|
19
|
+
deliberately reused, and the resumable-run manifests above exempt the legitimate retry/resume
|
|
20
|
+
flows. --force-tag consciously overrides every guard.
|
|
21
|
+
|
|
22
|
+
enforce_tag_guards() is called from main() immediately before command dispatch
|
|
23
|
+
(post-validation, post-DB-init, pre-any-work).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import argparse
|
|
29
|
+
import logging
|
|
30
|
+
import os
|
|
31
|
+
import sys
|
|
32
|
+
|
|
33
|
+
from aetherscan.config import get_config
|
|
34
|
+
from aetherscan.db import get_db
|
|
35
|
+
from aetherscan.run_state import STAGE_FINAL_SAVE, load_run_state, run_state_path
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def find_train_tag_collisions(tag: str) -> list[str]:
|
|
41
|
+
"""
|
|
42
|
+
Human-readable descriptions of existing training state that would collide with `tag`:
|
|
43
|
+
the final encoder artifact under model_path, the saved config JSON under output_path,
|
|
44
|
+
and non-superseded training_stats DB rows. Empty list = no collisions.
|
|
45
|
+
"""
|
|
46
|
+
config = get_config()
|
|
47
|
+
if config is None:
|
|
48
|
+
raise ValueError("get_config() returned None")
|
|
49
|
+
db = get_db()
|
|
50
|
+
collisions: list[str] = []
|
|
51
|
+
|
|
52
|
+
encoder_path = os.path.join(config.model_path, f"vae_encoder_{tag}.keras")
|
|
53
|
+
if os.path.exists(encoder_path):
|
|
54
|
+
collisions.append(f"model artifact exists: {encoder_path}")
|
|
55
|
+
|
|
56
|
+
config_path = os.path.join(config.output_path, f"config_{tag}.json")
|
|
57
|
+
if os.path.exists(config_path):
|
|
58
|
+
collisions.append(f"saved run config exists: {config_path}")
|
|
59
|
+
|
|
60
|
+
if db is not None:
|
|
61
|
+
rows = db.query_training_stat(tag=tag, columns=["tag"])
|
|
62
|
+
if rows:
|
|
63
|
+
collisions.append(
|
|
64
|
+
f"{len(rows)} non-superseded training_stats DB row(s) carry tag '{tag}'"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return collisions
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def find_inference_tag_collisions(tag: str) -> list[str]:
|
|
71
|
+
"""
|
|
72
|
+
Collisions scoped to what inference writes. A saved config_{tag}.json marks a *completed*
|
|
73
|
+
run under this tag (it is written at the very end of a successful pass) — reusing its tag
|
|
74
|
+
is always a collision. DB rows alone are only a collision on the legacy --test-files path
|
|
75
|
+
(no inference_cadences manifest rows): with manifest rows present, same-tag DB state is
|
|
76
|
+
exactly what the streaming path's resume flow consumes, so it must not be flagged.
|
|
77
|
+
"""
|
|
78
|
+
config = get_config()
|
|
79
|
+
if config is None:
|
|
80
|
+
raise ValueError("get_config() returned None")
|
|
81
|
+
db = get_db()
|
|
82
|
+
collisions: list[str] = []
|
|
83
|
+
|
|
84
|
+
config_path = os.path.join(config.output_path, f"config_{tag}.json")
|
|
85
|
+
if os.path.exists(config_path):
|
|
86
|
+
collisions.append(f"saved run config exists (completed run marker): {config_path}")
|
|
87
|
+
|
|
88
|
+
if db is not None and not db.query_inference_cadences(tag=tag, columns=["tag"]):
|
|
89
|
+
rows = db.query_inference_result(tag=tag, columns=["tag"])
|
|
90
|
+
if rows:
|
|
91
|
+
collisions.append(
|
|
92
|
+
f"{len(rows)} non-superseded inference_results DB row(s) carry tag '{tag}' "
|
|
93
|
+
f"(no resumable run manifest)"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return collisions
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _exit_on_collisions(tag: str, collisions: list[str], resume_hint: str) -> None:
|
|
100
|
+
"""Log the collision list plus the user's options, then hard-exit."""
|
|
101
|
+
logger.error("=" * 60)
|
|
102
|
+
logger.error(f"--save-tag '{tag}' collides with existing state from a previous run:")
|
|
103
|
+
for collision in collisions:
|
|
104
|
+
logger.error(f" - {collision}")
|
|
105
|
+
logger.error("Options:")
|
|
106
|
+
logger.error(" - pick a new --save-tag")
|
|
107
|
+
logger.error(f" - {resume_hint}")
|
|
108
|
+
logger.error(" - pass --force-tag to consciously override this guard")
|
|
109
|
+
logger.error("=" * 60)
|
|
110
|
+
sys.exit(1)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _guard_hf_tag(tag: str, force: bool) -> None:
|
|
114
|
+
"""
|
|
115
|
+
HF-side dedup guard, run at startup when --hf-upload is enabled so a tag collision on the
|
|
116
|
+
Hub surfaces now, not after ~30 h of training. A failed check (network/auth) only warns:
|
|
117
|
+
the upload stage itself is non-critical, so its guard must not block training either.
|
|
118
|
+
"""
|
|
119
|
+
config = get_config()
|
|
120
|
+
if config is None:
|
|
121
|
+
raise ValueError("get_config() returned None")
|
|
122
|
+
repo_id = config.hf.repo_id
|
|
123
|
+
from aetherscan.hf_hub import hf_tag_exists # noqa: PLC0415
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
exists = hf_tag_exists(repo_id, tag)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.warning(f"Could not check HF repo '{repo_id}' for tag collisions ({e}) — proceeding")
|
|
129
|
+
return
|
|
130
|
+
if not exists:
|
|
131
|
+
return
|
|
132
|
+
if force:
|
|
133
|
+
logger.warning(
|
|
134
|
+
f"Tag '{tag}' already exists on HF repo '{repo_id}' — --force-tag set, the "
|
|
135
|
+
f"upload stage will move it to the new commit"
|
|
136
|
+
)
|
|
137
|
+
return
|
|
138
|
+
logger.error("=" * 60)
|
|
139
|
+
logger.error(f"--hf-upload is enabled but tag '{tag}' already exists on HF repo '{repo_id}'.")
|
|
140
|
+
logger.error("Options: pick a new --save-tag, or pass --force-tag to move the HF tag.")
|
|
141
|
+
logger.error("=" * 60)
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def enforce_tag_guards(args: argparse.Namespace) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Fail-early save-tag dedup guards, dispatched by mode (see module docstring). Reads the
|
|
148
|
+
post-apply config singleton for the effective tag/force values and `args` only to learn
|
|
149
|
+
whether --save-tag was explicitly provided (default datetime tags are immune by
|
|
150
|
+
construction, so the local guards are skipped for them).
|
|
151
|
+
"""
|
|
152
|
+
config = get_config()
|
|
153
|
+
if config is None:
|
|
154
|
+
raise ValueError("get_config() returned None")
|
|
155
|
+
tag = config.checkpoint.save_tag
|
|
156
|
+
force = bool(config.checkpoint.force_tag)
|
|
157
|
+
explicit = getattr(args, "save_tag", None) is not None
|
|
158
|
+
command = getattr(args, "command", None)
|
|
159
|
+
|
|
160
|
+
if command == "train":
|
|
161
|
+
if explicit:
|
|
162
|
+
manifest_path = run_state_path(config.output_path, tag)
|
|
163
|
+
# Only an UNFINISHED run's manifest exempts the collision guard. The manifest
|
|
164
|
+
# persists on success, so a completed run's manifest must NOT keep disabling dedup
|
|
165
|
+
# for that tag — otherwise a reused --save-tag would silently overwrite a finished
|
|
166
|
+
# model with no warning (TG-1). "Unfinished" = final_save not yet done, or a
|
|
167
|
+
# recorded non-critical stage failure still pending retry.
|
|
168
|
+
state = load_run_state(manifest_path)
|
|
169
|
+
resumable = state is not None and (
|
|
170
|
+
not state.is_stage_done(STAGE_FINAL_SAVE) or bool(state.stages_failed)
|
|
171
|
+
)
|
|
172
|
+
if resumable:
|
|
173
|
+
logger.info(
|
|
174
|
+
f"Run-state manifest at {manifest_path} marks an unfinished run — tag "
|
|
175
|
+
f"'{tag}' is resumable, skipping the collision guard"
|
|
176
|
+
)
|
|
177
|
+
else:
|
|
178
|
+
collisions = find_train_tag_collisions(tag)
|
|
179
|
+
if collisions and force:
|
|
180
|
+
logger.warning(
|
|
181
|
+
f"--force-tag set: proceeding despite {len(collisions)} "
|
|
182
|
+
f"collision(s) on tag '{tag}'"
|
|
183
|
+
)
|
|
184
|
+
elif collisions:
|
|
185
|
+
_exit_on_collisions(
|
|
186
|
+
tag,
|
|
187
|
+
collisions,
|
|
188
|
+
"to resume the previous run, re-run its identical command "
|
|
189
|
+
"(resume requires its run-state manifest)",
|
|
190
|
+
)
|
|
191
|
+
if config.hf.upload_after_training:
|
|
192
|
+
_guard_hf_tag(tag, force)
|
|
193
|
+
|
|
194
|
+
elif command == "inference" and explicit:
|
|
195
|
+
collisions = find_inference_tag_collisions(tag)
|
|
196
|
+
if collisions and force:
|
|
197
|
+
logger.warning(
|
|
198
|
+
f"--force-tag set: proceeding despite {len(collisions)} collision(s) on tag '{tag}'"
|
|
199
|
+
)
|
|
200
|
+
elif collisions:
|
|
201
|
+
_exit_on_collisions(
|
|
202
|
+
tag,
|
|
203
|
+
collisions,
|
|
204
|
+
"an in-progress run (manifest rows, no saved config JSON) resumes by "
|
|
205
|
+
"re-running its identical command",
|
|
206
|
+
)
|