File size: 5,252 Bytes
68538d3 9d09275 68538d3 4af0f9f f26e1b4 1419c2f 4af0f9f 1419c2f 9d09275 68538d3 4af0f9f 68538d3 4fdde39 68538d3 9d09275 f26e1b4 4af0f9f 9d09275 68538d3 9d09275 f26e1b4 9d09275 f26e1b4 68538d3 9d09275 f26e1b4 68538d3 9d09275 68538d3 9d09275 68538d3 9d09275 f26e1b4 9d09275 f26e1b4 9d09275 f26e1b4 9d09275 68538d3 9d09275 68538d3 9d09275 | 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 | from flask import Flask, request, render_template
import torch
import re
import numpy as np
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import os
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = Flask(__name__)
# Set multiple cache environment variables to ensure they're all pointing to writable locations
cache_dir = "/app/cache"
os.environ["TRANSFORMERS_CACHE"] = cache_dir
os.environ["HF_HOME"] = cache_dir
os.environ["HUGGINGFACE_HUB_CACHE"] = cache_dir
# Name of your finetuned model on Hugging Face
MODEL_NAME = "Priyasi/TransVi_3"
KMER_SIZE = 3 # Must match the k-mer size used in pretraining
# Virus label mapping - 0-indexed to match model output
LABELS = {
1: "SARS-COV-1",
2: "MERS",
3: "SARS-COV-2",
4: "Ebola",
5: "Dengue",
6: "Influenza"
}
# Global variables to store model and tokenizer
tokenizer = None
model = None
def load_model():
"""Load the tokenizer and model"""
global tokenizer, model
try:
logger.info(f"Loading tokenizer and model from {MODEL_NAME}...")
logger.info(f"Using cache directory: {cache_dir}")
logger.info(f"TRANSFORMERS_CACHE: {os.environ.get('TRANSFORMERS_CACHE')}")
logger.info(f"HF_HOME: {os.environ.get('HF_HOME')}")
# Load with explicit cache directory and additional parameters
tokenizer = AutoTokenizer.from_pretrained(
MODEL_NAME,
cache_dir=cache_dir,
local_files_only=False,
use_auth_token=False
)
model = AutoModelForSequenceClassification.from_pretrained(
MODEL_NAME,
cache_dir=cache_dir,
local_files_only=False,
use_auth_token=False
)
model.eval()
logger.info("Model and tokenizer loaded successfully!")
except Exception as e:
logger.error(f"Error loading model: {str(e)}")
raise e
def filter_seq(seq):
"""
Filter out non-ATGC characters and convert U to T for RNA sequences.
"""
seq = str(seq).upper()
seq = seq.replace('U', 'T') # Convert Uracil to Thymine for compatibility
return re.sub(r'[^ATGC]', '', seq)
def create_kmers(sequence, k=3):
"""
Create k-mer representation from the sequence.
Returns a string of k-mers separated by spaces.
"""
if len(sequence) < k:
return ""
kmers = [sequence[i:i+k] for i in range(len(sequence) - k + 1)]
return ' '.join(kmers)
@app.route('/', methods=['GET'])
def home():
return render_template('index.html')
@app.route('/predict', methods=['POST'])
def predict():
global tokenizer, model
# Ensure model is loaded
if tokenizer is None or model is None:
return render_template('index.html',
prediction="Model not loaded. Please try again later.",
error=True)
try:
sequence = request.form.get("sequence")
if not sequence:
return render_template('index.html',
prediction="No sequence provided.",
error=True)
# Preprocess the sequence
filtered_sequence = filter_seq(sequence)
if len(filtered_sequence) < KMER_SIZE:
return render_template('index.html',
prediction=f"Sequence too short after filtering (must be at least {KMER_SIZE} valid characters).",
error=True)
kmers = create_kmers(filtered_sequence, k=KMER_SIZE)
# Tokenize input (using max_length and padding settings similar to training)
inputs = tokenizer(kmers, return_tensors="pt", max_length=512,
padding='max_length', truncation=True)
# Make prediction using the loaded model
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits
probabilities = torch.softmax(logits, dim=1).tolist()[0]
predicted_class_idx = int(np.argmax(probabilities))
prediction = LABELS.get(predicted_class_idx, "Unknown")
confidence = probabilities[predicted_class_idx]
return render_template('index.html',
prediction=prediction,
confidence=f"{confidence:.2%}",
error=False)
except Exception as e:
logger.error(f"Error during prediction: {str(e)}")
return render_template('index.html',
prediction="An error occurred during prediction. Please try again.",
error=True)
@app.route('/health', methods=['GET'])
def health_check():
"""Health check endpoint for container orchestration"""
return {"status": "healthy", "model_loaded": model is not None}
if __name__ == '__main__':
# Load model at startup
load_model()
# Get port from environment variable (useful for deployment platforms)
port = int(os.environ.get('PORT', 7860))
# For production deployment
app.run(debug=False, host='0.0.0.0', port=port) |