openadapt-ml 0.2.0__py3-none-any.whl → 0.2.1__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.
- openadapt_ml/baselines/__init__.py +121 -0
- openadapt_ml/baselines/adapter.py +185 -0
- openadapt_ml/baselines/cli.py +314 -0
- openadapt_ml/baselines/config.py +448 -0
- openadapt_ml/baselines/parser.py +922 -0
- openadapt_ml/baselines/prompts.py +787 -0
- openadapt_ml/benchmarks/__init__.py +13 -115
- openadapt_ml/benchmarks/agent.py +265 -421
- openadapt_ml/benchmarks/azure.py +28 -19
- openadapt_ml/benchmarks/azure_ops_tracker.py +521 -0
- openadapt_ml/benchmarks/cli.py +1722 -4847
- openadapt_ml/benchmarks/trace_export.py +631 -0
- openadapt_ml/benchmarks/viewer.py +22 -5
- openadapt_ml/benchmarks/vm_monitor.py +530 -29
- openadapt_ml/benchmarks/waa_deploy/Dockerfile +47 -53
- openadapt_ml/benchmarks/waa_deploy/api_agent.py +21 -20
- openadapt_ml/cloud/azure_inference.py +3 -5
- openadapt_ml/cloud/lambda_labs.py +722 -307
- openadapt_ml/cloud/local.py +2038 -487
- openadapt_ml/cloud/ssh_tunnel.py +68 -26
- openadapt_ml/datasets/next_action.py +40 -30
- openadapt_ml/evals/grounding.py +8 -3
- openadapt_ml/evals/plot_eval_metrics.py +15 -13
- openadapt_ml/evals/trajectory_matching.py +41 -26
- openadapt_ml/experiments/demo_prompt/format_demo.py +16 -6
- openadapt_ml/experiments/demo_prompt/run_experiment.py +26 -16
- openadapt_ml/experiments/representation_shootout/__init__.py +70 -0
- openadapt_ml/experiments/representation_shootout/conditions.py +708 -0
- openadapt_ml/experiments/representation_shootout/config.py +390 -0
- openadapt_ml/experiments/representation_shootout/evaluator.py +659 -0
- openadapt_ml/experiments/representation_shootout/runner.py +687 -0
- openadapt_ml/experiments/waa_demo/runner.py +29 -14
- openadapt_ml/export/parquet.py +36 -24
- openadapt_ml/grounding/detector.py +18 -14
- openadapt_ml/ingest/__init__.py +8 -6
- openadapt_ml/ingest/capture.py +25 -22
- openadapt_ml/ingest/loader.py +7 -4
- openadapt_ml/ingest/synthetic.py +189 -100
- openadapt_ml/models/api_adapter.py +14 -4
- openadapt_ml/models/base_adapter.py +10 -2
- openadapt_ml/models/providers/__init__.py +288 -0
- openadapt_ml/models/providers/anthropic.py +266 -0
- openadapt_ml/models/providers/base.py +299 -0
- openadapt_ml/models/providers/google.py +376 -0
- openadapt_ml/models/providers/openai.py +342 -0
- openadapt_ml/models/qwen_vl.py +46 -19
- openadapt_ml/perception/__init__.py +35 -0
- openadapt_ml/perception/integration.py +399 -0
- openadapt_ml/retrieval/demo_retriever.py +50 -24
- openadapt_ml/retrieval/embeddings.py +9 -8
- openadapt_ml/retrieval/retriever.py +3 -1
- openadapt_ml/runtime/__init__.py +50 -0
- openadapt_ml/runtime/policy.py +18 -5
- openadapt_ml/runtime/safety_gate.py +471 -0
- openadapt_ml/schema/__init__.py +9 -0
- openadapt_ml/schema/converters.py +74 -27
- openadapt_ml/schema/episode.py +31 -18
- openadapt_ml/scripts/capture_screenshots.py +530 -0
- openadapt_ml/scripts/compare.py +85 -54
- openadapt_ml/scripts/demo_policy.py +4 -1
- openadapt_ml/scripts/eval_policy.py +15 -9
- openadapt_ml/scripts/make_gif.py +1 -1
- openadapt_ml/scripts/prepare_synthetic.py +3 -1
- openadapt_ml/scripts/train.py +21 -9
- openadapt_ml/segmentation/README.md +920 -0
- openadapt_ml/segmentation/__init__.py +97 -0
- openadapt_ml/segmentation/adapters/__init__.py +5 -0
- openadapt_ml/segmentation/adapters/capture_adapter.py +420 -0
- openadapt_ml/segmentation/annotator.py +610 -0
- openadapt_ml/segmentation/cache.py +290 -0
- openadapt_ml/segmentation/cli.py +674 -0
- openadapt_ml/segmentation/deduplicator.py +656 -0
- openadapt_ml/segmentation/frame_describer.py +788 -0
- openadapt_ml/segmentation/pipeline.py +340 -0
- openadapt_ml/segmentation/schemas.py +622 -0
- openadapt_ml/segmentation/segment_extractor.py +634 -0
- openadapt_ml/training/azure_ops_viewer.py +1097 -0
- openadapt_ml/training/benchmark_viewer.py +52 -41
- openadapt_ml/training/shared_ui.py +7 -7
- openadapt_ml/training/stub_provider.py +57 -35
- openadapt_ml/training/trainer.py +143 -86
- openadapt_ml/training/trl_trainer.py +70 -21
- openadapt_ml/training/viewer.py +323 -108
- openadapt_ml/training/viewer_components.py +180 -0
- {openadapt_ml-0.2.0.dist-info → openadapt_ml-0.2.1.dist-info}/METADATA +215 -14
- openadapt_ml-0.2.1.dist-info/RECORD +116 -0
- openadapt_ml/benchmarks/base.py +0 -366
- openadapt_ml/benchmarks/data_collection.py +0 -432
- openadapt_ml/benchmarks/live_tracker.py +0 -180
- openadapt_ml/benchmarks/runner.py +0 -418
- openadapt_ml/benchmarks/waa.py +0 -761
- openadapt_ml/benchmarks/waa_live.py +0 -619
- openadapt_ml-0.2.0.dist-info/RECORD +0 -86
- {openadapt_ml-0.2.0.dist-info → openadapt_ml-0.2.1.dist-info}/WHEEL +0 -0
- {openadapt_ml-0.2.0.dist-info → openadapt_ml-0.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
|
|
13
13
|
def _get_background_tasks_panel_css() -> str:
|
|
14
14
|
"""Return CSS for background tasks panel."""
|
|
15
|
-
return
|
|
15
|
+
return """
|
|
16
16
|
.tasks-panel {
|
|
17
17
|
background: linear-gradient(135deg, rgba(100, 100, 255, 0.1) 0%, rgba(100, 100, 255, 0.05) 100%);
|
|
18
18
|
border: 1px solid rgba(100, 100, 255, 0.3);
|
|
@@ -287,12 +287,12 @@ def _get_background_tasks_panel_css() -> str:
|
|
|
287
287
|
border-radius: 3px;
|
|
288
288
|
transition: width 0.5s ease;
|
|
289
289
|
}
|
|
290
|
-
|
|
290
|
+
"""
|
|
291
291
|
|
|
292
292
|
|
|
293
293
|
def _get_background_tasks_panel_html() -> str:
|
|
294
294
|
"""Return HTML for background tasks panel with JS polling and improved styling."""
|
|
295
|
-
return
|
|
295
|
+
return """
|
|
296
296
|
<div class="tasks-panel" id="tasks-panel">
|
|
297
297
|
<div class="tasks-header">
|
|
298
298
|
<div class="tasks-title">
|
|
@@ -701,12 +701,12 @@ def _get_background_tasks_panel_html() -> str:
|
|
|
701
701
|
fetchBackgroundTasks();
|
|
702
702
|
setInterval(fetchBackgroundTasks, 10000);
|
|
703
703
|
</script>
|
|
704
|
-
|
|
704
|
+
"""
|
|
705
705
|
|
|
706
706
|
|
|
707
707
|
def _get_live_evaluation_panel_css() -> str:
|
|
708
708
|
"""Return CSS for live evaluation progress panel."""
|
|
709
|
-
return
|
|
709
|
+
return """
|
|
710
710
|
.live-eval-panel {
|
|
711
711
|
background: linear-gradient(135deg, rgba(139, 92, 246, 0.15) 0%, rgba(139, 92, 246, 0.05) 100%);
|
|
712
712
|
border: 1px solid rgba(139, 92, 246, 0.3);
|
|
@@ -859,12 +859,12 @@ def _get_live_evaluation_panel_css() -> str:
|
|
|
859
859
|
0%, 100% { opacity: 1; }
|
|
860
860
|
50% { opacity: 0.3; }
|
|
861
861
|
}
|
|
862
|
-
|
|
862
|
+
"""
|
|
863
863
|
|
|
864
864
|
|
|
865
865
|
def _get_live_evaluation_panel_html() -> str:
|
|
866
866
|
"""Return HTML for live evaluation panel with SSE and polling fallback."""
|
|
867
|
-
return
|
|
867
|
+
return """
|
|
868
868
|
<div class="live-eval-panel" id="live-eval-panel">
|
|
869
869
|
<div class="live-eval-header">
|
|
870
870
|
<div class="live-eval-title">
|
|
@@ -1237,12 +1237,12 @@ def _get_live_evaluation_panel_html() -> str:
|
|
|
1237
1237
|
if (window.sseManager) window.sseManager.disconnect();
|
|
1238
1238
|
});
|
|
1239
1239
|
</script>
|
|
1240
|
-
|
|
1240
|
+
"""
|
|
1241
1241
|
|
|
1242
1242
|
|
|
1243
1243
|
def _get_azure_jobs_panel_css() -> str:
|
|
1244
1244
|
"""Return CSS for the Azure jobs status panel with color-coded status indicators."""
|
|
1245
|
-
return
|
|
1245
|
+
return """
|
|
1246
1246
|
.azure-jobs-panel {
|
|
1247
1247
|
background: linear-gradient(135deg, rgba(0, 120, 212, 0.15) 0%, rgba(0, 120, 212, 0.05) 100%);
|
|
1248
1248
|
border: 1px solid rgba(0, 120, 212, 0.3);
|
|
@@ -1535,7 +1535,7 @@ def _get_azure_jobs_panel_css() -> str:
|
|
|
1535
1535
|
@keyframes spin {
|
|
1536
1536
|
to { transform: rotate(360deg); }
|
|
1537
1537
|
}
|
|
1538
|
-
|
|
1538
|
+
"""
|
|
1539
1539
|
|
|
1540
1540
|
|
|
1541
1541
|
def _get_azure_jobs_panel_html() -> str:
|
|
@@ -1545,7 +1545,7 @@ def _get_azure_jobs_panel_html() -> str:
|
|
|
1545
1545
|
is used for training jobs, not for WAA benchmarks (which require nested virtualization
|
|
1546
1546
|
that managed compute doesn't support).
|
|
1547
1547
|
"""
|
|
1548
|
-
return
|
|
1548
|
+
return """
|
|
1549
1549
|
<div class="azure-jobs-panel collapsed" id="azure-jobs-panel">
|
|
1550
1550
|
<div class="azure-jobs-header" onclick="toggleAzureJobsPanel()" title="Azure ML training jobs">
|
|
1551
1551
|
<div class="azure-jobs-title">
|
|
@@ -1928,12 +1928,12 @@ def _get_azure_jobs_panel_html() -> str:
|
|
|
1928
1928
|
setInterval(fetchAzureJobs, 30000);
|
|
1929
1929
|
setInterval(fetchJobLogs, 5000); // Poll logs every 5 seconds
|
|
1930
1930
|
</script>
|
|
1931
|
-
|
|
1931
|
+
"""
|
|
1932
1932
|
|
|
1933
1933
|
|
|
1934
1934
|
def _get_vm_discovery_panel_css() -> str:
|
|
1935
1935
|
"""Return CSS for VM Discovery panel with prominent VNC button."""
|
|
1936
|
-
return
|
|
1936
|
+
return """
|
|
1937
1937
|
.vm-discovery-panel {
|
|
1938
1938
|
background: linear-gradient(135deg, rgba(16, 185, 129, 0.15) 0%, rgba(5, 150, 105, 0.05) 100%);
|
|
1939
1939
|
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
@@ -2262,12 +2262,12 @@ def _get_vm_discovery_panel_css() -> str:
|
|
|
2262
2262
|
cursor: pointer;
|
|
2263
2263
|
font-size: 0.85rem;
|
|
2264
2264
|
}
|
|
2265
|
-
|
|
2265
|
+
"""
|
|
2266
2266
|
|
|
2267
2267
|
|
|
2268
2268
|
def _get_vm_discovery_panel_html() -> str:
|
|
2269
2269
|
"""Return HTML for VM Discovery panel with prominent VNC button and loading states."""
|
|
2270
|
-
return
|
|
2270
|
+
return """
|
|
2271
2271
|
<div class="vm-discovery-panel" id="vm-discovery-panel">
|
|
2272
2272
|
<div class="vm-discovery-header">
|
|
2273
2273
|
<div class="vm-discovery-title">
|
|
@@ -2571,12 +2571,12 @@ def _get_vm_discovery_panel_html() -> str:
|
|
|
2571
2571
|
fetchVMs();
|
|
2572
2572
|
setInterval(fetchVMs, 10000);
|
|
2573
2573
|
</script>
|
|
2574
|
-
|
|
2574
|
+
"""
|
|
2575
2575
|
|
|
2576
2576
|
|
|
2577
2577
|
def _get_run_benchmark_panel_css() -> str:
|
|
2578
2578
|
"""Return CSS for the Run Benchmark configuration panel."""
|
|
2579
|
-
return
|
|
2579
|
+
return """
|
|
2580
2580
|
.run-benchmark-panel {
|
|
2581
2581
|
background: linear-gradient(135deg, rgba(16, 185, 129, 0.1) 0%, rgba(16, 185, 129, 0.05) 100%);
|
|
2582
2582
|
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
@@ -2742,12 +2742,12 @@ def _get_run_benchmark_panel_css() -> str:
|
|
|
2742
2742
|
color: #6ee7b7;
|
|
2743
2743
|
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
2744
2744
|
}
|
|
2745
|
-
|
|
2745
|
+
"""
|
|
2746
2746
|
|
|
2747
2747
|
|
|
2748
2748
|
def _get_run_benchmark_panel_html() -> str:
|
|
2749
2749
|
"""Return HTML for the Run Benchmark configuration panel."""
|
|
2750
|
-
return
|
|
2750
|
+
return """
|
|
2751
2751
|
<div class="run-benchmark-panel" id="run-benchmark-panel">
|
|
2752
2752
|
<div class="run-benchmark-header">
|
|
2753
2753
|
<div class="run-benchmark-title">
|
|
@@ -2828,7 +2828,7 @@ def _get_run_benchmark_panel_html() -> str:
|
|
|
2828
2828
|
|
|
2829
2829
|
<div class="run-benchmark-status" id="run-benchmark-status"></div>
|
|
2830
2830
|
</div>
|
|
2831
|
-
|
|
2831
|
+
"""
|
|
2832
2832
|
|
|
2833
2833
|
|
|
2834
2834
|
def _get_run_benchmark_panel_js(include_script_tags: bool = True) -> str:
|
|
@@ -2838,7 +2838,7 @@ def _get_run_benchmark_panel_js(include_script_tags: bool = True) -> str:
|
|
|
2838
2838
|
include_script_tags: If True, wrap JS in <script> tags. Set to False when
|
|
2839
2839
|
inserting into an existing script block.
|
|
2840
2840
|
"""
|
|
2841
|
-
js_code =
|
|
2841
|
+
js_code = """
|
|
2842
2842
|
// Handle model dropdown change to show/hide custom input
|
|
2843
2843
|
function handleModelChange() {
|
|
2844
2844
|
const select = document.getElementById('benchmark-model');
|
|
@@ -2958,9 +2958,9 @@ def _get_run_benchmark_panel_js(include_script_tags: bool = True) -> str:
|
|
|
2958
2958
|
document.addEventListener('DOMContentLoaded', function() {
|
|
2959
2959
|
updateTaskSelectionState();
|
|
2960
2960
|
});
|
|
2961
|
-
|
|
2961
|
+
"""
|
|
2962
2962
|
if include_script_tags:
|
|
2963
|
-
return f
|
|
2963
|
+
return f"<script>{js_code}</script>"
|
|
2964
2964
|
return js_code
|
|
2965
2965
|
|
|
2966
2966
|
|
|
@@ -3045,7 +3045,10 @@ def generate_benchmark_viewer(
|
|
|
3045
3045
|
task_results.append(task_result)
|
|
3046
3046
|
|
|
3047
3047
|
# Import shared header components from trainer
|
|
3048
|
-
from openadapt_ml.training.trainer import
|
|
3048
|
+
from openadapt_ml.training.trainer import (
|
|
3049
|
+
_get_shared_header_css,
|
|
3050
|
+
_generate_shared_header_html,
|
|
3051
|
+
)
|
|
3049
3052
|
|
|
3050
3053
|
# Generate HTML
|
|
3051
3054
|
html = _generate_benchmark_viewer_html(
|
|
@@ -3127,21 +3130,26 @@ def generate_multi_run_benchmark_viewer(
|
|
|
3127
3130
|
}
|
|
3128
3131
|
task_results.append(task_result)
|
|
3129
3132
|
|
|
3130
|
-
all_runs.append(
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3133
|
+
all_runs.append(
|
|
3134
|
+
{
|
|
3135
|
+
"run_name": metadata.get("run_name", benchmark_dir.name),
|
|
3136
|
+
"model_id": metadata.get("model_id", "unknown"),
|
|
3137
|
+
"created_at": metadata.get("created_at", ""),
|
|
3138
|
+
"benchmark_name": metadata.get("benchmark_name", ""),
|
|
3139
|
+
"dir_name": benchmark_dir.name, # For screenshot paths
|
|
3140
|
+
"summary": summary,
|
|
3141
|
+
"tasks": task_results,
|
|
3142
|
+
}
|
|
3143
|
+
)
|
|
3139
3144
|
|
|
3140
3145
|
if not all_runs:
|
|
3141
3146
|
return generate_empty_benchmark_viewer(output_path)
|
|
3142
3147
|
|
|
3143
3148
|
# Import shared header components from trainer
|
|
3144
|
-
from openadapt_ml.training.trainer import
|
|
3149
|
+
from openadapt_ml.training.trainer import (
|
|
3150
|
+
_get_shared_header_css,
|
|
3151
|
+
_generate_shared_header_html,
|
|
3152
|
+
)
|
|
3145
3153
|
|
|
3146
3154
|
# Generate HTML
|
|
3147
3155
|
html = _generate_multi_run_benchmark_viewer_html(
|
|
@@ -3167,7 +3175,10 @@ def generate_empty_benchmark_viewer(output_path: Path | str) -> Path:
|
|
|
3167
3175
|
output_path = Path(output_path)
|
|
3168
3176
|
|
|
3169
3177
|
# Import shared header components from trainer
|
|
3170
|
-
from openadapt_ml.training.trainer import
|
|
3178
|
+
from openadapt_ml.training.trainer import (
|
|
3179
|
+
_get_shared_header_css,
|
|
3180
|
+
_generate_shared_header_html,
|
|
3181
|
+
)
|
|
3171
3182
|
|
|
3172
3183
|
shared_header_css = _get_shared_header_css()
|
|
3173
3184
|
shared_header_html = _generate_shared_header_html("benchmarks")
|
|
@@ -3182,7 +3193,7 @@ def generate_empty_benchmark_viewer(output_path: Path | str) -> Path:
|
|
|
3182
3193
|
vm_discovery_css = _get_vm_discovery_panel_css()
|
|
3183
3194
|
vm_discovery_html = _get_vm_discovery_panel_html()
|
|
3184
3195
|
|
|
3185
|
-
html = f
|
|
3196
|
+
html = f"""<!DOCTYPE html>
|
|
3186
3197
|
<html lang="en">
|
|
3187
3198
|
<head>
|
|
3188
3199
|
<meta charset="UTF-8">
|
|
@@ -3331,7 +3342,7 @@ uv run python -m openadapt_ml.benchmarks.cli run-azure --workers 4</code>
|
|
|
3331
3342
|
</div>
|
|
3332
3343
|
</div>
|
|
3333
3344
|
</body>
|
|
3334
|
-
</html>
|
|
3345
|
+
</html>"""
|
|
3335
3346
|
|
|
3336
3347
|
output_path.write_text(html)
|
|
3337
3348
|
return output_path
|
|
@@ -3368,7 +3379,7 @@ def _generate_benchmark_viewer_html(
|
|
|
3368
3379
|
domains_json = json.dumps(domains)
|
|
3369
3380
|
|
|
3370
3381
|
# Generate HTML
|
|
3371
|
-
html = f
|
|
3382
|
+
html = f"""<!DOCTYPE html>
|
|
3372
3383
|
<html lang="en">
|
|
3373
3384
|
<head>
|
|
3374
3385
|
<meta charset="UTF-8">
|
|
@@ -3987,7 +3998,7 @@ def _generate_benchmark_viewer_html(
|
|
|
3987
3998
|
init();
|
|
3988
3999
|
</script>
|
|
3989
4000
|
</body>
|
|
3990
|
-
</html>
|
|
4001
|
+
</html>"""
|
|
3991
4002
|
|
|
3992
4003
|
return html
|
|
3993
4004
|
|
|
@@ -4039,7 +4050,7 @@ def _generate_multi_run_benchmark_viewer_html(
|
|
|
4039
4050
|
run_options_html = "\n".join(run_options)
|
|
4040
4051
|
|
|
4041
4052
|
# Generate HTML
|
|
4042
|
-
html = f
|
|
4053
|
+
html = f"""<!DOCTYPE html>
|
|
4043
4054
|
<html lang="en">
|
|
4044
4055
|
<head>
|
|
4045
4056
|
<meta charset="UTF-8">
|
|
@@ -4758,6 +4769,6 @@ def _generate_multi_run_benchmark_viewer_html(
|
|
|
4758
4769
|
init();
|
|
4759
4770
|
</script>
|
|
4760
4771
|
</body>
|
|
4761
|
-
</html>
|
|
4772
|
+
</html>"""
|
|
4762
4773
|
|
|
4763
4774
|
return html
|
|
@@ -13,7 +13,7 @@ def get_shared_header_css() -> str:
|
|
|
13
13
|
This CSS is used by both the Training Dashboard and the Viewer.
|
|
14
14
|
Any changes here will affect all dashboards consistently.
|
|
15
15
|
"""
|
|
16
|
-
return
|
|
16
|
+
return """
|
|
17
17
|
.unified-header {
|
|
18
18
|
display: flex;
|
|
19
19
|
align-items: center;
|
|
@@ -101,7 +101,7 @@ def get_shared_header_css() -> str:
|
|
|
101
101
|
color: var(--text-muted);
|
|
102
102
|
font-family: "SF Mono", Monaco, monospace;
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
"""
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
def generate_shared_header_html(
|
|
@@ -125,14 +125,14 @@ def generate_shared_header_html(
|
|
|
125
125
|
|
|
126
126
|
controls_section = ""
|
|
127
127
|
if controls_html or meta_html:
|
|
128
|
-
controls_section = f
|
|
128
|
+
controls_section = f"""
|
|
129
129
|
<div class="controls-section">
|
|
130
130
|
{controls_html}
|
|
131
|
-
{f'<span class="header-meta">{meta_html}</span>' if meta_html else
|
|
131
|
+
{f'<span class="header-meta">{meta_html}</span>' if meta_html else ""}
|
|
132
132
|
</div>
|
|
133
|
-
|
|
133
|
+
"""
|
|
134
134
|
|
|
135
|
-
return f
|
|
135
|
+
return f"""
|
|
136
136
|
<div class="unified-header">
|
|
137
137
|
<div class="nav-tabs">
|
|
138
138
|
<a href="dashboard.html" class="nav-tab {training_active}">Training</a>
|
|
@@ -141,7 +141,7 @@ def generate_shared_header_html(
|
|
|
141
141
|
</div>
|
|
142
142
|
{controls_section}
|
|
143
143
|
</div>
|
|
144
|
-
|
|
144
|
+
"""
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
def build_nav_links() -> list[tuple[str, str]]:
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import random
|
|
5
|
-
import sys
|
|
6
5
|
import time
|
|
7
6
|
from datetime import datetime
|
|
8
7
|
from pathlib import Path
|
|
@@ -92,13 +91,15 @@ class StubTrainingProvider:
|
|
|
92
91
|
|
|
93
92
|
elapsed = time.time() - self.start_time
|
|
94
93
|
|
|
95
|
-
self.losses.append(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
self.losses.append(
|
|
95
|
+
{
|
|
96
|
+
"epoch": self.current_epoch,
|
|
97
|
+
"step": self.current_step + 1,
|
|
98
|
+
"loss": loss,
|
|
99
|
+
"lr": 5e-5,
|
|
100
|
+
"time": elapsed,
|
|
101
|
+
}
|
|
102
|
+
)
|
|
102
103
|
|
|
103
104
|
self.current_step += 1
|
|
104
105
|
|
|
@@ -123,32 +124,37 @@ class StubTrainingProvider:
|
|
|
123
124
|
if not sample_path.exists():
|
|
124
125
|
# Try to copy from common capture location
|
|
125
126
|
import shutil
|
|
126
|
-
|
|
127
|
+
|
|
128
|
+
capture_screenshots = (
|
|
129
|
+
Path.home() / "oa/src/openadapt-capture/turn-off-nightshift/screenshots"
|
|
130
|
+
)
|
|
127
131
|
if capture_screenshots.exists():
|
|
128
132
|
sample_path.parent.mkdir(parents=True, exist_ok=True)
|
|
129
133
|
for img in capture_screenshots.glob("*.png"):
|
|
130
134
|
shutil.copy(img, sample_path)
|
|
131
135
|
break # Just copy the first one
|
|
132
136
|
|
|
133
|
-
self.evaluations.append(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
"
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
self.evaluations.append(
|
|
138
|
+
{
|
|
139
|
+
"epoch": self.current_epoch,
|
|
140
|
+
"sample_idx": 7, # Match the real training sample
|
|
141
|
+
"image_path": "screenshots/sample.png",
|
|
142
|
+
"human_action": {
|
|
143
|
+
"type": "click",
|
|
144
|
+
"x": 0.65,
|
|
145
|
+
"y": 0.65,
|
|
146
|
+
"text": None,
|
|
147
|
+
},
|
|
148
|
+
"predicted_action": {
|
|
149
|
+
"type": "click",
|
|
150
|
+
"x": 0.65 + random.uniform(-0.15, 0.15) * (1 - accuracy_boost),
|
|
151
|
+
"y": 0.65 + random.uniform(-0.15, 0.15) * (1 - accuracy_boost),
|
|
152
|
+
"raw_output": f"Thought: [Stub] Epoch {self.current_epoch} - analyzing screenshot to find target element. The model is learning to identify UI components.\nAction: CLICK(x=0.65, y=0.65)",
|
|
153
|
+
},
|
|
154
|
+
"distance": random.uniform(0.05, 0.2) * (1 - accuracy_boost),
|
|
155
|
+
"correct": random.random() > (0.5 - accuracy_boost),
|
|
156
|
+
}
|
|
157
|
+
)
|
|
152
158
|
|
|
153
159
|
def get_status(self) -> dict:
|
|
154
160
|
"""Return current training status.
|
|
@@ -161,7 +167,11 @@ class StubTrainingProvider:
|
|
|
161
167
|
|
|
162
168
|
# Determine status
|
|
163
169
|
if self.termination_status:
|
|
164
|
-
status =
|
|
170
|
+
status = (
|
|
171
|
+
"completed"
|
|
172
|
+
if self.termination_status == "auto_complete"
|
|
173
|
+
else self.termination_status
|
|
174
|
+
)
|
|
165
175
|
elif self.is_complete():
|
|
166
176
|
status = "completed"
|
|
167
177
|
else:
|
|
@@ -215,11 +225,17 @@ class StubTrainingProvider:
|
|
|
215
225
|
Args:
|
|
216
226
|
callback: Optional function called after each step with status dict
|
|
217
227
|
"""
|
|
218
|
-
self._log(
|
|
228
|
+
self._log(
|
|
229
|
+
f"[Stub] Starting simulated training: {self.epochs} epochs, {self.steps_per_epoch} steps/epoch"
|
|
230
|
+
)
|
|
219
231
|
self._log(f"[Stub] Output: {self.output_dir}")
|
|
220
|
-
self._log(
|
|
232
|
+
self._log(
|
|
233
|
+
f"[Stub] Step delay: {self.step_delay}s (total ~{self.epochs * self.steps_per_epoch * self.step_delay:.0f}s)"
|
|
234
|
+
)
|
|
221
235
|
if self.early_stop_loss > 0:
|
|
222
|
-
self._log(
|
|
236
|
+
self._log(
|
|
237
|
+
f"[Stub] Early stop: loss < {self.early_stop_loss} for {self.early_stop_patience} steps"
|
|
238
|
+
)
|
|
223
239
|
self._log("")
|
|
224
240
|
|
|
225
241
|
while not self.is_complete():
|
|
@@ -239,9 +255,13 @@ class StubTrainingProvider:
|
|
|
239
255
|
if self.early_stop_loss > 0 and loss < self.early_stop_loss:
|
|
240
256
|
self.consecutive_low_loss += 1
|
|
241
257
|
if self.consecutive_low_loss >= self.early_stop_patience:
|
|
242
|
-
self._log(
|
|
258
|
+
self._log(
|
|
259
|
+
f"\n[Stub] Auto-stopped: loss ({loss:.4f}) < {self.early_stop_loss} for {self.early_stop_patience} steps"
|
|
260
|
+
)
|
|
243
261
|
self.termination_status = "auto_low_loss"
|
|
244
|
-
self.termination_message =
|
|
262
|
+
self.termination_message = (
|
|
263
|
+
f"Loss reached {loss:.4f} (< {self.early_stop_loss})"
|
|
264
|
+
)
|
|
245
265
|
self.write_status()
|
|
246
266
|
break
|
|
247
267
|
else:
|
|
@@ -253,7 +273,9 @@ class StubTrainingProvider:
|
|
|
253
273
|
epoch = status["epoch"]
|
|
254
274
|
step = status["step"]
|
|
255
275
|
display_epoch = min(epoch + 1, self.epochs) # Cap at max for display
|
|
256
|
-
self._log(
|
|
276
|
+
self._log(
|
|
277
|
+
f" Epoch {display_epoch}/{self.epochs} | Step {step} | Loss: {loss:.4f}"
|
|
278
|
+
)
|
|
257
279
|
|
|
258
280
|
if callback:
|
|
259
281
|
callback(status)
|