Skip to content

Commit 6ce7d24

Browse files
mattyoreillyclaude
andcommitted
Mechanical budgets and H2O-style stopping-rule names
- rename: patience -> stopping_rounds, stopping tolerance now named stopping_tolerance (H2O conventions); old meta names honoured on resume - max_steps / max_runtime: hard budgets enforced in code, not prompt - run_r_code refuses past the limit and tells the agent to finalise; warnings appear in tool results from 80% spend; refine/validate phases and repair rounds are skipped once exhausted; budget is disclosed in the system prompt when finite Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent dde8eb1 commit 6ce7d24

13 files changed

Lines changed: 254 additions & 79 deletions

File tree

R/app.R

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ atlas_app_ui <- function() {
6868
bslib::accordion_panel(
6969
"When to stop",
7070
shiny::numericInput(
71-
"patience", "Attempts in a row without improvement",
71+
"stopping_rounds", "Attempts in a row without improvement",
7272
value = 3, min = 1, max = 10, step = 1),
7373
shiny::numericInput(
74-
"min_improve", "Smallest improvement that counts (0.05 = 5%)",
74+
"stopping_tolerance", "Smallest improvement that counts (0.05 = 5%)",
7575
value = 0.05, min = 0, max = 1, step = 0.01)
7676
)
7777
),
@@ -232,8 +232,8 @@ atlas_app_server <- function(input, output, session) {
232232
atlas_app_worker,
233233
args = list(dir = dir, outcome = input$outcome,
234234
n_models = input$n_models, goal = input$goal,
235-
rules = input$rules, patience = input$patience,
236-
min_improve = input$min_improve,
235+
rules = input$rules, stopping_rounds = input$stopping_rounds,
236+
stopping_tolerance = input$stopping_tolerance,
237237
exclude = setdiff(setdiff(names(df), input$outcome),
238238
input$features)),
239239
stdout = "|", stderr = "2>&1"
@@ -493,7 +493,7 @@ atlas_load_results <- function(dir) {
493493
# stdout, which the app tails. With `instruction` set it resumes the existing
494494
# session and sends a follow-up instead of starting a fresh build.
495495
atlas_app_worker <- function(dir, outcome = NULL, n_models = 3, goal = NULL,
496-
rules = NULL, patience = 3, min_improve = 0.05,
496+
rules = NULL, stopping_rounds = 3, stopping_tolerance = 0.05,
497497
exclude = NULL, instruction = NULL) {
498498
ask_via_files <- function(question) {
499499
qf <- file.path(dir, "question.txt")
@@ -541,7 +541,7 @@ atlas_app_worker <- function(dir, outcome = NULL, n_models = 3, goal = NULL,
541541
s <- Atlas::AtlasSession$new(data, outcome, n_models = n_models, goal = goal,
542542
constraints = cons, dir = dir,
543543
on_ask = ask_via_files, display = "markdown",
544-
patience = patience, min_improve = min_improve,
544+
stopping_rounds = stopping_rounds, stopping_tolerance = stopping_tolerance,
545545
exclude = exclude,
546546
interject = interject_via_files)
547547
s$build(verbose = TRUE)

R/atlas.R

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
#' @param data A data.frame.
1212
#' @param outcome Name of the outcome column (string).
1313
#' @param n_models Maximum number of candidate models to build; the agent
14-
#' stops earlier when the stopping rules trigger (see `patience` and
15-
#' `min_improve`).
16-
#' @param patience Stopping rule: give up on an iteration (adding candidate
14+
#' stops earlier when the stopping rules trigger (see `stopping_rounds` and
15+
#' `stopping_tolerance`).
16+
#' @param stopping_rounds Stopping rule: give up on an iteration (adding candidate
1717
#' models, or a refinement loop like "keep improving the features") after
1818
#' this many consecutive attempts without improvement.
19-
#' @param min_improve Stopping rule: an attempt only counts as an improvement
19+
#' @param stopping_tolerance Stopping rule: an attempt only counts as an improvement
2020
#' if it beats the best validation metric so far by at least this relative
2121
#' fraction, between 0 and 1 — e.g. `0.05` for 5%.
2222
#' @param exclude Columns the models must not use — because they won't be
@@ -38,8 +38,8 @@
3838
#' @param refine After the winning algorithm is found (and constraints pass),
3939
#' keep iterating on its feature selection and engineering — one change per
4040
#' attempt, same validation scheme — until the stopping rules trigger
41-
#' (`patience` consecutive attempts without a relative gain of at least
42-
#' `min_improve`). The refined model lands in the results as
41+
#' (`stopping_rounds` consecutive attempts without a relative gain of at least
42+
#' `stopping_tolerance`). The refined model lands in the results as
4343
#' `<winner>_refined`, alongside the original.
4444
#' @param validate Produce reviewable validation output for the winning model
4545
#' (gain, calibration, grouped residuals, one-ways, PDPs) as interactive
@@ -55,9 +55,9 @@
5555
#' @param verbose Stream the agent's narration to the console.
5656
#' @param autonomous Run with no human in the loop: the agent states its plan
5757
#' and proceeds instead of waiting for approval, and never asks questions.
58-
#' Combine with a generous `n_models`/`patience` and `test_prop` for
58+
#' Combine with a generous `n_models`/`stopping_rounds` and `test_prop` for
5959
#' unattended experimentation runs — e.g.
60-
#' `atlas(d, "y", autonomous = TRUE, n_models = 10, patience = 8,
60+
#' `atlas(d, "y", autonomous = TRUE, n_models = 10, stopping_rounds = 8,
6161
#' test_prop = 0.2)` — where the agent iterates keep/discard experiments
6262
#' and the survivors are judged on the held-out test set at the end.
6363
#' @param test_prop Proportion of rows (0 to <1) to hold out as a final test
@@ -73,6 +73,12 @@
7373
#' Keeps long runs inside the context window and stops them paying to
7474
#' re-read their own history. `Inf` disables. The total cost of a session
7575
#' is reported as `cost` in the results and by `print()`.
76+
#' @param max_steps,max_runtime Hard budgets, mechanically enforced (unlike
77+
#' the stopping rules, which the agent applies itself): the maximum number
78+
#' of code executions and wall-clock seconds for the session. The agent is
79+
#' warned in tool results as a budget nears exhaustion; past the limit,
80+
#' code execution is refused and it must finalise from what it has. `Inf`
81+
#' (default) disables. Recommended for `autonomous` runs.
7682
#' @return An object of class `atlas`: list with `models` (named list of
7783
#' fitted models), `leaderboard` (data.frame of validation metrics),
7884
#' `test_leaderboard` (held-out test metrics, when `test_prop > 0`),
@@ -98,14 +104,16 @@
98104
atlas <- function(data, outcome, n_models = 3, goal = NULL,
99105
constraints = NULL, chat = NULL, dir = NULL,
100106
verbose = TRUE, max_fix_rounds = 2,
101-
patience = 3, min_improve = 0.05, refine = TRUE,
107+
stopping_rounds = 3, stopping_tolerance = 0.05, refine = TRUE,
102108
validate = TRUE, exclude = NULL,
103-
autonomous = FALSE, test_prop = 0, compact_at = 1e5) {
109+
autonomous = FALSE, test_prop = 0, compact_at = 1e5,
110+
max_steps = Inf, max_runtime = Inf) {
104111
session <- AtlasSession$new(data, outcome, n_models = n_models, goal = goal,
105112
constraints = constraints, chat = chat, dir = dir,
106-
patience = patience, min_improve = min_improve,
113+
stopping_rounds = stopping_rounds, stopping_tolerance = stopping_tolerance,
107114
exclude = exclude, autonomous = autonomous,
108-
test_prop = test_prop, compact_at = compact_at)
115+
test_prop = test_prop, compact_at = compact_at,
116+
max_steps = max_steps, max_runtime = max_runtime)
109117
session$build(verbose = verbose, max_fix_rounds = max_fix_rounds,
110118
refine = refine, validate = validate)
111119
session$results()

0 commit comments

Comments
 (0)