import json import gradio as gr from textblob import TextBlob import os def sentiment_analysis(text: str) -> dict: """ Analyze the sentiment of the given text. Simplified version for Hugging Face Spaces. """ if not text or not text.strip(): return { "error": "Please enter some text to analyze", "polarity": 0, "subjectivity": 0, "assessment": "neutral", "confidence": "low" } try: blob = TextBlob(text) sentiment = blob.sentiment # Calculate confidence based on polarity strength polarity_abs = abs(sentiment.polarity) if polarity_abs >= 0.7: confidence = "high" elif polarity_abs >= 0.3: confidence = "medium" else: confidence = "low" # More nuanced assessment if sentiment.polarity > 0.1: assessment = "positive" elif sentiment.polarity < -0.1: assessment = "negative" else: assessment = "neutral" result = { "polarity": round(sentiment.polarity, 3), "subjectivity": round(sentiment.subjectivity, 3), "assessment": assessment, "confidence": confidence, "word_count": len(text.split()), "character_count": len(text), "text_preview": text[:100] + "..." if len(text) > 100 else text } return result except Exception as e: return { "error": f"Analysis failed: {str(e)}", "polarity": 0, "subjectivity": 0, "assessment": "error", "confidence": "low" } def format_results(result: dict) -> str: """Format the analysis results for better display.""" if "error" in result: return f"❌ **Error:** {result['error']}" # Emoji mapping for sentiment emoji_map = { "positive": "😊", "negative": "😞", "neutral": "😐", "error": "❌" } # Color coding for polarity polarity = result["polarity"] if polarity > 0: polarity_color = "🟢" polarity_desc = "Positive" elif polarity < 0: polarity_color = "🔴" polarity_desc = "Negative" else: polarity_color = "🟡" polarity_desc = "Neutral" # Confidence indicators confidence_icons = { "high": "🔥", "medium": "⚡", "low": "💫" } formatted = f""" ## 📊 Sentiment Analysis Results ### {emoji_map[result['assessment']]} Overall Assessment: **{result['assessment'].title()}** ### 📈 Detailed Metrics: - **Polarity:** {polarity_color} **{result['polarity']}** ({polarity_desc}) - Range: -1.0 (very negative) to +1.0 (very positive) - **Subjectivity:** 🎯 **{result['subjectivity']}** - Range: 0.0 (objective) to 1.0 (subjective) - **Confidence:** {confidence_icons.get(result['confidence'], '❓')} **{result['confidence'].title()}** ### 📝 Text Statistics: - **Words:** {result['word_count']} - **Characters:** {result['character_count']} - **Preview:** "{result.get('text_preview', 'N/A')}" ### 💡 Interpretation: - **Polarity** measures emotional tone from negative to positive - **Subjectivity** measures opinion vs factual content - **Confidence** indicates strength of sentiment signal --- *🔗 Powered by TextBlob NLP • Ready for MCP integration* """ return formatted def analyze_with_formatting(text: str) -> str: """Wrapper function that combines analysis and formatting.""" result = sentiment_analysis(text) return format_results(result) def batch_analyze_simple(texts_input: str) -> str: """Simple batch analysis for multiple texts.""" if not texts_input.strip(): return "❌ Please enter some texts, one per line." texts = [line.strip() for line in texts_input.split('\n') if line.strip()] if not texts: return "❌ No valid texts found." results = [] positive_count = 0 negative_count = 0 neutral_count = 0 total_polarity = 0 for i, text in enumerate(texts, 1): result = sentiment_analysis(text) if "error" not in result: assessment = result["assessment"] if assessment == "positive": positive_count += 1 elif assessment == "negative": negative_count += 1 else: neutral_count += 1 total_polarity += result["polarity"] results.append(f"**Text {i}:** {result['assessment']} ({result['polarity']}) - \"{result['text_preview']}\"") else: results.append(f"**Text {i}:** Error - {result['error']}") avg_polarity = total_polarity / len(texts) if texts else 0 summary = f""" ## 📊 Batch Analysis Results ### 📈 Summary Statistics: - **Total Texts:** {len(texts)} - **Average Polarity:** {round(avg_polarity, 3)} - **Positive:** {positive_count} ({round(positive_count/len(texts)*100, 1)}%) - **Negative:** {negative_count} ({round(negative_count/len(texts)*100, 1)}%) - **Neutral:** {neutral_count} ({round(neutral_count/len(texts)*100, 1)}%) ### 📋 Individual Results: {chr(10).join(results)} """ return summary # Sample texts for quick testing sample_texts = [ "I absolutely love this product! It's amazing and works perfectly.", "This is the worst experience I've ever had. Completely disappointed.", "The weather today is partly cloudy with a chance of rain.", "I'm not sure how I feel about this new update. It has some good features but also some issues.", "Artificial intelligence is transforming various industries including healthcare, finance, and transportation." ] # Create the Gradio interface with gr.Blocks( theme=gr.themes.Soft(), title="🎯 Sentiment Analyzer", css=""" .gradio-container { max-width: 1200px !important; margin: auto !important; } .main-header { text-align: center; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-size: 2.5em; font-weight: bold; margin-bottom: 20px; } .subtitle { text-align: center; color: #666; font-size: 1.2em; margin-bottom: 30px; } """ ) as demo: gr.HTML("""