entropy25 commited on
Commit
866f669
Β·
verified Β·
1 Parent(s): d7cd2ec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +551 -14
app.py CHANGED
@@ -113,7 +113,7 @@ class ModelManager:
113
  model_manager = ModelManager()
114
 
115
  class HistoryManager:
116
- """Manages analysis history"""
117
  def __init__(self):
118
  self._history = []
119
 
@@ -122,9 +122,32 @@ class HistoryManager:
122
  if len(self._history) > config.MAX_HISTORY_SIZE:
123
  self._history = self._history[-config.MAX_HISTORY_SIZE:]
124
 
 
 
 
 
 
125
  def get_history(self) -> List[Dict]:
126
  return self._history.copy()
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  def clear(self) -> int:
129
  count = len(self._history)
130
  self._history.clear()
@@ -136,13 +159,19 @@ class HistoryManager:
136
 
137
  sentiments = [item['sentiment'] for item in self._history]
138
  confidences = [item['confidence'] for item in self._history]
 
139
 
140
  return {
141
  'total_analyses': len(self._history),
142
  'positive_count': sentiments.count('Positive'),
143
  'negative_count': sentiments.count('Negative'),
 
144
  'avg_confidence': np.mean(confidences),
145
- 'languages_detected': len(set(item.get('language', 'en') for item in self._history))
 
 
 
 
146
  }
147
 
148
  history_manager = HistoryManager()
@@ -182,6 +211,12 @@ class TextProcessor:
182
  word_freq = Counter(words)
183
  return [word for word, _ in word_freq.most_common(top_k)]
184
 
 
 
 
 
 
 
185
  class SentimentAnalyzer:
186
  """Enhanced sentiment analysis"""
187
 
@@ -262,6 +297,27 @@ class SentimentAnalyzer:
262
  logger.error(f"Analysis failed: {e}")
263
  raise
264
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  class PlotlyVisualizer:
266
  """Enhanced visualizations with Plotly"""
267
 
@@ -340,6 +396,55 @@ class PlotlyVisualizer:
340
  )
341
 
342
  return fig
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
 
344
  @staticmethod
345
  def create_history_dashboard(history: List[Dict]) -> go.Figure:
@@ -435,7 +540,8 @@ def analyze_single_text(text: str, language: str, theme: str, clean_text: bool,
435
  'neg_prob': result['neg_prob'],
436
  'neu_prob': result.get('neu_prob', 0),
437
  'language': result['language'],
438
- 'timestamp': datetime.now().isoformat()
 
439
  }
440
  history_manager.add_entry(history_entry)
441
 
@@ -458,20 +564,256 @@ def analyze_single_text(text: str, language: str, theme: str, clean_text: bool,
458
  logger.error(f"Analysis failed: {e}")
459
  return f"Error: {str(e)}", None, None
460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  def get_history_stats():
462
- """Get history statistics"""
463
  stats = history_manager.get_stats()
464
  if not stats:
465
  return "No analysis history available"
466
 
467
  return f"""
468
- **History Statistics:**
 
 
469
  - Total Analyses: {stats['total_analyses']}
470
- - Positive: {stats['positive_count']} | Negative: {stats['negative_count']}
 
 
 
 
471
  - Average Confidence: {stats['avg_confidence']:.3f}
 
 
 
 
472
  - Languages Detected: {stats['languages_detected']}
 
 
 
 
473
  """
474
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  def plot_history_dashboard():
476
  """Create history dashboard"""
477
  history = history_manager.get_history()
@@ -481,6 +823,20 @@ def plot_history_dashboard():
481
  fig = PlotlyVisualizer.create_history_dashboard(history)
482
  return fig, f"Dashboard showing {len(history)} analyses"
483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  def export_history_excel():
485
  """Export history to Excel"""
486
  history = history_manager.get_history()
@@ -500,6 +856,18 @@ def clear_all_history():
500
  count = history_manager.clear()
501
  return f"Cleared {count} entries from history"
502
 
 
 
 
 
 
 
 
 
 
 
 
 
503
  # Sample data
504
  SAMPLE_TEXTS = [
505
  # Auto Detect
@@ -524,11 +892,16 @@ SAMPLE_TEXTS = [
524
  ["Filmen var en besvikelse – trΓ₯kig handling, ΓΆverdrivet skΓ₯despeleri och ett slut som inte gav nΓ₯got avslut alls."]
525
  ]
526
 
 
 
 
 
 
527
 
528
  # Gradio Interface
529
- with gr.Blocks(theme=gr.themes.Soft(), title="Advanced Sentiment Analyzer") as demo:
530
- gr.Markdown("# 🎭 Multilingual Sentiment Analyzer")
531
- gr.Markdown("Analyze sentiment with multiple languages, themes, and advanced visualizations")
532
 
533
  with gr.Tab("πŸ“ Single Analysis"):
534
  with gr.Row():
@@ -541,7 +914,7 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Advanced Sentiment Analyzer") as d
541
 
542
  with gr.Row():
543
  language_select = gr.Dropdown(
544
- choices=['Auto Detect', 'English', 'Chinese', 'Spanish', 'French', 'German'],
545
  value='Auto Detect',
546
  label="Language"
547
  )
@@ -571,37 +944,201 @@ with gr.Blocks(theme=gr.themes.Soft(), title="Advanced Sentiment Analyzer") as d
571
  gauge_plot = gr.Plot(label="Sentiment Gauge")
572
  bars_plot = gr.Plot(label="Probability Distribution")
573
 
574
- with gr.Tab("πŸ“Š History & Analytics"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
  with gr.Row():
576
- stats_btn = gr.Button("πŸ“ˆ Get Statistics")
577
  dashboard_btn = gr.Button("πŸ“Š View Dashboard")
578
  clear_btn = gr.Button("πŸ—‘οΈ Clear History", variant="stop")
579
 
580
  with gr.Row():
581
- export_excel_btn = gr.Button("πŸ“ Export Excel")
 
582
 
583
- stats_output = gr.Markdown("Click 'Get Statistics' to view analysis history")
584
  dashboard_plot = gr.Plot(label="Analytics Dashboard")
 
 
 
 
 
 
585
  excel_file = gr.File(label="Download Excel Report")
586
  history_status = gr.Textbox(label="Status", interactive=False)
587
 
588
  # Event handlers
 
 
589
  analyze_btn.click(
590
  analyze_single_text,
591
  inputs=[text_input, language_select, theme_select, clean_text, remove_punct, remove_nums],
592
  outputs=[result_info, gauge_plot, bars_plot]
593
  )
594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
  stats_btn.click(
596
  get_history_stats,
597
  outputs=stats_output
598
  )
599
 
 
 
 
 
 
 
 
 
 
 
 
600
  dashboard_btn.click(
601
  plot_history_dashboard,
602
  outputs=[dashboard_plot, history_status]
603
  )
604
 
 
 
 
 
 
605
  export_excel_btn.click(
606
  export_history_excel,
607
  outputs=[excel_file, history_status]
 
113
  model_manager = ModelManager()
114
 
115
  class HistoryManager:
116
+ """Enhanced history manager with more features"""
117
  def __init__(self):
118
  self._history = []
119
 
 
122
  if len(self._history) > config.MAX_HISTORY_SIZE:
123
  self._history = self._history[-config.MAX_HISTORY_SIZE:]
124
 
125
+ def add_batch_entries(self, entries: List[Dict]):
126
+ """Add multiple entries at once"""
127
+ for entry in entries:
128
+ self.add_entry(entry)
129
+
130
  def get_history(self) -> List[Dict]:
131
  return self._history.copy()
132
 
133
+ def get_recent_history(self, n: int = 10) -> List[Dict]:
134
+ """Get n most recent entries"""
135
+ return self._history[-n:] if self._history else []
136
+
137
+ def filter_history(self, sentiment: str = None, language: str = None,
138
+ min_confidence: float = None) -> List[Dict]:
139
+ """Filter history by criteria"""
140
+ filtered = self._history
141
+
142
+ if sentiment:
143
+ filtered = [h for h in filtered if h['sentiment'] == sentiment]
144
+ if language:
145
+ filtered = [h for h in filtered if h.get('language', 'en') == language]
146
+ if min_confidence:
147
+ filtered = [h for h in filtered if h['confidence'] >= min_confidence]
148
+
149
+ return filtered
150
+
151
  def clear(self) -> int:
152
  count = len(self._history)
153
  self._history.clear()
 
159
 
160
  sentiments = [item['sentiment'] for item in self._history]
161
  confidences = [item['confidence'] for item in self._history]
162
+ languages = [item.get('language', 'en') for item in self._history]
163
 
164
  return {
165
  'total_analyses': len(self._history),
166
  'positive_count': sentiments.count('Positive'),
167
  'negative_count': sentiments.count('Negative'),
168
+ 'neutral_count': sentiments.count('Neutral'),
169
  'avg_confidence': np.mean(confidences),
170
+ 'max_confidence': np.max(confidences),
171
+ 'min_confidence': np.min(confidences),
172
+ 'languages_detected': len(set(languages)),
173
+ 'most_common_language': Counter(languages).most_common(1)[0][0] if languages else 'en',
174
+ 'avg_text_length': np.mean([len(item.get('full_text', '')) for item in self._history])
175
  }
176
 
177
  history_manager = HistoryManager()
 
211
  word_freq = Counter(words)
212
  return [word for word, _ in word_freq.most_common(top_k)]
213
 
214
+ @staticmethod
215
+ def parse_batch_input(text: str) -> List[str]:
216
+ """Parse batch input from textarea"""
217
+ lines = text.strip().split('\n')
218
+ return [line.strip() for line in lines if line.strip()]
219
+
220
  class SentimentAnalyzer:
221
  """Enhanced sentiment analysis"""
222
 
 
297
  logger.error(f"Analysis failed: {e}")
298
  raise
299
 
300
+ @staticmethod
301
+ def analyze_batch(texts: List[str], language: str = 'auto',
302
+ preprocessing_options: Dict = None) -> List[Dict]:
303
+ """Analyze multiple texts"""
304
+ results = []
305
+ for i, text in enumerate(texts):
306
+ try:
307
+ result = SentimentAnalyzer.analyze_text(text, language, preprocessing_options)
308
+ result['batch_index'] = i
309
+ results.append(result)
310
+ except Exception as e:
311
+ # Add error result
312
+ results.append({
313
+ 'sentiment': 'Error',
314
+ 'confidence': 0.0,
315
+ 'error': str(e),
316
+ 'batch_index': i,
317
+ 'text': text
318
+ })
319
+ return results
320
+
321
  class PlotlyVisualizer:
322
  """Enhanced visualizations with Plotly"""
323
 
 
396
  )
397
 
398
  return fig
399
+
400
+ @staticmethod
401
+ def create_batch_summary(results: List[Dict], theme: str = 'default') -> go.Figure:
402
+ """Create batch analysis summary"""
403
+ colors = config.THEMES[theme]
404
+
405
+ # Count sentiments
406
+ sentiments = [r['sentiment'] for r in results if 'sentiment' in r]
407
+ sentiment_counts = Counter(sentiments)
408
+
409
+ # Create pie chart
410
+ fig = go.Figure(data=[go.Pie(
411
+ labels=list(sentiment_counts.keys()),
412
+ values=list(sentiment_counts.values()),
413
+ marker_colors=[colors.get(s.lower()[:3], '#999999') for s in sentiment_counts.keys()],
414
+ textinfo='label+percent',
415
+ hole=0.3
416
+ )])
417
+
418
+ fig.update_layout(
419
+ title=f"Batch Analysis Summary ({len(results)} texts)",
420
+ height=400
421
+ )
422
+
423
+ return fig
424
+
425
+ @staticmethod
426
+ def create_confidence_distribution(results: List[Dict]) -> go.Figure:
427
+ """Create confidence distribution plot"""
428
+ confidences = [r['confidence'] for r in results if 'confidence' in r and r['sentiment'] != 'Error']
429
+
430
+ if not confidences:
431
+ return go.Figure()
432
+
433
+ fig = go.Figure(data=[go.Histogram(
434
+ x=confidences,
435
+ nbinsx=20,
436
+ marker_color='skyblue',
437
+ opacity=0.7
438
+ )])
439
+
440
+ fig.update_layout(
441
+ title="Confidence Distribution",
442
+ xaxis_title="Confidence Score",
443
+ yaxis_title="Frequency",
444
+ height=400
445
+ )
446
+
447
+ return fig
448
 
449
  @staticmethod
450
  def create_history_dashboard(history: List[Dict]) -> go.Figure:
 
540
  'neg_prob': result['neg_prob'],
541
  'neu_prob': result.get('neu_prob', 0),
542
  'language': result['language'],
543
+ 'timestamp': datetime.now().isoformat(),
544
+ 'analysis_type': 'single'
545
  }
546
  history_manager.add_entry(history_entry)
547
 
 
564
  logger.error(f"Analysis failed: {e}")
565
  return f"Error: {str(e)}", None, None
566
 
567
+ def analyze_batch_texts(batch_text: str, language: str, theme: str,
568
+ clean_text: bool, remove_punct: bool, remove_nums: bool):
569
+ """Batch text analysis"""
570
+ try:
571
+ if not batch_text.strip():
572
+ return "Please enter texts (one per line)", None, None, None
573
+
574
+ # Parse batch input
575
+ texts = TextProcessor.parse_batch_input(batch_text)
576
+
577
+ if len(texts) > config.BATCH_SIZE_LIMIT:
578
+ return f"Too many texts. Maximum {config.BATCH_SIZE_LIMIT} allowed.", None, None, None
579
+
580
+ if not texts:
581
+ return "No valid texts found", None, None, None
582
+
583
+ # Map display names back to language codes
584
+ language_map = {
585
+ 'Auto Detect': 'auto',
586
+ 'English': 'en',
587
+ 'Chinese': 'zh',
588
+ 'Spanish': 'es',
589
+ 'French': 'fr',
590
+ 'German': 'de',
591
+ 'Swedish': 'sv'
592
+ }
593
+ language_code = language_map.get(language, 'auto')
594
+
595
+ preprocessing_options = {
596
+ 'clean_text': clean_text,
597
+ 'remove_punctuation': remove_punct,
598
+ 'remove_numbers': remove_nums
599
+ }
600
+
601
+ # Analyze all texts
602
+ results = SentimentAnalyzer.analyze_batch(texts, language_code, preprocessing_options)
603
+
604
+ # Add to history
605
+ batch_entries = []
606
+ for i, (text, result) in enumerate(zip(texts, results)):
607
+ if 'error' not in result:
608
+ entry = {
609
+ 'text': text[:100] + '...' if len(text) > 100 else text,
610
+ 'full_text': text,
611
+ 'sentiment': result['sentiment'],
612
+ 'confidence': result['confidence'],
613
+ 'pos_prob': result['pos_prob'],
614
+ 'neg_prob': result['neg_prob'],
615
+ 'neu_prob': result.get('neu_prob', 0),
616
+ 'language': result['language'],
617
+ 'timestamp': datetime.now().isoformat(),
618
+ 'analysis_type': 'batch',
619
+ 'batch_index': i
620
+ }
621
+ batch_entries.append(entry)
622
+
623
+ history_manager.add_batch_entries(batch_entries)
624
+
625
+ # Create visualizations
626
+ summary_fig = PlotlyVisualizer.create_batch_summary(results, theme)
627
+ confidence_fig = PlotlyVisualizer.create_confidence_distribution(results)
628
+
629
+ # Create results table
630
+ df_data = []
631
+ for i, (text, result) in enumerate(zip(texts, results)):
632
+ if 'error' in result:
633
+ df_data.append({
634
+ 'Index': i+1,
635
+ 'Text': text[:50] + '...' if len(text) > 50 else text,
636
+ 'Sentiment': 'Error',
637
+ 'Confidence': 0.0,
638
+ 'Language': 'Unknown',
639
+ 'Error': result['error']
640
+ })
641
+ else:
642
+ df_data.append({
643
+ 'Index': i+1,
644
+ 'Text': text[:50] + '...' if len(text) > 50 else text,
645
+ 'Sentiment': result['sentiment'],
646
+ 'Confidence': f"{result['confidence']:.3f}",
647
+ 'Language': result['language'].upper(),
648
+ 'Keywords': ', '.join(result['keywords'][:3])
649
+ })
650
+
651
+ df = pd.DataFrame(df_data)
652
+
653
+ # Summary info
654
+ successful_results = [r for r in results if 'error' not in r]
655
+ error_count = len(results) - len(successful_results)
656
+
657
+ if successful_results:
658
+ sentiment_counts = Counter([r['sentiment'] for r in successful_results])
659
+ avg_confidence = np.mean([r['confidence'] for r in successful_results])
660
+
661
+ summary_text = f"""
662
+ **Batch Analysis Summary:**
663
+ - **Total Texts:** {len(texts)}
664
+ - **Successful:** {len(successful_results)}
665
+ - **Errors:** {error_count}
666
+ - **Average Confidence:** {avg_confidence:.3f}
667
+ - **Sentiments:** {dict(sentiment_counts)}
668
+ """
669
+ else:
670
+ summary_text = f"All {len(texts)} texts failed to analyze."
671
+
672
+ return summary_text, df, summary_fig, confidence_fig
673
+
674
+ except Exception as e:
675
+ logger.error(f"Batch analysis failed: {e}")
676
+ return f"Error: {str(e)}", None, None, None
677
+
678
+ def analyze_advanced_text(text: str, language: str, theme: str, include_keywords: bool,
679
+ keyword_count: int, min_confidence: float):
680
+ """Advanced analysis with additional features"""
681
+ try:
682
+ if not text.strip():
683
+ return "Please enter text", None, None
684
+
685
+ # Map display names back to language codes
686
+ language_map = {
687
+ 'Auto Detect': 'auto',
688
+ 'English': 'en',
689
+ 'Chinese': 'zh',
690
+ 'Spanish': 'es',
691
+ 'French': 'fr',
692
+ 'German': 'de',
693
+ 'Swedish': 'sv'
694
+ }
695
+ language_code = language_map.get(language, 'auto')
696
+
697
+ result = SentimentAnalyzer.analyze_text(text, language_code)
698
+
699
+ # Advanced keyword extraction
700
+ if include_keywords:
701
+ result['keywords'] = TextProcessor.extract_keywords(text, keyword_count)
702
+
703
+ # Confidence filtering
704
+ meets_confidence = result['confidence'] >= min_confidence
705
+
706
+ # Add to history
707
+ history_entry = {
708
+ 'text': text[:100] + '...' if len(text) > 100 else text,
709
+ 'full_text': text,
710
+ 'sentiment': result['sentiment'],
711
+ 'confidence': result['confidence'],
712
+ 'pos_prob': result['pos_prob'],
713
+ 'neg_prob': result['neg_prob'],
714
+ 'neu_prob': result.get('neu_prob', 0),
715
+ 'language': result['language'],
716
+ 'timestamp': datetime.now().isoformat(),
717
+ 'analysis_type': 'advanced',
718
+ 'meets_confidence_threshold': meets_confidence
719
+ }
720
+ history_manager.add_entry(history_entry)
721
+
722
+ # Create visualizations
723
+ gauge_fig = PlotlyVisualizer.create_sentiment_gauge(result, theme)
724
+ bars_fig = PlotlyVisualizer.create_probability_bars(result, theme)
725
+
726
+ # Create detailed info text
727
+ confidence_status = "βœ… High Confidence" if meets_confidence else "⚠️ Low Confidence"
728
+
729
+ info_text = f"""
730
+ **Advanced Analysis Results:**
731
+ - **Sentiment:** {result['sentiment']} ({result['confidence']:.3f} confidence)
732
+ - **Confidence Status:** {confidence_status}
733
+ - **Language:** {result['language'].upper()}
734
+ - **Text Statistics:**
735
+ - Words: {result['word_count']}
736
+ - Characters: {result['char_count']}
737
+ - Average word length: {result['char_count']/max(result['word_count'], 1):.1f}
738
+ """
739
+
740
+ if include_keywords:
741
+ info_text += f"\n- **Top Keywords:** {', '.join(result['keywords'])}"
742
+
743
+ if not meets_confidence:
744
+ info_text += f"\n\n⚠️ **Note:** Confidence ({result['confidence']:.3f}) is below threshold ({min_confidence})"
745
+
746
+ return info_text, gauge_fig, bars_fig
747
+
748
+ except Exception as e:
749
+ logger.error(f"Advanced analysis failed: {e}")
750
+ return f"Error: {str(e)}", None, None
751
+
752
  def get_history_stats():
753
+ """Get enhanced history statistics"""
754
  stats = history_manager.get_stats()
755
  if not stats:
756
  return "No analysis history available"
757
 
758
  return f"""
759
+ **Comprehensive History Statistics:**
760
+
761
+ **Analysis Counts:**
762
  - Total Analyses: {stats['total_analyses']}
763
+ - Positive: {stats['positive_count']}
764
+ - Negative: {stats['negative_count']}
765
+ - Neutral: {stats['neutral_count']}
766
+
767
+ **Confidence Metrics:**
768
  - Average Confidence: {stats['avg_confidence']:.3f}
769
+ - Highest Confidence: {stats['max_confidence']:.3f}
770
+ - Lowest Confidence: {stats['min_confidence']:.3f}
771
+
772
+ **Language Statistics:**
773
  - Languages Detected: {stats['languages_detected']}
774
+ - Most Common Language: {stats['most_common_language'].upper()}
775
+
776
+ **Text Statistics:**
777
+ - Average Text Length: {stats['avg_text_length']:.1f} characters
778
  """
779
 
780
+ def filter_history_display(sentiment_filter: str, language_filter: str, min_confidence: float):
781
+ """Display filtered history"""
782
+ # Convert filters
783
+ sentiment = sentiment_filter if sentiment_filter != "All" else None
784
+ language = language_filter.lower() if language_filter != "All" else None
785
+
786
+ filtered_history = history_manager.filter_history(
787
+ sentiment=sentiment,
788
+ language=language,
789
+ min_confidence=min_confidence if min_confidence > 0 else None
790
+ )
791
+
792
+ if not filtered_history:
793
+ return "No entries match the filter criteria", None
794
+
795
+ # Create DataFrame for display
796
+ df_data = []
797
+ for entry in filtered_history[-20:]: # Show last 20 entries
798
+ df_data.append({
799
+ 'Timestamp': entry['timestamp'][:16], # YYYY-MM-DD HH:MM
800
+ 'Text': entry['text'],
801
+ 'Sentiment': entry['sentiment'],
802
+ 'Confidence': f"{entry['confidence']:.3f}",
803
+ 'Language': entry['language'].upper(),
804
+ 'Type': entry.get('analysis_type', 'single')
805
+ })
806
+
807
+ df = pd.DataFrame(df_data)
808
+
809
+ summary = f"""
810
+ **Filtered Results:**
811
+ - Found {len(filtered_history)} entries matching criteria
812
+ - Showing most recent {min(20, len(filtered_history))} entries
813
+ """
814
+
815
+ return summary, df
816
+
817
  def plot_history_dashboard():
818
  """Create history dashboard"""
819
  history = history_manager.get_history()
 
823
  fig = PlotlyVisualizer.create_history_dashboard(history)
824
  return fig, f"Dashboard showing {len(history)} analyses"
825
 
826
+ def export_history_csv():
827
+ """Export history to CSV"""
828
+ history = history_manager.get_history()
829
+ if not history:
830
+ return None, "No history to export"
831
+
832
+ try:
833
+ df = pd.DataFrame(history)
834
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.csv', mode='w')
835
+ df.to_csv(temp_file.name, index=False)
836
+ return temp_file.name, f"Exported {len(history)} entries to CSV"
837
+ except Exception as e:
838
+ return None, f"Export failed: {str(e)}"
839
+
840
  def export_history_excel():
841
  """Export history to Excel"""
842
  history = history_manager.get_history()
 
856
  count = history_manager.clear()
857
  return f"Cleared {count} entries from history"
858
 
859
+ def get_recent_analyses():
860
+ """Get recent analysis summary"""
861
+ recent = history_manager.get_recent_history(10)
862
+ if not recent:
863
+ return "No recent analyses available"
864
+
865
+ summary_text = "**Recent Analyses (Last 10):**\n\n"
866
+ for i, entry in enumerate(recent, 1):
867
+ summary_text += f"{i}. **{entry['sentiment']}** ({entry['confidence']:.3f}) - {entry['text']}\n"
868
+
869
+ return summary_text
870
+
871
  # Sample data
872
  SAMPLE_TEXTS = [
873
  # Auto Detect
 
892
  ["Filmen var en besvikelse – trΓ₯kig handling, ΓΆverdrivet skΓ₯despeleri och ett slut som inte gav nΓ₯got avslut alls."]
893
  ]
894
 
895
+ BATCH_SAMPLE = """I love this product! It works perfectly.
896
+ The service was terrible and slow.
897
+ Not sure if I like it or not.
898
+ Amazing quality and fast delivery!
899
+ Could be better, but it's okay."""
900
 
901
  # Gradio Interface
902
+ with gr.Blocks(theme=gr.themes.Soft(), title="Advanced Multilingual Sentiment Analyzer") as demo:
903
+ gr.Markdown("# 🎭 Advanced Multilingual Sentiment Analyzer")
904
+ gr.Markdown("Comprehensive sentiment analysis with batch processing, advanced analytics, and multilingual support")
905
 
906
  with gr.Tab("πŸ“ Single Analysis"):
907
  with gr.Row():
 
914
 
915
  with gr.Row():
916
  language_select = gr.Dropdown(
917
+ choices=['Auto Detect', 'English', 'Chinese', 'Spanish', 'French', 'German', 'Swedish'],
918
  value='Auto Detect',
919
  label="Language"
920
  )
 
944
  gauge_plot = gr.Plot(label="Sentiment Gauge")
945
  bars_plot = gr.Plot(label="Probability Distribution")
946
 
947
+ with gr.Tab("πŸ“Š Batch Analysis"):
948
+ with gr.Row():
949
+ with gr.Column(scale=2):
950
+ batch_input = gr.Textbox(
951
+ label="Batch Text Input (One text per line)",
952
+ placeholder="Enter multiple texts, one per line...",
953
+ lines=8
954
+ )
955
+
956
+ with gr.Row():
957
+ batch_language = gr.Dropdown(
958
+ choices=['Auto Detect', 'English', 'Chinese', 'Spanish', 'French', 'German', 'Swedish'],
959
+ value='Auto Detect',
960
+ label="Language"
961
+ )
962
+ batch_theme = gr.Dropdown(
963
+ choices=list(config.THEMES.keys()),
964
+ value='default',
965
+ label="Theme"
966
+ )
967
+
968
+ with gr.Row():
969
+ batch_clean = gr.Checkbox(label="Clean Text", value=False)
970
+ batch_remove_punct = gr.Checkbox(label="Remove Punctuation", value=True)
971
+ batch_remove_nums = gr.Checkbox(label="Remove Numbers", value=False)
972
+
973
+ batch_analyze_btn = gr.Button("πŸ” Analyze Batch", variant="primary", size="lg")
974
+
975
+ gr.Examples(
976
+ examples=[[BATCH_SAMPLE]],
977
+ inputs=batch_input,
978
+ label="Sample Batch Input"
979
+ )
980
+
981
+ with gr.Column(scale=1):
982
+ batch_summary = gr.Markdown("Enter texts and click Analyze Batch")
983
+
984
+ with gr.Row():
985
+ batch_results_table = gr.DataFrame(
986
+ label="Detailed Results",
987
+ interactive=False
988
+ )
989
+
990
+ with gr.Row():
991
+ batch_summary_plot = gr.Plot(label="Sentiment Summary")
992
+ batch_confidence_plot = gr.Plot(label="Confidence Distribution")
993
+
994
+ with gr.Tab("πŸ”¬ Advanced Analysis"):
995
+ with gr.Row():
996
+ with gr.Column(scale=2):
997
+ advanced_input = gr.Textbox(
998
+ label="Text for Advanced Analysis",
999
+ placeholder="Enter text for detailed analysis...",
1000
+ lines=4
1001
+ )
1002
+
1003
+ with gr.Row():
1004
+ advanced_language = gr.Dropdown(
1005
+ choices=['Auto Detect', 'English', 'Chinese', 'Spanish', 'French', 'German', 'Swedish'],
1006
+ value='Auto Detect',
1007
+ label="Language"
1008
+ )
1009
+ advanced_theme = gr.Dropdown(
1010
+ choices=list(config.THEMES.keys()),
1011
+ value='default',
1012
+ label="Theme"
1013
+ )
1014
+
1015
+ with gr.Row():
1016
+ include_keywords = gr.Checkbox(label="Extract Keywords", value=True)
1017
+ keyword_count = gr.Slider(
1018
+ minimum=3,
1019
+ maximum=10,
1020
+ value=5,
1021
+ step=1,
1022
+ label="Number of Keywords"
1023
+ )
1024
+
1025
+ min_confidence_slider = gr.Slider(
1026
+ minimum=0.0,
1027
+ maximum=1.0,
1028
+ value=0.7,
1029
+ step=0.1,
1030
+ label="Minimum Confidence Threshold"
1031
+ )
1032
+
1033
+ advanced_analyze_btn = gr.Button("πŸ”¬ Advanced Analyze", variant="primary", size="lg")
1034
+
1035
+ with gr.Column(scale=1):
1036
+ advanced_result_info = gr.Markdown("Configure settings and click Advanced Analyze")
1037
+
1038
+ with gr.Row():
1039
+ advanced_gauge_plot = gr.Plot(label="Sentiment Gauge")
1040
+ advanced_bars_plot = gr.Plot(label="Probability Distribution")
1041
+
1042
+ with gr.Tab("πŸ“ˆ History & Analytics"):
1043
+ with gr.Row():
1044
+ with gr.Column():
1045
+ gr.Markdown("### πŸ“Š Statistics")
1046
+ stats_btn = gr.Button("πŸ“ˆ Get Statistics")
1047
+ recent_btn = gr.Button("πŸ•’ Recent Analyses")
1048
+ stats_output = gr.Markdown("Click 'Get Statistics' to view analysis history")
1049
+
1050
+ with gr.Column():
1051
+ gr.Markdown("### πŸ” Filter History")
1052
+ with gr.Row():
1053
+ sentiment_filter = gr.Dropdown(
1054
+ choices=["All", "Positive", "Negative", "Neutral"],
1055
+ value="All",
1056
+ label="Filter by Sentiment"
1057
+ )
1058
+ language_filter = gr.Dropdown(
1059
+ choices=["All", "English", "Chinese", "Spanish", "French", "German", "Swedish"],
1060
+ value="All",
1061
+ label="Filter by Language"
1062
+ )
1063
+
1064
+ confidence_filter = gr.Slider(
1065
+ minimum=0.0,
1066
+ maximum=1.0,
1067
+ value=0.0,
1068
+ step=0.1,
1069
+ label="Minimum Confidence"
1070
+ )
1071
+
1072
+ filter_btn = gr.Button("πŸ” Filter History")
1073
+
1074
  with gr.Row():
 
1075
  dashboard_btn = gr.Button("πŸ“Š View Dashboard")
1076
  clear_btn = gr.Button("πŸ—‘οΈ Clear History", variant="stop")
1077
 
1078
  with gr.Row():
1079
+ export_csv_btn = gr.Button("πŸ“„ Export CSV")
1080
+ export_excel_btn = gr.Button("πŸ“Š Export Excel")
1081
 
 
1082
  dashboard_plot = gr.Plot(label="Analytics Dashboard")
1083
+
1084
+ with gr.Row():
1085
+ filtered_results = gr.Markdown("Use filters to view specific entries")
1086
+ filtered_table = gr.DataFrame(label="Filtered History", interactive=False)
1087
+
1088
+ csv_file = gr.File(label="Download CSV Report")
1089
  excel_file = gr.File(label="Download Excel Report")
1090
  history_status = gr.Textbox(label="Status", interactive=False)
1091
 
1092
  # Event handlers
1093
+
1094
+ # Single Analysis
1095
  analyze_btn.click(
1096
  analyze_single_text,
1097
  inputs=[text_input, language_select, theme_select, clean_text, remove_punct, remove_nums],
1098
  outputs=[result_info, gauge_plot, bars_plot]
1099
  )
1100
 
1101
+ # Batch Analysis
1102
+ batch_analyze_btn.click(
1103
+ analyze_batch_texts,
1104
+ inputs=[batch_input, batch_language, batch_theme, batch_clean, batch_remove_punct, batch_remove_nums],
1105
+ outputs=[batch_summary, batch_results_table, batch_summary_plot, batch_confidence_plot]
1106
+ )
1107
+
1108
+ # Advanced Analysis
1109
+ advanced_analyze_btn.click(
1110
+ analyze_advanced_text,
1111
+ inputs=[advanced_input, advanced_language, advanced_theme, include_keywords, keyword_count, min_confidence_slider],
1112
+ outputs=[advanced_result_info, advanced_gauge_plot, advanced_bars_plot]
1113
+ )
1114
+
1115
+ # History & Analytics
1116
  stats_btn.click(
1117
  get_history_stats,
1118
  outputs=stats_output
1119
  )
1120
 
1121
+ recent_btn.click(
1122
+ get_recent_analyses,
1123
+ outputs=stats_output
1124
+ )
1125
+
1126
+ filter_btn.click(
1127
+ filter_history_display,
1128
+ inputs=[sentiment_filter, language_filter, confidence_filter],
1129
+ outputs=[filtered_results, filtered_table]
1130
+ )
1131
+
1132
  dashboard_btn.click(
1133
  plot_history_dashboard,
1134
  outputs=[dashboard_plot, history_status]
1135
  )
1136
 
1137
+ export_csv_btn.click(
1138
+ export_history_csv,
1139
+ outputs=[csv_file, history_status]
1140
+ )
1141
+
1142
  export_excel_btn.click(
1143
  export_history_excel,
1144
  outputs=[excel_file, history_status]