Compact UI: merge telemetry and mission summary into one ops console.
Browse files
README.md
CHANGED
|
@@ -37,7 +37,7 @@ Credentials and publish permissions are handled by deployment runtime settings.
|
|
| 37 |
- `Enforce Quality Gate`: enables/disables promotion gate checks.
|
| 38 |
- `Gate Min pass@1`, `Gate Min pass@k`, `Gate Min Rows`: runtime gate thresholds.
|
| 39 |
- `Live Tactical Telemetry`: real-time stage progression, runtime posture, loss sparkline, and gate/push state.
|
| 40 |
-
- `
|
| 41 |
- `Validation Mode (No Training)`: validates pipeline with `--dry-run`.
|
| 42 |
- `Force Dataset Redownload`: bypasses cached parquet files.
|
| 43 |
- `Abort Active Run`: cancels active subprocess tree.
|
|
|
|
| 37 |
- `Enforce Quality Gate`: enables/disables promotion gate checks.
|
| 38 |
- `Gate Min pass@1`, `Gate Min pass@k`, `Gate Min Rows`: runtime gate thresholds.
|
| 39 |
- `Live Tactical Telemetry`: real-time stage progression, runtime posture, loss sparkline, and gate/push state.
|
| 40 |
+
- `Ops Console (Live Log + Mission JSON)`: unified panel for line-by-line runtime stream, heartbeats, and structured mission summary.
|
| 41 |
- `Validation Mode (No Training)`: validates pipeline with `--dry-run`.
|
| 42 |
- `Force Dataset Redownload`: bypasses cached parquet files.
|
| 43 |
- `Abort Active Run`: cancels active subprocess tree.
|
app.py
CHANGED
|
@@ -396,6 +396,17 @@ def summary_text(summary: Dict[str, Any]) -> str:
|
|
| 396 |
return json.dumps(summary, ensure_ascii=True, indent=2)
|
| 397 |
|
| 398 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 399 |
def _as_dict(value: Any) -> Dict[str, Any]:
|
| 400 |
return value if isinstance(value, dict) else {}
|
| 401 |
|
|
@@ -913,8 +924,8 @@ def make_copyable_textbox(
|
|
| 913 |
return gr.Textbox(**textbox_kwargs)
|
| 914 |
|
| 915 |
|
| 916 |
-
def clear_outputs() -> Tuple[str, str, str
|
| 917 |
-
return "", "Idle",
|
| 918 |
|
| 919 |
|
| 920 |
def cancel_pipeline() -> str:
|
|
@@ -1281,7 +1292,7 @@ def run_pipeline(
|
|
| 1281 |
push_to_hub: bool,
|
| 1282 |
force_redownload: bool,
|
| 1283 |
preflight_only: bool,
|
| 1284 |
-
) -> Generator[Tuple[str, str, str
|
| 1285 |
pipeline = run_pipeline_core(
|
| 1286 |
dataset_repo_id=dataset_repo_id,
|
| 1287 |
model_repo_id=model_repo_id,
|
|
@@ -1301,7 +1312,8 @@ def run_pipeline(
|
|
| 1301 |
)
|
| 1302 |
for logs_text, status_text, summary_json in pipeline:
|
| 1303 |
summary = _parse_summary_json(summary_json)
|
| 1304 |
-
|
|
|
|
| 1305 |
|
| 1306 |
|
| 1307 |
with gr.Blocks(title="Math Conjecture Trainer Space") as demo:
|
|
@@ -1369,11 +1381,10 @@ with gr.Blocks(title="Math Conjecture Trainer Space") as demo:
|
|
| 1369 |
|
| 1370 |
ops_visual = gr.HTML(value=render_ops_visual({}, "Idle", ""))
|
| 1371 |
status = gr.Textbox(label="Run Status", value="Idle", interactive=False)
|
| 1372 |
-
logs = make_copyable_textbox(
|
| 1373 |
-
|
| 1374 |
-
|
| 1375 |
-
|
| 1376 |
-
max_lines=24,
|
| 1377 |
interactive=False,
|
| 1378 |
)
|
| 1379 |
|
|
@@ -1396,10 +1407,10 @@ with gr.Blocks(title="Math Conjecture Trainer Space") as demo:
|
|
| 1396 |
force_redownload,
|
| 1397 |
preflight_only,
|
| 1398 |
],
|
| 1399 |
-
outputs=[logs, status,
|
| 1400 |
)
|
| 1401 |
stop_button.click(fn=cancel_pipeline, inputs=None, outputs=[status], queue=False)
|
| 1402 |
-
clear_button.click(fn=clear_outputs, inputs=None, outputs=[logs, status,
|
| 1403 |
gr.HTML(TACTICAL_FOOTER_HTML)
|
| 1404 |
|
| 1405 |
|
|
|
|
| 396 |
return json.dumps(summary, ensure_ascii=True, indent=2)
|
| 397 |
|
| 398 |
|
| 399 |
+
def compose_ops_console(log_text: str, summary_json: str) -> str:
|
| 400 |
+
payload = (log_text or "").strip()
|
| 401 |
+
summary_payload = (summary_json or "").strip()
|
| 402 |
+
if summary_payload:
|
| 403 |
+
if payload:
|
| 404 |
+
payload += "\n\n" + ("-" * 52) + "\nMission Summary (JSON)\n" + summary_payload
|
| 405 |
+
else:
|
| 406 |
+
payload = "Mission Summary (JSON)\n" + summary_payload
|
| 407 |
+
return payload
|
| 408 |
+
|
| 409 |
+
|
| 410 |
def _as_dict(value: Any) -> Dict[str, Any]:
|
| 411 |
return value if isinstance(value, dict) else {}
|
| 412 |
|
|
|
|
| 924 |
return gr.Textbox(**textbox_kwargs)
|
| 925 |
|
| 926 |
|
| 927 |
+
def clear_outputs() -> Tuple[str, str, str]:
|
| 928 |
+
return "", "Idle", render_ops_visual({}, "Idle", "")
|
| 929 |
|
| 930 |
|
| 931 |
def cancel_pipeline() -> str:
|
|
|
|
| 1292 |
push_to_hub: bool,
|
| 1293 |
force_redownload: bool,
|
| 1294 |
preflight_only: bool,
|
| 1295 |
+
) -> Generator[Tuple[str, str, str], None, None]:
|
| 1296 |
pipeline = run_pipeline_core(
|
| 1297 |
dataset_repo_id=dataset_repo_id,
|
| 1298 |
model_repo_id=model_repo_id,
|
|
|
|
| 1312 |
)
|
| 1313 |
for logs_text, status_text, summary_json in pipeline:
|
| 1314 |
summary = _parse_summary_json(summary_json)
|
| 1315 |
+
console_text = compose_ops_console(logs_text, summary_json)
|
| 1316 |
+
yield console_text, status_text, render_ops_visual(summary, status_text, logs_text)
|
| 1317 |
|
| 1318 |
|
| 1319 |
with gr.Blocks(title="Math Conjecture Trainer Space") as demo:
|
|
|
|
| 1381 |
|
| 1382 |
ops_visual = gr.HTML(value=render_ops_visual({}, "Idle", ""))
|
| 1383 |
status = gr.Textbox(label="Run Status", value="Idle", interactive=False)
|
| 1384 |
+
logs = make_copyable_textbox(
|
| 1385 |
+
label="Ops Console (Live Log + Mission JSON)",
|
| 1386 |
+
lines=26,
|
| 1387 |
+
max_lines=36,
|
|
|
|
| 1388 |
interactive=False,
|
| 1389 |
)
|
| 1390 |
|
|
|
|
| 1407 |
force_redownload,
|
| 1408 |
preflight_only,
|
| 1409 |
],
|
| 1410 |
+
outputs=[logs, status, ops_visual],
|
| 1411 |
)
|
| 1412 |
stop_button.click(fn=cancel_pipeline, inputs=None, outputs=[status], queue=False)
|
| 1413 |
+
clear_button.click(fn=clear_outputs, inputs=None, outputs=[logs, status, ops_visual], queue=False)
|
| 1414 |
gr.HTML(TACTICAL_FOOTER_HTML)
|
| 1415 |
|
| 1416 |
|