Skip to content

Non-agentic evals: parameterize evalchemy sbatch paths by $USER - #85

Open
mrinal-bespoke wants to merge 5 commits into
open-thoughts:mainfrom
mrinal-bespoke:pr/a-evalchemy-user-paths
Open

Non-agentic evals: parameterize evalchemy sbatch paths by $USER#85
mrinal-bespoke wants to merge 5 commits into
open-thoughts:mainfrom
mrinal-bespoke:pr/a-evalchemy-user-paths

Conversation

@mrinal-bespoke

Copy link
Copy Markdown

Problem

The four evalchemy sbatch scripts hardcode /leonardo_work/AIFAC_5C0_290/bfeuer00/...
for every path — conda root, the evalchemy-marin clone, nltk data, HF cache, JIT
caches, and the output root. A second operator cannot run a non-agentic eval at all.

Change

Split paths by whether they are read-only shared runtime or per-user writable:

  • Read-only runtime (conda env, evalchemy-marin clone, nltk data) — use the
    submitter's own copy if present, else fall back to the shared bfeuer00 one. A new
    operator does not have to duplicate a ~20 GB conda env to run an eval.
  • Writable (HF_HOME/HF_HUB_CACHE, CACHE_ROOT, OUT_ROOT) — always per-user.
  • #SBATCH --output uses SLURM's %u.

Each is ${VAR:-<default>}, so an explicit env var still wins.

This is a no-op for the original operator: with USER=bfeuer00 every path resolves
to the same byte-identical string as before.

Notable fixes

Conda fallback must validate the env, not the root. Testing only for a miniforge3
directory is not enough — an operator can have a partial install (e.g. otagent but not
evalchemy-marin) and would then fail with EnvironmentNameNotFound: evalchemy-marin
instead of falling back to the shared root. The check is now for
<root>/envs/evalchemy-marin.

--output directories must pre-exist. SLURM opens the log file before the job script
runs and does not create intermediate directories, so a new operator gets an instant
"Unable to open file" that reads like a launch bug rather than a missing mkdir. The script
cannot self-heal this — its own mkdir -p runs far too late — so the one-time setup is
documented inline next to each path.

Reviewer note

With HF_HUB_OFFLINE=1 and HF_HOME now per-user, a new operator's cache starts empty,
so models will not resolve until they pre-cache or symlink them in. That is inherent to
making the cache writable (one shared HF cache across operators is not safe), and the
symlink workaround is documented in the diff — but it is a genuine behaviour change for a
new user.

Testing

  • bash -n clean on all four scripts.
  • Path resolution simulated for three cases: original operator (all-own, byte-identical),
    new operator (shared fallback for runtime, per-user for writable), and partial install
    (correctly prefers shared over an incomplete own root).
  • Comments-only in the final commit.

🤖 Generated with Claude Code

mrinal-bespoke and others added 5 commits August 4, 2026 11:58
…ed runtime falls back)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… prior commit)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…st the miniforge3 root

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The --output paths are now $USER-scoped via SLURM's %u. That is correct, but
SLURM opens the log file BEFORE the job script runs and does not create
intermediate directories, so a new operator whose
/leonardo_work/AIFAC_5C0_290/$USER/experiments/delphi-eval/ does not exist yet
gets an instant job failure ('Unable to open file') that reads like a launch bug
rather than a missing mkdir.

The job script cannot self-heal this -- its own mkdir -p runs far too late. So
document the one-time setup inline, next to the path it applies to, including
the qwen3-baseline subdirectory that only that sbatch needs.

No behaviour change: comments only. Byte-identical for the original operator,
whose directories already exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…l checkout

Review catch (P2). _OTA_REPO defaulted to $WORK/$USER/code/OpenThoughts-Agent,
which only holds for operators who cloned at exactly that path. Anyone else fell
through to the BASH_SOURCE branch — which under SLURM is the
/var/spool/slurmd/jobNNN/ copy — so it re-created the very ExitCode-127 'No such
file or directory' that the comment three lines above says this block exists to
prevent.

The blast radius was wider than the exec target. _OTA_REPO also feeds
CHAT_TEMPLATE_OVERRIDE (delphi_eval) and THINK_TEMPLATE
(delphi_rl_think_eval), so a noncanonical checkout silently pointed lm-eval at a
missing chat template instead of reporting that the repo was not found.

Resolve by PROBING for a marker file (eval/evalchemy/evalchemy_eval.sbatch),
taking the first candidate that actually contains it:

  1. OTAGENT_REPO_DIR              explicit override
  2. $WORK/$USER/code/...          canonical per-user checkout
  3. SLURM_SUBMIT_DIR + parents    where the operator actually ran sbatch
  4. shared bfeuer00 checkout      same borrow pattern as conda/evalchemy-marin
  5. script dir + parents          interactive / non-SLURM only

Walking up from SLURM_SUBMIT_DIR matters because operators typically submit from
a subdirectory of the repo, not its root.

If nothing matches, fail LOUDLY listing every candidate tried, instead of
exec'ing a nonexistent path and leaving a bare 127.

Unchanged for the original operator: candidate 2 hits first when USER=bfeuer00.

Verified: canonical operator, noncanonical checkout via SLURM_SUBMIT_DIR,
noncanonical with only the spool dir (falls back to shared), explicit override,
and the nothing-found path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant