# Importing Libraries import os import sys import io os.environ['CUDA_VISIBLE_DEVICES'] = '-1' os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' os.environ['GRADIO_HOT_RELOAD'] = 'false' os.environ['WRAPT_DISABLE_EXTENSIONS'] = 'true' os.environ['PYTHONWARNINGS'] = 'ignore' import re import nltk import pickle import string import warnings import numpy as np import gradio as gr from keras.models import load_model from keras.preprocessing.sequence import pad_sequences # Suppress all warnings warnings.filterwarnings('ignore') warnings.simplefilter('ignore') # Constants MAX_LEN = 100 MODEL_PATH = "sentiment_analysis_best.keras" TOKENIZER_PATH = "tokenizer.pkl" nltk.download('stopwords', quiet=True) # Expand common English contractions def expand_contractions(text): contractions = { "i'm": "i am", "you're": "you are", "he's": "he is", "she's": "she is", "it's": "it is", "we're": "we are", "they're": "they are", "i've": "i have", "you've": "you have", "we've": "we have", "they've": "they have", "i'll": "i will", "you'll": "you will", "he'll": "he will", "she'll": "she will", "we'll": "we will", "they'll": "they will", "i'd": "i would", "you'd": "you would", "he'd": "he would", "she'd": "she would", "we'd": "we would", "they'd": "they would", "don't": "do not", "doesn't": "does not", "didn't": "did not", "can't": "cannot", "couldn't": "could not", "won't": "will not", "wouldn't": "would not", "shouldn't": "should not", "isn't": "is not", "aren't": "are not", "wasn't": "was not", "weren't": "were not", "hasn't": "has not", "haven't": "have not", "hadn't": "had not", "mightn't": "might not", "mustn't": "must not", "needn't": "need not", "shan't": "shall not" } for contraction, expansion in contractions.items(): text = re.sub(r'\b' + contraction + r'\b', expansion, text, flags=re.IGNORECASE) return text # Preprocessing Function def preprocess(text): negations = {"not", "no", "nor", "never", "n't", "nobody", "nothing", "neither", "nowhere", "none"} important_words = {"am", "is", "are", "was", "were", "be", "been", "being"} try: from nltk.corpus import stopwords stop_words = set(stopwords.words("english")) - negations - important_words except: stop_words = set() text = text.lower() text = expand_contractions(text) text = re.sub(r"\d+", "", text) text = text.translate(str.maketrans('', '', string.punctuation)) words = [w for w in text.split() if w not in stop_words or w in negations or w in important_words] return " ".join(words) # Load Train Model and Tokenizer def load_resources(): try: model = load_model(MODEL_PATH) print(f"✓ Model loaded successfully from {MODEL_PATH}") with open(TOKENIZER_PATH, "rb") as f: tokenizer = pickle.load(f) print(f"✓ Tokenizer loaded successfully from {TOKENIZER_PATH}") return model, tokenizer except FileNotFoundError as e: print(f"✗ Error: Model or Tokenizer file not found!") print(f" Make sure {MODEL_PATH} AND {TOKENIZER_PATH} are in the same directory.") raise e except Exception as e: print(f"✗ Error loading resources: {e}") raise e # Load model and tokenizer globally model, tokenizer = load_resources() # Prediction Function def predict_sentiment(text): if not text or not text.strip(): return "⚠️ Neutral", "33.33%", "Please enter some text to analyze!" processed_text = preprocess(text) if not processed_text.strip(): return "⚠️ Neutral", "33.33%", "Text is empty after preprocessing. Try adding more words." seq = tokenizer.texts_to_sequences([processed_text]) padded = pad_sequences(seq, maxlen=MAX_LEN, padding='post') pred = model.predict(padded, verbose=0) label_idx = np.argmax(pred, axis=1)[0] confidence = pred[0][label_idx] labels = ["😞 Negative", "😊 Positive", "😐 Neutral"] sentiment = labels[label_idx] confidence_percentage = f"{confidence * 100:.2f}%" detailed_results = f""" ### 📊 Detailed Analysis: **Original Text:** {text} **Processed Text:** {processed_text} **Prediction Probabilities:** - 😞 Negative: {pred[0][0] * 100:.2f}% - 😊 Positive: {pred[0][1] * 100:.2f}% - 😐 Neutral: {pred[0][2] * 100:.2f}% **Final Sentiment:** {sentiment} **Confidence:** {confidence_percentage} """ return sentiment, confidence_percentage, detailed_results # GRADIO INTERFACE def create_gradio_interface(): """Create and configure Gradio interface""" examples = [ ["I'm so happy with my purchase! Highly recommended!"], ["I don't like this at all. Very disappointing."], ["I absolutely love this product! It's amazing!"], ["This is the worst experience I've ever had."], ["Fantastic! Best decision I ever made!"], ["I'm not sure how I feel about this."], ["It's okay, nothing special really."], ["Amazing work! Best I've ever seen!"], ["This is the worst experience ever"], ["This is terrible and I hate it"], ["It works fine, no complaints."], ["Not bad, but could be better."], ["He is no good boy"], ["I'm doing great"], ["I'm not normal"], ["Both of you"], ["I am fine"], ["I am good"], ["I'm okay"] ] with gr.Blocks(title="Sentiment Analysis") as interface: gr.Markdown(""" # 🎭 Sentiment Analysis - AI Powered ### Analyze the sentiment of your text using Deep Learning (LSTM Model) **Instructions:** Enter any text in English and the model will predict whether it's Positive, Negative, or Neutral. """) with gr.Row(): with gr.Column(scale=1): text_input = gr.Textbox( label="📝 Enter Your Text", placeholder="Type your text here... (e.g., 'I love this product!')", lines=5, max_lines=10 ) with gr.Row(): analyze_btn = gr.Button("🔍 Analyze Sentiment", variant="primary", size="lg") clear_btn = gr.ClearButton([text_input], value="🗑️ Clear", size="lg") with gr.Column(scale=1): sentiment_output = gr.Textbox( label="🎯 Predicted Sentiment", interactive=False ) confidence_output = gr.Textbox( label="📈 Confidence Score", interactive=False ) detailed_output = gr.Markdown( label="📊 Detailed Analysis", value="Results will appear here after analysis..." ) gr.Markdown("### 💡 Try These Examples:") gr.Examples( examples=examples, inputs=text_input, outputs=[sentiment_output, confidence_output, detailed_output], fn=predict_sentiment, cache_examples=False ) gr.Markdown(""" --- **Model Information:** - Architecture: Bidirectional LSTM with Embedding Layer - Classes: Negative (0), Positive (1), Neutral (2) - Max Sequence Length: 100 tokens **Tips for Best Results:** - Use clear, complete sentences - The model works best with English text - Longer texts provide more context for accurate predictions """) analyze_btn.click( fn=predict_sentiment, inputs=text_input, outputs=[sentiment_output, confidence_output, detailed_output] ) text_input.submit( fn=predict_sentiment, inputs=text_input, outputs=[sentiment_output, confidence_output, detailed_output] ) return interface # Context manager to suppress stderr temporarily class SuppressStderr: def __enter__(self): self.original_stderr = sys.stderr sys.stderr = io.StringIO() return self def __exit__(self, exc_type, exc_val, exc_tb): sys.stderr = self.original_stderr # MAIN EXECUTION if __name__ == "__main__": print("\n" + "=" * 70) print("🚀 Starting Sentiment Analysis Gradio Interface...") print("=" * 70 + "\n") # Create interface interface = create_gradio_interface() # Launch with stderr suppression to hide asyncio warnings print("⏳ Launching server...") with SuppressStderr(): # Launch configuration interface.launch( server_name="0.0.0.0", server_port=7860, share=False, show_error=False, ssr_mode=False, theme=gr.themes.Soft(), quiet=False, prevent_thread_lock=False ) print("\n" + "=" * 70) print("✅ Interface is LIVE and ready to use!") print(" 🌐 Local URL: http://localhost:7860") print(" ⚡ Server is running smoothly") print(" 🛑 Press Ctrl+C to stop") print("=" * 70)