@mcptoolshop/style-dataset-lab 3.3.0 → 3.5.0
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.
- package/CHANGELOG.md +60 -0
- package/README.es.md +117 -55
- package/README.fr.md +125 -65
- package/README.hi.md +117 -68
- package/README.it.md +119 -58
- package/README.ja.md +124 -74
- package/README.md +73 -7
- package/README.pt-BR.md +128 -63
- package/README.zh.md +116 -65
- package/bin/sdlab.js +100 -4
- package/lib/adapters/ai-toolkit.js +224 -35
- package/lib/adapters/comfyui-runner.js +79 -26
- package/lib/adapters/comfyui-workflows.js +94 -11
- package/lib/adapters/diffusers-lora.js +37 -5
- package/lib/adapters/generic-image-caption.js +43 -5
- package/lib/args.js +16 -1
- package/lib/asset-ingest.js +575 -0
- package/lib/asset-masks.js +323 -0
- package/lib/asset-source.js +1176 -0
- package/lib/batch-modes.js +29 -8
- package/lib/batch-runs.js +29 -1
- package/lib/batch-sheet-render.js +13 -3
- package/lib/brief-compiler.js +19 -0
- package/lib/candidate-sheet.js +327 -0
- package/lib/canon-author.js +350 -0
- package/lib/canon-build/build.js +146 -93
- package/lib/canon-review-gate.js +205 -0
- package/lib/captions.js +57 -0
- package/lib/card.js +74 -2
- package/lib/colab-launcher-guards.js +285 -0
- package/lib/comfyui.js +116 -18
- package/lib/config.js +116 -12
- package/lib/critique-engine.js +36 -2
- package/lib/eligibility.js +121 -9
- package/lib/eval-pack.js +14 -14
- package/lib/eval-runs.js +33 -0
- package/lib/export.js +122 -34
- package/lib/freeze-gate.js +16 -3
- package/lib/freeze-stamp.js +28 -3
- package/lib/generated-provenance.js +194 -6
- package/lib/implementation-packs.js +95 -17
- package/lib/ingest.js +396 -0
- package/lib/judgment-provenance.js +220 -0
- package/lib/lane1-render.js +668 -0
- package/lib/measure.js +422 -0
- package/lib/memory-store.js +663 -0
- package/lib/model-licences.js +305 -0
- package/lib/npy-meta.js +130 -0
- package/lib/paths.js +196 -7
- package/lib/png-meta.js +512 -0
- package/lib/records.js +54 -8
- package/lib/reingest-selected.js +113 -17
- package/lib/reingest.js +27 -3
- package/lib/run-manifest.js +159 -25
- package/lib/run-summary.js +12 -6
- package/lib/runtime-runs.js +45 -4
- package/lib/snapshot.js +114 -15
- package/lib/split.js +364 -48
- package/lib/train-runs.js +214 -0
- package/lib/training-manifests.js +114 -21
- package/lib/training-packages.js +147 -15
- package/lib/verifier.js +3 -0
- package/lib/verify-chain.js +367 -0
- package/lib/workflow-profiles.js +24 -3
- package/package.json +4 -3
- package/runtime/comfyui/txt2img-qwen.json +38 -0
- package/runtime/comfyui/txt2img-standard.json +21 -0
- package/scripts/_resume.js +62 -0
- package/scripts/_shared-args.js +44 -0
- package/scripts/asset-ingest.js +160 -0
- package/scripts/brief-compile.js +2 -1
- package/scripts/brief-show.js +2 -1
- package/scripts/canon-bind.js +2 -2
- package/scripts/canon-build.js +27 -20
- package/scripts/canon-draft.js +82 -0
- package/scripts/canon-drift.js +16 -7
- package/scripts/canon-freeze-status.js +14 -6
- package/scripts/canon-freeze.js +31 -11
- package/scripts/canon-unfreeze.js +17 -9
- package/scripts/card.js +2 -2
- package/scripts/colab/REAL_SERVICE_ASSUMPTIONS.md +14 -0
- package/scripts/colab/ai-toolkit-override-py315.txt +45 -0
- package/scripts/colab/colab_window.sh +587 -0
- package/scripts/colab/lane1_render.py +970 -0
- package/scripts/colab/launch_guards.py +564 -0
- package/scripts/colab/launch_lane1_stub.sh +309 -0
- package/scripts/colab/launch_lane3_stub.sh +366 -0
- package/scripts/colab/remote_runner.py +59 -0
- package/scripts/compare.js +2 -2
- package/scripts/critique.js +16 -1
- package/scripts/curate.js +2 -2
- package/scripts/doctor.js +182 -55
- package/scripts/eligibility.js +42 -2
- package/scripts/eval-pack.js +2 -2
- package/scripts/eval-run.js +2 -2
- package/scripts/export.js +2 -2
- package/scripts/generate-controlnet.js +45 -25
- package/scripts/generate-identity.js +53 -23
- package/scripts/generate-ipadapter.js +44 -23
- package/scripts/generate.js +86 -17
- package/scripts/implementation-pack.js +2 -2
- package/scripts/ingest.js +145 -0
- package/scripts/init.js +73 -13
- package/scripts/measure.js +170 -0
- package/scripts/measure_image.py +458 -0
- package/scripts/migrate-records.js +142 -0
- package/scripts/painterly-test.js +4 -3
- package/scripts/painterly.js +7 -3
- package/scripts/qwen_generate.py +138 -20
- package/scripts/reingest.js +2 -2
- package/scripts/sheet.js +142 -0
- package/scripts/snapshot.js +2 -2
- package/scripts/split.js +2 -2
- package/scripts/training-manifest.js +2 -2
- package/scripts/training-package.js +2 -2
- package/scripts/training-profile.js +2 -2
- package/scripts/verify.js +67 -0
- package/scripts/workflow-list.js +2 -1
- package/scripts/workflow-show.js +2 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stub launch kit for Lane 1 (render) Colab CPU high-mem window (Part C, PR #45).
|
|
3
|
+
# Checks pinned input sha256s (including itself) before opening, holds /tmp/colab-window-open.lock,
|
|
4
|
+
# opens CPU --high-mem, runs CPython 3.15.1 uv venv + pinned ComfyUI --cpu + comfy-headless + 64x64
|
|
5
|
+
# fixture render + stamp read-back + kill + resume, enforces live launch_guards.py (wall, cap,
|
|
6
|
+
# vitals/DEAD HARNESS, host-RAM), scrubs VM-side logs before tarring, downloads result tar, merges
|
|
7
|
+
# VM facts/balances/rate/downloaded shas into window.json, and stops its own session in an EXIT trap.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
PINNED_UV_VERSION="0.13.5"
|
|
11
|
+
PINNED_PYTHON_VERSION="3.15.1"
|
|
12
|
+
PINNED_PYTORCH_INDEX_URL="https://download.pytorch.org/whl/cu130"
|
|
13
|
+
PINNED_COMFYUI_REPO="https://github.com/comfyanonymous/ComfyUI.git"
|
|
14
|
+
PINNED_COMFYUI_COMMIT="158419f3a0017c2ce123484b14b6c527716d6ec8"
|
|
15
|
+
PINNED_COMFY_HEADLESS_SPEC="comfy-headless==3.1.0"
|
|
16
|
+
PINNED_LANE1_RENDER_SHA="75c3b356644287e2c57efd4c3b89a5bde4a6ae4705438a98c383af392e114013"
|
|
17
|
+
PINNED_LAUNCH_GUARDS_SHA="8e664906e6deb45b498a0193e916d2d424f7e9b5839f39e63ea07f81a4682a78"
|
|
18
|
+
PINNED_REMOTE_RUNNER_SHA="7d4fc25401c1504910615f1aaea4418a6694196530380c11c9a9a25b02f83537"
|
|
19
|
+
PINNED_COLAB_WINDOW_SHA="9e956d486dbeb0fbd37e61f30edcc12f13d2565cacba8be4c6bffeb13ec82ed3"
|
|
20
|
+
PINNED_SELF_SHA="51de88a27b640a8f7620c1eb0095ae1238c49991ce0c99e9334862b56ec07f35"
|
|
21
|
+
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
SELF_SH="${SCRIPT_DIR}/launch_lane1_stub.sh"
|
|
24
|
+
# shellcheck source=scripts/colab/colab_window.sh
|
|
25
|
+
source "${SCRIPT_DIR}/colab_window.sh"
|
|
26
|
+
|
|
27
|
+
CARD="${CARD:-CPU-high-mem}"
|
|
28
|
+
SESSION="sdlab-lane1-stub-$(date -u +%Y%m%dT%H%M%SZ)"
|
|
29
|
+
OUT_DIR=""
|
|
30
|
+
CAP="${CAP:-0.05}"
|
|
31
|
+
WALL_S="${WALL_S:-900}"
|
|
32
|
+
GRACE_S="${GRACE_S:-60}"
|
|
33
|
+
MARGIN="${MARGIN:-0.01}"
|
|
34
|
+
|
|
35
|
+
while [ "$#" -gt 0 ]; do
|
|
36
|
+
case "$1" in
|
|
37
|
+
--card) CARD="$2"; shift 2 ;;
|
|
38
|
+
--session) SESSION="$2"; shift 2 ;;
|
|
39
|
+
--out-dir) OUT_DIR="$2"; shift 2 ;;
|
|
40
|
+
--cap) CAP="$2"; shift 2 ;;
|
|
41
|
+
--wall-s) WALL_S="$2"; shift 2 ;;
|
|
42
|
+
--grace-s) GRACE_S="$2"; shift 2 ;;
|
|
43
|
+
--margin) MARGIN="$2"; shift 2 ;;
|
|
44
|
+
*)
|
|
45
|
+
echo "REFUSED: unknown argument: $1" >&2
|
|
46
|
+
exit 2
|
|
47
|
+
;;
|
|
48
|
+
esac
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
if [ -z "${OUT_DIR}" ]; then
|
|
52
|
+
OUT_DIR="/tmp/${SESSION}"
|
|
53
|
+
fi
|
|
54
|
+
colab_refuse_nonempty_out_dir "${OUT_DIR}"
|
|
55
|
+
mkdir -p "${OUT_DIR}"
|
|
56
|
+
|
|
57
|
+
PY_BIN="$(colab_resolve_python)"
|
|
58
|
+
GUARDS_PY="${SCRIPT_DIR}/launch_guards.py"
|
|
59
|
+
LANE1_PY="${SCRIPT_DIR}/lane1_render.py"
|
|
60
|
+
RUNNER_PY="${SCRIPT_DIR}/remote_runner.py"
|
|
61
|
+
WINDOW_SH="${SCRIPT_DIR}/colab_window.sh"
|
|
62
|
+
|
|
63
|
+
colab_guard_fake_cli_if_test
|
|
64
|
+
|
|
65
|
+
EXP_LANE1_SHA="${EXPECTED_LANE1_RENDER_SHA:-${PINNED_LANE1_RENDER_SHA}}"
|
|
66
|
+
EXP_GUARDS_SHA="${EXPECTED_LAUNCH_GUARDS_SHA:-${PINNED_LAUNCH_GUARDS_SHA}}"
|
|
67
|
+
EXP_RUNNER_SHA="${EXPECTED_REMOTE_RUNNER_SHA:-${PINNED_REMOTE_RUNNER_SHA}}"
|
|
68
|
+
EXP_WINDOW_SHA="${EXPECTED_COLAB_WINDOW_SHA:-${PINNED_COLAB_WINDOW_SHA}}"
|
|
69
|
+
EXP_SELF_SHA="${EXPECTED_LAUNCH_LANE1_STUB_SHA:-${PINNED_SELF_SHA}}"
|
|
70
|
+
|
|
71
|
+
SHAS_JSON="$(colab_verify_input_shas "${PY_BIN}" "${GUARDS_PY}" \
|
|
72
|
+
"${LANE1_PY}=${EXP_LANE1_SHA}" \
|
|
73
|
+
"${GUARDS_PY}=${EXP_GUARDS_SHA}" \
|
|
74
|
+
"${RUNNER_PY}=${EXP_RUNNER_SHA}" \
|
|
75
|
+
"${WINDOW_SH}=${EXP_WINDOW_SHA}" \
|
|
76
|
+
"${SELF_SH}=${EXP_SELF_SHA}")"
|
|
77
|
+
|
|
78
|
+
OPENED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
79
|
+
START_EPOCH="$(date -u +%s)"
|
|
80
|
+
SESSION_OPENED=0
|
|
81
|
+
WALL_WATCHER_PID=""
|
|
82
|
+
EXEC_PID=""
|
|
83
|
+
|
|
84
|
+
cleanup_on_exit() {
|
|
85
|
+
local rc=$?
|
|
86
|
+
trap - EXIT TERM INT
|
|
87
|
+
if [ -n "${EXEC_PID}" ]; then
|
|
88
|
+
pkill -P "${EXEC_PID}" 2>/dev/null || true
|
|
89
|
+
kill -9 "${EXEC_PID}" 2>/dev/null || true
|
|
90
|
+
fi
|
|
91
|
+
if [ -n "${WALL_WATCHER_PID}" ]; then
|
|
92
|
+
pkill -P "${WALL_WATCHER_PID}" 2>/dev/null || true
|
|
93
|
+
kill -9 "${WALL_WATCHER_PID}" 2>/dev/null || true
|
|
94
|
+
fi
|
|
95
|
+
if [ "${SESSION_OPENED}" -eq 1 ]; then
|
|
96
|
+
colab_stop_and_log_closing "${PY_BIN}" "${SESSION}" "${OUT_DIR}"
|
|
97
|
+
fi
|
|
98
|
+
local closed_at
|
|
99
|
+
closed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
100
|
+
colab_write_window_and_outcome \
|
|
101
|
+
"${PY_BIN}" "${OUT_DIR}" "render" "${SESSION}" "${CARD}" \
|
|
102
|
+
"${CAP}" "${WALL_S}" "${GRACE_S}" "${MARGIN}" \
|
|
103
|
+
"${OPENED_AT}" "${closed_at}" "${rc}" "${SHAS_JSON}" || true
|
|
104
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}" || true
|
|
105
|
+
exit "${rc}"
|
|
106
|
+
}
|
|
107
|
+
trap cleanup_on_exit EXIT
|
|
108
|
+
trap 'exit 143' TERM INT
|
|
109
|
+
|
|
110
|
+
# Pre-open cap and host-RAM check via launch_guards.py
|
|
111
|
+
colab_check_cap_and_ram "${PY_BIN}" "${GUARDS_PY}" "stub" "0" "${WALL_S}" "${GRACE_S}" "${CAP}" "${MARGIN}" "${OUT_DIR}"
|
|
112
|
+
|
|
113
|
+
# Independent wall watcher (cannot be blocked by a child timeout)
|
|
114
|
+
WALL_INT="${WALL_S%.*}"
|
|
115
|
+
GRACE_INT="${GRACE_S%.*}"
|
|
116
|
+
WALL_LIMIT_S="$(( WALL_INT > GRACE_INT ? WALL_INT - GRACE_INT : 1 ))"
|
|
117
|
+
MAIN_PID="$$"
|
|
118
|
+
(
|
|
119
|
+
exec >/dev/null 2>&1 </dev/null
|
|
120
|
+
sleep "${WALL_LIMIT_S}"
|
|
121
|
+
echo "WALL_GUARD_TRIPPED after ${WALL_LIMIT_S}s" >> "${OUT_DIR}/guards.log"
|
|
122
|
+
kill -TERM "${MAIN_PID}" 2>/dev/null || true
|
|
123
|
+
) &
|
|
124
|
+
WALL_WATCHER_PID="$!"
|
|
125
|
+
|
|
126
|
+
# Hold /tmp/colab-window-open.lock while opening with colab new (--high-mem default)
|
|
127
|
+
SESSION_OPENED=1
|
|
128
|
+
colab_open_session_locked "${SESSION}" "${CARD}" "${OUT_DIR}"
|
|
129
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}"
|
|
130
|
+
|
|
131
|
+
REMOTE_RUNNER="${OUT_DIR}/remote_lane1_stub.sh"
|
|
132
|
+
cat > "${REMOTE_RUNNER}" << REMOTEEOF
|
|
133
|
+
#!/usr/bin/env bash
|
|
134
|
+
set -euo pipefail
|
|
135
|
+
export CUDA_VISIBLE_DEVICES=""
|
|
136
|
+
mkdir -p /content/lane1_out
|
|
137
|
+
|
|
138
|
+
: "\${PINNED_UV_VERSION:?missing PINNED_UV_VERSION}"
|
|
139
|
+
: "\${PINNED_PYTHON_VERSION:?missing PINNED_PYTHON_VERSION}"
|
|
140
|
+
: "\${PINNED_PYTORCH_INDEX_URL:?missing PINNED_PYTORCH_INDEX_URL}"
|
|
141
|
+
: "\${PINNED_COMFYUI_REPO:?missing PINNED_COMFYUI_REPO}"
|
|
142
|
+
: "\${PINNED_COMFYUI_COMMIT:?missing PINNED_COMFYUI_COMMIT}"
|
|
143
|
+
: "\${PINNED_COMFY_HEADLESS_SPEC:?missing PINNED_COMFY_HEADLESS_SPEC}"
|
|
144
|
+
|
|
145
|
+
echo "setup" > /content/lane1_out/phase.txt
|
|
146
|
+
: > /content/lane1_out/setup.log
|
|
147
|
+
(
|
|
148
|
+
while true; do
|
|
149
|
+
{
|
|
150
|
+
echo "=== VITALS \$(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
|
|
151
|
+
if [ -f /sys/fs/cgroup/memory.current ]; then
|
|
152
|
+
echo "CGROUP_MEM_CURRENT: \$(cat /sys/fs/cgroup/memory.current)" || true
|
|
153
|
+
fi
|
|
154
|
+
if [ -f /sys/fs/cgroup/memory.max ]; then
|
|
155
|
+
echo "CGROUP_MEM_MAX: \$(cat /sys/fs/cgroup/memory.max)" || true
|
|
156
|
+
fi
|
|
157
|
+
if [ -f /sys/fs/cgroup/memory.events ]; then
|
|
158
|
+
sed 's/^/CGROUP_MEM: /' /sys/fs/cgroup/memory.events || true
|
|
159
|
+
fi
|
|
160
|
+
grep -E '^(MemTotal|MemAvailable|AnonPages):' /proc/meminfo | sed 's/^/MEM: /' || true
|
|
161
|
+
SETUP_SZ="\$(wc -c < /content/lane1_out/setup.log 2>/dev/null | tr -d '[:space:]' || echo 0)"
|
|
162
|
+
echo "SETUP_BYTES: \${SETUP_SZ:-0}"
|
|
163
|
+
echo "PROC:"
|
|
164
|
+
ps -ef | grep -E "comfy|main\.py|lane1_render\.py" | grep -v grep || true
|
|
165
|
+
CUR_PHASE="\$(cat /content/lane1_out/phase.txt 2>/dev/null || echo setup)"
|
|
166
|
+
printf 'HARNESS: {"phase": "%s"}\n' "\${CUR_PHASE}"
|
|
167
|
+
} | tee -a /content/lane1_out/vitals.log
|
|
168
|
+
sleep 15
|
|
169
|
+
done
|
|
170
|
+
) &
|
|
171
|
+
VITALS_PID="\$!"
|
|
172
|
+
trap 'kill "\${VITALS_PID}" 2>/dev/null || true' EXIT
|
|
173
|
+
|
|
174
|
+
{
|
|
175
|
+
unset UV_SYSTEM_PYTHON
|
|
176
|
+
export UV_PYTHON_INSTALL_DIR="/content/.sdlab_python_315/install"
|
|
177
|
+
pip install --quiet "uv==\${PINNED_UV_VERSION}"
|
|
178
|
+
uv python install "\${PINNED_PYTHON_VERSION}"
|
|
179
|
+
uv venv --python "\${PINNED_PYTHON_VERSION}" --seed /content/venv-lane1
|
|
180
|
+
/content/venv-lane1/bin/python -c '
|
|
181
|
+
import sys
|
|
182
|
+
if not (sys.version.startswith("3.15.1") and sys.prefix.startswith("/content/venv-lane")):
|
|
183
|
+
sys.stderr.write(f"REFUSED: VENV_PYTHON_MISMATCH version={sys.version!r} prefix={sys.prefix!r}\n")
|
|
184
|
+
raise SystemExit(1)
|
|
185
|
+
'
|
|
186
|
+
/content/venv-lane1/bin/python -c 'import sys; assert sys.version.startswith("3.15.1"), sys.version; assert sys.prefix.startswith("/content/venv-lane"), sys.prefix'
|
|
187
|
+
} 2>&1 | tee -a /content/lane1_out/setup.log
|
|
188
|
+
{
|
|
189
|
+
unset UV_SYSTEM_PYTHON
|
|
190
|
+
export UV_PYTHON_INSTALL_DIR="/content/.sdlab_python_315/install"
|
|
191
|
+
if [ ! -d /content/ComfyUI ]; then
|
|
192
|
+
git clone "\${PINNED_COMFYUI_REPO}" /content/ComfyUI
|
|
193
|
+
fi
|
|
194
|
+
git -C /content/ComfyUI fetch --depth 1 origin "\${PINNED_COMFYUI_COMMIT}" || true
|
|
195
|
+
git -C /content/ComfyUI checkout "\${PINNED_COMFYUI_COMMIT}"
|
|
196
|
+
ACTUAL_COMFYUI_COMMIT="\$(git -C /content/ComfyUI rev-parse HEAD)"
|
|
197
|
+
if [ "\${ACTUAL_COMFYUI_COMMIT}" != "\${PINNED_COMFYUI_COMMIT}" ]; then
|
|
198
|
+
echo "REFUSED: ComfyUI commit mismatch: got \${ACTUAL_COMFYUI_COMMIT}, expected \${PINNED_COMFYUI_COMMIT}" >&2
|
|
199
|
+
exit 1
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
uv pip install --python /content/venv-lane1/bin/python \
|
|
203
|
+
-r /content/ComfyUI/requirements.txt \
|
|
204
|
+
--extra-index-url "\${PINNED_PYTORCH_INDEX_URL}" \
|
|
205
|
+
--index-strategy unsafe-best-match
|
|
206
|
+
uv pip install --python /content/venv-lane1/bin/python "\${PINNED_COMFY_HEADLESS_SPEC}"
|
|
207
|
+
/content/venv-lane1/bin/python -c '
|
|
208
|
+
import importlib
|
|
209
|
+
import sys
|
|
210
|
+
|
|
211
|
+
REQUIRED = ("comfy_headless", "torch", "safetensors", "PIL", "yaml", "aiohttp")
|
|
212
|
+
for mod_name in REQUIRED:
|
|
213
|
+
try:
|
|
214
|
+
mod = importlib.import_module(mod_name)
|
|
215
|
+
except Exception as exc:
|
|
216
|
+
sys.stderr.write(f"REFUSED: VENV_IMPORT_FAILED {mod_name}: {exc}\n")
|
|
217
|
+
raise SystemExit(1)
|
|
218
|
+
mod_file = getattr(mod, "__file__", None) or ""
|
|
219
|
+
print(f"VENV_IMPORT {mod_name} {mod_file}", flush=True)
|
|
220
|
+
if not mod_file.startswith("/content/venv-lane1/"):
|
|
221
|
+
sys.stderr.write(f"REFUSED: VENV_IMPORT_OUTSIDE_VENV {mod_name}: {mod_file}\n")
|
|
222
|
+
raise SystemExit(1)
|
|
223
|
+
from comfy_headless import ComfyClient
|
|
224
|
+
assert ComfyClient is not None
|
|
225
|
+
'
|
|
226
|
+
} 2>&1 | tee -a /content/lane1_out/setup.log
|
|
227
|
+
|
|
228
|
+
echo "run" > /content/lane1_out/phase.txt
|
|
229
|
+
/content/venv-lane1/bin/python /content/ComfyUI/main.py --cpu --listen 127.0.0.1 --port 8188 --disable-auto-launch \
|
|
230
|
+
> /content/lane1_out/comfyui.log 2>&1 &
|
|
231
|
+
COMFY_PID="\$!"
|
|
232
|
+
|
|
233
|
+
for _ in \$(seq 1 60); do
|
|
234
|
+
if curl -sf http://127.0.0.1:8188/system_stats >/dev/null 2>&1; then
|
|
235
|
+
break
|
|
236
|
+
fi
|
|
237
|
+
sleep 1
|
|
238
|
+
done
|
|
239
|
+
|
|
240
|
+
cat > /content/lane1_out/jobs.jsonl << 'JOBSEOF'
|
|
241
|
+
{"job_id":"stub_01","run_id":"run_stub_01","template_id":"stub_fixture_64","seed":101,"width":64,"height":64,"canon_sha":"a881cb5ba656e0618080d2269498fda7f36ac93a","entry_id":"ships/brig","entry_sha256":"sha256:1111111111111111111111111111111111111111111111111111111111111111","workflow_sha":"sha256:2222222222222222222222222222222222222222222222222222222222222222"}
|
|
242
|
+
{"job_id":"stub_02","run_id":"run_stub_01","template_id":"stub_fixture_64","seed":102,"width":64,"height":64,"canon_sha":"a881cb5ba656e0618080d2269498fda7f36ac93a","entry_id":"ships/brig","entry_sha256":"sha256:1111111111111111111111111111111111111111111111111111111111111111","workflow_sha":"sha256:2222222222222222222222222222222222222222222222222222222222222222"}
|
|
243
|
+
JOBSEOF
|
|
244
|
+
|
|
245
|
+
set +e
|
|
246
|
+
/content/venv-lane1/bin/python /content/lane1_render.py \
|
|
247
|
+
--cpu --bootstrap \
|
|
248
|
+
--comfy-pid "\${COMFY_PID}" \
|
|
249
|
+
--comfyui-commit "\${PINNED_COMFYUI_COMMIT}" \
|
|
250
|
+
--window-json /content/lane1_out/vm_window.json \
|
|
251
|
+
--jobs /content/lane1_out/jobs.jsonl \
|
|
252
|
+
--renders /content/lane1_out/renders.jsonl \
|
|
253
|
+
--out-dir /content/lane1_out/pngs \
|
|
254
|
+
--copy-back-dir /content/lane1_out/copy_back \
|
|
255
|
+
--copy-back-every 1 \
|
|
256
|
+
--kill-after 1
|
|
257
|
+
RC1=\$?
|
|
258
|
+
set -e
|
|
259
|
+
if [ "\${RC1}" -ne 75 ]; then
|
|
260
|
+
echo "Expected exit 75 on deliberate kill-after=1, got \${RC1}" >&2
|
|
261
|
+
exit 1
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
SHA_BEFORE="\$(sha256sum /content/lane1_out/pngs/stub_01.png | awk '{print \$1}')"
|
|
265
|
+
|
|
266
|
+
/content/venv-lane1/bin/python /content/lane1_render.py \
|
|
267
|
+
--cpu \
|
|
268
|
+
--jobs /content/lane1_out/jobs.jsonl \
|
|
269
|
+
--renders /content/lane1_out/renders.jsonl \
|
|
270
|
+
--out-dir /content/lane1_out/pngs \
|
|
271
|
+
--copy-back-dir /content/lane1_out/copy_back \
|
|
272
|
+
--copy-back-every 1
|
|
273
|
+
|
|
274
|
+
SHA_AFTER="\$(sha256sum /content/lane1_out/pngs/stub_01.png | awk '{print \$1}')"
|
|
275
|
+
SHA_COPY="\$(sha256sum /content/lane1_out/copy_back/stub_01.png | awk '{print \$1}')"
|
|
276
|
+
if [ "\${SHA_BEFORE}" != "\${SHA_AFTER}" ] || [ "\${SHA_BEFORE}" != "\${SHA_COPY}" ]; then
|
|
277
|
+
echo "Resume hash mismatch: before=\${SHA_BEFORE} after=\${SHA_AFTER} copy=\${SHA_COPY}" >&2
|
|
278
|
+
exit 1
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
kill "\${COMFY_PID}" 2>/dev/null || true
|
|
282
|
+
while IFS= read -r -d '' f; do
|
|
283
|
+
/content/venv-lane1/bin/python /content/launch_guards.py --scrub-file "\${f}" </dev/null || true
|
|
284
|
+
done < <(find /content/lane1_out -type f \( -name "*.log" -o -name "*.json" -o -name "*.txt" \) -print0 2>/dev/null || true)
|
|
285
|
+
tar -czf /content/lane1_stub_bundle.tar.gz -C /content/lane1_out .
|
|
286
|
+
REMOTEEOF
|
|
287
|
+
|
|
288
|
+
colab upload -s "${SESSION}" "${LANE1_PY}" /content/lane1_render.py </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
289
|
+
colab upload -s "${SESSION}" "${GUARDS_PY}" /content/launch_guards.py </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
290
|
+
colab upload -s "${SESSION}" "${REMOTE_RUNNER}" /content/remote_lane1_stub.sh </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
291
|
+
|
|
292
|
+
colab_run_exec_with_live_guards \
|
|
293
|
+
"${PY_BIN}" "${GUARDS_PY}" "${SESSION}" "${RUNNER_PY}" \
|
|
294
|
+
"${START_EPOCH}" "${WALL_S}" "${GRACE_S}" "${CAP}" "${MARGIN}" "${OUT_DIR}" \
|
|
295
|
+
"SDLAB_REMOTE_SCRIPT=/content/remote_lane1_stub.sh" \
|
|
296
|
+
"PINNED_UV_VERSION=${PINNED_UV_VERSION}" \
|
|
297
|
+
"PINNED_PYTHON_VERSION=${PINNED_PYTHON_VERSION}" \
|
|
298
|
+
"PINNED_PYTORCH_INDEX_URL=${PINNED_PYTORCH_INDEX_URL}" \
|
|
299
|
+
"PINNED_COMFYUI_REPO=${PINNED_COMFYUI_REPO}" \
|
|
300
|
+
"PINNED_COMFYUI_COMMIT=${PINNED_COMFYUI_COMMIT}" \
|
|
301
|
+
"PINNED_COMFY_HEADLESS_SPEC=${PINNED_COMFY_HEADLESS_SPEC}"
|
|
302
|
+
|
|
303
|
+
# Download result tar before EXIT trap stops the session
|
|
304
|
+
colab download -s "${SESSION}" /content/lane1_stub_bundle.tar.gz "${OUT_DIR}/lane1_stub_bundle.tar.gz" </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
305
|
+
if [ ! -s "${OUT_DIR}/lane1_stub_bundle.tar.gz" ]; then
|
|
306
|
+
echo "REFUSED: downloaded bundle ${OUT_DIR}/lane1_stub_bundle.tar.gz is missing or empty" >&2
|
|
307
|
+
exit 1
|
|
308
|
+
fi
|
|
309
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}"
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stub launch kit for Lane 3 (train) Colab CPU high-mem window (Part C, PR #47).
|
|
3
|
+
# Checks pinned input sha256s (including itself) before opening, holds /tmp/colab-window-open.lock,
|
|
4
|
+
# opens CPU --high-mem, runs CPython 3.15.1 uv venv + pinned ostris/ai-toolkit install with
|
|
5
|
+
# av/torchcodec filtered + ai-toolkit-override-py315.txt + PyTorch cp315 wheel index (proving
|
|
6
|
+
# sentencepiece==0.2.1 and wheels) + generates synth_job.yaml for a 1-step CPU training run on the
|
|
7
|
+
# synthetic package + verifies the .safetensors checkpoint exists and records its path in window.json,
|
|
8
|
+
# enforces live launch_guards.py (wall, cap, vitals/DEAD HARNESS, host-RAM), scrubs VM-side logs
|
|
9
|
+
# before tarring, downloads result tar, and stops its own session in an EXIT trap on every exit path.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
PINNED_UV_VERSION="0.13.5"
|
|
13
|
+
PINNED_PYTHON_VERSION="3.15.1"
|
|
14
|
+
PINNED_PYTORCH_INDEX_URL="https://download.pytorch.org/whl/cu130"
|
|
15
|
+
PINNED_AI_TOOLKIT_REPO="https://github.com/ostris/ai-toolkit.git"
|
|
16
|
+
PINNED_AI_TOOLKIT_COMMIT="73ebae1334d2c98089f1b90f8cb19257825f891a"
|
|
17
|
+
PINNED_OVERRIDE_SHA="42eab7931fb6c9b9fec187ded6668bd4ee00bd95dadb4c31e0dc940cffc9e3a9"
|
|
18
|
+
PINNED_LAUNCH_GUARDS_SHA="8e664906e6deb45b498a0193e916d2d424f7e9b5839f39e63ea07f81a4682a78"
|
|
19
|
+
PINNED_REMOTE_RUNNER_SHA="7d4fc25401c1504910615f1aaea4418a6694196530380c11c9a9a25b02f83537"
|
|
20
|
+
PINNED_COLAB_WINDOW_SHA="9e956d486dbeb0fbd37e61f30edcc12f13d2565cacba8be4c6bffeb13ec82ed3"
|
|
21
|
+
PINNED_SELF_SHA="67c27c3d227eeead8593c58a36d802c01b45beb53821fb2bcddf1838a36a2866"
|
|
22
|
+
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
SELF_SH="${SCRIPT_DIR}/launch_lane3_stub.sh"
|
|
25
|
+
# shellcheck source=scripts/colab/colab_window.sh
|
|
26
|
+
source "${SCRIPT_DIR}/colab_window.sh"
|
|
27
|
+
|
|
28
|
+
CARD="${CARD:-CPU-high-mem}"
|
|
29
|
+
SESSION="sdlab-lane3-stub-$(date -u +%Y%m%dT%H%M%SZ)"
|
|
30
|
+
OUT_DIR=""
|
|
31
|
+
CAP="${CAP:-0.05}"
|
|
32
|
+
WALL_S="${WALL_S:-900}"
|
|
33
|
+
GRACE_S="${GRACE_S:-60}"
|
|
34
|
+
MARGIN="${MARGIN:-0.01}"
|
|
35
|
+
|
|
36
|
+
while [ "$#" -gt 0 ]; do
|
|
37
|
+
case "$1" in
|
|
38
|
+
--card) CARD="$2"; shift 2 ;;
|
|
39
|
+
--session) SESSION="$2"; shift 2 ;;
|
|
40
|
+
--out-dir) OUT_DIR="$2"; shift 2 ;;
|
|
41
|
+
--cap) CAP="$2"; shift 2 ;;
|
|
42
|
+
--wall-s) WALL_S="$2"; shift 2 ;;
|
|
43
|
+
--grace-s) GRACE_S="$2"; shift 2 ;;
|
|
44
|
+
--margin) MARGIN="$2"; shift 2 ;;
|
|
45
|
+
*)
|
|
46
|
+
echo "REFUSED: unknown argument: $1" >&2
|
|
47
|
+
exit 2
|
|
48
|
+
;;
|
|
49
|
+
esac
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
if [ -z "${OUT_DIR}" ]; then
|
|
53
|
+
OUT_DIR="/tmp/${SESSION}"
|
|
54
|
+
fi
|
|
55
|
+
colab_refuse_nonempty_out_dir "${OUT_DIR}"
|
|
56
|
+
mkdir -p "${OUT_DIR}"
|
|
57
|
+
|
|
58
|
+
PY_BIN="$(colab_resolve_python)"
|
|
59
|
+
GUARDS_PY="${SCRIPT_DIR}/launch_guards.py"
|
|
60
|
+
OVERRIDE_TXT="${SCRIPT_DIR}/ai-toolkit-override-py315.txt"
|
|
61
|
+
RUNNER_PY="${SCRIPT_DIR}/remote_runner.py"
|
|
62
|
+
WINDOW_SH="${SCRIPT_DIR}/colab_window.sh"
|
|
63
|
+
|
|
64
|
+
colab_guard_fake_cli_if_test
|
|
65
|
+
|
|
66
|
+
EXP_OVERRIDE_SHA="${EXPECTED_OVERRIDE_SHA:-${PINNED_OVERRIDE_SHA}}"
|
|
67
|
+
EXP_GUARDS_SHA="${EXPECTED_LAUNCH_GUARDS_SHA:-${PINNED_LAUNCH_GUARDS_SHA}}"
|
|
68
|
+
EXP_RUNNER_SHA="${EXPECTED_REMOTE_RUNNER_SHA:-${PINNED_REMOTE_RUNNER_SHA}}"
|
|
69
|
+
EXP_WINDOW_SHA="${EXPECTED_COLAB_WINDOW_SHA:-${PINNED_COLAB_WINDOW_SHA}}"
|
|
70
|
+
EXP_SELF_SHA="${EXPECTED_LAUNCH_LANE3_STUB_SHA:-${PINNED_SELF_SHA}}"
|
|
71
|
+
|
|
72
|
+
SHAS_JSON="$(colab_verify_input_shas "${PY_BIN}" "${GUARDS_PY}" \
|
|
73
|
+
"${OVERRIDE_TXT}=${EXP_OVERRIDE_SHA}" \
|
|
74
|
+
"${GUARDS_PY}=${EXP_GUARDS_SHA}" \
|
|
75
|
+
"${RUNNER_PY}=${EXP_RUNNER_SHA}" \
|
|
76
|
+
"${WINDOW_SH}=${EXP_WINDOW_SHA}" \
|
|
77
|
+
"${SELF_SH}=${EXP_SELF_SHA}")"
|
|
78
|
+
|
|
79
|
+
OPENED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
80
|
+
START_EPOCH="$(date -u +%s)"
|
|
81
|
+
SESSION_OPENED=0
|
|
82
|
+
WALL_WATCHER_PID=""
|
|
83
|
+
EXEC_PID=""
|
|
84
|
+
|
|
85
|
+
cleanup_on_exit() {
|
|
86
|
+
local rc=$?
|
|
87
|
+
trap - EXIT TERM INT
|
|
88
|
+
if [ -n "${EXEC_PID}" ]; then
|
|
89
|
+
pkill -P "${EXEC_PID}" 2>/dev/null || true
|
|
90
|
+
kill -9 "${EXEC_PID}" 2>/dev/null || true
|
|
91
|
+
fi
|
|
92
|
+
if [ -n "${WALL_WATCHER_PID}" ]; then
|
|
93
|
+
pkill -P "${WALL_WATCHER_PID}" 2>/dev/null || true
|
|
94
|
+
kill -9 "${WALL_WATCHER_PID}" 2>/dev/null || true
|
|
95
|
+
fi
|
|
96
|
+
if [ "${SESSION_OPENED}" -eq 1 ]; then
|
|
97
|
+
colab_stop_and_log_closing "${PY_BIN}" "${SESSION}" "${OUT_DIR}"
|
|
98
|
+
fi
|
|
99
|
+
local closed_at
|
|
100
|
+
closed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
101
|
+
colab_write_window_and_outcome \
|
|
102
|
+
"${PY_BIN}" "${OUT_DIR}" "train" "${SESSION}" "${CARD}" \
|
|
103
|
+
"${CAP}" "${WALL_S}" "${GRACE_S}" "${MARGIN}" \
|
|
104
|
+
"${OPENED_AT}" "${closed_at}" "${rc}" "${SHAS_JSON}" || true
|
|
105
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}" || true
|
|
106
|
+
exit "${rc}"
|
|
107
|
+
}
|
|
108
|
+
trap cleanup_on_exit EXIT
|
|
109
|
+
trap 'exit 143' TERM INT
|
|
110
|
+
|
|
111
|
+
# Pre-open cap and host-RAM check via launch_guards.py
|
|
112
|
+
colab_check_cap_and_ram "${PY_BIN}" "${GUARDS_PY}" "stub" "0" "${WALL_S}" "${GRACE_S}" "${CAP}" "${MARGIN}" "${OUT_DIR}"
|
|
113
|
+
|
|
114
|
+
# Independent wall watcher (cannot be blocked by a child timeout)
|
|
115
|
+
WALL_INT="${WALL_S%.*}"
|
|
116
|
+
GRACE_INT="${GRACE_S%.*}"
|
|
117
|
+
WALL_LIMIT_S="$(( WALL_INT > GRACE_INT ? WALL_INT - GRACE_INT : 1 ))"
|
|
118
|
+
MAIN_PID="$$"
|
|
119
|
+
(
|
|
120
|
+
exec >/dev/null 2>&1 </dev/null
|
|
121
|
+
sleep "${WALL_LIMIT_S}"
|
|
122
|
+
echo "WALL_GUARD_TRIPPED after ${WALL_LIMIT_S}s" >> "${OUT_DIR}/guards.log"
|
|
123
|
+
kill -TERM "${MAIN_PID}" 2>/dev/null || true
|
|
124
|
+
) &
|
|
125
|
+
WALL_WATCHER_PID="$!"
|
|
126
|
+
|
|
127
|
+
# Hold /tmp/colab-window-open.lock while opening with colab new (--high-mem default)
|
|
128
|
+
SESSION_OPENED=1
|
|
129
|
+
colab_open_session_locked "${SESSION}" "${CARD}" "${OUT_DIR}"
|
|
130
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}"
|
|
131
|
+
|
|
132
|
+
REMOTE_RUNNER="${OUT_DIR}/remote_lane3_stub.sh"
|
|
133
|
+
cat > "${REMOTE_RUNNER}" << REMOTEEOF
|
|
134
|
+
#!/usr/bin/env bash
|
|
135
|
+
set -euo pipefail
|
|
136
|
+
export CUDA_VISIBLE_DEVICES=""
|
|
137
|
+
mkdir -p /content/lane3_out /content/lane3_out/checkpoints
|
|
138
|
+
|
|
139
|
+
: "\${PINNED_UV_VERSION:?missing PINNED_UV_VERSION}"
|
|
140
|
+
: "\${PINNED_PYTHON_VERSION:?missing PINNED_PYTHON_VERSION}"
|
|
141
|
+
: "\${PINNED_PYTORCH_INDEX_URL:?missing PINNED_PYTORCH_INDEX_URL}"
|
|
142
|
+
: "\${PINNED_AI_TOOLKIT_REPO:?missing PINNED_AI_TOOLKIT_REPO}"
|
|
143
|
+
: "\${PINNED_AI_TOOLKIT_COMMIT:?missing PINNED_AI_TOOLKIT_COMMIT}"
|
|
144
|
+
|
|
145
|
+
echo "setup" > /content/lane3_out/phase.txt
|
|
146
|
+
: > /content/lane3_out/setup.log
|
|
147
|
+
(
|
|
148
|
+
while true; do
|
|
149
|
+
{
|
|
150
|
+
echo "=== VITALS \$(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
|
|
151
|
+
if [ -f /sys/fs/cgroup/memory.current ]; then
|
|
152
|
+
echo "CGROUP_MEM_CURRENT: \$(cat /sys/fs/cgroup/memory.current)" || true
|
|
153
|
+
fi
|
|
154
|
+
if [ -f /sys/fs/cgroup/memory.max ]; then
|
|
155
|
+
echo "CGROUP_MEM_MAX: \$(cat /sys/fs/cgroup/memory.max)" || true
|
|
156
|
+
fi
|
|
157
|
+
if [ -f /sys/fs/cgroup/memory.events ]; then
|
|
158
|
+
sed 's/^/CGROUP_MEM: /' /sys/fs/cgroup/memory.events || true
|
|
159
|
+
fi
|
|
160
|
+
grep -E '^(MemTotal|MemAvailable|AnonPages):' /proc/meminfo | sed 's/^/MEM: /' || true
|
|
161
|
+
SETUP_SZ="\$(wc -c < /content/lane3_out/setup.log 2>/dev/null | tr -d '[:space:]' || echo 0)"
|
|
162
|
+
echo "SETUP_BYTES: \${SETUP_SZ:-0}"
|
|
163
|
+
echo "PROC:"
|
|
164
|
+
ps -ef | grep -E "ai-toolkit|run\.py" | grep -v grep || true
|
|
165
|
+
CUR_PHASE="\$(cat /content/lane3_out/phase.txt 2>/dev/null || echo setup)"
|
|
166
|
+
printf 'HARNESS: {"phase": "%s"}\n' "\${CUR_PHASE}"
|
|
167
|
+
} | tee -a /content/lane3_out/vitals.log
|
|
168
|
+
sleep 15
|
|
169
|
+
done
|
|
170
|
+
) &
|
|
171
|
+
VITALS_PID="\$!"
|
|
172
|
+
trap 'kill "\${VITALS_PID}" 2>/dev/null || true' EXIT
|
|
173
|
+
|
|
174
|
+
OVERRIDE_SHA="\$(sha256sum /content/ai-toolkit-override-py315.txt | awk '{print \$1}')"
|
|
175
|
+
echo "\${OVERRIDE_SHA} /content/ai-toolkit-override-py315.txt" > /content/lane3_out/override.sha256
|
|
176
|
+
|
|
177
|
+
{
|
|
178
|
+
unset UV_SYSTEM_PYTHON
|
|
179
|
+
export UV_PYTHON_INSTALL_DIR="/content/.sdlab_python_315/install"
|
|
180
|
+
if command -v apt-get >/dev/null 2>&1; then
|
|
181
|
+
apt-get update -qq && apt-get install -y -qq cmake pkg-config build-essential libsentencepiece-dev || true
|
|
182
|
+
fi
|
|
183
|
+
pip install --quiet "uv==\${PINNED_UV_VERSION}"
|
|
184
|
+
uv python install "\${PINNED_PYTHON_VERSION}"
|
|
185
|
+
uv venv --python "\${PINNED_PYTHON_VERSION}" --seed /content/venv-lane3
|
|
186
|
+
/content/venv-lane3/bin/python -c '
|
|
187
|
+
import sys
|
|
188
|
+
if not (sys.version.startswith("3.15.1") and sys.prefix.startswith("/content/venv-lane")):
|
|
189
|
+
sys.stderr.write(f"REFUSED: VENV_PYTHON_MISMATCH version={sys.version!r} prefix={sys.prefix!r}\n")
|
|
190
|
+
raise SystemExit(1)
|
|
191
|
+
'
|
|
192
|
+
/content/venv-lane3/bin/python -c 'import sys; assert sys.version.startswith("3.15.1"), sys.version; assert sys.prefix.startswith("/content/venv-lane"), sys.prefix'
|
|
193
|
+
} 2>&1 | tee -a /content/lane3_out/setup.log
|
|
194
|
+
{
|
|
195
|
+
unset UV_SYSTEM_PYTHON
|
|
196
|
+
export UV_PYTHON_INSTALL_DIR="/content/.sdlab_python_315/install"
|
|
197
|
+
if [ ! -d /content/ai-toolkit ]; then
|
|
198
|
+
git clone "\${PINNED_AI_TOOLKIT_REPO}" /content/ai-toolkit
|
|
199
|
+
fi
|
|
200
|
+
git -C /content/ai-toolkit fetch --depth 1 origin "\${PINNED_AI_TOOLKIT_COMMIT}" || true
|
|
201
|
+
git -C /content/ai-toolkit checkout "\${PINNED_AI_TOOLKIT_COMMIT}"
|
|
202
|
+
ACTUAL_AI_TOOLKIT_COMMIT="\$(git -C /content/ai-toolkit rev-parse HEAD)"
|
|
203
|
+
if [ "\${ACTUAL_AI_TOOLKIT_COMMIT}" != "\${PINNED_AI_TOOLKIT_COMMIT}" ]; then
|
|
204
|
+
echo "REFUSED: ai-toolkit commit mismatch: got \${ACTUAL_AI_TOOLKIT_COMMIT}, expected \${PINNED_AI_TOOLKIT_COMMIT}" >&2
|
|
205
|
+
exit 1
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
grep -Ev '^(av|torchcodec)([=<>!~[:space:]]|\$)' /content/ai-toolkit/requirements.txt \
|
|
209
|
+
> /content/lane3_out/requirements.filtered.txt
|
|
210
|
+
|
|
211
|
+
uv pip install --python /content/venv-lane3/bin/python \
|
|
212
|
+
-r /content/lane3_out/requirements.filtered.txt \
|
|
213
|
+
--override /content/ai-toolkit-override-py315.txt \
|
|
214
|
+
--extra-index-url "\${PINNED_PYTORCH_INDEX_URL}" \
|
|
215
|
+
--index-strategy unsafe-best-match \
|
|
216
|
+
2>&1 | tee /content/lane3_out/wheels.log
|
|
217
|
+
|
|
218
|
+
/content/venv-lane3/bin/python -c '
|
|
219
|
+
import importlib
|
|
220
|
+
import sys
|
|
221
|
+
|
|
222
|
+
REQUIRED = ("sentencepiece", "torch", "safetensors", "yaml", "oyaml", "PIL")
|
|
223
|
+
for mod_name in REQUIRED:
|
|
224
|
+
try:
|
|
225
|
+
mod = importlib.import_module(mod_name)
|
|
226
|
+
except Exception as exc:
|
|
227
|
+
sys.stderr.write(f"REFUSED: VENV_IMPORT_FAILED {mod_name}: {exc}\n")
|
|
228
|
+
raise SystemExit(1)
|
|
229
|
+
mod_file = getattr(mod, "__file__", None) or ""
|
|
230
|
+
print(f"VENV_IMPORT {mod_name} {mod_file}", flush=True)
|
|
231
|
+
if not mod_file.startswith("/content/venv-lane3/"):
|
|
232
|
+
sys.stderr.write(f"REFUSED: VENV_IMPORT_OUTSIDE_VENV {mod_name}: {mod_file}\n")
|
|
233
|
+
raise SystemExit(1)
|
|
234
|
+
import sentencepiece as spm
|
|
235
|
+
print("SENTENCEPIECE_OK", spm.__version__, flush=True)
|
|
236
|
+
' | tee /content/lane3_out/sentencepiece.txt
|
|
237
|
+
} 2>&1 | tee -a /content/lane3_out/setup.log
|
|
238
|
+
|
|
239
|
+
/content/venv-lane3/bin/python - << 'SYNTHEOF'
|
|
240
|
+
import hashlib
|
|
241
|
+
import json
|
|
242
|
+
import struct
|
|
243
|
+
import zlib
|
|
244
|
+
from pathlib import Path
|
|
245
|
+
|
|
246
|
+
pkg = Path("/content/lane3_out/synth_pkg")
|
|
247
|
+
pkg.mkdir(parents=True, exist_ok=True)
|
|
248
|
+
|
|
249
|
+
def make_png(seed_b: int) -> bytes:
|
|
250
|
+
sig = b"\x89PNG\r\n\x1a\n"
|
|
251
|
+
ihdr_d = struct.pack(">IIBBBBB", 64, 64, 8, 2, 0, 0, 0)
|
|
252
|
+
ihdr = struct.pack(">I", 13) + b"IHDR" + ihdr_d + struct.pack(">I", zlib.crc32(b"IHDR" + ihdr_d) & 0xFFFFFFFF)
|
|
253
|
+
row = bytes([0] + [seed_b & 0xFF, (seed_b * 3) & 0xFF, (seed_b * 7) & 0xFF] * 64)
|
|
254
|
+
idat_d = zlib.compress(row * 64)
|
|
255
|
+
idat = struct.pack(">I", len(idat_d)) + b"IDAT" + idat_d + struct.pack(">I", zlib.crc32(b"IDAT" + idat_d) & 0xFFFFFFFF)
|
|
256
|
+
iend = struct.pack(">I", 0) + b"IEND" + struct.pack(">I", zlib.crc32(b"IEND") & 0xFFFFFFFF)
|
|
257
|
+
return sig + ihdr + idat + iend
|
|
258
|
+
|
|
259
|
+
items = []
|
|
260
|
+
for idx in (1, 2):
|
|
261
|
+
img_b = make_png(idx * 17)
|
|
262
|
+
img_p = pkg / f"sample_{idx:02d}.png"
|
|
263
|
+
txt_p = pkg / f"sample_{idx:02d}.txt"
|
|
264
|
+
img_p.write_bytes(img_b)
|
|
265
|
+
txt_p.write_text(f"portlight ship synthetic fixture {idx}\n", encoding="utf-8")
|
|
266
|
+
items.append({"image": img_p.name, "sha256": hashlib.sha256(img_b).hexdigest()})
|
|
267
|
+
|
|
268
|
+
(pkg / "dataset_manifest.json").write_text(json.dumps({"seed": 42, "items": items}, indent=2) + "\n", encoding="utf-8")
|
|
269
|
+
SYNTHEOF
|
|
270
|
+
|
|
271
|
+
cat > /content/lane3_out/synth_job.yaml << 'YAMLEOF'
|
|
272
|
+
job: extension
|
|
273
|
+
config:
|
|
274
|
+
name: synth_lora
|
|
275
|
+
process:
|
|
276
|
+
- type: sd_trainer
|
|
277
|
+
training_folder: /content/lane3_out/checkpoints
|
|
278
|
+
device: cpu
|
|
279
|
+
network:
|
|
280
|
+
type: lora
|
|
281
|
+
linear: 4
|
|
282
|
+
linear_alpha: 4
|
|
283
|
+
save:
|
|
284
|
+
dtype: float32
|
|
285
|
+
save_every: 1
|
|
286
|
+
max_step_saves_to_keep: 1
|
|
287
|
+
datasets:
|
|
288
|
+
- folder_path: /content/lane3_out/synth_pkg
|
|
289
|
+
caption_ext: txt
|
|
290
|
+
resolution: [64, 64]
|
|
291
|
+
train:
|
|
292
|
+
batch_size: 1
|
|
293
|
+
steps: 1
|
|
294
|
+
lr: 0.0001
|
|
295
|
+
optimizer: adamw
|
|
296
|
+
dtype: fp32
|
|
297
|
+
YAMLEOF
|
|
298
|
+
|
|
299
|
+
echo "run" > /content/lane3_out/phase.txt
|
|
300
|
+
/content/venv-lane3/bin/python /content/ai-toolkit/run.py /content/lane3_out/synth_job.yaml \
|
|
301
|
+
> /content/lane3_out/train.log 2>&1
|
|
302
|
+
|
|
303
|
+
CHECKPOINT_PATH="/content/lane3_out/checkpoints/synth_lora.safetensors"
|
|
304
|
+
if [ ! -s "\${CHECKPOINT_PATH}" ]; then
|
|
305
|
+
FOUND_CKPT="\$(find /content/lane3_out/checkpoints -name '*.safetensors' -type f | head -n 1 || true)"
|
|
306
|
+
if [ -n "\${FOUND_CKPT}" ] && [ -s "\${FOUND_CKPT}" ]; then
|
|
307
|
+
cp "\${FOUND_CKPT}" "\${CHECKPOINT_PATH}"
|
|
308
|
+
else
|
|
309
|
+
echo "REFUSED: expected non-empty .safetensors checkpoint at \${CHECKPOINT_PATH}" >&2
|
|
310
|
+
exit 1
|
|
311
|
+
fi
|
|
312
|
+
fi
|
|
313
|
+
|
|
314
|
+
/content/venv-lane3/bin/python - "\${PINNED_AI_TOOLKIT_COMMIT}" "\${OVERRIDE_SHA}" "\${CHECKPOINT_PATH}" << 'WINPYEOF'
|
|
315
|
+
import hashlib
|
|
316
|
+
import json
|
|
317
|
+
import subprocess
|
|
318
|
+
import sys
|
|
319
|
+
from pathlib import Path
|
|
320
|
+
|
|
321
|
+
ai_commit = sys.argv[1]
|
|
322
|
+
override_sha = sys.argv[2]
|
|
323
|
+
ckpt_path = sys.argv[3]
|
|
324
|
+
sys_py = subprocess.run(["/usr/bin/python3", "--version"], capture_output=True, text=True, check=False).stdout.strip().split()[-1]
|
|
325
|
+
uv_ver = subprocess.run(["uv", "--version"], capture_output=True, text=True, check=False).stdout.strip()
|
|
326
|
+
py_sha = "sha256:" + hashlib.sha256(Path(sys.executable).read_bytes()).hexdigest()
|
|
327
|
+
rec = {
|
|
328
|
+
"system_python": sys_py,
|
|
329
|
+
"python": sys.version.split()[0],
|
|
330
|
+
"python_sha256": py_sha,
|
|
331
|
+
"uv": uv_ver,
|
|
332
|
+
"ai_toolkit_commit": ai_commit,
|
|
333
|
+
"override_sha256": f"sha256:{override_sha}",
|
|
334
|
+
"checkpoint_path": ckpt_path,
|
|
335
|
+
}
|
|
336
|
+
Path("/content/lane3_out/vm_window.json").write_text(json.dumps(rec, indent=2) + "\n", encoding="utf-8")
|
|
337
|
+
print("WINDOW_JSON " + json.dumps(rec), flush=True)
|
|
338
|
+
WINPYEOF
|
|
339
|
+
|
|
340
|
+
while IFS= read -r -d '' f; do
|
|
341
|
+
/content/venv-lane3/bin/python /content/launch_guards.py --scrub-file "\${f}" </dev/null || true
|
|
342
|
+
done < <(find /content/lane3_out -type f \( -name "*.log" -o -name "*.json" -o -name "*.txt" \) -print0 2>/dev/null || true)
|
|
343
|
+
tar -czf /content/lane3_stub_bundle.tar.gz -C /content/lane3_out .
|
|
344
|
+
REMOTEEOF
|
|
345
|
+
|
|
346
|
+
colab upload -s "${SESSION}" "${OVERRIDE_TXT}" /content/ai-toolkit-override-py315.txt </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
347
|
+
colab upload -s "${SESSION}" "${GUARDS_PY}" /content/launch_guards.py </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
348
|
+
colab upload -s "${SESSION}" "${REMOTE_RUNNER}" /content/remote_lane3_stub.sh </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
349
|
+
|
|
350
|
+
colab_run_exec_with_live_guards \
|
|
351
|
+
"${PY_BIN}" "${GUARDS_PY}" "${SESSION}" "${RUNNER_PY}" \
|
|
352
|
+
"${START_EPOCH}" "${WALL_S}" "${GRACE_S}" "${CAP}" "${MARGIN}" "${OUT_DIR}" \
|
|
353
|
+
"SDLAB_REMOTE_SCRIPT=/content/remote_lane3_stub.sh" \
|
|
354
|
+
"PINNED_UV_VERSION=${PINNED_UV_VERSION}" \
|
|
355
|
+
"PINNED_PYTHON_VERSION=${PINNED_PYTHON_VERSION}" \
|
|
356
|
+
"PINNED_PYTORCH_INDEX_URL=${PINNED_PYTORCH_INDEX_URL}" \
|
|
357
|
+
"PINNED_AI_TOOLKIT_REPO=${PINNED_AI_TOOLKIT_REPO}" \
|
|
358
|
+
"PINNED_AI_TOOLKIT_COMMIT=${PINNED_AI_TOOLKIT_COMMIT}"
|
|
359
|
+
|
|
360
|
+
# Download result tar before EXIT trap stops the session
|
|
361
|
+
colab download -s "${SESSION}" /content/lane3_stub_bundle.tar.gz "${OUT_DIR}/lane3_stub_bundle.tar.gz" </dev/null >> "${OUT_DIR}/colab.log" 2>&1
|
|
362
|
+
if [ ! -s "${OUT_DIR}/lane3_stub_bundle.tar.gz" ]; then
|
|
363
|
+
echo "REFUSED: downloaded bundle ${OUT_DIR}/lane3_stub_bundle.tar.gz is missing or empty" >&2
|
|
364
|
+
exit 1
|
|
365
|
+
fi
|
|
366
|
+
colab_scrub_all_logs "${PY_BIN}" "${GUARDS_PY}" "${OUT_DIR}"
|