|
Download README.md from ChatterjeeLab/StapleBridge: direct link, hf CLI and curl.
- Browser
- Download file 13.9 kB
-
https://huggingface.co/ChatterjeeLab/StapleBridge/resolve/main/README.md
- Command line
-
hf download hf://ChatterjeeLab/StapleBridge/README.md
-
curl -L -o README.md https://huggingface.co/ChatterjeeLab/StapleBridge/resolve/main/README.md
13.9 kB
| # StapleBridge | |
| Official training code for **StapleBridge**, a chemistry-aware framework for optimizing existing peptide leads through hydrocarbon stapling. | |
| StapleBridge constructs a finite set of chemically and geometrically feasible stapling interventions for each peptide, learns to rank these interventions, and executes the selected plan with minimal sequence edits. | |
| This repository contains the **main StapleBridge training pipeline** and **one representative pretrained checkpoint**. | |
| ## Framework | |
| [](figure/framework.pdf) | |
| --- | |
| ## 1. What is included | |
| The code required to **train the main StapleBridge model**, and one | |
| representative pretrained checkpoint. | |
| ``` | |
| release/staplebridge_training/ | |
| ├── README.md | |
| ├── THIRD_PARTY_NOTICES.md | |
| ├── requirements.txt | |
| ├── .gitignore | |
| ├── configs/ | |
| │ └── staplebridge_main.yaml # configuration used for the checkpoint | |
| ├── scripts/ | |
| │ └──train.py # canonical training entry point | |
| ├── staplebridge/ | |
| │ ├── chemistry/ # design state, actions, edit distance | |
| │ ├── data/ # split loading, schemas, catalog, vocab | |
| │ ├── hydrocarbon/ # plans, catalog, q_ref, q*, q_theta, geometry | |
| │ ├── models/ # policy / value nets, controlled kernel | |
| │ ├── oracles/ # ESM2 + anchor/block reference priors | |
| │ ├── reference/ # reference energy and kernel | |
| │ ├── training/ # stack construction, main loop, losses | |
| │ ├── integrations/ # PeptiVerse wrapper | |
| │ └── utils/ # paths, profiling | |
| ├── data/ | |
| │ └── README.md # expected input schema and file layout | |
| └── checkpoints/ | |
| └── staplebridge_seed42_best.pt # representative seed=42 model | |
| ``` | |
| The training code in `staplebridge/training/` is numerically identical to the | |
| run that produced the shipped checkpoint. | |
| <!-- ## 2. What is intentionally not included | |
| This release covers **training only**. Not included: | |
| - Baseline and ablation implementations, and their checkpoints. | |
| - Alternative stapling chemistries. | |
| - Downstream and post-hoc evaluation pipelines, including the test-set | |
| evaluator, structural and docking analyses, and permeability benchmarking. | |
| - Analysis, figure-generation and manuscript material. | |
| - Training outputs: logs, cached predictions, intermediate checkpoints. | |
| - **Processed training and validation data** — see §5; these will be handled | |
| separately. | |
| One checkpoint is shipped: the representative seed=42 model. | |
| Reproducing the paper's *evaluation* numbers requires the evaluation pipelines, | |
| which are outside this release. What is here reproduces *training*. --> | |
| ## 2. Environment setup | |
| The released checkpoint was trained under: | |
| | | Version | | |
| | --- | --- | | |
| | Python | 3.10.20 | | |
| | PyTorch | 2.12.1+cu130 (CUDA 13.0) | | |
| | NumPy | 2.0.2 | | |
| | PyYAML | 6.0.3 | | |
| | RDKit | 2026.03.5 | | |
| | transformers | 4.46.0 | | |
| ```bash | |
| python -m venv .venv && source .venv/bin/activate | |
| # Install torch first, matched to your CUDA build: https://pytorch.org | |
| pip install -r requirements.txt | |
| ``` | |
| <!-- StapleBridge's own model is small (~142k parameters total) and runs on CPU. A | |
| GPU is needed in practice because the frozen ESM2-650M prior and the PeptiVerse | |
| oracles are invoked per candidate. Set the device in one place — the config | |
| requires `training.device`, `property_predictor.device` and | |
| `reference_priors.peptide.device` to agree, and `check_config.py` enforces it. --> | |
| ## 3. External model dependencies | |
| **No third-party model weights are bundled.** Four external resources must be | |
| provided and referenced from the config: the ESM2-650M snapshot, the PeptiVerse | |
| distribution, and the two SMILES encoders PeptiVerse depends on. Paths may be | |
| absolute, or relative to the package root. | |
| ### ESM2-650M (frozen sequence context) | |
| `facebook/esm2_t33_650M_UR50D`, used frozen — never fine-tuned. It supplies the | |
| reference-process peptide prior and the V2 plan head's anchor/local-context | |
| features. It is also the feature source for the plan head, which refuses to | |
| build without it. | |
| ```bash | |
| huggingface-cli download facebook/esm2_t33_650M_UR50D \ | |
| --local-dir models/esm2_t33_650M_UR50D | |
| ``` | |
| Then set, in `configs/staplebridge_main.yaml`: | |
| ```yaml | |
| reference_priors: | |
| peptide: | |
| model_name_or_path: models/esm2_t33_650M_UR50D | |
| property_predictor: | |
| esm_model_name_or_path: models/esm2_t33_650M_UR50D | |
| ``` | |
| The config runs the prior with `offline: true` and `strict_runtime: true`, so the | |
| snapshot must already be on disk; training fails fast rather than downloading or | |
| silently substituting a fallback. Licensed by Meta under the ESM2 terms. | |
| ### PeptiVerse (property oracles) | |
| The main training objective optimises the PeptiVerse | |
| permeability-penetrance E/Z product mean. Obtain the PeptiVerse checkout and its | |
| classifier weights separately, then set: | |
| ```yaml | |
| property_predictor: | |
| peptiverse_root: external/PeptiVerse | |
| classifier_weight_root: external/PeptiVerse | |
| manifest_path: external/PeptiVerse/basic_models.txt | |
| ``` | |
| Scoring is **strict**: `strict: true`, `enable_fallback: false`, | |
| `allow_wt_token_fallback: false`. If the oracle stack cannot load, training | |
| aborts — it never degrades to a heuristic. | |
| Toxicity, hemolysis and half-life are monitored only. Solubility and binding | |
| affinity are excluded from the objective. | |
| ### PeptideCLM-23M and ChemBERTa-77M (required) | |
| The `basic_models.txt` manifest selects predictors embedded with PeptideCLM and | |
| ChemBERTa, so **both are required** — not optional. The permeability-penetrance | |
| predictor that defines the objective is itself ChemBERTa-embedded. Loading fails | |
| fast without them. | |
| ```bash | |
| huggingface-cli download aaronfeller/PeptideCLM-23M-all \ | |
| --local-dir models/PeptideCLM-23M-all | |
| huggingface-cli download DeepChem/ChemBERTa-77M-MLM \ | |
| --local-dir models/ChemBERTa-77M-MLM | |
| ``` | |
| ```yaml | |
| property_predictor: | |
| peptideclm_model_name_or_path: models/PeptideCLM-23M-all | |
| chemberta_model_name_or_path: models/ChemBERTa-77M-MLM | |
| ``` | |
| `scripts/check_config.py` verifies all four before training starts. | |
| ## 4. Data | |
| **The processed training and validation data are not included in this release** | |
| and will be handled separately. No preprocessing, download or reconstruction | |
| utilities are provided. | |
| Training reads two JSON Lines files, resolved from the config: | |
| ``` | |
| data/real/ # data.root | |
| ├── train.jsonl # data.train_file | |
| └── valid.jsonl # data.valid_file | |
| ``` | |
| See [`data/README.md`](data/README.md) for the expected input schema — in | |
| particular the required per-residue Cα coordinates, which staple-geometry | |
| feasibility depends on. | |
| The reference protocol uses 4020 training and 111 validation leads; | |
| `scripts/check_config.py` asserts those counts, so substituting a differently | |
| sized dataset requires relaxing the check. | |
| ## 5. Training command | |
| ```bash | |
| python scripts/train.py \ | |
| --config configs/staplebridge_main.yaml \ | |
| --out-dir outputs/main_seed42 | |
| ``` | |
| <!-- `check_config.py` is read-only: it verifies the configuration and the presence of | |
| the external assets without loading a model or training. Run it first — it turns | |
| a misconfiguration into an immediate error rather than a failure hours in. | |
| The CLI is intentionally small — **seed (42) and device come from the config**, | |
| not from flags, so a run cannot silently diverge from the recorded protocol. | |
| `--resume <checkpoint>` restores model, optimizer and RNG state so the remaining | |
| epochs match an uninterrupted run. `train.py` refuses to start in a non-empty | |
| `--out-dir`. | |
| Written to `--out-dir`: `resolved_config.yaml`, `metrics.jsonl` (per-epoch), | |
| `run_summary.json`, per-epoch validation summaries, and | |
| `checkpoints/{best_kl,best_pv,latest,epoch_NNN}.pt`. **`best_kl.pt` is the | |
| selected model** — see §7. --> | |
| <!-- ## 7. Main reproducibility settings | |
| Read from `configs/staplebridge_main.yaml` and asserted by | |
| `scripts/check_config.py`: | |
| | Setting | Value | | |
| | --- | --- | | |
| | Splits | `train.jsonl` (4020) / `valid.jsonl` (111), full validation every epoch | | |
| | Seed | 42 | | |
| | Epochs | 10, no early stopping (all 10 always run) | | |
| | Horizon | 8 (training and validation must match) | | |
| | Max neighboring actions | 128 | | |
| | Chunk size | 32 | | |
| | Committed plans per lead | 4 | | |
| | `beta` (Exact-SB) | 1.0 | | |
| | Plan-loss weight | 1.0 | | |
| | Plan head | hidden dim 128, frozen ESM2-650M features | | |
| | Objective | `permeability_penetrance`, E/Z product mean, neutral-canonical SMILES | | |
| | Monitored only | toxicity, hemolysis, half-life | | |
| | Excluded | solubility, binding affinity | | |
| | PeptiVerse | strict SMILES mode, all fallbacks disabled | | |
| | Catalog | hydrocarbon only (`include_optional: false`): S5-S5/i,i+4 and R8-S5/i,i+7 | | |
| | Hard constraints | chemistry + geometry + edit budget 6.0, min sequence identity 0.6, protected edits forbidden, exact committed-plan completion | | |
| | Decoding | strict hierarchical plan-first (`hierarchical_plan_ranking: true`) | | |
| | **Checkpoint selection** | **minimum validation `q_star_vs_q_theta_kl`**, guarded by `require_both_topologies` | | |
| Optimizer: Adam, lr 1e-3, grad-norm clip 1.0. | |
| ### Checkpoint selection | |
| The rule is: the epoch minimising `KL(q* ‖ q_theta)` on the full 111-lead | |
| validation split, among epochs where both staple topologies appear in the | |
| selected candidates. Validation permeability and the test split play no part in | |
| selecting it. | |
| For the shipped checkpoint that rule chose **epoch 9**, validation | |
| `q_star_vs_q_theta_kl = 0.081568` — the minimum over all 10 epochs (epoch 10 rose | |
| to 0.082585). `train.py` also maintains `best_pv.pt` by validation | |
| delta-penetrance for monitoring; it is **not** the selected model and is not | |
| shipped. | |
| ## 8. Checkpoint loading | |
| `checkpoints/staplebridge_seed42_best.pt` is the `best_kl.pt` of the seed=42 | |
| training run, copied byte-for-byte with weights unmodified | |
| (sha256 `22d273164a3132d43617c51649947028f11859f90ca0bee28540edc9ad62a298`). | |
| Verify it loads against this package's model definitions: --> | |
| <!-- ```bash | |
| python scripts/smoke_test.py | |
| ``` | |
| This checks imports, config, model construction and a strict checkpoint load | |
| (zero missing / unexpected keys). It is not an evaluation suite. | |
| Minimal manual load: | |
| ```python | |
| import torch, yaml | |
| from staplebridge.hydrocarbon.plan_control import build_hydrocarbon_plan_head | |
| from staplebridge.models.policy_net import PolicyNet | |
| from staplebridge.models.value_net import ValueNet | |
| config = yaml.safe_load(open("configs/staplebridge_main.yaml")) | |
| emb_dim = int(config["model"]["emb_dim"]) | |
| ckpt = torch.load("checkpoints/staplebridge_seed42_best.pt", | |
| map_location="cpu", weights_only=False) | |
| policy = PolicyNet(emb_dim=emb_dim) | |
| value = ValueNet(emb_dim=emb_dim) | |
| policy.load_state_dict(ckpt["policy_state_dict"]) # strict, exact match | |
| value.load_state_dict(ckpt["value_state_dict"]) | |
| print("epoch:", ckpt["epoch"]) # -> 9 | |
| ``` | |
| The plan head is the one component that cannot be built without the frozen | |
| ESM2-650M prior — it refuses a stand-in by design, so training can never | |
| silently substitute a different context model: | |
| ```python | |
| from staplebridge.training.stack import build_stack | |
| stack = build_stack(config, seed=42) # requires ESM2 on disk | |
| head = build_hydrocarbon_plan_head(config, emb_dim, "cpu", | |
| esm2_prior=stack["reference_priors"].peptide) | |
| head.load_state_dict(ckpt["plan_head_state_dict"]) | |
| ``` | |
| Checkpoint payload: `policy_state_dict` (20 tensors), `value_state_dict` (20), | |
| `plan_head_state_dict` (6), plus non-model metadata — `epoch`, the full resolved | |
| `config`, `plan_control_enabled`, `optimizer_state_dict`, and RNG state | |
| (`plan_rng_state`, `python_random_state`, `numpy_random_state`, | |
| `torch_rng_state`, `cuda_rng_state_all`). The optimizer and RNG entries exist so | |
| `--resume` can continue a run bit-identically; they are not model weights. | |
| ## 9. Reproducibility note | |
| - **Seed.** Fixed at 42 in the config and applied to Python, NumPy and Torch | |
| (including all CUDA devices). Plan sampling uses its own seeded | |
| `random.Random(42)`, checkpointed so `--resume` continues the same stream. | |
| - **Determinism.** `torch.use_deterministic_algorithms(False)`, matching the | |
| reference run. Results are therefore **device- and version-dependent**: a | |
| different GPU model, CUDA version, or PyTorch build can shift metrics | |
| slightly. Exact bit-level reproduction requires the environment in §3. | |
| - **External models.** The frozen ESM2-650M snapshot and the PeptiVerse | |
| classifier stack are part of the training objective. Different versions of | |
| either change the optimisation target and will not reproduce these numbers. | |
| - **Caches.** Training maintains a persistent ESM2 prior cache and an exact-SB | |
| target cache (SQLite, under `outputs/cache/`). These are pure speedups — | |
| deterministic values keyed by content — and do not change results. | |
| - **Cost.** 10 epochs over 4020 leads with full 111-lead validation each epoch. | |
| The reference run totalled about 3.9 h of epoch time on one GPU (~16 GiB peak). | |
| Cache warming dominates the first epoch — 4964 s, against 760-890 s for later | |
| epochs once the ESM2 and exact-SB caches are populated. | |
| - **Scale guard.** `train.py` hard-asserts `train_n == 4020` and `epochs == 10`, | |
| so the protocol cannot be shrunk by editing the config alone. | |
| ## License | |
| See [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) for third-party | |
| components. A license for the StapleBridge code itself has not yet been | |
| selected; add a `LICENSE` file before publishing. --> | |