import os os.environ["CUDA_VISIBLE_DEVICES"] = "-1" from huggingface_hub import hf_hub_download import gradio as gr from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch import torch.nn as nn import pickle import numpy as np import re import fasttext svm_repo_id = "HighFive-OPJ/svm-sentiment-model" svm_model_path = hf_hub_download(repo_id=svm_repo_id, filename="svm_model.pkl") with open(svm_model_path, "rb") as f: svm_model = pickle.load(f) vectorizer_path = hf_hub_download(repo_id=svm_repo_id, filename="vectorizer.pkl") with open(vectorizer_path, "rb") as f: vectorizer = pickle.load(f) fasttext_path = hf_hub_download( repo_id="HighFive-OPJ/Deep_Learning", filename="FastText.bin", repo_type="dataset" ) ft_model = fasttext.load_model(fasttext_path) class LSTMClassifier(nn.Module): def __init__(self, input_dim=300, hidden_dim=256, num_classes=3): super().__init__() self.lstm = nn.LSTM(input_dim, hidden_dim, batch_first=True, bidirectional=True) self.fc = nn.Linear(hidden_dim * 2, num_classes) def forward(self, x): _, (hn, _) = self.lstm(x) hn = torch.cat((hn[-2], hn[-1]), dim=1) out = self.fc(hn) return out lstm_repo_id = "HighFive-OPJ/lstm-sentiment-model" lstm_model_path = hf_hub_download(repo_id=lstm_repo_id, filename="fasttext_lstm.pt") device = torch.device("cuda" if torch.cuda.is_available() else "cpu") lstm_model = LSTMClassifier() lstm_model.load_state_dict(torch.load(lstm_model_path, map_location=device)) lstm_model.to(device) lstm_model.eval() bert_repo_id = "HighFive-OPJ/bertic_sentiment" bert_tokenizer = AutoTokenizer.from_pretrained(bert_repo_id) bert_model = AutoModelForSequenceClassification.from_pretrained(bert_repo_id) bert_model.to(device) bert_model.eval() def preprocess_text(text): text = text.lower() text = re.sub(r"[^a-zA-Z\s]", "", text).strip() return text def text_to_fasttext_tensor(text, max_len=200): tokens = preprocess_text(text).split() vectors = [] for t in tokens[:max_len]: vec = ft_model.get_word_vector(t) vectors.append(vec) while len(vectors) < max_len: vectors.append(np.zeros(300)) return torch.tensor([vectors], dtype=torch.float32).to(device) def predict_with_svm(text): transformed = vectorizer.transform([text]) prediction = svm_model.predict(transformed) return int(prediction[0]) def predict_with_lstm(text): input_tensor = text_to_fasttext_tensor(text) with torch.no_grad(): outputs = lstm_model(input_tensor) pred = torch.argmax(outputs, dim=1).item() return pred def predict_with_bert(text): inputs = bert_tokenizer([text], padding=True, truncation=True, max_length=512, return_tensors="pt").to(device) with torch.no_grad(): outputs = bert_model(**inputs) logits = outputs.logits predictions = logits.argmax(axis=-1).cpu().numpy() bert_score = int(predictions[0]) if bert_score <= 2: return 0 elif bert_score == 3: return 1 else: return 2 def analyze_sentiment(text): try: svm_result = predict_with_svm(text) except Exception as e: svm_result = f"Error: {str(e)}" try: lstm_result = predict_with_lstm(text) except Exception as e: lstm_result = f"Error: {str(e)}" try: bert_result = predict_with_bert(text) except Exception as e: bert_result = f"Error: {str(e)}" try: scores = [] for r in [svm_result, lstm_result, bert_result]: if isinstance(r, int): scores.append(r) average = np.mean(scores) if scores else float("nan") stats = f"Average Score (0=Pos,1=Neg,2=Neu): {average:.2f}\n" except Exception as e: stats = f"Error calculating stats: {str(e)}" def format_output(result): return convert_to_stars(result) if isinstance(result, int) else result return ( format_output(svm_result), format_output(lstm_result), format_output(bert_result), stats ) def convert_to_stars(score): star_map = {0: 5, 1: 1, 2: 3} stars = star_map.get(score, 3) return "★" * stars + "☆" * (5 - stars) def process_input(text): if not text.strip(): return ("", "", "", "Please enter valid text.") try: return analyze_sentiment(text) except Exception as e: error_message = f"Error during sentiment analysis:\n{str(e)}" return ("error", "error", "error", error_message) with gr.Blocks() as demo: gr.Markdown("# Sentiment Analysis Demo") gr.Markdown(""" Enter a review and see how different models evaluate its sentiment! This app uses: - SVM for classic machine learning - LSTM for deep learning (using FastText) - BERTić for transformer-based analysis Rating guide: 5 ★ → positive sentiment 3 ★ → neutral sentiment 1 ★ → negative sentiment """) with gr.Row(): with gr.Column(): input_text = gr.Textbox(label="Enter your review:", lines=3) analyze_button = gr.Button("Analyze Sentiment") with gr.Column(): svm_output = gr.Textbox(label="SVM", interactive=False) lstm_output = gr.Textbox(label="LSTM", interactive=False) bert_output = gr.Textbox(label="BERTić", interactive=False) stats_output = gr.Textbox(label="Statistics", interactive=False) analyze_button.click( process_input, inputs=[input_text], outputs=[svm_output, lstm_output, bert_output, stats_output] ) demo.launch()