Instructions to use Synthyra/ESM3_small with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Synthyra/ESM3_small with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="Synthyra/ESM3_small", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Synthyra/ESM3_small", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Update FastPLMs files
Browse files- README.md +54 -12
- fastplms/models.toml +8 -8
- fastplms/models/esm3/__init__.py +12 -2
- fastplms/models/esm3/modeling_esm3.py +319 -7
- fastplms_bundle.py +0 -0
- modeling_fastplms.py +9 -4
README.md
CHANGED
|
@@ -14,15 +14,16 @@ This checkpoint contains the FastPLMs `ESM3` implementation.
|
|
| 14 |
|
| 15 |
Accepted inputs are sequence, structure, and function tracks prepared through
|
| 16 |
the multimodal helpers.
|
| 17 |
-
Supported Transformers entry points are `AutoConfig`, `AutoModel`
|
|
|
|
| 18 |
|
| 19 |
## Capabilities
|
| 20 |
|
| 21 |
| Feature | Status |
|
| 22 |
| --- | --- |
|
| 23 |
-
| Sequence classification |
|
| 24 |
-
| Token classification |
|
| 25 |
-
| PEFT fine-tuning | Supported pattern:
|
| 26 |
| Embeddings | Supported: shared ordered embedding API |
|
| 27 |
| Test-time training | Supported: low-rank masked-residue adaptation |
|
| 28 |
| Attention variants | Supported: `eager`, `sdpa`, `flex_attention` |
|
|
@@ -95,6 +96,45 @@ Set `output` and `format="safetensors"` or `"sqlite"` for transactional,
|
|
| 95 |
bounded-memory storage. Resume checks input order, model state, tokenizer
|
| 96 |
policy, backend, dtype, and pooling configuration before it appends data.
|
| 97 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
## PEFT fine-tuning
|
| 99 |
|
| 100 |
Install the training dependencies. Then attach LoRA to the loaded checkpoint:
|
|
@@ -104,20 +144,22 @@ python -m pip install "datasets>=4.8,<5" "peft>=0.19,<0.20"
|
|
| 104 |
```
|
| 105 |
|
| 106 |
```python
|
| 107 |
-
from peft import LoraConfig, get_peft_model
|
| 108 |
|
| 109 |
peft_model = get_peft_model(
|
| 110 |
-
|
| 111 |
LoraConfig(
|
|
|
|
| 112 |
r=8,
|
| 113 |
lora_alpha=16,
|
| 114 |
target_modules="all-linear",
|
|
|
|
| 115 |
),
|
| 116 |
)
|
| 117 |
```
|
| 118 |
|
| 119 |
-
This checkpoint
|
| 120 |
-
|
| 121 |
All FastPLMs checkpoints follow the Transformers `PreTrainedModel` contract and
|
| 122 |
can use PEFT. The ESM2-specific shipped CLI is an example, not a
|
| 123 |
support boundary. Record the target modules, base revision, data identity, and
|
|
@@ -193,8 +235,8 @@ not experimental measurements of structure or function.
|
|
| 193 |
## Runtime contract
|
| 194 |
|
| 195 |
- Public input: Sequence, structure, and function tracks prepared through the multimodal helpers
|
| 196 |
-
- Advertised AutoClasses: `AutoConfig`, `AutoModel`
|
| 197 |
-
- AutoClass weight status: `AutoConfig` = `FastPLMs extension`, `AutoModel` = `pretrained`
|
| 198 |
- Attention implementations: `eager`, `sdpa`, `flex_attention`
|
| 199 |
- Precision policies: `default`
|
| 200 |
- BF16 execution: `fp32_parameters_autocast`
|
|
@@ -208,8 +250,8 @@ not experimental measurements of structure or function.
|
|
| 208 |
## Release record
|
| 209 |
|
| 210 |
- FastPLMs weights: `Synthyra/ESM3_small`
|
| 211 |
-
- Runtime revision: recorded in the built artifact and published commit
|
| 212 |
-
-
|
| 213 |
- Official checkpoint: `biohub/esm3-sm-open-v1`
|
| 214 |
- Artifact source: `fast`
|
| 215 |
- State transform: `esm3_to_fastplms_v1`
|
|
|
|
| 14 |
|
| 15 |
Accepted inputs are sequence, structure, and function tracks prepared through
|
| 16 |
the multimodal helpers.
|
| 17 |
+
Supported Transformers entry points are `AutoConfig`, `AutoModel`,
|
| 18 |
+
`AutoModelForSequenceClassification`, `AutoModelForTokenClassification`.
|
| 19 |
|
| 20 |
## Capabilities
|
| 21 |
|
| 22 |
| Feature | Status |
|
| 23 |
| --- | --- |
|
| 24 |
+
| Sequence classification | Supported: base weights with an untrained task head |
|
| 25 |
+
| Token classification | Supported: base weights with an untrained task head |
|
| 26 |
+
| PEFT fine-tuning | Supported pattern: preserve the separately trained `classifier` |
|
| 27 |
| Embeddings | Supported: shared ordered embedding API |
|
| 28 |
| Test-time training | Supported: low-rank masked-residue adaptation |
|
| 29 |
| Attention variants | Supported: `eager`, `sdpa`, `flex_attention` |
|
|
|
|
| 96 |
bounded-memory storage. Resume checks input order, model state, tokenizer
|
| 97 |
policy, backend, dtype, and pooling configuration before it appends data.
|
| 98 |
|
| 99 |
+
## Downstream prediction
|
| 100 |
+
|
| 101 |
+
The sequence and token prediction AutoClasses use the checkpoint backbone and
|
| 102 |
+
create a new, untrained `classifier`. Sequence labels have shape `(b,)`.
|
| 103 |
+
Residue labels have shape `(b, l)` and use `-100` outside biological positions.
|
| 104 |
+
|
| 105 |
+
```python
|
| 106 |
+
import torch
|
| 107 |
+
from transformers import AutoTokenizer
|
| 108 |
+
from transformers import (
|
| 109 |
+
AutoModelForSequenceClassification,
|
| 110 |
+
AutoModelForTokenClassification,
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
model_id = "Synthyra/ESM3_small"
|
| 114 |
+
sequence_model = AutoModelForSequenceClassification.from_pretrained(
|
| 115 |
+
model_id, num_labels=2, trust_remote_code=True
|
| 116 |
+
).eval()
|
| 117 |
+
token_model = AutoModelForTokenClassification.from_pretrained(
|
| 118 |
+
model_id, num_labels=3, trust_remote_code=True
|
| 119 |
+
).eval()
|
| 120 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
|
| 121 |
+
sequences = ["MSTNPKPQRKTKRNT", "MKTIIALSYIFCLVFA"]
|
| 122 |
+
batch = tokenizer(sequences, padding=True, return_tensors="pt")
|
| 123 |
+
biological = batch["attention_mask"].bool()
|
| 124 |
+
for special_id in tokenizer.all_special_ids:
|
| 125 |
+
biological &= batch["input_ids"].ne(special_id)
|
| 126 |
+
|
| 127 |
+
sequence_labels = torch.zeros(len(sequences), dtype=torch.long)
|
| 128 |
+
token_labels = torch.full_like(batch["input_ids"], -100)
|
| 129 |
+
token_labels[biological] = 0
|
| 130 |
+
|
| 131 |
+
with torch.inference_mode():
|
| 132 |
+
sequence_output = sequence_model(**batch, labels=sequence_labels)
|
| 133 |
+
token_output = token_model(**batch, labels=token_labels)
|
| 134 |
+
print(sequence_output.logits.shape) # (b, 2)
|
| 135 |
+
print(token_output.logits.shape) # (b, l, 3)
|
| 136 |
+
```
|
| 137 |
+
|
| 138 |
## PEFT fine-tuning
|
| 139 |
|
| 140 |
Install the training dependencies. Then attach LoRA to the loaded checkpoint:
|
|
|
|
| 144 |
```
|
| 145 |
|
| 146 |
```python
|
| 147 |
+
from peft import LoraConfig, TaskType, get_peft_model
|
| 148 |
|
| 149 |
peft_model = get_peft_model(
|
| 150 |
+
sequence_model,
|
| 151 |
LoraConfig(
|
| 152 |
+
task_type=TaskType.SEQ_CLS,
|
| 153 |
r=8,
|
| 154 |
lora_alpha=16,
|
| 155 |
target_modules="all-linear",
|
| 156 |
+
modules_to_save=["classifier"],
|
| 157 |
),
|
| 158 |
)
|
| 159 |
```
|
| 160 |
|
| 161 |
+
This checkpoint advertises a classification head. Save the separately trained
|
| 162 |
+
`classifier` with the adapter.
|
| 163 |
All FastPLMs checkpoints follow the Transformers `PreTrainedModel` contract and
|
| 164 |
can use PEFT. The ESM2-specific shipped CLI is an example, not a
|
| 165 |
support boundary. Record the target modules, base revision, data identity, and
|
|
|
|
| 235 |
## Runtime contract
|
| 236 |
|
| 237 |
- Public input: Sequence, structure, and function tracks prepared through the multimodal helpers
|
| 238 |
+
- Advertised AutoClasses: `AutoConfig`, `AutoModel`, `AutoModelForSequenceClassification`, `AutoModelForTokenClassification`
|
| 239 |
+
- AutoClass weight status: `AutoConfig` = `FastPLMs extension`, `AutoModel` = `pretrained`, `AutoModelForSequenceClassification` = `base weights + untrained task head`, `AutoModelForTokenClassification` = `base weights + untrained task head`
|
| 240 |
- Attention implementations: `eager`, `sdpa`, `flex_attention`
|
| 241 |
- Precision policies: `default`
|
| 242 |
- BF16 execution: `fp32_parameters_autocast`
|
|
|
|
| 250 |
## Release record
|
| 251 |
|
| 252 |
- FastPLMs weights: `Synthyra/ESM3_small`
|
| 253 |
+
- Runtime revision: recorded separately in the built artifact and published commit
|
| 254 |
+
- Runtime source identities: recorded in `source-record.json`
|
| 255 |
- Official checkpoint: `biohub/esm3-sm-open-v1`
|
| 256 |
- Artifact source: `fast`
|
| 257 |
- State transform: `esm3_to_fastplms_v1`
|
fastplms/models.toml
CHANGED
|
@@ -199,7 +199,7 @@ representative = "esmc_small"
|
|
| 199 |
documentation = "docs/models.md#esm-and-esmc"
|
| 200 |
test_tiers = ["check", "compliance", "feature", "artifact", "benchmark"]
|
| 201 |
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/esm_plusplus", "models/ttt.py"]
|
| 202 |
-
auto_map = { AutoConfig = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusConfig", AutoModel = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusModel", AutoModelForMaskedLM = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusForMaskedLM" }
|
| 203 |
|
| 204 |
[families.esm3]
|
| 205 |
architecture = "ESM3"
|
|
@@ -223,7 +223,7 @@ representative = "esm3_small"
|
|
| 223 |
documentation = "docs/models.md#esm3"
|
| 224 |
test_tiers = ["check", "compliance", "feature", "artifact", "benchmark"]
|
| 225 |
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/esm3", "models/ttt.py"]
|
| 226 |
-
auto_map = { AutoConfig = "fastplms.models.esm3.modeling_esm3.FastESM3Config", AutoModel = "fastplms.models.esm3.modeling_esm3.FastESM3Model" }
|
| 227 |
|
| 228 |
[families.e1]
|
| 229 |
architecture = "E1"
|
|
@@ -370,8 +370,8 @@ conversion_provenance = "Input: the pinned native Meta ESMFold checkpoint plus i
|
|
| 370 |
representative = "esmfold"
|
| 371 |
documentation = "docs/models.md#esmfold"
|
| 372 |
test_tiers = ["check", "compliance", "structure", "feature", "artifact", "benchmark"]
|
| 373 |
-
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/_esm_rotary.py", "models/esmfold"]
|
| 374 |
-
auto_map = { AutoConfig = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmFoldConfig", AutoModel = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmForProteinFolding" }
|
| 375 |
|
| 376 |
[families.esmfold2]
|
| 377 |
architecture = "ESMFold2"
|
|
@@ -396,8 +396,8 @@ conversion_provenance = "Input: each pinned Biohub ESMFold2 checkpoint and its s
|
|
| 396 |
representative = "esmfold2"
|
| 397 |
documentation = "docs/esmfold2.md"
|
| 398 |
test_tiers = ["check", "compliance", "structure", "feature", "artifact", "benchmark"]
|
| 399 |
-
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/esmfold2", "models/esm_plusplus", "models/ttt.py"]
|
| 400 |
-
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2.ESMFold2Model" }
|
| 401 |
|
| 402 |
[[models]]
|
| 403 |
id = "esm2_8m"
|
|
@@ -1215,7 +1215,7 @@ official_files = [
|
|
| 1215 |
"config.json=git-sha1:79ed0dc0f867b8f09bfa004d6f77397c2ab9b38d",
|
| 1216 |
"model.safetensors=sha256:01358c317428d38535e3db513cab177336fc0f7fab0d84002e64b7741d5181b3",
|
| 1217 |
]
|
| 1218 |
-
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2_experimental.ESMFold2ExperimentalModel" }
|
| 1219 |
|
| 1220 |
[[models]]
|
| 1221 |
id = "esmfold2_experimental_fast_cutoff2025"
|
|
@@ -1236,4 +1236,4 @@ official_files = [
|
|
| 1236 |
"config.json=git-sha1:0333d68ddb12ed2f066741dcb801142f466c0a2c",
|
| 1237 |
"model.safetensors=sha256:4e903b740ad6ad704ec60881bfd593e0d6c874a630ffa0f0838276e0b665088f",
|
| 1238 |
]
|
| 1239 |
-
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2_experimental.ESMFold2ExperimentalModel" }
|
|
|
|
| 199 |
documentation = "docs/models.md#esm-and-esmc"
|
| 200 |
test_tiers = ["check", "compliance", "feature", "artifact", "benchmark"]
|
| 201 |
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/esm_plusplus", "models/ttt.py"]
|
| 202 |
+
auto_map = { AutoConfig = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusConfig", AutoModel = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusModel", AutoModelForMaskedLM = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusForMaskedLM", AutoModelForSequenceClassification = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esm_plusplus.modeling_esm_plusplus.ESMplusplusForTokenClassification" }
|
| 203 |
|
| 204 |
[families.esm3]
|
| 205 |
architecture = "ESM3"
|
|
|
|
| 223 |
documentation = "docs/models.md#esm3"
|
| 224 |
test_tiers = ["check", "compliance", "feature", "artifact", "benchmark"]
|
| 225 |
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/esm3", "models/ttt.py"]
|
| 226 |
+
auto_map = { AutoConfig = "fastplms.models.esm3.modeling_esm3.FastESM3Config", AutoModel = "fastplms.models.esm3.modeling_esm3.FastESM3Model", AutoModelForSequenceClassification = "fastplms.models.esm3.modeling_esm3.FastESM3ForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esm3.modeling_esm3.FastESM3ForTokenClassification" }
|
| 227 |
|
| 228 |
[families.e1]
|
| 229 |
architecture = "E1"
|
|
|
|
| 370 |
representative = "esmfold"
|
| 371 |
documentation = "docs/models.md#esmfold"
|
| 372 |
test_tiers = ["check", "compliance", "structure", "feature", "artifact", "benchmark"]
|
| 373 |
+
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/_esm_rotary.py", "models/classification_probe.py", "models/esmfold"]
|
| 374 |
+
auto_map = { AutoConfig = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmFoldConfig", AutoModel = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmForProteinFolding", AutoModelForSequenceClassification = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esmfold.modeling_fast_esmfold.FastEsmForTokenClassification" }
|
| 375 |
|
| 376 |
[families.esmfold2]
|
| 377 |
architecture = "ESMFold2"
|
|
|
|
| 396 |
representative = "esmfold2"
|
| 397 |
documentation = "docs/esmfold2.md"
|
| 398 |
test_tiers = ["check", "compliance", "structure", "feature", "artifact", "benchmark"]
|
| 399 |
+
runtime_paths = ["__init__.py", "registry.py", "runtime.py", "models.toml", "models/__init__.py", "attention", "embeddings", "models/classification_probe.py", "models/_esm_rotary.py", "models/esmfold2", "models/esm_plusplus", "models/ttt.py"]
|
| 400 |
+
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2.ESMFold2Model", AutoModelForSequenceClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ForTokenClassification" }
|
| 401 |
|
| 402 |
[[models]]
|
| 403 |
id = "esm2_8m"
|
|
|
|
| 1215 |
"config.json=git-sha1:79ed0dc0f867b8f09bfa004d6f77397c2ab9b38d",
|
| 1216 |
"model.safetensors=sha256:01358c317428d38535e3db513cab177336fc0f7fab0d84002e64b7741d5181b3",
|
| 1217 |
]
|
| 1218 |
+
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2_experimental.ESMFold2ExperimentalModel", AutoModelForSequenceClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ExperimentalForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ExperimentalForTokenClassification" }
|
| 1219 |
|
| 1220 |
[[models]]
|
| 1221 |
id = "esmfold2_experimental_fast_cutoff2025"
|
|
|
|
| 1236 |
"config.json=git-sha1:0333d68ddb12ed2f066741dcb801142f466c0a2c",
|
| 1237 |
"model.safetensors=sha256:4e903b740ad6ad704ec60881bfd593e0d6c874a630ffa0f0838276e0b665088f",
|
| 1238 |
]
|
| 1239 |
+
auto_map = { AutoConfig = "fastplms.models.esmfold2.configuration_esmfold2.ESMFold2Config", AutoModel = "fastplms.models.esmfold2.modeling_esmfold2_experimental.ESMFold2ExperimentalModel", AutoModelForSequenceClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ExperimentalForSequenceClassification", AutoModelForTokenClassification = "fastplms.models.esmfold2.modeling_esmfold2_classification.ESMFold2ExperimentalForTokenClassification" }
|
fastplms/models/esm3/__init__.py
CHANGED
|
@@ -1,4 +1,14 @@
|
|
| 1 |
-
from fastplms.models.esm3.modeling_esm3 import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
|
| 4 |
-
__all__ = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastplms.models.esm3.modeling_esm3 import (
|
| 2 |
+
FastESM3Config,
|
| 3 |
+
FastESM3ForSequenceClassification,
|
| 4 |
+
FastESM3ForTokenClassification,
|
| 5 |
+
FastESM3Model,
|
| 6 |
+
)
|
| 7 |
|
| 8 |
|
| 9 |
+
__all__ = [
|
| 10 |
+
"FastESM3Config",
|
| 11 |
+
"FastESM3ForSequenceClassification",
|
| 12 |
+
"FastESM3ForTokenClassification",
|
| 13 |
+
"FastESM3Model",
|
| 14 |
+
]
|
fastplms/models/esm3/modeling_esm3.py
CHANGED
|
@@ -16,21 +16,26 @@ import os
|
|
| 16 |
import shutil
|
| 17 |
import stat
|
| 18 |
import tempfile
|
| 19 |
-
import einops
|
| 20 |
-
import torch
|
| 21 |
-
import torch.nn as nn
|
| 22 |
-
import torch.nn.functional as F
|
| 23 |
from contextlib import contextmanager
|
| 24 |
from dataclasses import dataclass
|
| 25 |
from pathlib import Path, PurePosixPath
|
| 26 |
from typing import ClassVar
|
| 27 |
from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
from einops import rearrange
|
| 29 |
from tokenizers import Tokenizer
|
| 30 |
from tokenizers.models import BPE
|
| 31 |
from tokenizers.processors import TemplateProcessing
|
| 32 |
from transformers import PretrainedConfig, PreTrainedModel, PreTrainedTokenizerFast
|
| 33 |
-
from transformers.modeling_outputs import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
try:
|
|
@@ -652,6 +657,8 @@ def _render_saved_runtime_bridge(archive_hash: str, tree_hash: str) -> str:
|
|
| 652 |
'_modeling = _import_without_bytecode("fastplms.models.esm3.modeling_esm3")',
|
| 653 |
"FastESM3Config = _modeling.FastESM3Config",
|
| 654 |
"FastESM3Model = _modeling.FastESM3Model",
|
|
|
|
|
|
|
| 655 |
"",
|
| 656 |
]
|
| 657 |
return "\n".join(lines)
|
|
@@ -707,6 +714,9 @@ def _validate_saved_runtime_destination(save_directory: Path) -> None:
|
|
| 707 |
def _write_saved_runtime(
|
| 708 |
save_directory: Path,
|
| 709 |
prepared_runtime: tuple[bytes, dict[str, object], str] | None = None,
|
|
|
|
|
|
|
|
|
|
| 710 |
) -> None:
|
| 711 |
"""Make one ESM3 ``save_pretrained`` directory independently loadable."""
|
| 712 |
|
|
@@ -729,10 +739,12 @@ def _write_saved_runtime(
|
|
| 729 |
raise RuntimeError("Saved ESM3 config.json is missing or invalid.") from error
|
| 730 |
if not isinstance(config, dict):
|
| 731 |
raise RuntimeError("Saved ESM3 config.json must contain a JSON object.")
|
| 732 |
-
|
| 733 |
"AutoConfig": "modeling_fastplms.FastESM3Config",
|
| 734 |
"AutoModel": "modeling_fastplms.FastESM3Model",
|
| 735 |
}
|
|
|
|
|
|
|
| 736 |
config_payload = (json.dumps(config, indent=2, sort_keys=True) + "\n").encode("utf-8")
|
| 737 |
_replace_saved_runtime_file(config_path, config_payload)
|
| 738 |
|
|
@@ -2255,7 +2267,12 @@ class FastESM3Model(FastPLMTestTimeTrainingMixin, FastESM3PreTrainedModel, Embed
|
|
| 2255 |
_validate_saved_runtime_destination(save_path)
|
| 2256 |
prepared_runtime = _build_saved_runtime_archive(Path(__file__).resolve().parents[2])
|
| 2257 |
super().save_pretrained(save_directory, *args, **kwargs)
|
| 2258 |
-
_write_saved_runtime(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2259 |
|
| 2260 |
def tokenize_sequences(
|
| 2261 |
self,
|
|
@@ -2576,3 +2593,298 @@ class FastESM3Model(FastPLMTestTimeTrainingMixin, FastESM3PreTrainedModel, Embed
|
|
| 2576 |
if not return_dict:
|
| 2577 |
return result.to_tuple()
|
| 2578 |
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
import shutil
|
| 17 |
import stat
|
| 18 |
import tempfile
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
from contextlib import contextmanager
|
| 20 |
from dataclasses import dataclass
|
| 21 |
from pathlib import Path, PurePosixPath
|
| 22 |
from typing import ClassVar
|
| 23 |
from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
|
| 24 |
+
|
| 25 |
+
import einops
|
| 26 |
+
import torch
|
| 27 |
+
import torch.nn as nn
|
| 28 |
+
import torch.nn.functional as F
|
| 29 |
from einops import rearrange
|
| 30 |
from tokenizers import Tokenizer
|
| 31 |
from tokenizers.models import BPE
|
| 32 |
from tokenizers.processors import TemplateProcessing
|
| 33 |
from transformers import PretrainedConfig, PreTrainedModel, PreTrainedTokenizerFast
|
| 34 |
+
from transformers.modeling_outputs import (
|
| 35 |
+
ModelOutput,
|
| 36 |
+
SequenceClassifierOutput,
|
| 37 |
+
TokenClassifierOutput,
|
| 38 |
+
)
|
| 39 |
|
| 40 |
|
| 41 |
try:
|
|
|
|
| 657 |
'_modeling = _import_without_bytecode("fastplms.models.esm3.modeling_esm3")',
|
| 658 |
"FastESM3Config = _modeling.FastESM3Config",
|
| 659 |
"FastESM3Model = _modeling.FastESM3Model",
|
| 660 |
+
"FastESM3ForSequenceClassification = _modeling.FastESM3ForSequenceClassification",
|
| 661 |
+
"FastESM3ForTokenClassification = _modeling.FastESM3ForTokenClassification",
|
| 662 |
"",
|
| 663 |
]
|
| 664 |
return "\n".join(lines)
|
|
|
|
| 714 |
def _write_saved_runtime(
|
| 715 |
save_directory: Path,
|
| 716 |
prepared_runtime: tuple[bytes, dict[str, object], str] | None = None,
|
| 717 |
+
*,
|
| 718 |
+
auto_class: str = "AutoModel",
|
| 719 |
+
model_class: str = "FastESM3Model",
|
| 720 |
) -> None:
|
| 721 |
"""Make one ESM3 ``save_pretrained`` directory independently loadable."""
|
| 722 |
|
|
|
|
| 739 |
raise RuntimeError("Saved ESM3 config.json is missing or invalid.") from error
|
| 740 |
if not isinstance(config, dict):
|
| 741 |
raise RuntimeError("Saved ESM3 config.json must contain a JSON object.")
|
| 742 |
+
auto_map = {
|
| 743 |
"AutoConfig": "modeling_fastplms.FastESM3Config",
|
| 744 |
"AutoModel": "modeling_fastplms.FastESM3Model",
|
| 745 |
}
|
| 746 |
+
auto_map[auto_class] = f"modeling_fastplms.{model_class}"
|
| 747 |
+
config["auto_map"] = auto_map
|
| 748 |
config_payload = (json.dumps(config, indent=2, sort_keys=True) + "\n").encode("utf-8")
|
| 749 |
_replace_saved_runtime_file(config_path, config_payload)
|
| 750 |
|
|
|
|
| 2267 |
_validate_saved_runtime_destination(save_path)
|
| 2268 |
prepared_runtime = _build_saved_runtime_archive(Path(__file__).resolve().parents[2])
|
| 2269 |
super().save_pretrained(save_directory, *args, **kwargs)
|
| 2270 |
+
_write_saved_runtime(
|
| 2271 |
+
save_path,
|
| 2272 |
+
prepared_runtime,
|
| 2273 |
+
auto_class=self._auto_class,
|
| 2274 |
+
model_class=type(self).__name__,
|
| 2275 |
+
)
|
| 2276 |
|
| 2277 |
def tokenize_sequences(
|
| 2278 |
self,
|
|
|
|
| 2593 |
if not return_dict:
|
| 2594 |
return result.to_tuple()
|
| 2595 |
return result
|
| 2596 |
+
|
| 2597 |
+
|
| 2598 |
+
def _esm3_classifier_attention_mask(
|
| 2599 |
+
attention_mask: torch.Tensor | None,
|
| 2600 |
+
input_ids: torch.Tensor | None,
|
| 2601 |
+
sequence_tokens: torch.Tensor | None,
|
| 2602 |
+
) -> torch.Tensor | None:
|
| 2603 |
+
"""Infer padding attention for classifier calls that provide sequence tokens."""
|
| 2604 |
+
|
| 2605 |
+
if attention_mask is not None:
|
| 2606 |
+
return attention_mask
|
| 2607 |
+
tokens = sequence_tokens if sequence_tokens is not None else input_ids
|
| 2608 |
+
return None if tokens is None else tokens.ne(SEQUENCE_PAD_TOKEN)
|
| 2609 |
+
|
| 2610 |
+
|
| 2611 |
+
def _esm3_residue_mask(
|
| 2612 |
+
hidden_states: torch.Tensor,
|
| 2613 |
+
attention_mask: torch.Tensor | None,
|
| 2614 |
+
input_ids: torch.Tensor | None,
|
| 2615 |
+
sequence_tokens: torch.Tensor | None,
|
| 2616 |
+
) -> torch.Tensor:
|
| 2617 |
+
"""Select biological residue positions from one ESM3 token-aligned output."""
|
| 2618 |
+
|
| 2619 |
+
tokens = sequence_tokens if sequence_tokens is not None else input_ids
|
| 2620 |
+
if attention_mask is None:
|
| 2621 |
+
mask = torch.ones(hidden_states.shape[:2], dtype=torch.bool, device=hidden_states.device)
|
| 2622 |
+
else:
|
| 2623 |
+
mask = attention_mask.to(device=hidden_states.device, dtype=torch.bool)
|
| 2624 |
+
if tokens is not None:
|
| 2625 |
+
tokens = tokens.to(hidden_states.device)
|
| 2626 |
+
special = (
|
| 2627 |
+
tokens.eq(SEQUENCE_BOS_TOKEN)
|
| 2628 |
+
| tokens.eq(SEQUENCE_PAD_TOKEN)
|
| 2629 |
+
| tokens.eq(SEQUENCE_EOS_TOKEN)
|
| 2630 |
+
| tokens.eq(SEQUENCE_CHAINBREAK_TOKEN)
|
| 2631 |
+
)
|
| 2632 |
+
mask = mask & ~special
|
| 2633 |
+
return mask
|
| 2634 |
+
|
| 2635 |
+
|
| 2636 |
+
def _esm3_problem_type(
|
| 2637 |
+
config: FastESM3Config,
|
| 2638 |
+
num_labels: int,
|
| 2639 |
+
labels: torch.Tensor,
|
| 2640 |
+
) -> str:
|
| 2641 |
+
if config.problem_type is None:
|
| 2642 |
+
if num_labels == 1:
|
| 2643 |
+
config.problem_type = "regression"
|
| 2644 |
+
elif labels.dtype in (torch.long, torch.int):
|
| 2645 |
+
config.problem_type = "single_label_classification"
|
| 2646 |
+
else:
|
| 2647 |
+
config.problem_type = "multi_label_classification"
|
| 2648 |
+
if config.problem_type not in {
|
| 2649 |
+
"regression",
|
| 2650 |
+
"single_label_classification",
|
| 2651 |
+
"multi_label_classification",
|
| 2652 |
+
}:
|
| 2653 |
+
raise ValueError(f"Unsupported problem_type: {config.problem_type!r}.")
|
| 2654 |
+
return config.problem_type
|
| 2655 |
+
|
| 2656 |
+
|
| 2657 |
+
def _esm3_sequence_classification_loss(
|
| 2658 |
+
logits: torch.Tensor,
|
| 2659 |
+
labels: torch.Tensor,
|
| 2660 |
+
problem_type: str,
|
| 2661 |
+
num_labels: int,
|
| 2662 |
+
) -> torch.Tensor:
|
| 2663 |
+
labels = labels.to(logits.device)
|
| 2664 |
+
if problem_type == "regression":
|
| 2665 |
+
if num_labels == 1:
|
| 2666 |
+
return F.mse_loss(logits.reshape(-1), labels.reshape(-1))
|
| 2667 |
+
return F.mse_loss(logits, labels)
|
| 2668 |
+
if problem_type == "single_label_classification":
|
| 2669 |
+
return F.cross_entropy(logits.view(-1, num_labels), labels.view(-1))
|
| 2670 |
+
return F.binary_cross_entropy_with_logits(logits, labels)
|
| 2671 |
+
|
| 2672 |
+
|
| 2673 |
+
def _esm3_token_classification_loss(
|
| 2674 |
+
logits: torch.Tensor,
|
| 2675 |
+
labels: torch.Tensor,
|
| 2676 |
+
residue_mask: torch.Tensor,
|
| 2677 |
+
problem_type: str,
|
| 2678 |
+
num_labels: int,
|
| 2679 |
+
) -> torch.Tensor:
|
| 2680 |
+
labels = labels.to(logits.device)
|
| 2681 |
+
if problem_type == "single_label_classification":
|
| 2682 |
+
if labels.shape != logits.shape[:2]:
|
| 2683 |
+
raise ValueError(
|
| 2684 |
+
"Single-label token targets must have shape (batch, sequence); "
|
| 2685 |
+
f"received {tuple(labels.shape)} for logits {tuple(logits.shape)}."
|
| 2686 |
+
)
|
| 2687 |
+
targets = labels.masked_fill(~residue_mask, -100)
|
| 2688 |
+
return F.cross_entropy(
|
| 2689 |
+
logits.reshape(-1, num_labels),
|
| 2690 |
+
targets.reshape(-1),
|
| 2691 |
+
ignore_index=-100,
|
| 2692 |
+
)
|
| 2693 |
+
|
| 2694 |
+
if problem_type == "regression" and num_labels == 1 and labels.ndim == 2:
|
| 2695 |
+
labels = labels.unsqueeze(-1)
|
| 2696 |
+
if labels.shape != logits.shape:
|
| 2697 |
+
raise ValueError(
|
| 2698 |
+
"Token regression and multilabel targets must match the logits shape; "
|
| 2699 |
+
f"received {tuple(labels.shape)} and {tuple(logits.shape)}."
|
| 2700 |
+
)
|
| 2701 |
+
valid = residue_mask.unsqueeze(-1) & labels.ne(-100)
|
| 2702 |
+
if not bool(valid.any()):
|
| 2703 |
+
raise ValueError("Token labels do not contain a supervised biological residue.")
|
| 2704 |
+
if problem_type == "regression":
|
| 2705 |
+
return F.mse_loss(logits[valid], labels[valid])
|
| 2706 |
+
return F.binary_cross_entropy_with_logits(logits[valid], labels[valid])
|
| 2707 |
+
|
| 2708 |
+
|
| 2709 |
+
class FastESM3ForSequenceClassification(FastESM3Model):
|
| 2710 |
+
"""ESM3 with a padding-aware classifier over final residue embeddings."""
|
| 2711 |
+
|
| 2712 |
+
_auto_class = "AutoModelForSequenceClassification"
|
| 2713 |
+
|
| 2714 |
+
def __init__(self, config: FastESM3Config, **kwargs) -> None:
|
| 2715 |
+
super().__init__(config, **kwargs)
|
| 2716 |
+
self.num_labels = config.num_labels
|
| 2717 |
+
dropout = getattr(config, "classifier_dropout", 0.0)
|
| 2718 |
+
self.dropout = nn.Dropout(0.0 if dropout is None else float(dropout))
|
| 2719 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 2720 |
+
self.classifier.apply(self._init_weights)
|
| 2721 |
+
|
| 2722 |
+
def forward(
|
| 2723 |
+
self,
|
| 2724 |
+
input_ids: torch.Tensor | None = None,
|
| 2725 |
+
attention_mask: torch.Tensor | None = None,
|
| 2726 |
+
sequence_tokens: torch.Tensor | None = None,
|
| 2727 |
+
structure_tokens: torch.Tensor | None = None,
|
| 2728 |
+
ss8_tokens: torch.Tensor | None = None,
|
| 2729 |
+
sasa_tokens: torch.Tensor | None = None,
|
| 2730 |
+
function_tokens: torch.Tensor | None = None,
|
| 2731 |
+
residue_annotation_tokens: torch.Tensor | None = None,
|
| 2732 |
+
average_plddt: torch.Tensor | None = None,
|
| 2733 |
+
per_res_plddt: torch.Tensor | None = None,
|
| 2734 |
+
structure_coords: torch.Tensor | None = None,
|
| 2735 |
+
chain_id: torch.Tensor | None = None,
|
| 2736 |
+
sequence_id: torch.Tensor | None = None,
|
| 2737 |
+
labels: torch.Tensor | None = None,
|
| 2738 |
+
output_attentions: bool | None = None,
|
| 2739 |
+
output_hidden_states: bool | None = None,
|
| 2740 |
+
return_dict: bool | None = None,
|
| 2741 |
+
**kwargs,
|
| 2742 |
+
) -> SequenceClassifierOutput | tuple[torch.Tensor, ...]:
|
| 2743 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 2744 |
+
classifier_attention_mask = _esm3_classifier_attention_mask(
|
| 2745 |
+
attention_mask,
|
| 2746 |
+
input_ids,
|
| 2747 |
+
sequence_tokens,
|
| 2748 |
+
)
|
| 2749 |
+
output = super().forward(
|
| 2750 |
+
input_ids=input_ids,
|
| 2751 |
+
attention_mask=classifier_attention_mask,
|
| 2752 |
+
sequence_tokens=sequence_tokens,
|
| 2753 |
+
structure_tokens=structure_tokens,
|
| 2754 |
+
ss8_tokens=ss8_tokens,
|
| 2755 |
+
sasa_tokens=sasa_tokens,
|
| 2756 |
+
function_tokens=function_tokens,
|
| 2757 |
+
residue_annotation_tokens=residue_annotation_tokens,
|
| 2758 |
+
average_plddt=average_plddt,
|
| 2759 |
+
per_res_plddt=per_res_plddt,
|
| 2760 |
+
structure_coords=structure_coords,
|
| 2761 |
+
chain_id=chain_id,
|
| 2762 |
+
sequence_id=sequence_id,
|
| 2763 |
+
labels=None,
|
| 2764 |
+
output_attentions=output_attentions,
|
| 2765 |
+
output_hidden_states=output_hidden_states,
|
| 2766 |
+
return_dict=True,
|
| 2767 |
+
**kwargs,
|
| 2768 |
+
)
|
| 2769 |
+
hidden_states = output.last_hidden_state
|
| 2770 |
+
if hidden_states is None:
|
| 2771 |
+
raise RuntimeError("ESM3 did not return final residue embeddings.")
|
| 2772 |
+
residue_mask = _esm3_residue_mask(
|
| 2773 |
+
hidden_states,
|
| 2774 |
+
classifier_attention_mask,
|
| 2775 |
+
input_ids,
|
| 2776 |
+
sequence_tokens,
|
| 2777 |
+
)
|
| 2778 |
+
residue_counts = residue_mask.sum(dim=1, keepdim=True)
|
| 2779 |
+
if not bool(residue_counts.all()):
|
| 2780 |
+
raise ValueError("Sequence classification requires one biological residue per row.")
|
| 2781 |
+
pooled = (hidden_states * residue_mask.unsqueeze(-1)).sum(dim=1)
|
| 2782 |
+
pooled = pooled / residue_counts.to(hidden_states.dtype)
|
| 2783 |
+
logits = self.classifier(self.dropout(pooled))
|
| 2784 |
+
|
| 2785 |
+
loss = None
|
| 2786 |
+
if labels is not None:
|
| 2787 |
+
problem_type = _esm3_problem_type(self.config, self.num_labels, labels)
|
| 2788 |
+
loss = _esm3_sequence_classification_loss(
|
| 2789 |
+
logits,
|
| 2790 |
+
labels,
|
| 2791 |
+
problem_type,
|
| 2792 |
+
self.num_labels,
|
| 2793 |
+
)
|
| 2794 |
+
result = SequenceClassifierOutput(
|
| 2795 |
+
loss=loss,
|
| 2796 |
+
logits=logits,
|
| 2797 |
+
hidden_states=output.hidden_states,
|
| 2798 |
+
attentions=output.attentions,
|
| 2799 |
+
)
|
| 2800 |
+
return result if return_dict else result.to_tuple()
|
| 2801 |
+
|
| 2802 |
+
|
| 2803 |
+
class FastESM3ForTokenClassification(FastESM3Model):
|
| 2804 |
+
"""ESM3 with a token task head over final residue embeddings."""
|
| 2805 |
+
|
| 2806 |
+
_auto_class = "AutoModelForTokenClassification"
|
| 2807 |
+
|
| 2808 |
+
def __init__(self, config: FastESM3Config, **kwargs) -> None:
|
| 2809 |
+
super().__init__(config, **kwargs)
|
| 2810 |
+
self.num_labels = config.num_labels
|
| 2811 |
+
dropout = getattr(config, "classifier_dropout", 0.0)
|
| 2812 |
+
self.dropout = nn.Dropout(0.0 if dropout is None else float(dropout))
|
| 2813 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels)
|
| 2814 |
+
self.classifier.apply(self._init_weights)
|
| 2815 |
+
|
| 2816 |
+
def forward(
|
| 2817 |
+
self,
|
| 2818 |
+
input_ids: torch.Tensor | None = None,
|
| 2819 |
+
attention_mask: torch.Tensor | None = None,
|
| 2820 |
+
sequence_tokens: torch.Tensor | None = None,
|
| 2821 |
+
structure_tokens: torch.Tensor | None = None,
|
| 2822 |
+
ss8_tokens: torch.Tensor | None = None,
|
| 2823 |
+
sasa_tokens: torch.Tensor | None = None,
|
| 2824 |
+
function_tokens: torch.Tensor | None = None,
|
| 2825 |
+
residue_annotation_tokens: torch.Tensor | None = None,
|
| 2826 |
+
average_plddt: torch.Tensor | None = None,
|
| 2827 |
+
per_res_plddt: torch.Tensor | None = None,
|
| 2828 |
+
structure_coords: torch.Tensor | None = None,
|
| 2829 |
+
chain_id: torch.Tensor | None = None,
|
| 2830 |
+
sequence_id: torch.Tensor | None = None,
|
| 2831 |
+
labels: torch.Tensor | None = None,
|
| 2832 |
+
output_attentions: bool | None = None,
|
| 2833 |
+
output_hidden_states: bool | None = None,
|
| 2834 |
+
return_dict: bool | None = None,
|
| 2835 |
+
**kwargs,
|
| 2836 |
+
) -> TokenClassifierOutput | tuple[torch.Tensor, ...]:
|
| 2837 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 2838 |
+
classifier_attention_mask = _esm3_classifier_attention_mask(
|
| 2839 |
+
attention_mask,
|
| 2840 |
+
input_ids,
|
| 2841 |
+
sequence_tokens,
|
| 2842 |
+
)
|
| 2843 |
+
output = super().forward(
|
| 2844 |
+
input_ids=input_ids,
|
| 2845 |
+
attention_mask=classifier_attention_mask,
|
| 2846 |
+
sequence_tokens=sequence_tokens,
|
| 2847 |
+
structure_tokens=structure_tokens,
|
| 2848 |
+
ss8_tokens=ss8_tokens,
|
| 2849 |
+
sasa_tokens=sasa_tokens,
|
| 2850 |
+
function_tokens=function_tokens,
|
| 2851 |
+
residue_annotation_tokens=residue_annotation_tokens,
|
| 2852 |
+
average_plddt=average_plddt,
|
| 2853 |
+
per_res_plddt=per_res_plddt,
|
| 2854 |
+
structure_coords=structure_coords,
|
| 2855 |
+
chain_id=chain_id,
|
| 2856 |
+
sequence_id=sequence_id,
|
| 2857 |
+
labels=None,
|
| 2858 |
+
output_attentions=output_attentions,
|
| 2859 |
+
output_hidden_states=output_hidden_states,
|
| 2860 |
+
return_dict=True,
|
| 2861 |
+
**kwargs,
|
| 2862 |
+
)
|
| 2863 |
+
hidden_states = output.last_hidden_state
|
| 2864 |
+
if hidden_states is None:
|
| 2865 |
+
raise RuntimeError("ESM3 did not return final residue embeddings.")
|
| 2866 |
+
residue_mask = _esm3_residue_mask(
|
| 2867 |
+
hidden_states,
|
| 2868 |
+
classifier_attention_mask,
|
| 2869 |
+
input_ids,
|
| 2870 |
+
sequence_tokens,
|
| 2871 |
+
)
|
| 2872 |
+
logits = self.classifier(self.dropout(hidden_states))
|
| 2873 |
+
|
| 2874 |
+
loss = None
|
| 2875 |
+
if labels is not None:
|
| 2876 |
+
problem_type = _esm3_problem_type(self.config, self.num_labels, labels)
|
| 2877 |
+
loss = _esm3_token_classification_loss(
|
| 2878 |
+
logits,
|
| 2879 |
+
labels,
|
| 2880 |
+
residue_mask,
|
| 2881 |
+
problem_type,
|
| 2882 |
+
self.num_labels,
|
| 2883 |
+
)
|
| 2884 |
+
result = TokenClassifierOutput(
|
| 2885 |
+
loss=loss,
|
| 2886 |
+
logits=logits,
|
| 2887 |
+
hidden_states=output.hidden_states,
|
| 2888 |
+
attentions=output.attentions,
|
| 2889 |
+
)
|
| 2890 |
+
return result if return_dict else result.to_tuple()
|
fastplms_bundle.py
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
modeling_fastplms.py
CHANGED
|
@@ -8,11 +8,12 @@ import sys
|
|
| 8 |
import tempfile
|
| 9 |
from io import BytesIO
|
| 10 |
from pathlib import Path
|
|
|
|
| 11 |
from zipfile import ZIP_DEFLATED, ZipFile
|
| 12 |
|
| 13 |
from .fastplms_bundle import RUNTIME_DATA, RUNTIME_HASH
|
| 14 |
|
| 15 |
-
if RUNTIME_HASH != "
|
| 16 |
raise RuntimeError("FastPLMs runtime identity differs from the bridge.")
|
| 17 |
|
| 18 |
_RUNTIME_TEMPORARIES = []
|
|
@@ -179,8 +180,12 @@ def _install_runtime():
|
|
| 179 |
return package
|
| 180 |
|
| 181 |
_install_runtime()
|
| 182 |
-
|
| 183 |
-
FastESM3Config =
|
| 184 |
FastESM3Config.__module__ = __name__
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
FastESM3Model.__module__ = __name__
|
|
|
|
| 8 |
import tempfile
|
| 9 |
from io import BytesIO
|
| 10 |
from pathlib import Path
|
| 11 |
+
from typing import ClassVar
|
| 12 |
from zipfile import ZIP_DEFLATED, ZipFile
|
| 13 |
|
| 14 |
from .fastplms_bundle import RUNTIME_DATA, RUNTIME_HASH
|
| 15 |
|
| 16 |
+
if RUNTIME_HASH != "3471ed179d0b65b2145d6ee0069ad26a013096034f66661efa5a7e52aecba71d":
|
| 17 |
raise RuntimeError("FastPLMs runtime identity differs from the bridge.")
|
| 18 |
|
| 19 |
_RUNTIME_TEMPORARIES = []
|
|
|
|
| 180 |
return package
|
| 181 |
|
| 182 |
_install_runtime()
|
| 183 |
+
_module_182 = _import_without_bytecode("fastplms.models.esm3.modeling_esm3")
|
| 184 |
+
FastESM3Config = _module_182.FastESM3Config
|
| 185 |
FastESM3Config.__module__ = __name__
|
| 186 |
+
FastESM3ForSequenceClassification = _module_182.FastESM3ForSequenceClassification
|
| 187 |
+
FastESM3ForSequenceClassification.__module__ = __name__
|
| 188 |
+
FastESM3ForTokenClassification = _module_182.FastESM3ForTokenClassification
|
| 189 |
+
FastESM3ForTokenClassification.__module__ = __name__
|
| 190 |
+
FastESM3Model = _module_182.FastESM3Model
|
| 191 |
FastESM3Model.__module__ = __name__
|