Upload folder using huggingface_hub
Browse files- README.md +115 -0
- checkpoints/best.pt +3 -0
- checkpoints/electrolyte_model.pt +3 -0
- processed/descriptor_stats.json +1 -0
- processed/meta.json +37 -0
- processed/vocab.json +1 -0
README.md
CHANGED
|
@@ -1,3 +1,118 @@
|
|
| 1 |
---
|
| 2 |
license: mit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
license: mit
|
| 3 |
+
library_name: pytorch
|
| 4 |
+
tags:
|
| 5 |
+
- chemistry
|
| 6 |
+
- molecule-generation
|
| 7 |
+
- generative-model
|
| 8 |
+
- vae
|
| 9 |
+
- selfies
|
| 10 |
+
- rdkit
|
| 11 |
+
- drug-discovery
|
| 12 |
+
- electrolyte
|
| 13 |
+
- batteries
|
| 14 |
+
- cheminformatics
|
| 15 |
---
|
| 16 |
+
|
| 17 |
+
# MolForge — a conditional SELFIES-VAE for de-novo molecule & battery-electrolyte design
|
| 18 |
+
|
| 19 |
+
MolForge is a ~42M-parameter **conditional variational autoencoder** over
|
| 20 |
+
[SELFIES](https://github.com/aspuru-guzik-group/selfies) string representations of
|
| 21 |
+
molecules. It learns a smooth 256-dimensional latent space you can **sample, traverse,
|
| 22 |
+
and optimize**, and because it decodes SELFIES, **~100% of generated strings are valid
|
| 23 |
+
molecules**. It was built for de-novo design of drug-like molecules and, in particular,
|
| 24 |
+
**battery-electrolyte solvents / additives** across chemistries (Li / Na / K / Mg / Zn / …).
|
| 25 |
+
|
| 26 |
+
- **Code / library:** https://github.com/NealKapadia/molforge
|
| 27 |
+
- **Weights (this repo):** `checkpoints/best.pt`
|
| 28 |
+
- **Architecture:** embedding 512 → bidirectional GRU encoder (1024 × 2 layers) →
|
| 29 |
+
latent 256 → GRU decoder (1024 × 2 layers), conditioned on **11 RDKit descriptors**,
|
| 30 |
+
with an auxiliary latent→property head. Decoder word-dropout 0.25 (Bowman et al.) for a
|
| 31 |
+
meaningful latent. SELFIES robust alphabet, 79 tokens, max length 120.
|
| 32 |
+
- **Training data:** the Molport "All Stock" compound catalog (~6.1M drug-like molecules
|
| 33 |
+
after filtering: heavy atoms 3–60, organic element set). Validity-critical fix: trained
|
| 34 |
+
with the **default** SELFIES constraints (S=6 / P=5 allowed) so sulfonyl/phosphate
|
| 35 |
+
electrolyte motifs round-trip.
|
| 36 |
+
- **Selected checkpoint:** `best.pt` = early-stopped epoch (~12M molecules seen), selected by
|
| 37 |
+
`val_token_acc + 0.25·valid_rate`.
|
| 38 |
+
|
| 39 |
+
## Conditioning properties (fixed order)
|
| 40 |
+
|
| 41 |
+
`MolWt, MolLogP, TPSA, QED, NumHDonors, NumHAcceptors, NumRotatableBonds, NumAromaticRings, NumRings, FractionCSP3, HeavyAtomCount`
|
| 42 |
+
|
| 43 |
+
## Evaluation (best.pt, 5,000 samples @ temperature 0.9)
|
| 44 |
+
|
| 45 |
+
| Metric | Value |
|
| 46 |
+
|---|---|
|
| 47 |
+
| Validity | **1.000** |
|
| 48 |
+
| Uniqueness | 0.998 |
|
| 49 |
+
| Novelty (vs. training set) | 0.995 |
|
| 50 |
+
| Internal diversity | 0.894 |
|
| 51 |
+
| Reconstruction (exact) | 0.945 |
|
| 52 |
+
| Reconstruction (token acc) | 0.998 |
|
| 53 |
+
|
| 54 |
+
Latent→property head R² (held-out): MolWt 0.994, TPSA 0.977, MolLogP 0.962,
|
| 55 |
+
NumHAcceptors / NumRotatableBonds 0.969, QED 0.926, NumHDonors 0.922.
|
| 56 |
+
|
| 57 |
+
> On the standard generative benchmark columns (validity / uniqueness / novelty /
|
| 58 |
+
> diversity) this model is competitive with — and on several columns exceeds — the
|
| 59 |
+
> autoregressive **ElectrolyteGPT** (Kim et al., *JACS Au*, 2026, 6, 2288–2302). The
|
| 60 |
+
> structural advantage is the **latent space**: smooth interpolation and gradient-based
|
| 61 |
+
> property optimization, which a left-to-right token model does not offer.
|
| 62 |
+
|
| 63 |
+
## Files
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
checkpoints/best.pt # the SELFIES-VAE generator weights
|
| 67 |
+
checkpoints/electrolyte_model.pt # optional: formulation property model (conductivity etc.)
|
| 68 |
+
processed/vocab.json # SELFIES token vocabulary
|
| 69 |
+
processed/descriptor_stats.json # descriptor normalization (mean/std)
|
| 70 |
+
processed/meta.json # vocab size, max length, property order, constraints
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
This is exactly the layout the `molforge` library expects under `MOLVAE_ART_DIR`.
|
| 74 |
+
|
| 75 |
+
## Usage
|
| 76 |
+
|
| 77 |
+
```bash
|
| 78 |
+
pip install "git+https://github.com/NealKapadia/molforge.git"
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
```python
|
| 82 |
+
from huggingface_hub import snapshot_download
|
| 83 |
+
from molforge import MolForge
|
| 84 |
+
|
| 85 |
+
art = snapshot_download("NealKapadia/Molforge") # downloads checkpoints/ + processed/
|
| 86 |
+
mf = MolForge(device="cpu", artifacts_dir=art) # or device="cuda"
|
| 87 |
+
|
| 88 |
+
mf.generate(10) # 10 valid, novel SMILES
|
| 89 |
+
mf.generate(5, spec={"MolWt": 250, "QED": 0.8}) # property-targeted
|
| 90 |
+
z = mf.encode("OCCN(CCO)CCO"); mf.decode(z) # latent round-trip
|
| 91 |
+
mf.properties("CCO") # RDKit descriptors
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
Or set the path manually instead of `artifacts_dir=`:
|
| 95 |
+
`export MOLVAE_ART_DIR=/path/to/download` (Windows: `$env:MOLVAE_ART_DIR="..."`).
|
| 96 |
+
|
| 97 |
+
## Limitations & intended use
|
| 98 |
+
|
| 99 |
+
- **Research / educational use** for molecular design and screening — **not** a substitute
|
| 100 |
+
for experimental validation, synthesis feasibility, or safety assessment.
|
| 101 |
+
- **Soft conditioning:** `spec` targets nudge generation toward a value; they are not exact.
|
| 102 |
+
For hard constraints, over-generate and filter by RDKit-computed properties.
|
| 103 |
+
- The base generator is **drug-like**; very small electrolyte molecules (EC/DEC/MeCN) are
|
| 104 |
+
somewhat out-of-distribution for the base checkpoint.
|
| 105 |
+
- The electrolyte property model has labeled data for **Li / Na / K** only; the generator
|
| 106 |
+
proposes candidates for any chemistry, but quantitative ranking beyond Li/Na/K needs
|
| 107 |
+
additional labeled data.
|
| 108 |
+
|
| 109 |
+
## Training data & license
|
| 110 |
+
|
| 111 |
+
Trained on structures from the **Molport "All Stock"** catalog. Please review Molport's
|
| 112 |
+
terms for the underlying catalog data. The weights and code are released under the license
|
| 113 |
+
declared in the metadata above — **confirm/replace this license before relying on it**.
|
| 114 |
+
|
| 115 |
+
## Citation
|
| 116 |
+
|
| 117 |
+
If you use MolForge, please cite this repository and the SELFIES paper
|
| 118 |
+
(Krenn et al., *Mach. Learn.: Sci. Technol.* 2020).
|
checkpoints/best.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7fd88d8b1b0fb049dd3a006d9b1746d1f543bbffe5158550c9401c1ceb460ed8
|
| 3 |
+
size 503633904
|
checkpoints/electrolyte_model.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3dd43f5a5626969616fc8b5db142d0f40331a333d5ea157eba7d6f8869ffc8c6
|
| 3 |
+
size 828396
|
processed/descriptor_stats.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"properties": ["MolWt", "MolLogP", "TPSA", "QED", "NumHDonors", "NumHAcceptors", "NumRotatableBonds", "NumAromaticRings", "NumRings", "FractionCSP3", "HeavyAtomCount"], "mean": [365.96527099609375, 3.1327805519104004, 70.4820556640625, 0.640363872051239, 1.0642004013061523, 4.472788333892822, 4.757150173187256, 2.3169329166412354, 3.2396657466888428, 0.345050185918808, 25.594316482543945], "std": [93.11808776855469, 1.6074011325836182, 27.75464630126953, 0.18775396049022675, 0.9152066111564636, 1.7360092401504517, 2.4416964054107666, 1.108630895614624, 1.2000303268432617, 0.2074769288301468, 6.741006851196289]}
|
processed/meta.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"shards": [
|
| 3 |
+
"shard_000",
|
| 4 |
+
"shard_001",
|
| 5 |
+
"shard_002",
|
| 6 |
+
"shard_003",
|
| 7 |
+
"shard_004",
|
| 8 |
+
"shard_005",
|
| 9 |
+
"shard_006",
|
| 10 |
+
"shard_007",
|
| 11 |
+
"shard_008",
|
| 12 |
+
"shard_009",
|
| 13 |
+
"shard_010",
|
| 14 |
+
"shard_011",
|
| 15 |
+
"shard_012",
|
| 16 |
+
"shard_013",
|
| 17 |
+
"shard_014",
|
| 18 |
+
"shard_015"
|
| 19 |
+
],
|
| 20 |
+
"total": 7116053,
|
| 21 |
+
"max_len": 120,
|
| 22 |
+
"vocab_size": 79,
|
| 23 |
+
"properties": [
|
| 24 |
+
"MolWt",
|
| 25 |
+
"MolLogP",
|
| 26 |
+
"TPSA",
|
| 27 |
+
"QED",
|
| 28 |
+
"NumHDonors",
|
| 29 |
+
"NumHAcceptors",
|
| 30 |
+
"NumRotatableBonds",
|
| 31 |
+
"NumAromaticRings",
|
| 32 |
+
"NumRings",
|
| 33 |
+
"FractionCSP3",
|
| 34 |
+
"HeavyAtomCount"
|
| 35 |
+
],
|
| 36 |
+
"constraints": "default"
|
| 37 |
+
}
|
processed/vocab.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"itos": ["<pad>", "<bos>", "<eos>", "<unk>", "[#B-1]", "[#B]", "[#Br]", "[#Branch1]", "[#Branch2]", "[#Branch3]", "[#C+1]", "[#C-1]", "[#C]", "[#Cl]", "[#I]", "[#N+1]", "[#N]", "[#O+1]", "[#P+1]", "[#P-1]", "[#P]", "[#S+1]", "[#S-1]", "[#S]", "[=B+1]", "[=B-1]", "[=B]", "[=Br]", "[=Branch1]", "[=Branch2]", "[=Branch3]", "[=C+1]", "[=C-1]", "[=C]", "[=Cl]", "[=I]", "[=N+1]", "[=N-1]", "[=N]", "[=O+1]", "[=O]", "[=P+1]", "[=P-1]", "[=P]", "[=Ring1]", "[=Ring2]", "[=Ring3]", "[=S+1]", "[=S-1]", "[=S]", "[B+1]", "[B-1]", "[B]", "[Br]", "[Branch1]", "[Branch2]", "[Branch3]", "[C+1]", "[C-1]", "[C]", "[Cl]", "[F]", "[H]", "[I]", "[N+1]", "[N-1]", "[N]", "[O+1]", "[O-1]", "[O]", "[P+1]", "[P-1]", "[P]", "[Ring1]", "[Ring2]", "[Ring3]", "[S+1]", "[S-1]", "[S]"], "constraints": "hypervalent", "max_len": 120}
|