opal-optimizer 0.3.6__tar.gz → 0.3.7__tar.gz
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.
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/CHANGELOG.md +8 -0
- {opal_optimizer-0.3.6/opal_optimizer.egg-info → opal_optimizer-0.3.7}/PKG-INFO +16 -8
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/README.md +15 -7
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/docs/GUIDE.md +5 -12
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/README.md +26 -13
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/cifar10_resnet.py +2 -3
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/diffusion_mnist.py +2 -3
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/goldfish_swahili/README.md +8 -12
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/gpt_small.py +2 -3
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/mnist_mlp.py +2 -3
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/modded_nanogpt/README.md +1 -1
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/train.py +1 -1
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/raev2_b/README.md +14 -22
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/sit_b2/README.md +1 -1
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/_version.py +1 -1
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/wrapper.py +4 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7/opal_optimizer.egg-info}/PKG-INFO +16 -8
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/LICENSE +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/MANIFEST.in +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/modded_nanogpt/opal.patch +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/README.md +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/records.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/resnet.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/splits.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/sit_b2/opal.patch +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/__init__.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/agent.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/__init__.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/_codex_client.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/_privacy.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/base.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/claude.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/codex.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/mailbox.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/unavailable.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/cli.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/context.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/defaults.json +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/defaults.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/estimate.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/hf.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/__init__.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/aggressive.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/audit.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/boundary.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/checkpoint.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/ddp.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/integrity.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/nested.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/neutral_analysis.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/precision.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/recovery.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/schedulers.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/setup.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/skip.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/taskfacts.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/waiting.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/programs.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/prompts/example_updater.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/prompts/neutral.md +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report_page.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report_privacy.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/results.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/schedule.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/summaries.py +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/SOURCES.txt +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/dependency_links.txt +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/entry_points.txt +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/requires.txt +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/top_level.txt +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/pyproject.toml +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/setup.cfg +0 -0
- {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/skills/train-with-agent/SKILL.md +0 -0
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.7 (2026-10-22)
|
|
4
|
+
|
|
5
|
+
- Documentation and examples only, apart from one printed notice; the optimizer math, the agent prompt and the agent's tools are unchanged.
|
|
6
|
+
- The README and the examples page report each task's newest OPAL run (RAEv2-B 3.19, Goldfish 77.25, LightningDiT-B/1 2.31) and no longer list older-system numbers.
|
|
7
|
+
- The examples page has a section on training without waiting for the agent (`blocking=False`), with the RAEv2-B official, blocking and non-blocking runs.
|
|
8
|
+
- The README says why long runs suit OPAL, with measured waiting times.
|
|
9
|
+
- `blocking="auto"` is no longer documented or offered by the example scripts. Using it prints that it is experimental and untested on real training runs.
|
|
10
|
+
|
|
3
11
|
## 0.3.6 (2026-10-22)
|
|
4
12
|
|
|
5
13
|
- Fixes from a from-scratch test of the install and the agent prompt; the optimizer math, the agent prompt and the agent's tools are unchanged.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opal-optimizer
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: A coding agent inside your training run, rewriting the optimizer while it trains
|
|
5
5
|
Author: Xingjian Bai, Jia-Hao Liang, Jayden Teoh, Vincent Sitzmann
|
|
6
6
|
License-Expression: MIT
|
|
@@ -149,16 +149,24 @@ Each number is one run, and each agent started from the task's own recipe:
|
|
|
149
149
|
| Example | Measure | Official recipe | Reactive optimizer |
|
|
150
150
|
|---|---|---|---|
|
|
151
151
|
| SiT-B/2, ImageNet 256, 400K updates | FID-50K ↓ | 35.7 (our evaluator) | 23.6 |
|
|
152
|
-
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.
|
|
153
|
-
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.
|
|
152
|
+
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.19 |
|
|
153
|
+
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.25 |
|
|
154
154
|
| modded-nanogpt record #36 | validation loss ↓ | 3.2781 | 3.2749 |
|
|
155
|
-
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 |
|
|
155
|
+
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 | 2.31 |
|
|
156
156
|
|
|
157
157
|
It does not always help: a run of modded-nanogpt on OPAL 0.2.0 ended at 3.2878, worse than record #36. Your
|
|
158
158
|
numbers may also differ from ours, because the agent can choose differently from one run to the next. The
|
|
159
159
|
[examples page](https://github.com/xingjian-bai/opal/blob/main/examples/README.md) has every number with its version, hardware, time and cost, the small CPU and
|
|
160
160
|
one-GPU scripts, and how to rerun each setting.
|
|
161
161
|
|
|
162
|
+
**Long runs suit it best.** An agent decision takes about the same time in any run, about 40 s on average in ours,
|
|
163
|
+
so the waiting adds up to a roughly fixed cost. In our runs of several hours it came to 0.49 h of 3.75 h on RAEv2-B,
|
|
164
|
+
0.67 h of 5.65 h on Goldfish and 1.05 h of 11.2 h on SiT-B/2. In short runs it dominates: our one-GPU scripts, which
|
|
165
|
+
set 50 decisions, took 27 to 31 min with the agent against 1 to 3 min without, and with `blocking=False` they ended
|
|
166
|
+
before the first answer arrived. The small scripts are a quick way to try OPAL. If you have the compute, use it on runs
|
|
167
|
+
of a few hours or more, where `blocking=False` also
|
|
168
|
+
[kept the result](https://github.com/xingjian-bai/opal/blob/main/examples/README.md#training-without-waiting-for-the-agent).
|
|
169
|
+
|
|
162
170
|
Our run records and final weights are on Hugging Face: [snow-leopard/opal-results](https://huggingface.co/datasets/snow-leopard/opal-results).
|
|
163
171
|
|
|
164
172
|
## How it works
|
|
@@ -179,8 +187,8 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
179
187
|
steps. If it raises an error, the run goes back to the previous program. A failure at its first step is undone
|
|
180
188
|
exactly when a copy of the parameters and optimizer state fits in `snapshot_limit_gb` (default 2); a later failure
|
|
181
189
|
is not undone, and the agent is told. Every version is kept in `programs/`.
|
|
182
|
-
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks
|
|
183
|
-
|
|
190
|
+
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks. That is
|
|
191
|
+
faster, and noisier.
|
|
184
192
|
- **What the agent sees.** Your goal sentence, the names and shapes of the parameters, the training losses, its own
|
|
185
193
|
analysis reports, and read-only copies of your training script and model code (`share_code=False` keeps them out).
|
|
186
194
|
Values you log are only recorded, unless you pass `show_agent=True`. With `validation=N` it also sees the
|
|
@@ -192,7 +200,7 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
192
200
|
|---|---|---|
|
|
193
201
|
| `decisions` | see right | How many times the agent is asked. Each time it may also keep everything as it is. If you do not set it, a run that waits for the agent asks at most as many times as keep the waiting under 4× the run's own training time (`opal estimate` shows the number), and at most 50, but at least once, even when one decision already waits longer than that. If you set it, that cap is off. A fifth of the decisions fall in the first 5% of the run; `schedule="uniform"` spaces them evenly. More in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
194
202
|
| `every` | 50 | Steps between checks: losses are read, a non-finite loss is caught, the analysis program runs. |
|
|
195
|
-
| `blocking` | `True` | `False`
|
|
203
|
+
| `blocking` | `True` | `False` to keep training while the agent thinks. |
|
|
196
204
|
| `max_cost_usd` | none | Stop asking the agent once it has spent this much. |
|
|
197
205
|
| `backend_options` | `{}` | `model=` (default `claude-opus-5-5`), `effort=` (default `high`) and `timeout=`. A failed agent turn is retried with growing pauses; an agent that is unavailable (login, usage limit, outage) is waited for, with no deadline unless you set `unavailable_timeout=`. Details in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
198
206
|
| `prompt` | `"neutral"` | The agent's instructions: the facts of the run and the protocol, with no recommended values. `"aggressive"` adds a review of every group's hyperparameters at each decision. You can also pass the path of your own template. |
|
|
@@ -219,7 +227,7 @@ Code CLI against a local mock.
|
|
|
219
227
|
|
|
220
228
|
## Status and limitations
|
|
221
229
|
|
|
222
|
-
v0.3.
|
|
230
|
+
v0.3.7, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
|
|
223
231
|
Multi-node, FSDP and DeepSpeed are not supported. Accelerate works if you wrap after `accelerator.prepare`, without
|
|
224
232
|
fp16 GradScaler or Accelerate's gradient accumulation; the HF Trainer works through `opal.hf.OpalTrainer`. Both are
|
|
225
233
|
tested on CPU. Lightning should work through `opt.observe(loss)` but we have not tried it. The agent can make a run
|
|
@@ -121,16 +121,24 @@ Each number is one run, and each agent started from the task's own recipe:
|
|
|
121
121
|
| Example | Measure | Official recipe | Reactive optimizer |
|
|
122
122
|
|---|---|---|---|
|
|
123
123
|
| SiT-B/2, ImageNet 256, 400K updates | FID-50K ↓ | 35.7 (our evaluator) | 23.6 |
|
|
124
|
-
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.
|
|
125
|
-
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.
|
|
124
|
+
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.19 |
|
|
125
|
+
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.25 |
|
|
126
126
|
| modded-nanogpt record #36 | validation loss ↓ | 3.2781 | 3.2749 |
|
|
127
|
-
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 |
|
|
127
|
+
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 | 2.31 |
|
|
128
128
|
|
|
129
129
|
It does not always help: a run of modded-nanogpt on OPAL 0.2.0 ended at 3.2878, worse than record #36. Your
|
|
130
130
|
numbers may also differ from ours, because the agent can choose differently from one run to the next. The
|
|
131
131
|
[examples page](https://github.com/xingjian-bai/opal/blob/main/examples/README.md) has every number with its version, hardware, time and cost, the small CPU and
|
|
132
132
|
one-GPU scripts, and how to rerun each setting.
|
|
133
133
|
|
|
134
|
+
**Long runs suit it best.** An agent decision takes about the same time in any run, about 40 s on average in ours,
|
|
135
|
+
so the waiting adds up to a roughly fixed cost. In our runs of several hours it came to 0.49 h of 3.75 h on RAEv2-B,
|
|
136
|
+
0.67 h of 5.65 h on Goldfish and 1.05 h of 11.2 h on SiT-B/2. In short runs it dominates: our one-GPU scripts, which
|
|
137
|
+
set 50 decisions, took 27 to 31 min with the agent against 1 to 3 min without, and with `blocking=False` they ended
|
|
138
|
+
before the first answer arrived. The small scripts are a quick way to try OPAL. If you have the compute, use it on runs
|
|
139
|
+
of a few hours or more, where `blocking=False` also
|
|
140
|
+
[kept the result](https://github.com/xingjian-bai/opal/blob/main/examples/README.md#training-without-waiting-for-the-agent).
|
|
141
|
+
|
|
134
142
|
Our run records and final weights are on Hugging Face: [snow-leopard/opal-results](https://huggingface.co/datasets/snow-leopard/opal-results).
|
|
135
143
|
|
|
136
144
|
## How it works
|
|
@@ -151,8 +159,8 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
151
159
|
steps. If it raises an error, the run goes back to the previous program. A failure at its first step is undone
|
|
152
160
|
exactly when a copy of the parameters and optimizer state fits in `snapshot_limit_gb` (default 2); a later failure
|
|
153
161
|
is not undone, and the agent is told. Every version is kept in `programs/`.
|
|
154
|
-
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks
|
|
155
|
-
|
|
162
|
+
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks. That is
|
|
163
|
+
faster, and noisier.
|
|
156
164
|
- **What the agent sees.** Your goal sentence, the names and shapes of the parameters, the training losses, its own
|
|
157
165
|
analysis reports, and read-only copies of your training script and model code (`share_code=False` keeps them out).
|
|
158
166
|
Values you log are only recorded, unless you pass `show_agent=True`. With `validation=N` it also sees the
|
|
@@ -164,7 +172,7 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
164
172
|
|---|---|---|
|
|
165
173
|
| `decisions` | see right | How many times the agent is asked. Each time it may also keep everything as it is. If you do not set it, a run that waits for the agent asks at most as many times as keep the waiting under 4× the run's own training time (`opal estimate` shows the number), and at most 50, but at least once, even when one decision already waits longer than that. If you set it, that cap is off. A fifth of the decisions fall in the first 5% of the run; `schedule="uniform"` spaces them evenly. More in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
166
174
|
| `every` | 50 | Steps between checks: losses are read, a non-finite loss is caught, the analysis program runs. |
|
|
167
|
-
| `blocking` | `True` | `False`
|
|
175
|
+
| `blocking` | `True` | `False` to keep training while the agent thinks. |
|
|
168
176
|
| `max_cost_usd` | none | Stop asking the agent once it has spent this much. |
|
|
169
177
|
| `backend_options` | `{}` | `model=` (default `claude-opus-5-5`), `effort=` (default `high`) and `timeout=`. A failed agent turn is retried with growing pauses; an agent that is unavailable (login, usage limit, outage) is waited for, with no deadline unless you set `unavailable_timeout=`. Details in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
170
178
|
| `prompt` | `"neutral"` | The agent's instructions: the facts of the run and the protocol, with no recommended values. `"aggressive"` adds a review of every group's hyperparameters at each decision. You can also pass the path of your own template. |
|
|
@@ -191,7 +199,7 @@ Code CLI against a local mock.
|
|
|
191
199
|
|
|
192
200
|
## Status and limitations
|
|
193
201
|
|
|
194
|
-
v0.3.
|
|
202
|
+
v0.3.7, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
|
|
195
203
|
Multi-node, FSDP and DeepSpeed are not supported. Accelerate works if you wrap after `accelerator.prepare`, without
|
|
196
204
|
fp16 GradScaler or Accelerate's gradient accumulation; the HF Trainer works through `opal.hf.OpalTrainer`. Both are
|
|
197
205
|
tested on CPU. Lightning should work through `opt.observe(loss)` but we have not tried it. The agent can make a run
|
|
@@ -32,9 +32,8 @@ The picture shows `blocking=False`. With the default `blocking=True`, every rank
|
|
|
32
32
|
- A new program takes over at the next update boundary. On one GPU this happens at once. In DDP, rank 0 announces
|
|
33
33
|
it through an asynchronous broadcast every `sync_every` updates on a separate gloo group. The default is 20.
|
|
34
34
|
Every rank swaps at the same update.
|
|
35
|
-
- With `blocking=True`, all ranks wait at every decision, as in our published runs. With `blocking=
|
|
36
|
-
|
|
37
|
-
the loss turns non-finite. Waiting uses the gloo group, so a long agent turn does not trip an NCCL timeout.
|
|
35
|
+
- With `blocking=True`, all ranks wait at every decision, as in most of our published runs. With `blocking=False`, they wait
|
|
36
|
+
only once when the loss turns non-finite. Waiting uses the gloo group, so a long agent turn does not trip an NCCL timeout.
|
|
38
37
|
- A new updater runs on trial for `trial_steps` updates, by default 20. If it raises on any rank, every rank returns
|
|
39
38
|
to the previous updater. The fallback is the last updater that passed its trial, or the starting one.
|
|
40
39
|
An updater replaced during its trial does not become the fallback.
|
|
@@ -252,8 +251,7 @@ asked so far.
|
|
|
252
251
|
| `max_cost_usd` | none | Stop asking once Claude Code reports this spend. Checked before each decision. The Claude backend also caps each decision at the remainder with `--max-budget-usd`, which can overshoot by one model call. `backend_options=dict(max_budget_usd=...)` caps each decision. |
|
|
253
252
|
| `every` | 50 | Updates between checks. Decisions and the non-finite check happen at checks. |
|
|
254
253
|
| `backend_options` | `{}` | `model=` defaults to `claude-opus-5-5`, `effort=` to `high`, as in the blog's runs. Another model or effort prints a warning at the start that the blog's results may differ. `timeout=` is seconds per decision, default 3600. `shell_timeout=` is seconds per agent shell command. `max_budget_usd=` caps each decision through Claude Code's `--max-budget-usd`. It can overshoot by one model call. `retries=` retries a failed turn, such as a tool crash, from the programs it started with. Pauses start at `backoff=15` s and double up to `backoff_max=600` s while `timeout` allows. `None`, the default, retries as often as that allows. `0` never retries. Each failure's error goes to the run's log, `decisions/NNN/attempts.jsonl` and the broker's log. The broker flag is `opal broker --retries N`. An unavailable agent has a separate wait, described below. `unavailable_timeout=` sets its deadline. |
|
|
255
|
-
| `blocking` | True | Training waits for each decision, as in our published runs. False keeps training.
|
|
256
|
-
| `max_lag_updates` | 50 | With `blocking="auto"`, the predicted lag in updates above which training waits. |
|
|
254
|
+
| `blocking` | True | Training waits for each decision, as in most of our published runs. False keeps training. |
|
|
257
255
|
| `share_code` | True | False keeps the training script and source files out of the agent's folder. |
|
|
258
256
|
| `schedule` | "front" | When decisions are asked. The learning-rate schedule is `scheduler`. "front" puts a fifth evenly over the first 5% of training and the rest evenly over the remainder. "uniform" asks every total_steps // decisions updates. Segments such as `[(0.05, 20), (1.0, 30)]` give an end fraction and count: here 20 in the first 5%, then 30 over the rest. Update numbers such as `[500, 1000, 5000]` give the exact updates. A list sets the count: omit `decisions` or make it agree, or `wrap` raises. Each decision moves to the next check, every `every` updates. Two on one check merge. None falls in the last `every` updates. The first log line gives the remaining count. |
|
|
259
257
|
| `show_next_decision` | on with the neutral and aggressive prompts | True gives the next scheduled decision's update in each message. False turns it off. |
|
|
@@ -295,15 +293,10 @@ No new decision is asked meanwhile. A failed turn, such as a crash, time limit o
|
|
|
295
293
|
instead of the unavailable-agent wait.
|
|
296
294
|
|
|
297
295
|
By default, `blocking=True` waits for the answer at each decision. Its edit takes effect from the update where the
|
|
298
|
-
decision was asked, and the agent's thinking adds to wall time. `blocking=False`
|
|
296
|
+
decision was asked, and the agent's thinking adds to wall time. `blocking=False` allows faster
|
|
299
297
|
runs. Without waiting, an answer takes effect answer time / time per update updates after the state the agent saw.
|
|
300
298
|
No new decision is asked while one is in progress, so fast runs may ask far fewer times.
|
|
301
299
|
|
|
302
|
-
`blocking="auto"` waits when the answer would arrive more than `max_lag_updates` updates late, by default 50.
|
|
303
|
-
It divides the median of the last 5 answer times by the time per update. That update time is the median over the last
|
|
304
|
-
5 check intervals, excluding pauses. It always waits at the first decision.
|
|
305
|
-
Each choice, its reason and its lag are in `events.jsonl` and the report.
|
|
306
|
-
|
|
307
300
|
## The report
|
|
308
301
|
|
|
309
302
|
Each run keeps `report.html` in its folder. It shows the loss with a tick per decision, your `opt.log` values,
|
|
@@ -415,7 +408,7 @@ schedule.
|
|
|
415
408
|
The broker keeps waiting. When `close()` returns, the final `report.html` is written.
|
|
416
409
|
It waits up to 30 s for pending Claude summaries.
|
|
417
410
|
- `blocking=True` is deterministic given the agent's answers. Replaying a final program with `opal.replay` is
|
|
418
|
-
deterministic too. With `blocking=False
|
|
411
|
+
deterministic too. With `blocking=False`, timing decides when an edit takes effect.
|
|
419
412
|
Two runs with the same answers can differ.
|
|
420
413
|
- To turn the agent off mid-run, resume with `backend="keep"` or start a fresh run with `opal.replay(...)`.
|
|
421
414
|
- For the Hugging Face Trainer, use `opal.hf.OpalTrainer` in place of `Trainer`.
|
|
@@ -6,26 +6,39 @@ number comes from.
|
|
|
6
6
|
|
|
7
7
|
## Results by setting
|
|
8
8
|
|
|
9
|
-
Each number is one run, and each agent started from the task's own recipe.
|
|
10
|
-
from the harness this package grew out of
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
| [
|
|
17
|
-
| [
|
|
18
|
-
| [
|
|
19
|
-
|
|
|
20
|
-
| LightningDiT-B/1, ImageNet 256, 160 epochs (200K updates), 8× H100 | FID-50K ↓, with guidance / without | 3.22 / 10.12 | – | – | 2.31 / 7.56 |
|
|
9
|
+
Each number is one run, and each agent started from the task's own recipe. Runs on OPAL 0.3 used the neutral prompt
|
|
10
|
+
and Opus 5.5 at effort high. SiT-B/2 comes from the harness this package grew out of. In all of these runs, training
|
|
11
|
+
paused at each decision while the agent answered, which is OPAL's default.
|
|
12
|
+
|
|
13
|
+
| Example | Measure | Official recipe | Reactive optimizer | Made with |
|
|
14
|
+
|---|---|---|---|---|
|
|
15
|
+
| [SiT-B/2](sit_b2/), ImageNet 256, 400K updates, 8× H100 | FID-50K ↓ | 35.7 with our evaluator (the SiT paper reports 33.0 with the ADM evaluator; Muon: 30.3) | 23.6 | earlier harness |
|
|
16
|
+
| [RAEv2-B](raev2_b/), ImageNet 256, 20 epochs, 8× H100 | FID-50K ↓ | 3.39 | 3.19 | OPAL 0.3 |
|
|
17
|
+
| [Goldfish 125M GPT](goldfish_swahili/), 1 GB of Swahili, 1× H100 | FLORES-200 bits ↓ | 79.37 | 77.25 | OPAL 0.3 |
|
|
18
|
+
| [modded-nanogpt record #36](modded_nanogpt/), 162M GPT, 8× H100 | validation loss ↓ | 3.2781 | 3.2749 (a small gain: the track assumes σ = 0.0013 per run) | OPAL 0.1.0 |
|
|
19
|
+
| LightningDiT-B/1, ImageNet 256, 160 epochs (200K updates), 8× H100 | FID-50K ↓, with guidance / without | 3.22 / 10.12 | 2.31 / 7.56 | OPAL 0.3 |
|
|
21
20
|
|
|
22
21
|
It does not always help. On modded-nanogpt, a heavily tuned benchmark, a run on OPAL 0.2.0 with the neutral prompt
|
|
23
22
|
ended at 3.2878, worse than record #36. Your numbers may also differ from ours, because the agent can make different
|
|
24
|
-
choices from one run to the next and hosted models change between versions. Still, most of our
|
|
23
|
+
choices from one run to the next and hosted models change between versions. Still, most of our runs on OPAL 0.3
|
|
25
24
|
ended ahead of the recipe they started from. The [blog post](https://xingjianbai.com/reactive-optimizers/) has more.
|
|
26
25
|
|
|
27
26
|
LightningDiT-B/1 has no folder here. Both runs used the upstream LightningDiT training code and its 64-epoch config, changed to model B/1, 200,000 updates and `use_qknorm: true` (without query-key normalization the official run diverged near update 194,000). The official recipe trains with AdamW at a constant learning rate of 2e-4. FID-50K uses 50,000 samples against the ADM reference statistics, Euler sampling with 250 steps and timestep shift 0.3; "with guidance" is the upstream setting, a guidance scale of 10 from t = 0.10 on. The LightningDiT paper reports FID-10K for this model, which is not comparable.
|
|
28
27
|
|
|
28
|
+
## Training without waiting for the agent
|
|
29
|
+
|
|
30
|
+
With `blocking=False`, training continues on the current programs while the agent answers, and an edit takes effect
|
|
31
|
+
when its answer arrives. One run on RAEv2-B, OPAL 0.3, 8× H100:
|
|
32
|
+
|
|
33
|
+
| RAEv2-B, 20 epochs | Official recipe | OPAL, training waits (default) | OPAL, `blocking=False` |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| FID-50K ↓ after 25,000 updates | 3.39 | 3.19 | 3.17 |
|
|
36
|
+
| Run time, including evaluations | 3.21 h | 3.75 h, of which 0.49 h waiting for the agent | 3.22 h |
|
|
37
|
+
| Decisions asked / that changed code | – | 50 / 6 | 43 / 3 |
|
|
38
|
+
| Agent cost | – | $13.30 | $9.71 |
|
|
39
|
+
|
|
40
|
+
Without waiting, fewer decisions are asked, because no new decision is asked while one is in progress.
|
|
41
|
+
|
|
29
42
|
## Small examples (CPU)
|
|
30
43
|
|
|
31
44
|
`mnist_mlp.py` trains an MLP on MNIST with AdamW and a cosine schedule for 5 epochs. It doubles as the install
|
|
@@ -65,9 +65,8 @@ parser.add_argument(
|
|
|
65
65
|
nargs="?",
|
|
66
66
|
const="true",
|
|
67
67
|
default="true",
|
|
68
|
-
choices=["true", "false"
|
|
69
|
-
help="true (default): training waits for each answer; false: it keeps going
|
|
70
|
-
"only when an answer would land late",
|
|
68
|
+
choices=["true", "false"],
|
|
69
|
+
help="true (default): training waits for each answer; false: it keeps going",
|
|
71
70
|
)
|
|
72
71
|
parser.add_argument("--max_cost_usd", type=float, default=15.0, help="stop asking the agent after this much spend")
|
|
73
72
|
parser.add_argument(
|
|
@@ -52,9 +52,8 @@ parser.add_argument(
|
|
|
52
52
|
nargs="?",
|
|
53
53
|
const="true",
|
|
54
54
|
default="true",
|
|
55
|
-
choices=["true", "false"
|
|
56
|
-
help="true (default): training waits for each answer; false: it keeps going
|
|
57
|
-
"only when an answer would land late",
|
|
55
|
+
choices=["true", "false"],
|
|
56
|
+
help="true (default): training waits for each answer; false: it keeps going",
|
|
58
57
|
) # opal
|
|
59
58
|
args = parser.parse_args()
|
|
60
59
|
|
|
@@ -10,17 +10,13 @@ split at the middle character. This follows upstream's `eval_code/flores_eval_go
|
|
|
10
10
|
|
|
11
11
|
| FLORES-200 bits ↓ (one run each) | Official recipe | Reactive optimizer |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
| after the last update | 79.37 | **77.
|
|
13
|
+
| after the last update | 79.37 | **77.25** |
|
|
14
14
|
|
|
15
|
-
In this run the agent ended
|
|
15
|
+
In this run the agent ended 2.12 bits below the official recipe.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The agent run used OPAL 0.3 with the neutral prompt: 51 decisions of which 11 changed the program,
|
|
18
18
|
$17.41, 5 h 39 min on one H100. This wall time includes evaluations and waiting for the agent.
|
|
19
19
|
|
|
20
|
-
The table above comes from the earlier training system OPAL grew from in October 2026.
|
|
21
|
-
It used Claude Code, Opus 5.5 at effort `high`, with that system's neutral prompt and 100 decisions every 793 updates.
|
|
22
|
-
Training paused at each decision.
|
|
23
|
-
|
|
24
20
|
## Official code and data
|
|
25
21
|
|
|
26
22
|
- Training uses [tylerachang/goldfish](https://github.com/tylerachang/goldfish) at `d4a518a` with
|
|
@@ -73,9 +69,9 @@ Then run it once with `backend="keep"` for a few hundred updates: its losses mus
|
|
|
73
69
|
| | Official recipe | Reactive optimizer |
|
|
74
70
|
|---|---|---|
|
|
75
71
|
| Hardware | 1× H100 80GB | 1× H100 80GB |
|
|
76
|
-
| Reported run time, including agent waits | 4.8 h | 5.
|
|
77
|
-
| Agent cost | – | $17.
|
|
78
|
-
| Decisions answered / that changed code | – |
|
|
79
|
-
| FLORES-200 bits | 79.374 | 77.
|
|
72
|
+
| Reported run time, including agent waits | 4.8 h | 5.65 h, of which 0.67 h waiting for the agent |
|
|
73
|
+
| Agent cost | – | $17.41 |
|
|
74
|
+
| Decisions answered / that changed code | – | 51 / 11 |
|
|
75
|
+
| FLORES-200 bits | 79.374 | 77.250 |
|
|
80
76
|
|
|
81
|
-
The official 4.8 h sums logged update windows, including evaluations. The agent time includes its 0.
|
|
77
|
+
The official 4.8 h sums logged update windows, including evaluations. The agent time includes its 0.67 h wait.
|
|
@@ -70,9 +70,8 @@ parser.add_argument(
|
|
|
70
70
|
nargs="?",
|
|
71
71
|
const="true",
|
|
72
72
|
default="true",
|
|
73
|
-
choices=["true", "false"
|
|
74
|
-
help="true (default): training waits for each answer; false: it keeps going
|
|
75
|
-
"only when an answer would land late",
|
|
73
|
+
choices=["true", "false"],
|
|
74
|
+
help="true (default): training waits for each answer; false: it keeps going",
|
|
76
75
|
)
|
|
77
76
|
parser.add_argument("--max_cost_usd", type=float, default=15.0, help="stop asking the agent after this much spend")
|
|
78
77
|
parser.add_argument(
|
|
@@ -51,9 +51,8 @@ parser.add_argument(
|
|
|
51
51
|
nargs="?",
|
|
52
52
|
const="true",
|
|
53
53
|
default="true",
|
|
54
|
-
choices=["true", "false"
|
|
55
|
-
help="true (default): training waits for each answer; false: it keeps going
|
|
56
|
-
"only when an answer would land late",
|
|
54
|
+
choices=["true", "false"],
|
|
55
|
+
help="true (default): training waits for each answer; false: it keeps going",
|
|
57
56
|
) # opal
|
|
58
57
|
args = parser.parse_args()
|
|
59
58
|
|
|
@@ -14,7 +14,7 @@ The gap is about 2.5 times that, from one run on each side. Record #36's publish
|
|
|
14
14
|
It appears in row 36 of the [track README on master](https://github.com/KellerJordan/modded-nanogpt/blob/master/records/track_3_optimization/README.md).
|
|
15
15
|
The README at the pinned commit below predates that row and lists only records 1 to 12.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The 3.2749 run used OPAL 0.1.0 with that version's default prompt, which this release
|
|
18
18
|
no longer ships: Claude Code (Opus 5.5, effort `high`), 100 decisions requested with checks every 10 updates (97 after
|
|
19
19
|
snapping, all answered), training paused at each decision. A later run on OPAL 0.2.0 with the neutral prompt (50 evenly
|
|
20
20
|
spaced decisions, 2 GPUs, a goal worded as reaching the target loss) ended at **3.2878, worse than record #36**.
|
|
@@ -65,7 +65,7 @@ def parse(argv=None):
|
|
|
65
65
|
p.add_argument("--decisions", type=int, default=30)
|
|
66
66
|
p.add_argument("--decision-schedule", choices=["uniform", "front"], default="uniform") # when the agent is asked
|
|
67
67
|
p.add_argument("--every", type=int, default=50, help="OPAL's check interval, in updates")
|
|
68
|
-
p.add_argument("--blocking", choices=["true", "false"
|
|
68
|
+
p.add_argument("--blocking", choices=["true", "false"], default="true")
|
|
69
69
|
p.add_argument("--prompt", default="neutral")
|
|
70
70
|
p.add_argument("--no-share-code", dest="share_code", action="store_false")
|
|
71
71
|
p.add_argument("--max-cost-usd", type=float, default=None, help="stop asking the agent after this much spend")
|
|
@@ -5,22 +5,15 @@ It uses representation-autoencoder latents from a DINOv3 ViT-L/16 encoder and Vi
|
|
|
5
5
|
Training ran for 25,020 updates with batch 1,024, or 20 epochs.
|
|
6
6
|
The score is FID-50K of samples from the EMA weights, without guidance.
|
|
7
7
|
|
|
8
|
-
| FID-50K ↓ (one run each) | Official recipe (our run) | Reactive optimizer
|
|
9
|
-
|
|
10
|
-
| after 25,000 updates | 3.385 | **3.
|
|
8
|
+
| FID-50K ↓ (one run each) | Official recipe (our run) | Reactive optimizer |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| after 25,000 updates | 3.385 | **3.192** |
|
|
11
11
|
|
|
12
12
|
The paper's figure for this setting is 3.37 (its Table 6, B at 20 epochs).
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
The agent run used OPAL 0.3 with the neutral prompt: 50 decisions of which 6 changed the program,
|
|
15
15
|
$13.30, 3 h 45 min on 8× H100. This wall time includes evaluations and waiting for the agent.
|
|
16
16
|
|
|
17
|
-
The table above comes from the earlier training system OPAL grew from in October 2026.
|
|
18
|
-
It used Claude Code, Opus 5.5 at effort `high`, with 100 decisions every 250 updates.
|
|
19
|
-
Training paused at each decision. The better run asked for efficiency:
|
|
20
|
-
"Make this diffusion-model training run more efficient by designing its optimization algorithm and controlling it
|
|
21
|
-
online ... The aim is a better model from the same 25,020 updates."
|
|
22
|
-
That system's neutral prompt ended worse than the official recipe. OPAL defaults to a neutral prompt.
|
|
23
|
-
|
|
24
17
|
## Official code
|
|
25
18
|
|
|
26
19
|
[nanovisionx/RAEv2](https://github.com/nanovisionx/RAEv2) at commit `8a0d238f8dc3b261aba98b217f6c79c0182e8e94`.
|
|
@@ -81,19 +74,18 @@ EXPERIMENT_NAME=raev2-b20-agent OPAL_MAX_COST_USD=20 \
|
|
|
81
74
|
|
|
82
75
|
## Our runs
|
|
83
76
|
|
|
84
|
-
| | Official recipe |
|
|
85
|
-
|
|
86
|
-
| Hardware | 8× H100 80GB | 8× H100 80GB |
|
|
87
|
-
| Reported run time, including agent waits | 3.
|
|
88
|
-
| Agent cost | – | $
|
|
89
|
-
| Decisions answered / that changed code | – |
|
|
90
|
-
| FID-50K at 25,000 | 3.385 | 3.
|
|
77
|
+
| | Official recipe | Reactive optimizer |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Hardware | 8× H100 80GB | 8× H100 80GB |
|
|
80
|
+
| Reported run time, including agent waits | 3.21 h | 3.75 h, of which 0.49 h waiting for the agent |
|
|
81
|
+
| Agent cost | – | $13.30 |
|
|
82
|
+
| Decisions answered / that changed code | – | 50 / 6 |
|
|
83
|
+
| FID-50K at 25,000 | 3.385 | 3.192 |
|
|
91
84
|
|
|
92
|
-
The
|
|
93
|
-
them. The 4.6 h agent time above includes its 1.4 h wait.
|
|
85
|
+
The official run's log records 3.21 h including evaluations and 2.65 h without them.
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
That code
|
|
87
|
+
Both runs used upstream code with our logging, launched as above.
|
|
88
|
+
That code is not in this repository.
|
|
97
89
|
|
|
98
90
|
We evaluated FID-50K every 5,000 updates during training, using ImageNet validation labels, 50 Euler steps,
|
|
99
91
|
no guidance and EMA weights. Scoring used torch-fidelity against `imagenet_256_fid_stats`, the default ImageNet 256
|
|
@@ -8,7 +8,7 @@ The score is FID-50K of samples from the EMA weights, without guidance.
|
|
|
8
8
|
|---|---|---|---|
|
|
9
9
|
| at 400K updates | 35.68 | 30.29 | **23.64** |
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The numbers above come from the earlier training system OPAL grew from in October 2026.
|
|
12
12
|
A training-side host connected to a broker running Claude Code, Opus 5.5 at effort `high`, with that system's prompt.
|
|
13
13
|
It made 94 decisions: 19 every 1,251 updates, then every 5,004. Training paused at each decision.
|
|
14
14
|
The wiring below is for OPAL 0.3.x. It has CPU checks only.
|
|
@@ -643,6 +643,10 @@ class AgentOptimizer(
|
|
|
643
643
|
f"{'auto-blocking' if self._auto else 'blocking' if self.blocking else 'non-blocking'}; "
|
|
644
644
|
f"backend {self._backend_label}"
|
|
645
645
|
)
|
|
646
|
+
if self._auto:
|
|
647
|
+
self._notice(
|
|
648
|
+
'blocking="auto" is experimental and untested on real training runs; use True (default) or False'
|
|
649
|
+
)
|
|
646
650
|
describe = getattr(self.worker.backend, "describe", None) if self.worker else None
|
|
647
651
|
if describe:
|
|
648
652
|
self._log(describe())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opal-optimizer
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: A coding agent inside your training run, rewriting the optimizer while it trains
|
|
5
5
|
Author: Xingjian Bai, Jia-Hao Liang, Jayden Teoh, Vincent Sitzmann
|
|
6
6
|
License-Expression: MIT
|
|
@@ -149,16 +149,24 @@ Each number is one run, and each agent started from the task's own recipe:
|
|
|
149
149
|
| Example | Measure | Official recipe | Reactive optimizer |
|
|
150
150
|
|---|---|---|---|
|
|
151
151
|
| SiT-B/2, ImageNet 256, 400K updates | FID-50K ↓ | 35.7 (our evaluator) | 23.6 |
|
|
152
|
-
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.
|
|
153
|
-
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.
|
|
152
|
+
| RAEv2-B, ImageNet 256, 20 epochs | FID-50K ↓ | 3.39 | 3.19 |
|
|
153
|
+
| Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.25 |
|
|
154
154
|
| modded-nanogpt record #36 | validation loss ↓ | 3.2781 | 3.2749 |
|
|
155
|
-
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 |
|
|
155
|
+
| LightningDiT-B/1, ImageNet 256, 160 epochs | FID-50K ↓ (with guidance) | 3.22 | 2.31 |
|
|
156
156
|
|
|
157
157
|
It does not always help: a run of modded-nanogpt on OPAL 0.2.0 ended at 3.2878, worse than record #36. Your
|
|
158
158
|
numbers may also differ from ours, because the agent can choose differently from one run to the next. The
|
|
159
159
|
[examples page](https://github.com/xingjian-bai/opal/blob/main/examples/README.md) has every number with its version, hardware, time and cost, the small CPU and
|
|
160
160
|
one-GPU scripts, and how to rerun each setting.
|
|
161
161
|
|
|
162
|
+
**Long runs suit it best.** An agent decision takes about the same time in any run, about 40 s on average in ours,
|
|
163
|
+
so the waiting adds up to a roughly fixed cost. In our runs of several hours it came to 0.49 h of 3.75 h on RAEv2-B,
|
|
164
|
+
0.67 h of 5.65 h on Goldfish and 1.05 h of 11.2 h on SiT-B/2. In short runs it dominates: our one-GPU scripts, which
|
|
165
|
+
set 50 decisions, took 27 to 31 min with the agent against 1 to 3 min without, and with `blocking=False` they ended
|
|
166
|
+
before the first answer arrived. The small scripts are a quick way to try OPAL. If you have the compute, use it on runs
|
|
167
|
+
of a few hours or more, where `blocking=False` also
|
|
168
|
+
[kept the result](https://github.com/xingjian-bai/opal/blob/main/examples/README.md#training-without-waiting-for-the-agent).
|
|
169
|
+
|
|
162
170
|
Our run records and final weights are on Hugging Face: [snow-leopard/opal-results](https://huggingface.co/datasets/snow-leopard/opal-results).
|
|
163
171
|
|
|
164
172
|
## How it works
|
|
@@ -179,8 +187,8 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
179
187
|
steps. If it raises an error, the run goes back to the previous program. A failure at its first step is undone
|
|
180
188
|
exactly when a copy of the parameters and optimizer state fits in `snapshot_limit_gb` (default 2); a later failure
|
|
181
189
|
is not undone, and the agent is told. Every version is kept in `programs/`.
|
|
182
|
-
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks
|
|
183
|
-
|
|
190
|
+
- **Training waits for the agent by default.** With `blocking=False` training keeps going while the agent thinks. That is
|
|
191
|
+
faster, and noisier.
|
|
184
192
|
- **What the agent sees.** Your goal sentence, the names and shapes of the parameters, the training losses, its own
|
|
185
193
|
analysis reports, and read-only copies of your training script and model code (`share_code=False` keeps them out).
|
|
186
194
|
Values you log are only recorded, unless you pass `show_agent=True`. With `validation=N` it also sees the
|
|
@@ -192,7 +200,7 @@ Our run records and final weights are on Hugging Face: [snow-leopard/opal-result
|
|
|
192
200
|
|---|---|---|
|
|
193
201
|
| `decisions` | see right | How many times the agent is asked. Each time it may also keep everything as it is. If you do not set it, a run that waits for the agent asks at most as many times as keep the waiting under 4× the run's own training time (`opal estimate` shows the number), and at most 50, but at least once, even when one decision already waits longer than that. If you set it, that cap is off. A fifth of the decisions fall in the first 5% of the run; `schedule="uniform"` spaces them evenly. More in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
194
202
|
| `every` | 50 | Steps between checks: losses are read, a non-finite loss is caught, the analysis program runs. |
|
|
195
|
-
| `blocking` | `True` | `False`
|
|
203
|
+
| `blocking` | `True` | `False` to keep training while the agent thinks. |
|
|
196
204
|
| `max_cost_usd` | none | Stop asking the agent once it has spent this much. |
|
|
197
205
|
| `backend_options` | `{}` | `model=` (default `claude-opus-5-5`), `effort=` (default `high`) and `timeout=`. A failed agent turn is retried with growing pauses; an agent that is unavailable (login, usage limit, outage) is waited for, with no deadline unless you set `unavailable_timeout=`. Details in the [guide](https://github.com/xingjian-bai/opal/blob/main/docs/GUIDE.md#cost-and-limits). |
|
|
198
206
|
| `prompt` | `"neutral"` | The agent's instructions: the facts of the run and the protocol, with no recommended values. `"aggressive"` adds a review of every group's hyperparameters at each decision. You can also pass the path of your own template. |
|
|
@@ -219,7 +227,7 @@ Code CLI against a local mock.
|
|
|
219
227
|
|
|
220
228
|
## Status and limitations
|
|
221
229
|
|
|
222
|
-
v0.3.
|
|
230
|
+
v0.3.7, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
|
|
223
231
|
Multi-node, FSDP and DeepSpeed are not supported. Accelerate works if you wrap after `accelerator.prepare`, without
|
|
224
232
|
fp16 GradScaler or Accelerate's gradient accumulation; the HF Trainer works through `opal.hf.OpalTrainer`. Both are
|
|
225
233
|
tested on CPU. Lightning should work through `opt.observe(loss)` but we have not tried it. The agent can make a run
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|