Spaces:
Running on Zero
Running on Zero
| import os | |
| import re | |
| import gradio as gr | |
| import spaces | |
| import torch | |
| from transformers import LlamaForCausalLM, LlamaTokenizer | |
| from huggingface_hub import InferenceClient | |
| MODEL_NAME = "GreatCaptainNemo/ProLLaMA" | |
| print(f"Loading {MODEL_NAME} at startup (only happens once)...") | |
| tokenizer = LlamaTokenizer.from_pretrained(MODEL_NAME) | |
| model = LlamaForCausalLM.from_pretrained( | |
| MODEL_NAME, | |
| torch_dtype=torch.float32 | |
| ) | |
| model.eval() | |
| print("Model loaded.") | |
| KNOWN_SUPERFAMILIES = [ | |
| "Ankyrin repeat-containing domain superfamily", | |
| "Immunoglobulin-like fold", | |
| "TIM barrel", | |
| "Winged helix DNA-binding domain superfamily", | |
| "SH3-like domain superfamily", | |
| "Leucine-rich repeat domain superfamily", | |
| "Zinc finger domain superfamily", | |
| "Alpha/beta hydrolase fold", | |
| "P-loop containing nucleoside triphosphate hydrolase", | |
| "Globin-like superfamily", | |
| ] | |
| def extract_sequence(raw_output): | |
| raw_output = raw_output.upper() | |
| # Look for Seq=<...> | |
| match = re.search(r"SEQ=<([ACDEFGHIKLMNPQRSTVWY]+)>", raw_output) | |
| if match: | |
| return match.group(1) | |
| # Look for a line containing only amino acid letters | |
| for line in raw_output.splitlines(): | |
| line = line.strip() | |
| if re.fullmatch(r"[ACDEFGHIKLMNPQRSTVWY]{30,}", line): | |
| return line | |
| return "" | |
| def generate(description, max_new_tokens): | |
| model.to("cuda") | |
| prompt = f"""Design a protein sequence with the following function. | |
| Description: | |
| {description} | |
| Protein sequence: | |
| """ | |
| inputs = tokenizer(prompt, return_tensors="pt").to("cuda") | |
| with torch.no_grad(): | |
| output_ids = model.generate( | |
| **inputs, | |
| max_new_tokens=int(max_new_tokens), | |
| do_sample=True, | |
| top_p=0.9, | |
| temperature=0.8, | |
| repetition_penalty=1.2, | |
| pad_token_id=tokenizer.eos_token_id, | |
| ) | |
| # Decode ONLY the generated text | |
| generated_ids = output_ids[0][inputs["input_ids"].shape[1]:] | |
| raw = tokenizer.decode(generated_ids, skip_special_tokens=True) | |
| print("=" * 80) | |
| print("RAW MODEL OUTPUT:") | |
| print(raw) | |
| print("=" * 80) | |
| seq = extract_sequence(raw) | |
| return raw, seq | |
| demo = gr.Interface( | |
| fn=generate, | |
| inputs=[ | |
| gr.Textbox( | |
| label="Describe the protein you want", | |
| placeholder="e.g. a protein that binds to cancer cells", | |
| ), | |
| gr.Number( | |
| label="Max new tokens", | |
| value=200, | |
| ), | |
| ], | |
| outputs=[ | |
| gr.Textbox(label="Raw model output"), | |
| gr.Textbox(label="Extracted sequence"), | |
| ], | |
| description=( | |
| "IMPORTANT: this generates a sequence belonging to a structurally " | |
| "similar protein family. It is NOT validated to bind any specific " | |
| "target. Always verify predicted structures and experimentally " | |
| "validate any candidates." | |
| ), | |
| api_name="generate_protein", | |
| ) | |
| demo.launch() |