ci: GPU matrix lane for interpretability SAE recipes (merge-first, presence-guarded)#1667
Conversation
…2_megatron, presence-guarded) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
RFR: workflow-only GPU CI lane for the interpretability SAE recipes (evo2), modeled on the evo2_megatron lane and presence-guarded so it merges to main first as a green no-op and auto-activates once #1622 lands — verified locally on H100s ( |
|
/ok to test 797bdb7 |
Avoid summoning the L4 GPU runner when there is no real work: - Presence + relevance now live in a cheap `gate` job on ubuntu-latest; the GPU `unit-tests` job runs only when `gate` says so. - merge_group ignores `paths`, so the gate diffs against origin/main and skips the GPU suite when no interpretability/evo2 files changed - previously every merge into main rebuilt the Evo2 1B. - No-op refs (recipe absent) no longer occupy a GPU runner at all. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The lane ran only recipes/evo2/tests, leaving the shared SAE engine (sparse_autoencoders/sae) — which every recipe depends on — untested. Add a separate step running pytest on ../../sae/tests (kernels, topk, streaming, steering, and the tensor-parallel math tests; 51 tests). Separate step (not appended to the recipe run) for distinct failure attribution. .ci_build.sh already installs the SAE lib editable, and the two suites import cleanly apart (sae/tests is a package; recipe tests is not), so no shared-session basename clash. Validated on a single GPU: 51 passed in ~2min. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
HAve we verified this works with the CI-supported runners? do we have a log of that anywhere? |
|
/ok to test 7b593ff |
- Drop the workflow-level `paths:` filter: it never matched the blossom mirror push, so the lane never triggered (only the repo-wide lane fired). - Move relevance-gating into the `gate` job for push (not just merge_group): diff vs origin/main so the L4 only spins up when relevant files changed. - Scope that diff to the evo2 SAE recipe + shared `sae` lib + evo2_megatron (not all of interpretability/**, which includes codonfm/esm2). - schedule (nightly) always runs the full suite. Validated via the #1670 test PR (L4 ran: 54 recipe + 51 sae-lib tests passed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
… updated #1667 workflow Re-validates the interp GPU lane after (a) moving the steering hook out of shared sae into recipes/evo2/, and (b) the #1667 trigger/relevance fix (no paths filter; gate diffs vs main, scoped to evo2 + sae + evo2_megatron). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
…ron base) Gate on recipes/evo2/ + recipes/evo2_megatron/ only (drop the shared sae/ glob so a sae change - shared with codonfm/esm2 - doesn't drag those devs through the evo2 build). Test recipes/evo2/tests/ only (drop the separate sae/tests run; sae needs its own lane). evo2_megatron stays in the gate because the SAE engine wraps its internal bionemo.evo2 APIs, so a megatron change can break the recipe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
… workflow Uses the finalized #1667 lane: gate on recipes/evo2/ + recipes/evo2_megatron/ (no sae), tests recipes/evo2/tests/ only. Re-validates the trigger + the steering move on a real L4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
Replaces the single evo2 job with a changed-dirs + matrix pattern (modeled on the repo-wide unit-tests-recipes.yml), scoped to interpretability/sparse_autoencoders/recipes/*: - Eligible = any interp recipe with its own .ci_build.sh. Today that's evo2; codonfm/esm2 auto-join once they add a .ci_build.sh + tests. Empty before #1622 lands -> whole lane is a green no-op (presence guard = has .ci_build.sh). - A change under a recipe runs that recipe; a change to shared sae/, this workflow, or the nightly runs ALL eligible recipes. Each recipe's own .ci_build.sh owns its build, so a codonfm/esm2 change never triggers the Evo2 megatron build (and vice-versa). Matrix-selection logic verified locally across 8 scenarios. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
#1667 matrix Uses the finalized #1667 lane (changed-dirs + per-recipe matrix over interpretability/sparse_autoencoders/recipes/*). On this PR the diff touches recipes/evo2/, so the matrix = [evo2] and the L4 runs its .ci_build.sh + pytest tests/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
|
/ok to test db3b0b1 |
@polinabinder1, there was an error processing your request: See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/ |
|
Reviewed with Polina in a meeting together, lgtm. |
|
/ok to test bf06765 |
The eligibility loop used `[ -f .ci_build.sh ] && echo`; when the last recipe dir (evo2, alphabetically) lacks a .ci_build.sh the short-circuit leaves exit 1, and `set -e` turns that into a job failure instead of an empty (green no-op) matrix. This bit the lane on its own branch — before #1622 lands, NO recipe has a .ci_build.sh, so ALL=[] and changed-dirs errored (the "nothing eligible" path was never exercised; #1670 validated it stacked with #1622, where evo2 IS eligible). Use `if`, which returns 0 when the body is skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
|
/ok to test 6399b96 |
What
A GPU CI matrix lane for the SAE interpretability recipes under
interpretability/sparse_autoencoders/recipes/*. Modeled on the repo-wideunit-tests-recipes.yml: a cheap ubuntuchanged-dirsjob discovers which interp recipes to test and emits a matrix; a per-recipeunit-testsjob runs each on an L4 (its own.ci_build.sh+pytest tests/).Which recipes are eligible
Any interp recipe that has its own
.ci_build.sh. Today that's evo2.codonfm/esm2have no.ci_build.sh/tests yet, so they're skipped until they add them — at which point they auto-join this lane, no workflow change needed. (This is also the presence guard: before the evo2 SAE recipe lands, #1622, nothing is eligible → the whole lane is a green no-op, so it can merge first.)What runs, when
…/recipes/<X>/**<X>saelib —…/sparse_autoencoders/sae/**schedule@ 09:00 UTC.ci_build.showns its build: evo2 compiles/installs the mbridgebionemo.evo2(megatron) stack; a future HF-native esm2 or custom codonfm builds its own thing, no megatron. So a codonfm/esm2 change never pays for the Evo2 megatron build — it runs only on an evo2 change (or ansae/nightly run, which tests every consumer, evo2 included).svcbionemo023/…pytorch26.04-py3-squashed, dockerhub-cached → cheap after first pull) — the megatron-capable base evo2 needs. A future HF-native recipe runs in that base but doesn't build megatron on top. If a recipe later wants a lighter image, the matrix can carry a per-recipeimage(like the repo-wide lane'smatrix.recipe.image) — not needed while evo2 is the only active recipe. Net: shared base image, per-recipe (megatron-or-not) build.EVO2_CKPT_DIR), never in CI.extract/trainscripts (no unit tests).Validation
Proven end-to-end on a real L4 via the #1670 test PR:
https://github.com/NVIDIA-BioNeMo/bionemo-recipes/actions/runs/28535969801 — the L4 built via
.ci_build.shand ran the evo2 recipe suite green (54 recipe tests passed). Thechanged-dirsmatrix logic was verified locally across 8 scenarios (per-recipe / sae-change / nightly / pre-#1622-empty). Trigger = a maintainer commenting/ok to test <sha>.