""" app.py — Sentiment Analysis Demo Deployed on Hugging Face Spaces (Gradio) NLP Course Project — Dr. Rao Muhammad Adeel Nawab """ import gradio as gr import torch import re import os from transformers import pipeline # ── Load model — tries your fine-tuned model first, falls back to public ── HF_TOKEN = os.environ.get("HF_TOKEN", None) MY_MODEL = "Ahmadjunaid/tweet_sentiment_distilbert" BACKUP = "distilbert-base-uncased-finetuned-sst-2-english" try: classifier = pipeline( "text-classification", model=MY_MODEL, token=HF_TOKEN, device=-1, ) print(f"✅ Loaded custom model: {MY_MODEL}") except Exception as e: print(f"⚠️ Custom model failed ({e}), using backup model.") classifier = pipeline( "text-classification", model=BACKUP, device=-1, ) # ── Tweet cleaner ── def clean_tweet(text: str) -> str: text = re.sub(r"http\S+|www\S+", "", text) text = re.sub(r"@\w+", "", text) text = re.sub(r"#(\w+)", r"\1", text) text = re.sub(r"[^\w\s!?.,']", " ", text) return re.sub(r"\s+", " ", text).strip() # ── Inference ── def predict(tweet: str): if not tweet.strip(): return "⚠️ Please enter a tweet.", None, None clean = clean_tweet(tweet) result = classifier(clean)[0] raw_label = result["label"].upper() score = result["score"] if raw_label in ("POSITIVE", "LABEL_1"): label, emoji = "Positive", "😊" pos_score, neg_score = score, 1 - score else: label, emoji = "Negative", "😠" neg_score, pos_score = score, 1 - score result_text = f"{emoji} {label} ({score*100:.1f}% confident)" bar_data = { "Negative 😠": round(neg_score * 100, 1), "Positive 😊": round(pos_score * 100, 1), } return result_text, bar_data, f'"{clean}"' EXAMPLES = [ ["I absolutely love this new phone, it changed my life!"], ["This is the worst customer service I have ever experienced."], ["Just had coffee. Today feels like a normal day."], ["Can't believe how amazing the concert was last night!"], ["My flight got cancelled and I missed the meeting. Terrible."], ] CSS = """ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&display=swap'); body, .gradio-container { background: #0D1B2A !important; font-family: 'Space Grotesk', sans-serif !important; } #header-block { background: linear-gradient(135deg, #1565C0 0%, #0D47A1 50%, #00ACC1 100%); border-radius: 16px; padding: 32px 40px; margin-bottom: 24px; text-align: center; } #header-block h1 { font-size: 2.2rem !important; font-weight: 700; color: #fff; margin: 0 0 6px 0; } #header-block p { color: #B3E5FC; font-size: 0.95rem; margin: 4px 0 0 0; } label { color: #90CAF9 !important; font-weight: 600 !important; font-size: 0.85rem !important; text-transform: uppercase !important; } .footer-note { text-align: center; color: #455A6A; font-size: 0.8rem; margin-top: 16px; } """ with gr.Blocks(css=CSS, title="Tweet Sentiment Analysis") as demo: gr.HTML("""

🐦 Tweet Sentiment Analysis

Fine-tuned DistilBERT · Trained on 10,000 English Tweets · F1 = 0.85

NLP Course Project · Dr. Rao Muhammad Adeel Nawab

""") with gr.Row(): with gr.Column(scale=3): tweet_input = gr.Textbox(label="Enter a Tweet", placeholder="e.g. I love this! It completely changed my day 🎉", lines=3) with gr.Row(): submit_btn = gr.Button("Analyse Sentiment →", variant="primary") clear_btn = gr.Button("Clear", variant="secondary") gr.Examples(examples=EXAMPLES, inputs=tweet_input, label="Try an Example") with gr.Column(scale=2): result_out = gr.Textbox(label="Prediction") bar_out = gr.Json(label="Confidence Scores (%)") cleaned_out = gr.Textbox(label="Cleaned Input", lines=2) gr.HTML('') submit_btn.click(fn=predict, inputs=tweet_input, outputs=[result_out, bar_out, cleaned_out]) clear_btn.click(lambda: ("", None, ""), outputs=[result_out, bar_out, cleaned_out]) tweet_input.submit(fn=predict, inputs=tweet_input, outputs=[result_out, bar_out, cleaned_out]) demo.launch()