Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import torch | |
| import pandas as pd | |
| from transformers import AutoModelForSequenceClassification, BertTokenizerFast | |
| #Setting up the model | |
| model_save_path = "Kelmoir/2026-02-14_CAFA6_classification_Rostlab_prot_bert_v1" | |
| model = AutoModelForSequenceClassification.from_pretrained(model_save_path) | |
| tokenizer = BertTokenizerFast.from_pretrained("Rostlab/prot_bert", | |
| do_lower_case=False) | |
| # Setting up the computation device - cuda or CPU | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| # Get the id2label | |
| id2label = model.config.id2label | |
| model.to(device) | |
| def prepare_for_tokenization(input_prot_seq: str)-> str: | |
| """ | |
| This function shall insert a [SPACE] between each protein sequence item, and returns the resulting string, | |
| also, uppercases the sting and replaces unlike proteins | |
| A maximum length of 1024 is enforced as was used for model training | |
| """ | |
| if len(input_prot_seq) > 1024: | |
| input_prot_seq = input_prot_seq[:1024] | |
| input_prot_seq = input_prot_seq.strip().upper().replace(r"[UZOB]", "X") | |
| spaces = " "*len(input_prot_seq) | |
| # Source - https://stackoverflow.com/a | |
| # Posted by Ma0, modified by community. See post 'Timeline' for change history | |
| # Retrieved 2026-01-12, License - CC BY-SA 3.0 | |
| return ''.join(map(''.join, zip(input_prot_seq, spaces))).strip() # kudos @Coldspeed | |
| def process_result(logits, threshold=0.6, top_n=10): | |
| """ | |
| This function will take in a single protein logit prediction and turns it into alist of predicted GO-terms | |
| Args: | |
| **logits** a single Logit array | |
| **threshold** A float value between 0 and 1. Only GO-terms with a score higher than this value will be considered. | |
| **top_n** An integer value. If no GO-terms are above the threshold, the top_n GO-terms will be returned. | |
| Ensure, that the length is equal | |
| """ | |
| all_results = [] | |
| # Convert logits to probabilities using sigmoid | |
| probabilities = torch.sigmoid(logits).squeeze() | |
| # Get indices of GO terms above threshold | |
| above_threshold_indices = torch.where(probabilities > threshold)[0] | |
| # If no terms above threshold, take the top_n terms | |
| if len(above_threshold_indices) == 0: | |
| top_n_values, top_n_indices = torch.topk(probabilities, k=min(top_n, len(probabilities))) | |
| selected_indices = top_n_indices | |
| selected_probabilities = top_n_values | |
| else: | |
| selected_indices = above_threshold_indices | |
| selected_probabilities = probabilities[above_threshold_indices] | |
| # Sort selected terms by probability in descending order | |
| sorted_probabilities, sort_indices = torch.sort(selected_probabilities, descending=True) | |
| sorted_indices = selected_indices[sort_indices] | |
| for idx, prob in zip(sorted_indices, sorted_probabilities): | |
| go_term = id2label[idx.item()] | |
| score = prob.item() | |
| all_results.append([go_term, f"{score:.3f}"]) # Format score to 3 decimal places | |
| results_df = pd.DataFrame(all_results) | |
| # The request specifies 3 columns, all string, no headers, no index | |
| return results_df | |
| def predict_on_input(input: str, threshold:float): | |
| model.eval() | |
| with torch.inference_mode(): | |
| tokenized = tokenizer(prepare_for_tokenization(input), | |
| return_tensors="pt").to(device) | |
| output_logits = model(**tokenized) | |
| output_table = process_result(output_logits.logits, | |
| threshold=threshold) | |
| return output_table | |
| description = """ | |
| This is a demo project to showcase my attempts at predicting the protein functions - known as GO-terms based of the protein amino acid string. | |
| This is essentially the scope of the CAFA 6 challenge that was hosted on Kaggle - https://www.kaggle.com/competitions/cafa-6-protein-function-prediction/overview | |
| This demo takes in a single protein sequence, and will then predict the corresonding GO-terms based of that, and display the score. | |
| Right now, no further post-processing or frills are available. | |
| The model used to perform the predictions is a fine tuned ProtBERT Model. See: https://huggingface.co/Rostlab/prot_bert | |
| And finally, the model isn't to good right now, there is much more experimentation ahead. For instance, the example was reported with the following GO-terms: | |
| - GO:1990837 | |
| - GO:0005515 | |
| """ | |
| demo = gr.Interface( | |
| fn = predict_on_input, | |
| inputs = [ | |
| gr.Textbox(value="MHHRMNEMNLSPVGMEQLTSSSVSNALPVSGSHLGLAASPTHSAIPAPGLPVAIPNLGPSLSSLPSALSLMLPMGIGDRGVMCGLPERNYTLPPPPYPHLESSYFRTILPGILSYLADRPPPQYIHPNSINVDGNTALSITNNPSALDPYQSNGNVGLEPGIVSIDSRSVNTHGAQSLHPSDGHEVALDTAITMENVSRVTSPISTDGMAEELTMDGVAGEHSQIPNGSRSHEPLSVDSVSNNLAADAVGHGGVIPMHGNGLELPVVMETDHIASRVNGMSDSALSDSIHTVAMSTNSVSVALSTSHNLASLESVSLHEVGLSLEPVAVSSITQEVAMGTGHVDVSSDSLSFVSPSLQMEDSNSNKENMATLFTIWCTLCDRAYPSDCPEHGPVTFVPDTPIESRARLSLPKQLVLRQSIVGAEVGVWTGETIPVRTCFGPLIGQQSHSMEVAEWTDKAVNHIWKIYHNGVLEFCIITTDENECNWMMFVRKARNREEQNLVAYPHDGKIFFCTSQDIPPENELLFYYSRDYAQQIGVPEHPDVHLCNCGKECNSYTEFKAHLTSHIHNHLPTQGHSGSHGPSHSKERKWKCSMCPQAFISPSKLHVHFMGHMGMKPHKCDFCSKAFSDPSNLRTHLKIHTGQKNYRCTLCDKSFTQKAHLESHMVIHTGEKNLKCDYCDKLFMRRQDLKQHVLIHTQERQIKCPKCDKLFLRTNHLKKHLNSHEGKRDYVCEKCTKAYLTKYHLTRHLKTCKGPTSSSSAPEEEEEDDSEEEDLADSVGTEDCRINSAVYSADESLSAHK", | |
| label="Protein sequence", | |
| show_label=True), | |
| gr.Slider(minimum = -1, | |
| maximum = 1, | |
| step= 0.01, | |
| value=0.25, | |
| label="Prediction threshold", | |
| show_label=True) | |
| ], | |
| outputs = [ | |
| gr.Dataframe(label="Outpt table of Go-terms", | |
| show_label=True) | |
| ], | |
| description = description, | |
| title ="CAFA ProtBERT prediction demo V1", | |
| ) | |
| #demo.launch(debug=True) | |
| demo.launch() | |