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.
Files changed (74) hide show
  1. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/CHANGELOG.md +8 -0
  2. {opal_optimizer-0.3.6/opal_optimizer.egg-info → opal_optimizer-0.3.7}/PKG-INFO +16 -8
  3. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/README.md +15 -7
  4. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/docs/GUIDE.md +5 -12
  5. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/README.md +26 -13
  6. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/cifar10_resnet.py +2 -3
  7. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/diffusion_mnist.py +2 -3
  8. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/goldfish_swahili/README.md +8 -12
  9. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/gpt_small.py +2 -3
  10. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/mnist_mlp.py +2 -3
  11. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/modded_nanogpt/README.md +1 -1
  12. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/train.py +1 -1
  13. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/raev2_b/README.md +14 -22
  14. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/sit_b2/README.md +1 -1
  15. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/_version.py +1 -1
  16. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/wrapper.py +4 -0
  17. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7/opal_optimizer.egg-info}/PKG-INFO +16 -8
  18. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/LICENSE +0 -0
  19. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/MANIFEST.in +0 -0
  20. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/modded_nanogpt/opal.patch +0 -0
  21. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/README.md +0 -0
  22. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/records.py +0 -0
  23. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/resnet.py +0 -0
  24. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/overfit/splits.py +0 -0
  25. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/examples/sit_b2/opal.patch +0 -0
  26. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/__init__.py +0 -0
  27. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/agent.py +0 -0
  28. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/__init__.py +0 -0
  29. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/_codex_client.py +0 -0
  30. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/_privacy.py +0 -0
  31. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/base.py +0 -0
  32. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/claude.py +0 -0
  33. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/codex.py +0 -0
  34. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/mailbox.py +0 -0
  35. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/backends/unavailable.py +0 -0
  36. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/cli.py +0 -0
  37. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/context.py +0 -0
  38. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/defaults.json +0 -0
  39. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/defaults.py +0 -0
  40. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/estimate.py +0 -0
  41. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/hf.py +0 -0
  42. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/__init__.py +0 -0
  43. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/aggressive.py +0 -0
  44. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/audit.py +0 -0
  45. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/boundary.py +0 -0
  46. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/checkpoint.py +0 -0
  47. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/ddp.py +0 -0
  48. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/integrity.py +0 -0
  49. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/nested.py +0 -0
  50. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/neutral_analysis.py +0 -0
  51. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/precision.py +0 -0
  52. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/recovery.py +0 -0
  53. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/schedulers.py +0 -0
  54. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/setup.py +0 -0
  55. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/skip.py +0 -0
  56. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/taskfacts.py +0 -0
  57. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/misc/waiting.py +0 -0
  58. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/programs.py +0 -0
  59. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/prompts/example_updater.py +0 -0
  60. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/prompts/neutral.md +0 -0
  61. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report.py +0 -0
  62. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report_page.py +0 -0
  63. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/report_privacy.py +0 -0
  64. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/results.py +0 -0
  65. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/schedule.py +0 -0
  66. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal/summaries.py +0 -0
  67. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/SOURCES.txt +0 -0
  68. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/dependency_links.txt +0 -0
  69. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/entry_points.txt +0 -0
  70. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/requires.txt +0 -0
  71. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/opal_optimizer.egg-info/top_level.txt +0 -0
  72. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/pyproject.toml +0 -0
  73. {opal_optimizer-0.3.6 → opal_optimizer-0.3.7}/setup.cfg +0 -0
  74. {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.6
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.10 (prompt asked for efficiency), 3.46 (neutral prompt); rerun on OPAL 0.3: 3.19 |
153
- | Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.60; rerun on OPAL 0.3: 77.25 |
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 | rerun on OPAL 0.3: 2.31 |
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, and
183
- `"auto"` waits only when an edit would land too late. Both are faster, and noisier.
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` or `"auto"` to keep training while the agent thinks. |
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.6, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
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.10 (prompt asked for efficiency), 3.46 (neutral prompt); rerun on OPAL 0.3: 3.19 |
125
- | Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.60; rerun on OPAL 0.3: 77.25 |
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 | rerun on OPAL 0.3: 2.31 |
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, and
155
- `"auto"` waits only when an edit would land too late. Both are faster, and noisier.
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` or `"auto"` to keep training while the agent thinks. |
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.6, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
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="auto"`, they wait
36
- at decisions whose answers would arrive late, as described below. With `blocking=False`, they wait only once when
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. "auto" waits at the first decision and when an answer would arrive more than `max_lag_updates` updates late. |
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` and `blocking="auto"` allow faster
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` or `"auto"`, timing decides when an edit takes effect.
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. The "Reactive optimizer" column comes
10
- from the harness this package grew out of (for modded-nanogpt, from OPAL 0.1.0). The last column is a rerun on OPAL
11
- 0.3 with the neutral prompt and Opus 5.5 at effort high. In all of these runs, training paused at each decision while
12
- the agent answered, which is OPAL's default.
13
-
14
- | Example | Measure | Official recipe | Reactive optimizer | Made with | On OPAL 0.3 |
15
- |---|---|---|---|---|---|
16
- | [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 | not rerun |
17
- | [RAEv2-B](raev2_b/), ImageNet 256, 20 epochs, 8× H100 | FID-50K ↓ | 3.39 | 3.10 when asked for efficiency; 3.46 with the neutral prompt | earlier harness | 3.19 |
18
- | [Goldfish 125M GPT](goldfish_swahili/), 1 GB of Swahili, 1× H100 | FLORES-200 bits ↓ | 79.37 | 77.60 | earlier harness | 77.25 |
19
- | [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 | not rerun |
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 reruns on OPAL 0.3
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", "auto"],
69
- help="true (default): training waits for each answer; false: it keeps going; auto: it waits "
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", "auto"],
56
- help="true (default): training waits for each answer; false: it keeps going; auto: it waits "
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.60** |
13
+ | after the last update | 79.37 | **77.25** |
14
14
 
15
- In this run the agent ended 1.77 bits below the official recipe.
15
+ In this run the agent ended 2.12 bits below the official recipe.
16
16
 
17
- On OPAL 0.3, the rerun scored 77.25: one run, neutral prompt, 51 decisions of which 11 changed the program,
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.75 h, of which 0.77 h waiting for the agent |
77
- | Agent cost | – | $17.79 |
78
- | Decisions answered / that changed code | – | 100 / 4 (decisions 1, 2, 9 and 11) |
79
- | FLORES-200 bits | 79.374 | 77.600 |
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 h wait.
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", "auto"],
74
- help="true (default): training waits for each answer; false: it keeps going; auto: it waits "
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", "auto"],
55
- help="true (default): training waits for each answer; false: it keeps going; auto: it waits "
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
- **Not rerun on OPAL 0.3 yet.** The 3.2749 run used OPAL 0.1.0 with that version's default prompt, which this release
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", "auto"], default="true")
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, asked for efficiency | Reactive optimizer, neutral prompt |
9
- |---|---|---|---|
10
- | after 25,000 updates | 3.385 | **3.101** | 3.455 (worse than official) |
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
- On OPAL 0.3, the rerun scored 3.192: one run, neutral prompt, 50 decisions of which 6 changed the program,
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 | Asked for efficiency | Neutral prompt |
85
- |---|---|---|---|
86
- | Hardware | 8× H100 80GB | 8× H100 80GB | 8× H100 80GB |
87
- | Reported run time, including agent waits | 3.1 h | 4.6 h, of which 1.4 h waiting for the agent | – |
88
- | Agent cost | – | $15.99 | $9.94 |
89
- | Decisions answered / that changed code | – | 100 / 16 (the last at decision 45) | 100 / 6 |
90
- | FID-50K at 25,000 | 3.385 | 3.101 | 3.455 |
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 earlier summary gives 3.1 h for the official run. Its log records 3.21 h including evaluations and 2.65 h without
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
- The earlier runs used upstream code with an optimizer hook and our logging, launched as above.
96
- That code and the earlier training system are not in this repository.
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
- Not rerun on OPAL 0.3. The numbers above come from the earlier training system OPAL grew from in October 2026.
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.
@@ -1,3 +1,3 @@
1
1
  """The package, build metadata and backend clients share this version."""
2
2
 
3
- __version__ = "0.3.6"
3
+ __version__ = "0.3.7"
@@ -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.6
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.10 (prompt asked for efficiency), 3.46 (neutral prompt); rerun on OPAL 0.3: 3.19 |
153
- | Goldfish 125M GPT, Swahili | FLORES-200 bits ↓ | 79.37 | 77.60; rerun on OPAL 0.3: 77.25 |
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 | rerun on OPAL 0.3: 2.31 |
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, and
183
- `"auto"` waits only when an edit would land too late. Both are faster, and noisier.
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` or `"auto"` to keep training while the agent thinks. |
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.6, under active development. Tested on one GPU and on DDP within one node (NCCL, eager and `torch.compile`).
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