AdilzhanB commited on
Commit
6949b01
Β·
1 Parent(s): 79889f4

changes to app

Browse files
Files changed (2) hide show
  1. app.py +287 -293
  2. requirements.txt +1 -4
app.py CHANGED
@@ -1,333 +1,327 @@
1
  import json
2
  import gradio as gr
3
  from textblob import TextBlob
4
- from typing import Dict, Any, List
5
- import asyncio
6
 
7
- class SentimentMCPServer:
8
- """MCP Server for Sentiment Analysis using TextBlob"""
9
-
10
- def __init__(self):
11
- self.name = "sentiment-analyzer"
12
- self.version = "1.0.0"
13
-
14
- async def get_tools(self) -> List[Dict]:
15
- """Returns the list of tools available in this MCP"""
16
- return [
17
- {
18
- "name": "analyze_sentiment",
19
- "description": "Analyze the sentiment of text using TextBlob NLP",
20
- "inputSchema": {
21
- "type": "object",
22
- "properties": {
23
- "text": {
24
- "type": "string",
25
- "description": "Text to analyze for sentiment"
26
- },
27
- "detailed": {
28
- "type": "boolean",
29
- "description": "Return detailed analysis including confidence and statistics",
30
- "default": False
31
- }
32
- },
33
- "required": ["text"]
34
- }
35
- },
36
- {
37
- "name": "batch_analyze",
38
- "description": "Analyze sentiment for multiple texts at once",
39
- "inputSchema": {
40
- "type": "object",
41
- "properties": {
42
- "texts": {
43
- "type": "array",
44
- "items": {"type": "string"},
45
- "description": "Array of texts to analyze"
46
- }
47
- },
48
- "required": ["texts"]
49
- }
50
- },
51
- {
52
- "name": "sentiment_summary",
53
- "description": "Get summary statistics for analyzed texts",
54
- "inputSchema": {
55
- "type": "object",
56
- "properties": {
57
- "texts": {
58
- "type": "array",
59
- "items": {"type": "string"}
60
- }
61
- },
62
- "required": ["texts"]
63
- }
64
- }
65
- ]
66
 
67
- async def call_tool(self, name: str, arguments: Dict) -> Dict:
68
- """Call the specified tool with the given arguments."""
69
- if name == "analyze_sentiment":
70
- return await self.analyze_sentiment(
71
- arguments["text"],
72
- arguments.get("detailed", False)
73
- )
74
- elif name == "batch_analyze":
75
- return await self.batch_analyze(arguments["texts"])
76
- elif name == "sentiment_summary":
77
- return await self.sentiment_summary(arguments["texts"])
78
- else:
79
- raise ValueError(f"Unknown tool: {name}")
80
-
81
- async def analyze_sentiment(self, text: str, detailed: bool = False) -> Dict[str, Any]:
82
- """Main sentiment analysis function"""
83
- if not text or not text.strip():
84
- return {"error": "Text cannot be empty"}
85
-
86
  blob = TextBlob(text)
87
  sentiment = blob.sentiment
88
 
89
- # Base analysis result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  result = {
91
- "text": text[:100] + "..." if len(text) > 100 else text,
92
  "polarity": round(sentiment.polarity, 3),
93
  "subjectivity": round(sentiment.subjectivity, 3),
94
- "assessment": self._get_assessment(sentiment.polarity)
 
 
 
 
95
  }
96
 
97
- # Detailed analysis
98
- if detailed:
99
- result.update({
100
- "confidence": self._get_confidence(sentiment.polarity),
101
- "word_count": len(text.split()),
102
- "character_count": len(text),
103
- "interpretation": self._get_interpretation(sentiment)
104
- })
105
-
106
  return result
107
-
108
- async def batch_analyze(self, texts: List[str]) -> Dict[str, Any]:
109
- """Analyze sentiment for multiple texts"""
110
- results = []
111
- for i, text in enumerate(texts):
112
- try:
113
- result = await self.analyze_sentiment(text, detailed=True)
114
- result["index"] = i
115
- results.append(result)
116
- except Exception as e:
117
- results.append({"index": i, "error": str(e), "text": text})
118
-
119
- return {"results": results, "total_analyzed": len(texts)}
120
-
121
- async def sentiment_summary(self, texts: List[str]) -> Dict[str, Any]:
122
- """Generate summary statistics for a batch of texts"""
123
- batch_result = await self.batch_analyze(texts)
124
- results = batch_result["results"]
125
-
126
- # Π€ΠΈΠ»ΡŒΡ‚Ρ€ΡƒΠ΅ΠΌ ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹
127
- valid_results = [r for r in results if "error" not in r]
128
-
129
- if not valid_results:
130
- return {"error": "No valid results to summarize"}
131
-
132
- polarities = [r["polarity"] for r in valid_results]
133
- assessments = [r["assessment"] for r in valid_results]
134
-
135
- # ΠŸΠΎΠ΄ΡΡ‡Π΅Ρ‚ ΠΏΠΎ катСгориям
136
- positive = sum(1 for a in assessments if a == "positive")
137
- negative = sum(1 for a in assessments if a == "negative")
138
- neutral = sum(1 for a in assessments if a == "neutral")
139
 
 
140
  return {
141
- "total_texts": len(texts),
142
- "analyzed": len(valid_results),
143
- "average_polarity": round(sum(polarities) / len(polarities), 3),
144
- "sentiment_distribution": {
145
- "positive": positive,
146
- "negative": negative,
147
- "neutral": neutral
148
- },
149
- "percentages": {
150
- "positive": round(positive / len(valid_results) * 100, 1),
151
- "negative": round(negative / len(valid_results) * 100, 1),
152
- "neutral": round(neutral / len(valid_results) * 100, 1)
153
- }
154
  }
155
-
156
- def _get_assessment(self, polarity: float) -> str:
157
- """Sentiment assessment based on polarity"""
158
- if polarity > 0.1:
159
- return "positive"
160
- elif polarity < -0.1:
161
- return "negative"
162
- else:
163
- return "neutral"
164
-
165
- def _get_confidence(self, polarity: float) -> str:
166
- """Confidence level based on polarity"""
167
- abs_polarity = abs(polarity)
168
- if abs_polarity >= 0.7:
169
- return "high"
170
- elif abs_polarity >= 0.3:
171
- return "medium"
172
- else:
173
- return "low"
174
-
175
- def _get_interpretation(self, sentiment) -> str:
176
- """Reult interpretation based on sentiment analysis"""
177
- polarity = sentiment.polarity
178
- subjectivity = sentiment.subjectivity
179
-
180
- if subjectivity > 0.7:
181
- subj_desc = "highly subjective (opinion-based)"
182
- elif subjectivity > 0.3:
183
- subj_desc = "moderately subjective"
184
- else:
185
- subj_desc = "objective (fact-based)"
186
-
187
- if abs(polarity) > 0.5:
188
- pol_desc = "strong sentiment"
189
- elif abs(polarity) > 0.2:
190
- pol_desc = "moderate sentiment"
191
- else:
192
- pol_desc = "neutral sentiment"
193
-
194
- return f"This text shows {pol_desc} and is {subj_desc}."
195
-
196
- # Global instance of the MCP server
197
- mcp_server = SentimentMCPServer()
198
-
199
- def sentiment_analysis(text: str) -> Dict[str, Any]:
200
- """Wrapper for Gradio interface to call MCP server"""
201
- loop = asyncio.new_event_loop()
202
- asyncio.set_event_loop(loop)
203
- try:
204
- result = loop.run_until_complete(
205
- mcp_server.analyze_sentiment(text, detailed=True)
206
- )
207
- return result
208
- finally:
209
- loop.close()
210
 
211
- def format_results(result: Dict[str, Any]) -> str:
212
- """Format the results for display in Gradio"""
213
  if "error" in result:
214
  return f"❌ **Error:** {result['error']}"
215
 
216
- emoji_map = {"positive": "😊", "negative": "😞", "neutral": "😐"}
217
- polarity_color = "🟒" if result["polarity"] > 0 else "πŸ”΄" if result["polarity"] < 0 else "🟑"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
- return f"""
220
- ## πŸ“Š MCP Sentiment Analysis Results
 
 
 
 
 
 
 
221
 
222
- ### {emoji_map[result['assessment']]} Assessment: **{result['assessment'].title()}**
223
 
224
- ### πŸ“ˆ Metrics:
225
- - **Polarity:** {polarity_color} {result['polarity']}
226
- - **Subjectivity:** 🎯 {result['subjectivity']}
227
- - **Confidence:** {result.get('confidence', 'N/A').title()}
 
 
228
 
229
- ### πŸ“ Statistics:
230
- - **Words:** {result.get('word_count', 'N/A')}
231
- - **Characters:** {result.get('character_count', 'N/A')}
 
232
 
233
  ### πŸ’‘ Interpretation:
234
- {result.get('interpretation', 'No interpretation available')}
 
 
235
 
236
  ---
237
- *πŸ”— This analysis is available via MCP protocol for AI assistants*
238
  """
 
 
 
 
 
 
239
 
240
- # Gradio interface setup
241
- with gr.Blocks(title="🎯 MCP Sentiment Analyzer") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  gr.HTML("""
243
- <h1 style="text-align: center; color: #667eea;">
244
- 🎯 MCP-Enabled Sentiment Analyzer
245
- </h1>
246
- <p style="text-align: center; color: #666;">
247
- Advanced sentiment analysis with Model Context Protocol support
248
- </p>
249
  """)
250
 
251
- with gr.Tab("πŸ” Single Analysis"):
252
- text_input = gr.Textbox(
253
- placeholder="Enter text for sentiment analysis...",
254
- lines=5,
255
- label="Text to Analyze"
256
- )
257
- analyze_btn = gr.Button("πŸ” Analyze", variant="primary")
258
- output = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
- analyze_btn.click(
261
- fn=lambda x: format_results(sentiment_analysis(x)),
262
- inputs=text_input,
263
- outputs=output
264
- )
 
 
 
 
 
 
 
 
265
 
266
- with gr.Tab("πŸ“Š Batch Analysis"):
267
- batch_input = gr.Textbox(
268
- placeholder="Enter multiple texts, one per line...",
269
- lines=8,
270
- label="Multiple Texts"
271
- )
272
- batch_btn = gr.Button("πŸ“Š Batch Analyze", variant="primary")
273
- batch_output = gr.JSON(label="Batch Results")
274
-
275
- def batch_analyze_wrapper(texts_str: str):
276
- if not texts_str.strip():
277
- return {"error": "Please enter some texts"}
278
 
279
- texts = [line.strip() for line in texts_str.split('\n') if line.strip()]
280
- loop = asyncio.new_event_loop()
281
- asyncio.set_event_loop(loop)
282
- try:
283
- return loop.run_until_complete(mcp_server.batch_analyze(texts))
284
- finally:
285
- loop.close()
286
-
287
- batch_btn.click(
288
- fn=batch_analyze_wrapper,
289
- inputs=batch_input,
290
- outputs=batch_output
291
- )
 
 
 
 
 
292
 
293
- with gr.Tab("πŸ“ˆ Summary Stats"):
294
- summary_input = gr.Textbox(
295
- placeholder="Enter texts for summary statistics...",
296
- lines=6,
297
- label="Texts for Summary"
298
- )
299
- summary_btn = gr.Button("πŸ“ˆ Get Summary", variant="primary")
300
- summary_output = gr.JSON(label="Summary Statistics")
301
-
302
- def summary_wrapper(texts_str: str):
303
- if not texts_str.strip():
304
- return {"error": "Please enter some texts"}
305
- texts = [line.strip() for line in texts_str.split('\n') if line.strip()]
306
- loop = asyncio.new_event_loop()
307
- asyncio.set_event_loop(loop)
308
- try:
309
- return loop.run_until_complete(mcp_server.sentiment_summary(texts))
310
- finally:
311
- loop.close()
312
-
313
- summary_btn.click(
314
- fn=summary_wrapper,
315
- inputs=summary_input,
316
- outputs=summary_output
317
- )
 
 
 
 
 
318
 
 
319
  if __name__ == "__main__":
320
- print("πŸš€ Starting MCP-Enabled Sentiment Analyzer...")
321
- print("πŸ“‘ MCP Server: Available for AI assistant integration")
322
- print("πŸ”§ Available MCP tools:")
323
- print(" - analyze_sentiment: Single text analysis")
324
- print(" - batch_analyze: Multiple texts analysis")
325
- print(" - sentiment_summary: Statistical summary")
326
- print("🌐 Web UI: http://localhost:7860")
327
-
328
- demo.launch(
329
- mcp_server=True,
330
- server_name="127.0.0.1",
331
- server_port=7860,
332
- inbrowser=True
333
- )
 
1
  import json
2
  import gradio as gr
3
  from textblob import TextBlob
4
+ import os
 
5
 
6
+ def sentiment_analysis(text: str) -> dict:
7
+ """
8
+ Analyze the sentiment of the given text.
9
+ Simplified version for Hugging Face Spaces.
10
+ """
11
+ if not text or not text.strip():
12
+ return {
13
+ "error": "Please enter some text to analyze",
14
+ "polarity": 0,
15
+ "subjectivity": 0,
16
+ "assessment": "neutral",
17
+ "confidence": "low"
18
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  blob = TextBlob(text)
22
  sentiment = blob.sentiment
23
 
24
+ # Calculate confidence based on polarity strength
25
+ polarity_abs = abs(sentiment.polarity)
26
+ if polarity_abs >= 0.7:
27
+ confidence = "high"
28
+ elif polarity_abs >= 0.3:
29
+ confidence = "medium"
30
+ else:
31
+ confidence = "low"
32
+
33
+ # More nuanced assessment
34
+ if sentiment.polarity > 0.1:
35
+ assessment = "positive"
36
+ elif sentiment.polarity < -0.1:
37
+ assessment = "negative"
38
+ else:
39
+ assessment = "neutral"
40
+
41
  result = {
 
42
  "polarity": round(sentiment.polarity, 3),
43
  "subjectivity": round(sentiment.subjectivity, 3),
44
+ "assessment": assessment,
45
+ "confidence": confidence,
46
+ "word_count": len(text.split()),
47
+ "character_count": len(text),
48
+ "text_preview": text[:100] + "..." if len(text) > 100 else text
49
  }
50
 
 
 
 
 
 
 
 
 
 
51
  return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ except Exception as e:
54
  return {
55
+ "error": f"Analysis failed: {str(e)}",
56
+ "polarity": 0,
57
+ "subjectivity": 0,
58
+ "assessment": "error",
59
+ "confidence": "low"
 
 
 
 
 
 
 
 
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
+ def format_results(result: dict) -> str:
63
+ """Format the analysis results for better display."""
64
  if "error" in result:
65
  return f"❌ **Error:** {result['error']}"
66
 
67
+ # Emoji mapping for sentiment
68
+ emoji_map = {
69
+ "positive": "😊",
70
+ "negative": "😞",
71
+ "neutral": "😐",
72
+ "error": "❌"
73
+ }
74
+
75
+ # Color coding for polarity
76
+ polarity = result["polarity"]
77
+ if polarity > 0:
78
+ polarity_color = "🟒"
79
+ polarity_desc = "Positive"
80
+ elif polarity < 0:
81
+ polarity_color = "πŸ”΄"
82
+ polarity_desc = "Negative"
83
+ else:
84
+ polarity_color = "🟑"
85
+ polarity_desc = "Neutral"
86
 
87
+ # Confidence indicators
88
+ confidence_icons = {
89
+ "high": "πŸ”₯",
90
+ "medium": "⚑",
91
+ "low": "πŸ’«"
92
+ }
93
+
94
+ formatted = f"""
95
+ ## πŸ“Š Sentiment Analysis Results
96
 
97
+ ### {emoji_map[result['assessment']]} Overall Assessment: **{result['assessment'].title()}**
98
 
99
+ ### πŸ“ˆ Detailed Metrics:
100
+ - **Polarity:** {polarity_color} **{result['polarity']}** ({polarity_desc})
101
+ - Range: -1.0 (very negative) to +1.0 (very positive)
102
+ - **Subjectivity:** 🎯 **{result['subjectivity']}**
103
+ - Range: 0.0 (objective) to 1.0 (subjective)
104
+ - **Confidence:** {confidence_icons.get(result['confidence'], '❓')} **{result['confidence'].title()}**
105
 
106
+ ### πŸ“ Text Statistics:
107
+ - **Words:** {result['word_count']}
108
+ - **Characters:** {result['character_count']}
109
+ - **Preview:** "{result.get('text_preview', 'N/A')}"
110
 
111
  ### πŸ’‘ Interpretation:
112
+ - **Polarity** measures emotional tone from negative to positive
113
+ - **Subjectivity** measures opinion vs factual content
114
+ - **Confidence** indicates strength of sentiment signal
115
 
116
  ---
117
+ *πŸ”— Powered by TextBlob NLP β€’ Ready for MCP integration*
118
  """
119
+ return formatted
120
+
121
+ def analyze_with_formatting(text: str) -> str:
122
+ """Wrapper function that combines analysis and formatting."""
123
+ result = sentiment_analysis(text)
124
+ return format_results(result)
125
 
126
+ def batch_analyze_simple(texts_input: str) -> str:
127
+ """Simple batch analysis for multiple texts."""
128
+ if not texts_input.strip():
129
+ return "❌ Please enter some texts, one per line."
130
+
131
+ texts = [line.strip() for line in texts_input.split('\n') if line.strip()]
132
+
133
+ if not texts:
134
+ return "❌ No valid texts found."
135
+
136
+ results = []
137
+ positive_count = 0
138
+ negative_count = 0
139
+ neutral_count = 0
140
+ total_polarity = 0
141
+
142
+ for i, text in enumerate(texts, 1):
143
+ result = sentiment_analysis(text)
144
+ if "error" not in result:
145
+ assessment = result["assessment"]
146
+ if assessment == "positive":
147
+ positive_count += 1
148
+ elif assessment == "negative":
149
+ negative_count += 1
150
+ else:
151
+ neutral_count += 1
152
+
153
+ total_polarity += result["polarity"]
154
+
155
+ results.append(f"**Text {i}:** {result['assessment']} ({result['polarity']}) - \"{result['text_preview']}\"")
156
+ else:
157
+ results.append(f"**Text {i}:** Error - {result['error']}")
158
+
159
+ avg_polarity = total_polarity / len(texts) if texts else 0
160
+
161
+ summary = f"""
162
+ ## πŸ“Š Batch Analysis Results
163
+
164
+ ### πŸ“ˆ Summary Statistics:
165
+ - **Total Texts:** {len(texts)}
166
+ - **Average Polarity:** {round(avg_polarity, 3)}
167
+ - **Positive:** {positive_count} ({round(positive_count/len(texts)*100, 1)}%)
168
+ - **Negative:** {negative_count} ({round(negative_count/len(texts)*100, 1)}%)
169
+ - **Neutral:** {neutral_count} ({round(neutral_count/len(texts)*100, 1)}%)
170
+
171
+ ### πŸ“‹ Individual Results:
172
+ {chr(10).join(results)}
173
+ """
174
+ return summary
175
+
176
+ # Sample texts for quick testing
177
+ sample_texts = [
178
+ "I absolutely love this product! It's amazing and works perfectly.",
179
+ "This is the worst experience I've ever had. Completely disappointed.",
180
+ "The weather today is partly cloudy with a chance of rain.",
181
+ "I'm not sure how I feel about this new update. It has some good features but also some issues.",
182
+ "Artificial intelligence is transforming various industries including healthcare, finance, and transportation."
183
+ ]
184
+
185
+ # Create the Gradio interface
186
+ with gr.Blocks(
187
+ theme=gr.themes.Soft(),
188
+ title="🎯 Sentiment Analyzer",
189
+ css="""
190
+ .gradio-container {
191
+ max-width: 1200px !important;
192
+ margin: auto !important;
193
+ }
194
+ .main-header {
195
+ text-align: center;
196
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
197
+ -webkit-background-clip: text;
198
+ -webkit-text-fill-color: transparent;
199
+ background-clip: text;
200
+ font-size: 2.5em;
201
+ font-weight: bold;
202
+ margin-bottom: 20px;
203
+ }
204
+ .subtitle {
205
+ text-align: center;
206
+ color: #666;
207
+ font-size: 1.2em;
208
+ margin-bottom: 30px;
209
+ }
210
+ """
211
+ ) as demo:
212
+
213
  gr.HTML("""
214
+ <div class="main-header">
215
+ 🎯 AI Sentiment Analyzer
216
+ </div>
217
+ <div class="subtitle">
218
+ Advanced sentiment analysis powered by TextBlob NLP
219
+ </div>
220
  """)
221
 
222
+ with gr.Tabs():
223
+ with gr.Tab("πŸ” Single Analysis"):
224
+ with gr.Row():
225
+ with gr.Column(scale=1):
226
+ gr.Markdown("### πŸ“ Enter Your Text")
227
+ text_input = gr.Textbox(
228
+ placeholder="Type or paste your text here for sentiment analysis...",
229
+ lines=6,
230
+ max_lines=15,
231
+ label="Text to Analyze",
232
+ info="πŸ’‘ Tip: Longer texts generally provide more accurate sentiment analysis"
233
+ )
234
+
235
+ with gr.Row():
236
+ analyze_btn = gr.Button("πŸ” Analyze Sentiment", variant="primary", size="lg")
237
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", size="lg")
238
+
239
+ gr.Markdown("### 🎯 Try Quick Examples")
240
+ examples_dropdown = gr.Dropdown(
241
+ choices=sample_texts,
242
+ label="Select a sample text to analyze",
243
+ value=None,
244
+ interactive=True
245
+ )
246
+
247
+ with gr.Column(scale=1):
248
+ gr.Markdown("### πŸ“Š Analysis Results")
249
+ output = gr.Markdown(
250
+ value="πŸ‘‹ **Welcome!** Enter some text and click 'Analyze Sentiment' to get started with AI-powered sentiment analysis.",
251
+ label="Sentiment Analysis Output"
252
+ )
253
 
254
+ with gr.Tab("πŸ“Š Batch Analysis"):
255
+ gr.Markdown("### πŸ“ Analyze Multiple Texts")
256
+ batch_input = gr.Textbox(
257
+ placeholder="Enter multiple texts, one per line...\n\nExample:\nI love this product!\nThis is terrible.\nThe weather is nice today.",
258
+ lines=8,
259
+ label="Multiple Texts (one per line)",
260
+ info="Enter each text on a separate line for batch analysis"
261
+ )
262
+ batch_btn = gr.Button("πŸ“Š Analyze All", variant="primary", size="lg")
263
+ batch_output = gr.Markdown(
264
+ value="πŸ‘‹ Enter multiple texts above and click 'Analyze All' to get batch sentiment analysis.",
265
+ label="Batch Analysis Results"
266
+ )
267
 
268
+ # Additional info section
269
+ with gr.Row():
270
+ with gr.Column():
271
+ gr.Markdown("""
272
+ ### πŸ” About This Tool
 
 
 
 
 
 
 
273
 
274
+ This **AI-powered sentiment analyzer** uses advanced Natural Language Processing to determine:
275
+ - **Emotional tone** (positive, negative, neutral)
276
+ - **Subjectivity level** (opinion vs fact)
277
+ - **Confidence scores** based on signal strength
278
+
279
+ Perfect for analyzing:
280
+ - πŸ“ Customer reviews and feedback
281
+ - πŸ“± Social media posts and comments
282
+ - πŸ“§ Email and message sentiment
283
+ - πŸ“Š Survey responses and testimonials
284
+ - πŸ“ˆ Product feedback and ratings
285
+
286
+ **Features:**
287
+ - Real-time sentiment analysis
288
+ - Batch processing for multiple texts
289
+ - Detailed confidence metrics
290
+ - User-friendly interface
291
+ """)
292
 
293
+ # Event handlers for Single Analysis
294
+ analyze_btn.click(
295
+ fn=analyze_with_formatting,
296
+ inputs=text_input,
297
+ outputs=output
298
+ )
299
+
300
+ clear_btn.click(
301
+ fn=lambda: ("", "πŸ‘‹ **Welcome!** Enter some text and click 'Analyze Sentiment' to get started."),
302
+ outputs=[text_input, output]
303
+ )
304
+
305
+ examples_dropdown.change(
306
+ fn=lambda x: x if x else "",
307
+ inputs=examples_dropdown,
308
+ outputs=text_input
309
+ )
310
+
311
+ text_input.submit(
312
+ fn=analyze_with_formatting,
313
+ inputs=text_input,
314
+ outputs=output
315
+ )
316
+
317
+ # Event handlers for Batch Analysis
318
+ batch_btn.click(
319
+ fn=batch_analyze_simple,
320
+ inputs=batch_input,
321
+ outputs=batch_output
322
+ )
323
 
324
+ # Simple launch for Hugging Face Spaces
325
  if __name__ == "__main__":
326
+ print("πŸš€ Starting Sentiment Analyzer for Hugging Face Spaces...")
327
+ demo.launch(mcp_server=True)
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,6 +1,3 @@
1
  # Minimal requirements for basic MCP Sentiment Analyzer
2
  gradio>=4.0.0
3
- textblob>=0.17.1
4
- asyncio>=3.4.3
5
- pydantic>=2.0.0
6
- typing-extensions>=4.8.0
 
1
  # Minimal requirements for basic MCP Sentiment Analyzer
2
  gradio>=4.0.0
3
+ textblob>=0.17.1