AlienChen's picture
download
raw
5.84 kB
#!/usr/bin/env python3
"""
EditFlows sequence generation script.
Takes checkpoint and sampling parameters, and either a single input sequence
or a FASTA file. For each input, runs the EditFlows model to generate one
new sequence and prints it as it is generated. When input is a FASTA, the
script outputs a FASTA of all generated sequences (to stdout and optionally
to a file via --output_fasta).
"""
import argparse
import sys
import torch
import yaml
from easydict import EasyDict as edict
import sys
sys.path.append('/scratch/pranamlab/tong/pCoMol')
from model.reparam_models import EditFlow, ProteinEditFlowModel
from model.utils import generate_from_x0, generate_from_x0_multi_edit
from transformers import AutoModel, AutoTokenizer
from logic import flow
# from pcomol_cas import short_rollout_batch
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 = AutoTokenizer.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 main():
# parser = argparse.ArgumentParser(
# description="Generate sequences with EditFlows model from one or more inputs."
# )
# parser.add_argument(
# "--pcomol_config",
# type=str,
# required=True,
# help="Path to pcomol/config YAML (e.g. configs/config_peptides.yaml)",
# )
# parser.add_argument(
# "--ckpt",
# type=str,
# required=True,
# help="Path to model checkpoint (.ckpt)",
# )
# group = parser.add_mutually_exclusive_group(required=True)
# group.add_argument(
# "--input",
# type=str,
# help="Single input sequence string",
# )
# group.add_argument(
# "--input_fasta",
# type=str,
# help="Path to FASTA file of input sequences",
# )
# parser.add_argument(
# "--output_fasta",
# type=str,
# default=None,
# help="When using --input_fasta, write generated sequences to this FASTA file (default: only stdout)",
# )
# # Sampling parameters (aligned with pcomol_cas.py)
# parser.add_argument(
# "--num_steps",
# type=int,
# default=32,
# help="Number of flow steps (default: 32)",
# )
# parser.add_argument(
# "--max_len_cap",
# type=int,
# default=None,
# help="Maximum sequence length cap (default: None)",
# )
# parser.add_argument(
# "--deletion_rate_scale",
# type=float,
# default=1,
# help="Scaling factor for deletion rate (default: 1)",
# )
# parser.add_argument(
# "--zero_lam_ins",
# action="store_true",
# help="Set insertion rate to 0 (deletions and substitutions only)",
# )
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, weights_only=False)
editflow.load_state_dict(ckpt["state_dict"], strict=False)
model = editflow.model.to(device)
model.eval()
allowed_tokens = torch.tensor(
[tok for tok in source_dist._allowed_tokens if tok not in (eps_id,)],
device=device,
dtype=torch.long,
)
time_grid = torch.linspace(0.0, 1.0, steps=args.num_steps, device=device)
x0 = tokenizer(args.input, return_tensors='pt')['input_ids'].to(device)
with torch.no_grad():
x_T = generate_from_x0(
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 = tokenizer.decode(x_T.squeeze(0))
out_str = out_str.replace(" ", "")[5:-5].strip()
print(out_str)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
5.84 kB
·
Xet hash:
082d35f7231bc149dc83cb26a0fe33bbe25600fb6758f19e93d2c0a40c02ec43

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