AlienChen/Storage / pCoMole /gfp /generate.py
AlienChen's picture
download
raw
4.8 kB
import argparse
import torch
import yaml
from easydict import EasyDict as edict
from constraints import GFP
import sys
sys.path.append('/scratch/pranamlab/tong/pCoMol')
# from model.base_models import EditFlow, ProteinEditFlowModel, SMILESEditFlowModel
from model.reparam_models import EditFlow, ProteinEditFlowModel
from model.utils import generate_from_x0, generate_from_x0_multi_edit
from logic import flow
# tokenizers used in train.py
from transformers import EsmTokenizer
import pdb
def build_model_and_stuff(cfg, device):
"""
Rebuild exactly what train.py builds, but we won't set up lightning Trainer.
Returns:
editflow_module (LightningModule)
source_dist
(pad_id, bos_id, eos_id)
"""
tokenizer = EsmTokenizer.from_pretrained("facebook/esm2_t33_650M_UR50D")
vocab_size = 24
source_distribution = flow.get_source_distribution(
source_distribution=cfg.flow.source_distribution,
vocab_size=vocab_size,
special_token_ids=[0, 1, 2, 3],
)
pad_id = 1
bos_id = 0
eos_id = 2
model = ProteinEditFlowModel(vocab_size=vocab_size, pad_id=pad_id, config=cfg.model)
eps_id = getattr(cfg.flow, "eps_id", -1)
path = flow.get_path(
scheduler_type=cfg.flow.scheduler_type,
exponent=cfg.flow.exponent,
eps_id=eps_id,
)
loss_fn = flow.get_loss_function(
loss_function=cfg.flow.loss_function,
path=path,
)
editflow = EditFlow(
model,
loss_fn,
path,
source_distribution,
pad_id,
bos_id,
eos_id,
cfg,
).to(device)
return editflow, source_distribution, tokenizer, pad_id, bos_id, eos_id, eps_id
def tokenize_input_str(input_str, tokenizer, bos_id, eos_id, device):
toks = tokenizer(input_str, return_tensors='pt')
ids = toks["input_ids"][0].to(device)
if ids[0].item() != bos_id:
ids = torch.cat([torch.tensor([bos_id], device=device), ids], dim=0)
if ids[-1].item() != eos_id:
ids = torch.cat([ids, torch.tensor([eos_id], device=device)], dim=0)
x0 = ids.unsqueeze(0) # (1, L)
return x0
def detokenize_output(x, tokenizer, bos_id, eos_id, pad_id):
"""
Convert a single generated sequence (1, L) back to string.
"""
seq = x[0].tolist()
# strip padding
seq = [tok for tok in seq if tok != pad_id]
# strip BOS/EOS
if len(seq) > 0 and seq[0] == bos_id:
seq = seq[1:]
if len(seq) > 0 and seq[-1] == eos_id:
seq = seq[:-1]
return tokenizer.batch_decode([seq], skip_special_tokens=True)[0]
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--config", type=str, default="./configs/config_test.yaml")
parser.add_argument("--ckpt", type=str, required=True, help="path to lightning checkpoint (.ckpt)")
parser.add_argument("--input", type=str, required=True, help="input x_0 as raw string (smiles/protein/selfies)")
parser.add_argument("--num_steps", type=int, default=32)
parser.add_argument("--max_len_cap", type=int, default=None)
parser.add_argument("--op_temperature", type=float, default=1)
parser.add_argument("--token_temperature", type=float, default=1)
args = parser.parse_args()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
with open(args.config, "r") as f:
cfg = edict(yaml.safe_load(f))
editflow, source_dist, tokenizer, pad_id, bos_id, eos_id, eps_id = build_model_and_stuff(cfg, device)
ckpt = torch.load(args.ckpt, map_location=device)
editflow.load_state_dict(ckpt["state_dict"], strict=False)
model = editflow.model.to(device)
model.eval()
x0 = tokenize_input_str(args.input, tokenizer, bos_id, eos_id, device)
allowed_tokens = torch.tensor(
[tok for tok in source_dist._allowed_tokens if tok not in (eps_id,) and tok not in range(24,33)],
device=device,
dtype=torch.long,
)
x_gen = generate_from_x0_multi_edit(
model,
x0,
pad_id=pad_id,
bos_id=bos_id,
eos_id=eos_id,
allowed_tokens=allowed_tokens,
num_steps=args.num_steps,
max_len_cap=args.max_len_cap,
op_temperature=args.op_temperature, # soften op choice
token_temperature=args.token_temperature, # soften token choice
)
out_str = detokenize_output(x_gen, tokenizer, bos_id, eos_id, pad_id)
out_str = out_str.replace(' ', '')
print(len(out_str))
print('----------------------------')
print(f"Input Sequence: {args.input}\n")
print(f"Designed Sequence: {out_str}\n")
gfp_classifier = GFP(device)
gfp_probs = gfp_classifier.get_scores(out_str, return_probs=True)
print(gfp_probs)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
4.8 kB
·
Xet hash:
8db46e9ef400180757d9d0c99d78f0b301d54f78e9143a96398dd4c9b0ce5546

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.