feat(evo2-sae): streaming smoke test (producer/consumer) + Lepton convergence config#1668
feat(evo2-sae): streaming smoke test (producer/consumer) + Lepton convergence config#1668polinabinder1 wants to merge 6 commits into
Conversation
…vergence config Evo2 analogue of the ESM2 SAE smoke (#1663): Megatron predict forward passes feed activations into a bounded queue (sae.streaming); the SAE Trainer consumes in-process, no activation store on disk. Self-contained like the ESM2 smoke - the 1B checkpoint is fetched by identifier and converted in-job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
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 |
…ut-dim GPU-validated on Evo2-1B (1-GPU H100); baseline smoke unchanged (loss 0.9407). #1 --init-pre-bias hard-crashed: it ran a *second* Evo2 `predict` pass to sample activations, but `predict` leaves Megatron global state initialized with no teardown, so the second pass died with "num microbatches calculator is already initialized". Remove the broken second-pass init and fail fast with a clear NotImplementedError pointing at --no-init-pre-bias. Single-pass init (sample the first rows off the one training stream) tracked as a follow-up. #4 Guard --input-dim against the layer's true residual width on the first streamed chunk, so a mismatch fails clearly instead of as an opaque matmul error in the encoder. Add tests/test_streaming.py: CPU guards (fake predict module, no GPU/Megatron) for the --input-dim mismatch, happy-path streaming, predict-failure propagation, and the --init-pre-bias rejection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds `evo2_sae_smoke` to the workflow_dispatch model_config options so the Lepton 1B streaming smoke (config already in this PR at ci/lepton/.../recipes/evo2_sae_smoke.yaml) can be launched manually. NOT added to the biweekly schedule matrix: it's a liveness smoke (20 steps, log_to_wandb/log_to_kratos=false), so it collects no convergence metrics and doesn't belong on the convergence cron. (Because kratos is off, the convergence_tests.sh wrapper isn't invoked, so the wandb_dir wrapper bug is moot here — it'd only matter for a real telemetry-on convergence run.) Config composition verified locally (hydra compose over base.yaml resolves). The 1B streaming run itself is validated on H100 (see PR description); the actual Lepton submission is exercised by a first workflow_dispatch post-merge. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
Signed-off-by: polinabinder1 <pbinder@nvidia.com>
…12.4-driver nodes) The workspace's convergence nodes (e.g. yo-bom-lepton-001) run an NVIDIA driver on CUDA 12.4. The evo2 GPU-lane image (svcbionemo…pytorch26.04-py3-squashed) needs driver >= 12.8, so torch.cuda.is_available() is False there and Evo2 predict aborts with "Inference requires CUDA" (predict.py:236) — the first dispatch failed exactly this way after building + converting the checkpoint. Point the smoke at the base NGC image (nvcr.io/nvidia/pytorch:26.02-py3, what the other convergence recipes use), whose cuda-compat libs run on the 12.4 driver. Megatron/TE are added in-job by .ci_build.sh, so the base image suffices. This is also the only stack the recipe is validated on (system torch is nv26.02). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: polinabinder1 <pbinder@nvidia.com>
| @@ -0,0 +1,208 @@ | |||
| # @package _global_ | |||
| defaults: | |||
There was a problem hiding this comment.
Make sure not redundant to base
There was a problem hiding this comment.
Done — removed container (identical 26.02 image), node_group, and mount_from; all inherited from /base.
| # on those nodes with "Inference requires CUDA". Megatron/TransformerEngine are | ||
| # added in-job by .ci_build.sh (checkout_script), so this base image is enough. | ||
| ############################################################ | ||
| container: |
There was a problem hiding this comment.
these are in the base config so can remove
There was a problem hiding this comment.
Done — removed; inherited from /base.
| device_type: gpu | ||
| num_devices: 1 | ||
| gpu_type: h100-sxm | ||
| resource_shape: gpu.h100-sxm |
There was a problem hiding this comment.
bump to 2 gpus: (resource shape needs to change for the)
There was a problem hiding this comment.
Done — num_devices: 2 + templated resource_shape (→ gpu.2xh100-sxm). Implemented as a producer/consumer split rather than data-parallel: the Evo2 producer runs on cuda:0 and the SAE consumer trains on cuda:1 (activations cross as CPU tensors via the queue), so it stays one predict rank / --dp-size 1. Validated on Lepton — the job ran on gpu.2xh100-sxm and hit SMOKE OK, loss identical to the 1-GPU run.
| framework: sae | ||
| precision: bf16 | ||
| te_enabled: true | ||
| fp8_enabled: false |
There was a problem hiding this comment.
we don't need these markers for these tests (these are for TE recupes)
There was a problem hiding this comment.
Done — removed te_enabled/fp8_enabled/extras; the run_script never references them and the launcher does not either, so it is launcher-safe.
| fi | ||
| # Builds evo2_megatron's venv (bionemo.evo2 / predict) + installs sae + evo2_sae on top. | ||
| cd interpretability/sparse_autoencoders/recipes/evo2 | ||
| bash .ci_build.sh |
There was a problem hiding this comment.
Docker in Lepton must run on a privileged node (make sure we have that set)
There was a problem hiding this comment.
It looks like instead we actually are loading a checkpoint, so we don't need docker:
Successfully installed evo2-sae-0.1.0 fastapi-0.139.0 starlette-1.3.1 uvicorn-0.49.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
Reusing existing MBridge checkpoint: /data/interpretability/sae/evo2_smoke/outputs/evo2_1b_mbridge/iter_0000001
Chunked 4 sequences -> 4 chunks (16,384 bp) at window=8192
Using device: cuda
SAE: topk, input_dim=1920, hidden_dim=15360
There was a problem hiding this comment.
There was a problem hiding this comment.
It looks like the ci build actually comes from this: https://github.com/NVIDIA-BioNeMo/bionemo-recipes/blob/main/recipes/evo2_megatron/.ci_build.sh
Thus, if you're able to load a mbridge checkpoint and run evo2 inference (like what seems to be done here), maybe your other scripts don't need Docker to run? We don't use Docker here, can you double-check.
There was a problem hiding this comment.
Confirmed — no Docker. checkout_script runs recipes/evo2_megatron/.ci_build.sh and the run loads an MBridge checkpoint (the log you pasted is that path). Separately hardened the forward with a bf16 autocast wrap so an fp32_residual_connection=true ckpt override does not trip the TE dtype assertion.
|
/ok to test aabc352 |
|
Run logs: Which triggers runs on Lepton. See example run: https://dashboard.dgxc-lepton.nvidia.com/workspace/vfco61g2/compute/jobs/detail/evo2-sae-1b-smoke-59w4/replicas/list#/job/evo2-sae-1b-smoke-59w4/logs |
…eaming Lepton config (evo2_sae_smoke.yaml): - Dedupe against /base: drop container (identical 26.02 image), node_group, mount_from. - Drop te_enabled/fp8_enabled/extras (TE-recipe markers; the run_script never uses them). - num_devices: 2 + templated resource_shape (-> gpu.2xh100-sxm), matching sibling recipes. train_streaming.py: - 2-GPU as a producer/consumer pipeline (NOT data-parallel): the Evo2 producer runs on cuda:0 and the SAE consumer trains on cuda:1 when a 2nd GPU is visible, so the stages stop contending for one device. --dp-size stays 1; --device overrides. - Wrap predict.main() in bf16 autocast: robustness for fp32_residual_connection=true checkpoints (e.g. a 7B EVO2_CKPT_DIR override) that otherwise trip a TransformerEngine param/input dtype assertion. No-op for the default 1b-8k-bf16 (bf16-residual) path. - Add two missing docstrings (ruff D107/D102). Validated on 2xH100 with the real 1b-8k-bf16 checkpoint: producer cuda:0 / consumer cuda:1, trains, writes checkpoint_final.pt (exit 0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Evo2 analogue of the ESM2 SAE smoke (#1663). Adds a producer/consumer streaming path — Megatron
predictforward passes feed activations into a bounded queue (sae.streaming); the SAETrainerconsumes them in-process, no activation store on disk. Self-contained like the ESM2 smoke: the 1B checkpoint is fetched by identifier and converted in-job (nothing pre-staged).2 GPUs (producer/consumer, not data-parallel): when a second GPU is visible, the Evo2 producer runs its forwards on
cuda:0and the SAE consumer trains oncuda:1, so the two stages run concurrently instead of contending for one device (num_devices: 2,resource_shape → gpu.2xh100-sxm). It stays onepredictrank —--nproc_per_node 1,--dp-size 1; activations cross the boundary as CPU tensors via the queue, so no NCCL/DDP.Files
scripts/train_streaming.py—Evo2ActivationProducerbridgespredict's per-batch callback to a pull-generator (daemon thread + queue); SAE trains off the stream. Auto-places the SAE consumer on a 2nd GPU when available; wraps thepredictforward in bf16 autocast (see Robustness).scripts/prepare_1b_checkpoint.py—bionemo_load("evo2/1b-8k-bf16")→run_nemo2_to_mbridge(idempotent). HonorsEVO2_CKPT_DIR.ci/lepton/model_convergence/configs/recipes/evo2_sae_smoke.yaml+convergence-tests.yml— 2×H100 convergence config, plus theevo2_sae_smokedispatch option.Review feedback addressed
/base— droppedcontainer(identical 26.02 image),node_group,mount_from.te_enabled/fp8_enabled/extras) — the run_script never references them (verified the launcher doesn't either).gpu.2xh100-sxm).checkout_scriptrunsevo2_megatron/.ci_build.shand loads an MBridge checkpoint; nothing uses Docker.Robustness
--input-dimis validated against the layer's true residual width on the first streamed chunk — a mismatch fails with a clear message instead of an opaque matmul error inside the SAE encoder.predictforward — Evo2's params are bf16 andpredict's minimal-arg path sets no autocast region, so afp32_residual_connection=truecheckpoint (e.g. a 7BEVO2_CKPT_DIRoverride) would otherwise trip a TransformerEngine param/input dtype assertion. Harmless no-op on the default1b-8k-bf16(bf16-residual) path.--init-pre-biasis scoped out of the streaming path and fails fast pointing at--no-init-pre-bias(it would require a second Evo2predictpass, which doesn't compose with Megatron's process-global init). A single-pass implementation is a natural follow-up.Validation
dead_latents 0%,checkpoint_final.ptwritten.cuda:0/ consumer→cuda:1and trains to a loss identical to the single-GPU run to 4 decimals — the split changes device placement, not the math.tests/test_streaming.py, fakepredictmodule — no GPU/Megatron): queue semantics (backpressure, sentinel, exception propagation), the--input-dimmismatch, and the--init-pre-biasrejection.vfco61g2/yo-bom-lepton-001,gpu.2xh100-sxm; built via.ci_build.sh, ran Evo2predicton GPU, streamed-trained 20 steps →SMOKE OK(checkpoint_final.ptwritten).Launching on Lepton
Runs on the existing convergence system (
convergence-tests.yml→launch_job.py), not the #1667 L4 unit-test lane. This PR addsevo2_sae_smoketo theworkflow_dispatchmodel_configoptions.Dispatch: Actions → BioNeMo Model Convergence Tests → Run workflow →
model_config = evo2_sae_smoke,gpu_type = h100-sxm. Success =checkpoint_final.ptwritten. Dispatch-only (a 20-step liveness smoke, telemetry off) — deliberately not on the biweekly cron.Ordering
Stacked on #1622 (
pbinder/evo2-sae-serve), which adds the recipe's.ci_build.sh. Also useschunk_fasta.py, already onmain. Review/merge after #1622. Do not fold into #1667 (the presence-guarded unit-test lane, which must merge before the recipe).🤖 Generated with Claude Code