import streamlit as st import torch import torch.nn.functional as F import numpy as np from transformers import AutoTokenizer, AutoModelForSequenceClassification from normalizer import normalize import torch.nn as nn from transformers import AutoModel st.set_page_config(page_title="Political Sentiment", layout="wide") class BanglaPoliticalNet(nn.Module): def __init__(self, num_classes=5): super().__init__() self.banglabert = AutoModel.from_pretrained("csebuetnlp/banglabert") self.hidden_size = self.banglabert.config.hidden_size self.cnn_layers = nn.ModuleList([ nn.Conv1d(self.hidden_size, 128, kernel_size=k, padding=k//2) for k in [3,5,7] ]) self.attention = nn.MultiheadAttention(self.hidden_size, 8, batch_first=True) self.classifier = nn.Sequential( nn.Dropout(0.3), nn.Linear(self.hidden_size, 512), nn.ReLU(), nn.Dropout(0.2), nn.Linear(512, num_classes) ) def forward(self, input_ids, attention_mask=None): bert_out = self.banglabert(input_ids, attention_mask=attention_mask).last_hidden_state cnn_features = [] for cnn in self.cnn_layers: cnn_out = cnn(bert_out.transpose(1,2)).transpose(1,2) cnn_features.append(F.relu(cnn_out)) cnn_concat = torch.cat(cnn_features, dim=-1) proj = nn.Linear(384, self.hidden_size).to(input_ids.device) attn_input = proj(cnn_concat) attn_out, _ = self.attention(attn_input, attn_input, attn_input) attn_pooled = attn_out[:, 0, :] logits = self.classifier(attn_pooled) return logits st.markdown(""" """, unsafe_allow_html=True) id2label = {0: 'Very Negative', 1: 'Negative', 2: 'Neutral', 3: 'Positive', 4: 'Very Positive'} label_colors = { 'Very Negative': '#ef4444', 'Negative': '#f97316', 'Neutral': '#64748b', 'Positive': '#22c55e', 'Very Positive': '#16a34a' } @st.cache_resource def load_models(): models_loaded = {} target_models = { "model_banglabert": "rocky250/Sentiment-banglabert", "model_mbert": "rocky250/Sentiment-mbert", "model_bbase": "rocky250/Sentiment-bbase", "model_xlmr": "rocky250/Sentiment-xlmr", "bangla_political": "rocky250/bangla-political" } for name, repo in target_models.items(): try: tokenizer = AutoTokenizer.from_pretrained(repo) model = AutoModelForSequenceClassification.from_pretrained(repo) models_loaded[name] = (tokenizer, model.to('cuda' if torch.cuda.is_available() else 'cpu')) except: continue return models_loaded models_dict = load_models() def predict_single_model(text, model_name): clean_text = normalize(text) tokenizer, model = models_dict[model_name] device = next(model.parameters()).device inputs = tokenizer(clean_text, return_tensors="pt", truncation=True, padding=True, max_length=128).to(device) with torch.no_grad(): outputs = model(**inputs) logits = outputs.logits probs = F.softmax(logits, dim=1).cpu().numpy()[0] pred_id = np.argmax(probs) prediction = id2label[pred_id] return prediction, probs def predict_ensemble(text): clean_text = normalize(text) all_probs = [] all_predictions = [] for name in models_dict.keys(): try: pred, probs = predict_single_model(clean_text, name) all_probs.append(probs) all_predictions.append(pred) except: continue if all_probs: avg_probs = np.mean(all_probs, axis=0) final_pred = id2label[np.argmax(avg_probs)] return final_pred, all_predictions, avg_probs return "Error", [], np.zeros(5) st.markdown("""