kermt-add-cmim-pretrain · git:20260915.2cd3507 · 2026-09-15 · sha256 eed773f29585c8b8

kermt-add-cmim-pretrain git:20260915.2cd3507A

Immutable. This exact content is served forever at /api/v1/blob/eed773f29585c8b8.

---
name: kermt-add-cmim-pretrain
description: Convert a grover_base checkpoint (encoder-only or encoder + vocab heads) into a hybrid checkpoint by adding a randomly-initialized cMIM decoder + latent_dist, then continue pretraining on the user's corpus as hybrid (vocab + contrast). Effectively kermt-continue-pretrain with a one-time ckpt-conversion step prepended.
license: Apache-2.0
compatibility: Requires docker, nvidia-container-toolkit, and a CUDA-capable NVIDIA GPU. Designed for Claude Code, Codex, and Nemotron.
metadata:
  owner: evax@nvidia.com
  classification: workflow-skill
  risk_tier: skill
# Line/token budget: ~165 lines, ~1900 tokens — well within the
# 500-line / 5000-token cap for skill files.
---

# kermt-add-cmim-pretrain

Convert a grover_base checkpoint (legacy original-GROVER `grover.encoders.*`
or modern `kermt.encoders.*`, with or without vocab heads) into a fully-formed
hybrid (cMIM + vocab) checkpoint, then continue pretraining on the user's
corpus as hybrid.

This is a thin wrapper: `upgrade_to_hybrid.py` produces a new ckpt that
classifies as `model_type: hybrid` via `check_checkpoint.py`, and the rest of
the workflow is identical to `kermt-continue-pretrain`.

> **Status: experimental.** This workflow is functional end-to-end but has not
> been benchmarked against the manuscript's from-scratch hybrid training (which
> produces the released checkpoint). Use as an experimental alternative to
> `kermt-pretrain-scratch` when you want to extend an existing grover_base
> checkpoint rather than restart from random init. Validate downstream
> performance on your own benchmark before relying on the upgraded ckpt for
> production work.

## Skill and runtime paths

Set `SKILL_DIR` to the absolute path of this installed skill directory. Export
`KERMT_REPO` as the absolute path to the KERMT checkout used for model
execution. The bundled container helper mounts that checkout at
`/workspace` and this skill at `/skill` (read-only). Commands inside
the container use `/skill/scripts/`; defaults are bundled in `config/`.

## Hardware requirements

Same as `kermt-continue-pretrain` (the cMIM decoder adds parameters but not
substantially; VRAM headroom should be fine). The upgrade step itself is
fast (~5 s) and CPU-only — only the subsequent continue-pretrain consumes
GPU.

## When to invoke

- User has a grover_base checkpoint (encoder-only or with vocab heads) and
  wants to extend it into a hybrid (vocab + cMIM contrastive) pretrain.
- Useful for adding the SMILES-reconstruction contrastive objective to a
  pretrained encoder without restarting pretraining from scratch (which
  `kermt-pretrain-scratch` would do at days-scale).

For continuing an existing hybrid or cmim ckpt: use `kermt-continue-pretrain`
directly. For training a fresh model on a custom corpus: use
`kermt-pretrain-scratch`.

## Inputs

Required:

- `--ckpt <path>` — grover_base ckpt to upgrade. Validated via
  `check_checkpoint.py --mode upgrade_to_hybrid`; rejected if the ckpt
  already has a contrast head or task FFN.
- `--csv <path>` — pretrain corpus CSV. Same shape as
  `kermt-continue-pretrain`'s `--csv` input.

Optional (same as `kermt-continue-pretrain`):

- `--val-csv <path>` — separate validation CSV. Without it, prepare_data
  auto-splits by `--val-frac 0.1`.
- Training-hyperparameter overrides (`--epochs N`, `--batch-size N`, lr triple,
  `--warmup-epochs F`, etc.).
- `--vocab-loss-weight F` / `--latent-dim N` / `--contrastive-temperature F`.
- `--wandb-project NAME` / `--wandb-run-name NAME` — optional Weights & Biases
  logging (run name honored only alongside a project). Off by default.
- `--gpus 0,2`.

## Workflow

Let `$KERMT_REPO` be the path to your kermt repo checkout.

1. **Pre-flight: check_system** (same as `kermt-continue-pretrain` step 1).

2. **Compute run directory:**
   ```
   RUN_DIR=$KERMT_REPO/runs/add-cmim-pretrain_$(date -u +%Y-%m-%dT%H-%M-%SZ)
   ```

3. **Validate the input ckpt with `check_checkpoint --mode upgrade_to_hybrid`.**
   Abort on `ok: false`. The validator rejects ckpts that already have
   contrast head (suggest `kermt-continue-pretrain`) or task FFN heads
   (the ckpt has been finetuned; suggest using the original pretrain
   checkpoint).

4. **Validate the corpus** via `check_data --mode pretrain`. Abort on
   `ok: false`.

5. **Prepare the data** with `--mode pretrain` — *without* `--vocab-dir`.
   The upgrade builds fresh vocab heads sized to the corpus's vocab, so we
   want `prepare_data` to produce a new vocab from the corpus rather than
   passing through the ckpt's old vocab (which may not even exist for
   encoder-only legacy grover_base ckpts):
   ```
   "$SKILL_DIR/scripts/kermt_container.sh" run --data <user-csv> --run-dir $RUN_DIR -- \
       "python /skill/scripts/prepare_data.py --mode pretrain \\
            --csv /data/<basename> --out /runs/data \\
            [--val-csv /data/<val-basename>] [--val-frac 0.1] [--seed 0]"
   ```
   The output manifest has `vocab_source: "built_fresh"` and includes a
   `smiles_vocab` (built from the corpus, needed for the new decoder).

6. **Upgrade the ckpt.**
   ```
   "$SKILL_DIR/scripts/kermt_container.sh" run --ckpt <user-ckpt> --run-dir $RUN_DIR -- \
       "python /skill/scripts/upgrade_to_hybrid.py \\
            --ckpt /ckpt \\
            --prepare-manifest /runs/data/prepare_data.json \\
            --out /runs/upgraded.pt"
   ```
   Surface the JSON summary to the user — especially `warnings[]`, which
   includes any encoder-arch drift notes (e.g. legacy GROVER had two extra
   `act_func_*` keys that modern KERMTEmbedding doesn't) and the
   pretrain_ddp.py `--backbone` argparse-restriction note if the upgraded
   ckpt's backbone is anything other than `gtrans`.

7. **Estimate runtime + confirm with the user.** Same heuristic as
   `kermt-continue-pretrain` (corpus size × epochs × GPU count → wall time).

8. **Launch the runner detached.**
   ```
   "$SKILL_DIR/scripts/kermt_container.sh" run_detached \\
       --name kermt-add-cmim-pretrain-<ts> \\
       --run-dir $RUN_DIR -- \\
       "python /skill/scripts/run_pretrain_local.py \\
            --ckpt /runs/upgraded.pt \\
            --prepare-manifest /runs/data/prepare_data.json \\
            --out /runs \\
            [--epochs N --batch-size N ...]"
   ```
   The runner sees the upgraded ckpt as `model_type: hybrid`, so it auto-dispatches
   `--pretrain_mode hybrid --vocab_loss_weight 1.0` with smiles_vocab plumbed
   through.

9. **Report to the user** with the upgraded ckpt path + the same run.json
   pointer / log path / tensorboard URL pattern as `kermt-continue-pretrain`.

## Hard rules

- **Never modify the user's input ckpt.** The upgrade writes a new file at
  `<run_dir>/upgraded.pt`; the source ckpt stays untouched.
- **Vocab heads are always fresh.** Even if the input grover_base has vocab
  heads, they're discarded and rebuilt sized to the new corpus's vocab.
  Continue-pretraining the upgraded ckpt will train those new heads alongside
  the decoder.
- **Don't auto-relax `--backbone` choices.** If the upgrade warning fires
  because the input ckpt's backbone isn't `gtrans` (e.g. legacy `dualtrans`),
  surface the warning and ask the user. Do NOT silently modify parsing.py to
  add the legacy backbone to the choices list.

## Common errors

- `check_checkpoint rejected the ckpt` with model_type=hybrid or cmim →
  user's ckpt already has a contrast head. Redirect to
  `kermt-continue-pretrain`.
- `check_checkpoint rejected the ckpt` with task_ffn=true → the ckpt has
  been finetuned. The upgrade workflow only supports pretrain checkpoints.
- `prepare manifest missing smiles_vocab` → prepare_data was invoked with
  `--skip-vocab` or some equivalent that omitted the smiles vocab. Re-run
  prepare without those flags.
- `unexpected key(s) in encoder load` warning → legacy GROVER architectures
  saved a couple of `act_func_*` weights that modern KERMTEmbedding doesn't
  use. Benign; the rest of the encoder loaded correctly.

## What's in `run.json` after a successful run

Same reproducibility fields as `kermt-continue-pretrain`, plus the upgrade step's
`summary.json` is captured under the `inputs.upgrade_summary` path so the
provenance of the upgraded ckpt is auditable.

## Replayability

Same as `kermt-continue-pretrain`: `cmd_replay` rebuilds the
`run_pretrain_local.py --ckpt <upgraded.pt> ...` invocation. To redo the
full add-cmim flow end-to-end, the user also needs the input grover_base
ckpt and the corpus — both are captured in the prepare_data and upgrade
manifests by absolute path.