File size: 16,238 Bytes
3b99abb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
---
license: mit
language:
- en
- zh
tags:
- OneScience
- life-science
- protein
- protein-language-model
- structure-aware
- mutation-effect
- embedding
- inverse-folding
- SaProt
frameworks: PyTorch
---

<p align="center">
  <strong>
    <span style="font-size: 30px;">SaProt</span>
  </strong>
</p>

# Model Introduction

SaProt (Protein Language Modeling with Structure-aware Vocabulary) is a protein language model that jointly models protein amino acid sequences and structural information. Its central idea is to combine amino acids (AA) with the 3Di structural alphabet generated by Foldseek into structure-aware tokens, allowing the model to learn representations from both protein sequences and structural context.

SaProt can be used for protein representation extraction, zero-shot mutation effect prediction, protein inverse folding, and downstream task fine-tuning.

Paper:

> **SaProt: Protein Language Modeling with Structure-aware Vocabulary**  
> ICLR 2024 Spotlight  
> Follow-up work was published in Nature Biotechnology (2025)

# Model Description

SaProt models proteins using a structure-aware vocabulary formed by combining amino acids (AA) with the Foldseek 3Di structural alphabet.

For example, a structure-aware sequence can be represented as:

```text
M#EvVpQpL#VyQdYaKv
```

Every two characters form a structure-aware token: the first character represents the amino acid, and the second represents the corresponding 3Di structural state. `#` can be used to mask low-confidence structural regions.

The official release provides pretrained models at multiple scales:

| Model | Parameter scale | Training data |
| --- | ---: | --- |
| `SaProt_35M_AF2` | 35M | 40M AF2 structures |
| `SaProt_650M_PDB` | 650M | 40M AF2 structures + 60K PDB structures |
| `SaProt_650M_AF2` | 650M | 40M AF2 structures |
| `SaProt_1.3B_AF2` | 1.3B | 40M AF2 structures |
| `SaProt_1.3B_AFDB_OMG_NCBI` | 1.3B | AFDB + OMG_prot50 + NCBI |

For the 35M and 650M SaProt models, the official recommendation is to use SA-token inputs containing structural information for the best results. The 1.3B version can handle both structure-aware sequences and amino-acid-only sequences relatively well.

# Use Cases

| Use case | Description |
| --- | --- |
| Protein representation extraction | Extract residue-level or protein-level embeddings |
| Zero-shot mutation effect prediction | Evaluate single or multiple mutations directly without task-specific fine-tuning |
| Structure-aware protein modeling | Jointly use amino acid and 3Di structural tokens |
| Protein inverse folding | Design sequences from structural information |
| Downstream task fine-tuning | Apply to tasks such as EC, GO, stability, PPI, Contact, and DeepLoc |

# Usage

## 1. Using OneCode

Experience intelligent one-click AI4S programming in the OneCode online environment:

[Try intelligent one-click AI4S programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)

## 2. Manual Installation and Usage

**Hardware Requirements**

- SaProt supports inference on CPUs and GPUs/DCUs.
- The 35M model can be used for lightweight testing; GPUs/DCUs are recommended for the 650M and 1.3B models.
- Batch embedding, mutation scanning, pretraining, and fine-tuning substantially increase GPU memory and host memory requirements.

### Set Up the Runtime Environment

#### DCU Environment

```bash
# Activate DTK and CONDA first
conda create -n onescience311 python=3.11 -y
conda activate onescience311

pip install onescience[bio] \
  -i http://mirrors.onescience.ai:3141/pypi/simple/ \
  --trusted-host mirrors.onescience.ai
```

#### Environment Notes

- If you encounter missing dependencies or version incompatibilities during execution, refer to the dependency versions specified in `requirements.txt` and install or adjust the relevant dependencies as needed.

### Prepare Models and Data

#### 1) SaProt Model Weights

The official models are primarily released on Hugging Face:

```text
SaProt_35M_AF2
https://huggingface.co/westlake-repl/SaProt_35M_AF2

SaProt_650M_PDB
https://huggingface.co/westlake-repl/SaProt_650M_PDB

SaProt_650M_AF2
https://huggingface.co/westlake-repl/SaProt_650M_AF2

SaProt_1.3B_AF2
https://huggingface.co/westlake-repl/SaProt_1.3B_AF2

SaProt_1.3B_AFDB_OMG_NCBI
https://huggingface.co/westlake-repl/SaProt_1.3B_AFDB_OMG_NCBI
```

For example, download `SaProt_650M_AF2` in advance for offline use:

```bash
huggingface-cli download \
  westlake-repl/SaProt_650M_AF2 \
  --local-dir ./weight/PLMs/SaProt_650M_AF2
```

It is recommended to download all model weights under `weight/PLMs/`. The current SaProt configuration reads from:

```text
weight/PLMs/SaProt_650M_AF2
```

To run the ESM2 comparison experiment, also prepare:

```bash
huggingface-cli download \
  facebook/esm2_t33_650M_UR50D \
  --local-dir ./weight/PLMs/esm2_t33_650M_UR50D
```

The corresponding configuration reads from:

```text
weight/PLMs/esm2_t33_650M_UR50D
```

#### 2) Foldseek

SaProt structure-aware inputs require PDB/CIF structures to be encoded as Foldseek 3Di sequences first. The official README provides the following download link:

```text
https://drive.google.com/file/d/1B_9t3n_nlj8Y3Kpc_mMjtMdY0OPYa7Re/view
```

You can also use the official Foldseek Linux prebuilt package or a Foldseek installation already available on the system or platform.

For this adapted version, place Foldseek at:

```text
SaProt/
└── scripts/
    └── bin/
        └── foldseek
```

Then grant it execute permission:

```bash
chmod +x scripts/bin/foldseek
```

The Foldseek path used by the current configuration is:

```text
scripts/bin/foldseek
```

#### 3) Downstream Task Datasets

The official downstream task datasets are available at:

```text
https://drive.google.com/drive/folders/11dNGqPYfLE3M-Mbh4U7IQpuHxJpuRr4g?usp=sharing
```

For this adapted version, extract the downstream task data to:

```text
scripts/LMDB/
```

Typical paths used by the configuration include:

```text
scripts/LMDB/Thermostability/foldseek/train
scripts/LMDB/Thermostability/foldseek/valid
scripts/LMDB/Thermostability/foldseek/test
scripts/LMDB/ProteinGym/substitutions
scripts/LMDB/ClinVar
```

#### 4) Pretraining Dataset

To pretrain SaProt from scratch or continue pretraining, prepare the official pretraining data:

```text
westlake-repl/AF2_UniRef50
https://huggingface.co/datasets/westlake-repl/AF2_UniRef50
```

The official pretraining configuration uses LMDB data directories such as:

```text
scripts/LMDB/AF2_Uniref50/foldseek/train
scripts/LMDB/AF2_Uniref50/foldseek/valid
```

The pretraining dataset is large and is only needed when pretraining from scratch or continuing pretraining.

## 3. Quick Start

### Download the Model Package

```bash
hf download OneScience-Group/SaProt \
  --local-dir ./SaProt

cd SaProt
```

### Quick Verification

Check the dependencies:

```bash
python - <<'PY'
import torch
import transformers
import esm
import pytorch_lightning as pl

print("torch:", torch.__version__)
print("transformers:", transformers.__version__)
print("pytorch_lightning:", pl.__version__)
print("SaProt dependencies OK")
PY
```

Check Foldseek:

```bash
./scripts/bin/foldseek version
```

Test model loading:

```bash
python - <<'PY'
from transformers import EsmTokenizer, EsmForMaskedLM

model_path = "./weight/PLMs/SaProt_650M_AF2"

tokenizer = EsmTokenizer.from_pretrained(model_path)
model = EsmForMaskedLM.from_pretrained(model_path)

print("SaProt load OK")
PY
```

# Example Data

The official repository provides:

```text
scripts/example/8ac8.cif
```

This can be used to demonstrate conversion from a protein structure to a structure-aware sequence.

Your own structure input can be:

```text
*.pdb
*.cif
```

If you already have a Foldseek-encoded structure-aware sequence, you can pass it directly to SaProt without processing the structure file again.

# Inference Examples

## Load SaProt for Forward Inference

```bash
python - <<'PY'
import torch
from transformers import EsmTokenizer, EsmForMaskedLM

model_path = "weight/PLMs/SaProt_650M_AF2"
device = "cuda" if torch.cuda.is_available() else "cpu"

tokenizer = EsmTokenizer.from_pretrained(model_path)
model = EsmForMaskedLM.from_pretrained(model_path)
model.to(device)
model.eval()

seq = "M#EvVpQpL#VyQdYaKv"
tokens = tokenizer.tokenize(seq)
print(tokens)

inputs = tokenizer(seq, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}

with torch.no_grad():
    outputs = model(**inputs)

print(outputs.logits.shape)
PY
```

## Load SaProt with the ESM Interface

If the model directory contains `SaProt_650M_AF2.pt`, you can use the ESM loading function provided by the project:

```bash
python - <<'PY'
from scripts.utils.esm_loader import load_esm_saprot

model_path = "weight/PLMs/SaProt_650M_AF2/SaProt_650M_AF2.pt"
model, alphabet = load_esm_saprot(model_path)

print("ESM SaProt load OK")
PY
```

## Convert a Structure File to a Structure-Aware Sequence

```bash
python - <<'PY'
from scripts.utils.foldseek_util import get_struc_seq

pdb_path = "scripts/example/8ac8.cif"

parsed_seqs = get_struc_seq("scripts/bin/foldseek", pdb_path, ["A"], plddt_mask=False)["A"]
seq, foldseek_seq, combined_seq = parsed_seqs

print(f"seq: {seq}")
print(f"foldseek_seq: {foldseek_seq}")
print(f"combined_seq: {combined_seq}")
PY
```

The `A` chain selection extracts only chain A from the structure file. The `combined_seq` in the returned result is a structure-aware sequence that can be used directly by SaProt.

## Mutation Effect Prediction

```bash
python - <<'PY'
import torch
from model.saprot.saprot_foldseek_mutation_model import SaprotFoldseekMutationModel

config = {
    "foldseek_path": None,
    "config_path": "weight/PLMs/SaProt_650M_AF2",
    "load_pretrained": True,
}
model = SaprotFoldseekMutationModel(**config)
tokenizer = model.tokenizer

device = "cuda" if torch.cuda.is_available() else "cpu"
model.eval()
model.to(device)

seq = "M#EvVpQpL#VyQdYaKv"

mut_info = "V3A"
mut_value = model.predict_mut(seq, mut_info)
print(mut_value)

mut_info = "V3A:Q4M"
mut_value = model.predict_mut(seq, mut_info)
print(mut_value)

mut_pos = 3
mut_dict = model.predict_pos_mut(seq, mut_pos)
print(mut_dict)

mut_pos = 3
mut_dict = model.predict_pos_prob(seq, mut_pos)
print(mut_dict)
PY
```

## Extract Protein Embeddings

```bash
python - <<'PY'
import torch
from model.saprot.base import SaprotBaseModel
from transformers import EsmTokenizer

config = {
    "task": "base",
    "config_path": "weight/PLMs/SaProt_650M_AF2",
    "load_pretrained": True,
}

model = SaprotBaseModel(**config)
tokenizer = EsmTokenizer.from_pretrained(config["config_path"])

device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
model.eval()

seq = "M#EvVpQpL#VyQdYaKv"
tokens = tokenizer.tokenize(seq)
print(tokens)

inputs = tokenizer(seq, return_tensors="pt")
inputs = {k: v.to(device) for k, v in inputs.items()}

with torch.no_grad():
    embeddings = model.get_hidden_states(inputs, reduction="mean")

print(embeddings[0].shape)
PY
```

## Protein Inverse Folding

Inverse folding requires additional inverse folding model weights:

```text
https://huggingface.co/westlake-repl/SaProt_650M_AF2_inverse_folding
```

After downloading, place them at:

```text
weight/PLMs/SaProt_650M_AF2_inverse_folding
```

Example:

```bash
python - <<'PY'
import torch
from model.saprot.saprot_if_model import SaProtIFModel

config = {
    "config_path": "weight/PLMs/SaProt_650M_AF2_inverse_folding",
    "load_pretrained": True,
}

device = "cuda" if torch.cuda.is_available() else "cpu"
model = SaProtIFModel(**config)
model = model.to(device)

aa_seq = "##########"
struc_seq = "dddddddddd"

pred_aa_seq = model.predict(aa_seq, struc_seq)
print(pred_aa_seq)
PY
```

# Training

This repository uses a unified training entry point:

```bash
python scripts/training.py -c <config_path>
```

Configuration files are located in `conf/`, model code is located in `model/`, and data processing and utility code is located in `scripts/`. The current configuration uses the pretrained model weights in `weight/PLMs/SaProt_650M_AF2` by default.

## Pretraining

To pretrain SaProt from scratch or continue pretraining, first prepare the pretraining LMDB dataset, then run:

```bash
python scripts/training.py -c conf/pretrain/saprot.yaml
```

This configuration reads from the following paths by default:

```text
scripts/LMDB/AF2_Uniref50/foldseek/train
scripts/LMDB/AF2_Uniref50/foldseek/valid
```

## Downstream Fine-Tuning

Use the following commands to fine-tune SaProt on downstream tasks:

```bash
# Thermostability
python scripts/training.py -c conf/Thermostability/saprot.yaml

# EC
python scripts/training.py -c conf/EC/saprot.yaml

# GO
python scripts/training.py -c conf/GO/MF/saprot.yaml
python scripts/training.py -c conf/GO/BP/saprot.yaml
python scripts/training.py -c conf/GO/CC/saprot.yaml

# Metal ion binding
python scripts/training.py -c conf/MetalIonBinding/saprot.yaml

# Human PPI
python scripts/training.py -c conf/HumanPPI/saprot.yaml

# Contact prediction
python scripts/training.py -c conf/Contact/saprot.yaml

# DeepLoc
python scripts/training.py -c conf/DeepLoc/cls2/saprot.yaml
python scripts/training.py -c conf/DeepLoc/cls10/saprot.yaml
```

For single-GPU or limited-memory environments, use `conf/scnet/Thermostability_saprot_1gpu.yaml` as a starting point:

```bash
python scripts/training.py -c conf/scnet/Thermostability_saprot_1gpu.yaml
```

## Zero-Shot Mutation Effect Evaluation

ProteinGym evaluation:

```bash
python scripts/mutation_zeroshot.py -c conf/ProteinGym/saprot.yaml
```

The output file is saved by default to:

```text
output/ProteinGym/SaProt_650M_AF2.tsv
```

ClinVar evaluation:

```bash
python scripts/mutation_zeroshot.py -c conf/ClinVar/saprot.yaml
python scripts/compute_clinvar_auc.py -c conf/ClinVar/saprot.yaml
```

ClinVar prediction results are saved by default to:

```text
output/ClinVar/SaProt_650M_AF2
```

Single-GPU environments can also use the adapted configuration:

```bash
python scripts/mutation_zeroshot.py -c conf/scnet/ClinVar_saprot.yaml
python scripts/compute_clinvar_auc.py -c conf/scnet/ClinVar_saprot.yaml
```

## ESM2 Comparison Experiment

To run the ESM2 baseline, additionally prepare the weights in `weight/PLMs/esm2_t33_650M_UR50D` and the corresponding normal LMDB data. Example commands:

```bash
python scripts/training.py -c conf/Thermostability/esm2.yaml
python scripts/mutation_zeroshot.py -c conf/ProteinGym/esm2.yaml
```

# Output Description

| Task | Main output |
| --- | --- |
| Structure encoding | AA sequence, 3Di sequence, and structure-aware sequence |
| Model forward pass | Token-level logits |
| Protein representation | Residue-level/protein-level embeddings |
| Mutation effect prediction | Mutation score |
| Zero-shot evaluation | ProteinGym Spearman results or ClinVar AUC results |
| Inverse folding | Protein sequences generated or evaluated under structural conditions |
| Downstream fine-tuning | Prediction results and model checkpoint for the corresponding task |

# Official OneScience Information

| Platform | Main OneScience repository | Skills repository |
| --- | --- | --- |
| Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
| GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |

# Citation and License

- The official SaProt source repository is released under the **MIT License**, which permits use, modification, distribution, sublicensing, and commercial use. When copying or distributing it, retain the original copyright notice and the MIT License text.

- SaProt model weights are released independently through Hugging Face. For commercial use, redistribution, or other purposes, check and comply with the license on each corresponding model page. The relevant pretraining and downstream datasets are also subject to the licenses and terms of use on their respective dataset pages.

- This repository is a **DCU-adapted version** of SaProt. Use of the repository code, model weights, and related data remains subject to the licenses and terms of use of their respective original projects.