Spaces:
Sleeping
Sleeping
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(""" | |
<div class="main-header"> | |
π― AI Sentiment Analyzer | |
</div> | |
<div class="subtitle"> | |
Advanced sentiment analysis powered by TextBlob NLP | |
</div> | |
""") | |
with gr.Tabs(): | |
with gr.Tab("π Single Analysis"): | |
with gr.Row(): | |
with gr.Column(scale=1): | |
gr.Markdown("### π Enter Your Text") | |
text_input = gr.Textbox( | |
placeholder="Type or paste your text here for sentiment analysis...", | |
lines=6, | |
max_lines=15, | |
label="Text to Analyze", | |
info="π‘ Tip: Longer texts generally provide more accurate sentiment analysis" | |
) | |
with gr.Row(): | |
analyze_btn = gr.Button("π Analyze Sentiment", variant="primary", size="lg") | |
clear_btn = gr.Button("ποΈ Clear", variant="secondary", size="lg") | |
gr.Markdown("### π― Try Quick Examples") | |
examples_dropdown = gr.Dropdown( | |
choices=sample_texts, | |
label="Select a sample text to analyze", | |
value=None, | |
interactive=True | |
) | |
with gr.Column(scale=1): | |
gr.Markdown("### π Analysis Results") | |
output = gr.Markdown( | |
value="π **Welcome!** Enter some text and click 'Analyze Sentiment' to get started with AI-powered sentiment analysis.", | |
label="Sentiment Analysis Output" | |
) | |
with gr.Tab("π Batch Analysis"): | |
gr.Markdown("### π Analyze Multiple Texts") | |
batch_input = gr.Textbox( | |
placeholder="Enter multiple texts, one per line...\n\nExample:\nI love this product!\nThis is terrible.\nThe weather is nice today.", | |
lines=8, | |
label="Multiple Texts (one per line)", | |
info="Enter each text on a separate line for batch analysis" | |
) | |
batch_btn = gr.Button("π Analyze All", variant="primary", size="lg") | |
batch_output = gr.Markdown( | |
value="π Enter multiple texts above and click 'Analyze All' to get batch sentiment analysis.", | |
label="Batch Analysis Results" | |
) | |
# Additional info section | |
with gr.Row(): | |
with gr.Column(): | |
gr.Markdown(""" | |
### π About This Tool | |
This **AI-powered sentiment analyzer** uses advanced Natural Language Processing to determine: | |
- **Emotional tone** (positive, negative, neutral) | |
- **Subjectivity level** (opinion vs fact) | |
- **Confidence scores** based on signal strength | |
Perfect for analyzing: | |
- π Customer reviews and feedback | |
- π± Social media posts and comments | |
- π§ Email and message sentiment | |
- π Survey responses and testimonials | |
- π Product feedback and ratings | |
**Features:** | |
- Real-time sentiment analysis | |
- Batch processing for multiple texts | |
- Detailed confidence metrics | |
- User-friendly interface | |
""") | |
# Event handlers for Single Analysis | |
analyze_btn.click( | |
fn=analyze_with_formatting, | |
inputs=text_input, | |
outputs=output | |
) | |
clear_btn.click( | |
fn=lambda: ("", "π **Welcome!** Enter some text and click 'Analyze Sentiment' to get started."), | |
outputs=[text_input, output] | |
) | |
examples_dropdown.change( | |
fn=lambda x: x if x else "", | |
inputs=examples_dropdown, | |
outputs=text_input | |
) | |
text_input.submit( | |
fn=analyze_with_formatting, | |
inputs=text_input, | |
outputs=output | |
) | |
# Event handlers for Batch Analysis | |
batch_btn.click( | |
fn=batch_analyze_simple, | |
inputs=batch_input, | |
outputs=batch_output | |
) | |
# Simple launch for Hugging Face Spaces | |
if __name__ == "__main__": | |
print("π Starting Sentiment Analyzer for Hugging Face Spaces...") | |
demo.launch(mcp_server=True) |