Series A: local Qwen on the MacBook (remote server), 12 h window with hard stop, clean pause on server loss, dashboard card, docs/remote-model.md

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Kral
2026-10-05 21:57:01 +02:00
parent dc8d99a913
commit eb13453097
6 changed files with 576 additions and 6 deletions

View File

@@ -243,6 +243,65 @@ def agg_table(title, evs, rows, key, note=""):
% (E(title), E(key.replace("_", " ")), trs, "<div class=note>%s</div>" % E(note) if note else ""))
def local_card():
"""Card for series A (local Qwen on the MacBook): state.json of harness.localqwen. Empty string without a series."""
path = os.path.join(ROOT, "runs", "local_qwen", "state.json")
if not os.path.exists(path):
return ""
try:
st = json.load(open(path))
except ValueError:
return ""
now = time.time()
url = st.get("base_url") or ""
up = ping(url + "/models", timeout=4) if url else False # the dashboard asks the MacBook itself
status = st.get("status", "?")
left = st.get("window_start", now) + st.get("window_hours", 12) * 3600 - now
cur = st.get("current")
plan, res = st.get("plan", []), st.get("results", [])
chips = "<span class='chip %s'>server %s</span> <span class='chip %s'>%s</span>" % (
"ok" if up else "er", "answers" if up else "does not answer",
{"running": "ok", "paused": "wa", "finished": "gr", "window_over": "gr"}.get(status, "gr"), E(status))
rows = ""
per = {}
for r in res:
k = per.setdefault(r["kind"], {"runs": 0, "ok": 0, "scores": [], "fail": {}})
k["runs"] += 1
k["ok"] += r["accepted"]
if r.get("score") is not None:
k["scores"].append(r["score"])
for f in r.get("failure_types", []):
k["fail"][f] = k["fail"].get(f, 0) + 1
planned = {}
for p_ in plan:
planned[p_["kind"]] = planned.get(p_["kind"], 0) + 1
for kind in [x for x in ("INTF", "TABL", "STRU", "MSAG", "EXC", "DDLS") if x in planned or x in per]:
k = per.get(kind, {"runs": 0, "ok": 0, "scores": [], "fail": {}})
mean = "%.0f" % (sum(k["scores"]) / len(k["scores"])) if k["scores"] else "-"
rate = "%.0f%%" % (100.0 * k["ok"] / k["runs"]) if k["runs"] else "-"
fails = ", ".join("%s %d" % (f, n) for f, n in sorted(k["fail"].items(), key=lambda x: -x[1])) or "-"
rows += ("<tr><td>%s</td><td class=n>%d/%d</td><td class=n>%d</td><td class=n>%s</td><td class=n>%s</td><td>%s</td></tr>"
% (kind, k["runs"], planned.get(kind, 0), k["ok"], rate, mean, E(fails)))
if cur:
elapsed = (now - cur["start"]) / 60
curtxt = "%s (%s, %s), run %d min%s" % (cur["task"], cur["kind"], cur["category"], elapsed,
", restart %d" % cur["restarts"] if cur.get("restarts") else "")
else:
curtxt = "none (%s)" % status
evs = "".join("<div class=note>%s %s %s: %s</div>" % (time.strftime("%H:%M", time.localtime(e["t"])), E(e["kind"]),
E(e["task"]), E(e["text"])) for e in st.get("events", [])[-3:])
hdr = ("<div class=card style='grid-column:1/-1'><h2>Series A: local Qwen 3.8 27B on the MacBook (thinking off, 16384 tokens, loop guard 3, budget 60)</h2>"
"<div class=b>%s &nbsp; model <span class=mono>%s</span></div>"
"<div class=b><table><tr><td>Current task</td><td>%s</td><td>Done / planned</td><td class=n>%d / %d</td>"
"<td>Time left in the window</td><td class=n>%s</td><td>Paused</td><td class=n>%.0f min</td></tr></table></div>"
% (chips, E(os.path.basename(str(st.get("model_id", "")))), E(curtxt), len(res), len(plan),
("%dh %02dm" % (left // 3600, (left % 3600) // 60)) if left > 0 else "over", st.get("paused_seconds", 0) / 60))
tbl = ("<div class=b><table><tr><th>kind</th><th class=n>runs/planned</th><th class=n>accepted</th><th class=n>pass rate</th>"
"<th class=n>mean score</th><th>failure types</th></tr>%s</table></div>%s"
"<div class=note>Accepted trajectories of this series are kept apart (runs/local_qwen/accepted.jsonl), not for the first SFT.</div></div>" % (rows, evs))
return hdr + tbl
def mix_table(rows, evs):
kt = mix.accepted_task_counts()
kr = {}
@@ -376,7 +435,7 @@ def render(d):
% ("ok" if d["a4h"] else "er", "up" if d["a4h"] else "down", "ok" if d["mcp"] else "er", "up" if d["mcp"] else "down", scls, status,
E("\n".join(d["procs"]))))
logc = "<div class=card><h2>Pipeline log</h2><div class=b><div class='log mono'>%s</div></div></div>" % E("\n".join(d["log_tail"]))
body = (banner + "<div class=tiles>" + tiles + "</div><div class=grid>" + budget + prog + stops + sysc
body = (banner + "<div class=tiles>" + tiles + "</div><div class=grid>" + local_card() + budget + prog + stops + sysc
+ mix_table(rows, evs) + agg_table("Trajectories by category", evs, rows, "category") + agg_table("Trajectories by object type", evs, rows, "object_type")
+ gen_table(logs, "category", "Task generation by category") + gen_table(logs, "object_type", "Task generation by object type")
+ tok + recent + logc + "</div>")