Skip to content

Commit 924e4e0

Browse files
polinabinder1claude
andcommitted
build(evo2-sae): cache the megatron build separately from SAE code (Docker layers)
The Dockerfile copied the whole sparse_autoencoders tree before the single `RUN .ci_build.sh`, so editing any SAE file invalidated that layer and re-ran the ~30-min megatron compile. Split into two layers via a phase arg on .ci_build.sh (env | install | all): - Layer 1: COPY recipes/evo2_megatron + the recipe's .ci_build.sh, `RUN .ci_build.sh env` — the expensive mbridge build, depends ONLY on evo2_megatron, so it stays cached across code edits. - Layer 2: COPY the SAE source, `RUN .ci_build.sh install` — the two editable pip installs (seconds). A code change now invalidates only this layer. CI still calls `.ci_build.sh` (no arg = all). Adds a per-Dockerfile .dockerignore to keep node_modules/dist/__pycache__/.venv out of the build context. Not docker-built here (no docker in this env) — bash syntax + phase routing verified; CI builds it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Polina Binder <pbinder@nvidia.com>
1 parent 913ba8c commit 924e4e0

3 files changed

Lines changed: 41 additions & 8 deletions

File tree

interpretability/sparse_autoencoders/recipes/evo2/.ci_build.sh

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,16 @@
99
#
1010
# The CI checkout must also provide the sibling recipe (recipes/evo2_megatron); it pulls its
1111
# own bionemo-core / bionemo-recipeutils deps from git, so nothing else is required locally.
12+
#
13+
# Phases (arg, default "all") — let the Dockerfile cache the expensive megatron build separately
14+
# from the cheap, frequently-changing SAE installs (so a code edit doesn't rebuild megatron):
15+
# env build the bionemo.evo2 (mbridge) env only (depends on recipes/evo2_megatron)
16+
# install install the SAE library + this recipe only (depends on the SAE source)
17+
# all both (CI / default)
1218
set -euo pipefail
1319

20+
phase="${1:-all}"
21+
1422
HERE="$(cd "$(dirname "$0")" && pwd)"
1523
SAE_LIB="$HERE/../../sae" # sparse_autoencoders/sae
1624
MEGATRON="$HERE/../../../../recipes/evo2_megatron"
@@ -27,10 +35,14 @@ fi
2735

2836
# 1. Build the bionemo.evo2 (mbridge) environment. Creates $MEGATRON/.venv with the
2937
# system-site torch/TE plus the full megatron stack.
30-
( cd "$MEGATRON" && bash .ci_build.sh )
38+
if [[ "$phase" == "env" || "$phase" == "all" ]]; then
39+
( cd "$MEGATRON" && bash .ci_build.sh )
40+
fi
3141

3242
# 2. Add the generic SAE library + this recipe into that venv. PIP_CONSTRAINT= clears the
3343
# TE pin constraint evo2_megatron sets (it must not block our pure-Python installs).
34-
source "$MEGATRON/.venv/bin/activate"
35-
PIP_CONSTRAINT= pip install -e "$SAE_LIB"
36-
PIP_CONSTRAINT= pip install -e "$HERE"
44+
if [[ "$phase" == "install" || "$phase" == "all" ]]; then
45+
source "$MEGATRON/.venv/bin/activate"
46+
PIP_CONSTRAINT= pip install -e "$SAE_LIB"
47+
PIP_CONSTRAINT= pip install -e "$HERE"
48+
fi

interpretability/sparse_autoencoders/recipes/evo2/Dockerfile

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,23 @@ ARG BASE_IMAGE=nvcr.io/nvidia/pytorch:26.04-py3
1313
FROM ${BASE_IMAGE}
1414

1515
WORKDIR /workspace
16-
# evo2_megatron pulls its bionemo-core / bionemo-recipeutils deps from git, so only these two
17-
# trees are needed in the build context.
18-
COPY interpretability/sparse_autoencoders interpretability/sparse_autoencoders
16+
# Two layers so editing SAE code doesn't rebuild the ~30-min megatron stack:
17+
#
18+
# 1. Expensive, rarely-changing: build the bionemo.evo2 (mbridge) env. Depends ONLY on
19+
# recipes/evo2_megatron (which pulls its bionemo-core/recipeutils deps from git), so this layer
20+
# stays cached across SAE code edits. Copy just the recipe's .ci_build.sh to drive the build.
1921
COPY recipes/evo2_megatron recipes/evo2_megatron
22+
COPY interpretability/sparse_autoencoders/recipes/evo2/.ci_build.sh \
23+
interpretability/sparse_autoencoders/recipes/evo2/.ci_build.sh
24+
WORKDIR /workspace/interpretability/sparse_autoencoders/recipes/evo2
25+
RUN bash .ci_build.sh env
2026

27+
# 2. Cheap, frequently-changing: add the SAE library + this recipe, install editable. A code
28+
# change invalidates only this layer (the two pip installs, seconds), not the build above.
29+
WORKDIR /workspace
30+
COPY interpretability/sparse_autoencoders interpretability/sparse_autoencoders
2131
WORKDIR /workspace/interpretability/sparse_autoencoders/recipes/evo2
22-
RUN bash .ci_build.sh
32+
RUN bash .ci_build.sh install
2333

2434
# Default to the built venv so `docker run … pytest tests/` (or importing Evo2SAE) just works.
2535
ENV VIRTUAL_ENV=/workspace/recipes/evo2_megatron/.venv
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Per-Dockerfile ignore (BuildKit uses <dockerfile>.dockerignore when present). Paths are relative
2+
# to the build context (the repo root). Keep generated/heavy trees out of the context so they
3+
# neither bloat the upload nor bust the COPY cache when they change locally.
4+
**/node_modules/
5+
**/dist/
6+
**/.vite/
7+
**/__pycache__/
8+
**/*.pyc
9+
**/.venv/
10+
**/.pytest_cache/
11+
.git/

0 commit comments

Comments
 (0)