Ryan commited on
Commit
9a92712
·
1 Parent(s): 916f9cc
Files changed (3) hide show
  1. app.py +44 -25
  2. ui/roberta_screen.py +8 -5
  3. visualization/roberta_visualizer.py +68 -70
app.py CHANGED
@@ -586,25 +586,27 @@ def create_app():
586
  gr.update(visible=True, value=f"❌ **Error during analysis:**\n\n```\n{str(e)}\n```") # status_message
587
  )
588
 
589
- # RoBERTa Sentiment Analysis Tab (NEW)
590
  with gr.Tab("RoBERTa Sentiment"):
591
  # Create the RoBERTa analysis UI components
592
  run_roberta_btn, roberta_output, sentence_level, visualization_style, visualization_container, roberta_status = create_roberta_screen()
593
 
594
- # Container for visualization results
595
  with gr.Column() as roberta_viz_container:
596
- roberta_viz_components = []
 
 
597
 
598
- # Function to run RoBERTa sentiment analysis
599
  def run_roberta_analysis(dataset, sentence_level, visualization_style):
600
  try:
601
  if not dataset or "entries" not in dataset or not dataset["entries"]:
602
  return (
603
  {}, # roberta_results_state
604
- True, # status_message_visible
605
- gr.update(visible=True, value="❌ **Error:** No dataset loaded. Please create or load a dataset first."), # status_message
606
- False, # roberta_output visibility
607
- [] # empty visualization components
608
  )
609
 
610
  print(f"Running RoBERTa sentiment analysis with sentence-level={sentence_level}, style={visualization_style}")
@@ -616,23 +618,40 @@ def create_app():
616
  if "error" in roberta_results:
617
  return (
618
  roberta_results, # Store in state anyway for debugging
619
- True, # status_message_visible
620
- gr.update(visible=True, value=f"❌ **Error:** {roberta_results['error']}"), # status_message
621
- False, # Hide raw output
622
- [] # empty visualization components
623
  )
624
 
625
- # Create visualization components
626
  viz_components = process_and_visualize_sentiment_analysis(roberta_results)
627
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
  return (
629
  roberta_results, # roberta_results_state
630
- False, # status_message_visible
631
- gr.update(visible=False), # status_message
632
- False, # roberta_output visibility (hide raw output)
633
- viz_components # visualization components
634
  )
635
-
636
  except Exception as e:
637
  import traceback
638
  error_msg = f"Error in RoBERTa analysis: {str(e)}\n{traceback.format_exc()}"
@@ -640,22 +659,22 @@ def create_app():
640
 
641
  return (
642
  {"error": error_msg}, # roberta_results_state
643
- True, # status_message_visible
644
- gr.update(visible=True, value=f"❌ **Error during RoBERTa analysis:**\n\n```\n{str(e)}\n```"), # status_message
645
- False, # Hide raw output
646
- [] # empty visualization components
647
  )
648
 
649
- # Connect the run button to the analysis function
650
  run_roberta_btn.click(
651
  fn=run_roberta_analysis,
652
  inputs=[dataset_state, sentence_level, visualization_style],
653
  outputs=[
654
  roberta_results_state,
655
- gr.Checkbox(visible=False, value=False), # Hidden checkbox for status visibility
656
  roberta_status,
657
  roberta_output,
658
- roberta_viz_container
 
659
  ]
660
  )
661
 
 
586
  gr.update(visible=True, value=f"❌ **Error during analysis:**\n\n```\n{str(e)}\n```") # status_message
587
  )
588
 
589
+ # RoBERTa Sentiment Analysis Tab (FIXED)
590
  with gr.Tab("RoBERTa Sentiment"):
591
  # Create the RoBERTa analysis UI components
592
  run_roberta_btn, roberta_output, sentence_level, visualization_style, visualization_container, roberta_status = create_roberta_screen()
593
 
594
+ # Create a container for visualization results
595
  with gr.Column() as roberta_viz_container:
596
+ # We'll create placeholder components to update
597
+ roberta_viz_title = gr.Markdown("## RoBERTa Sentiment Analysis Results", visible=False)
598
+ roberta_viz_content = gr.HTML("", visible=False)
599
 
600
+ # Function to run RoBERTa sentiment analysis (FIXED)
601
  def run_roberta_analysis(dataset, sentence_level, visualization_style):
602
  try:
603
  if not dataset or "entries" not in dataset or not dataset["entries"]:
604
  return (
605
  {}, # roberta_results_state
606
+ gr.update(visible=True, value="❌ **Error:** No dataset loaded. Please create or load a dataset first."), # roberta_status
607
+ gr.update(visible=False), # roberta_output
608
+ gr.update(visible=False), # roberta_viz_title
609
+ gr.update(visible=False) # roberta_viz_content
610
  )
611
 
612
  print(f"Running RoBERTa sentiment analysis with sentence-level={sentence_level}, style={visualization_style}")
 
618
  if "error" in roberta_results:
619
  return (
620
  roberta_results, # Store in state anyway for debugging
621
+ gr.update(visible=True, value=f"❌ **Error:** {roberta_results['error']}"), # roberta_status
622
+ gr.update(visible=False), # Hide raw output
623
+ gr.update(visible=False), # roberta_viz_title
624
+ gr.update(visible=False) # roberta_viz_content
625
  )
626
 
627
+ # Process the visualization
628
  viz_components = process_and_visualize_sentiment_analysis(roberta_results)
629
 
630
+ # Convert the visualization components to HTML
631
+ html_content = "<div class='sentiment-visualization'>"
632
+
633
+ for component in viz_components:
634
+ if isinstance(component, gr.Markdown):
635
+ # Convert Markdown to HTML
636
+ html_content += f"<div class='markdown-content'>{component.value}</div>"
637
+ elif isinstance(component, gr.Plot):
638
+ # For Plot components, add a placeholder message
639
+ html_content += "<div class='plot-placeholder'>Sentiment plot will appear here</div>"
640
+ elif isinstance(component, gr.HTML):
641
+ # Directly include HTML components
642
+ html_content += component.value
643
+
644
+ html_content += "</div>"
645
+
646
+ # Return updated values
647
  return (
648
  roberta_results, # roberta_results_state
649
+ gr.update(visible=False), # roberta_status (hide status message)
650
+ gr.update(visible=False), # roberta_output (hide raw output)
651
+ gr.update(visible=True), # roberta_viz_title (show title)
652
+ gr.update(visible=True, value=html_content) # roberta_viz_content (show content)
653
  )
654
+
655
  except Exception as e:
656
  import traceback
657
  error_msg = f"Error in RoBERTa analysis: {str(e)}\n{traceback.format_exc()}"
 
659
 
660
  return (
661
  {"error": error_msg}, # roberta_results_state
662
+ gr.update(visible=True, value=f"❌ **Error during RoBERTa analysis:**\n\n```\n{str(e)}\n```"), # roberta_status
663
+ gr.update(visible=False), # Hide raw output
664
+ gr.update(visible=False), # roberta_viz_title
665
+ gr.update(visible=False) # roberta_viz_content
666
  )
667
 
668
+ # Connect the run button to the analysis function (FIXED)
669
  run_roberta_btn.click(
670
  fn=run_roberta_analysis,
671
  inputs=[dataset_state, sentence_level, visualization_style],
672
  outputs=[
673
  roberta_results_state,
 
674
  roberta_status,
675
  roberta_output,
676
+ roberta_viz_title,
677
+ roberta_viz_content
678
  ]
679
  )
680
 
ui/roberta_screen.py CHANGED
@@ -9,7 +9,7 @@ def create_roberta_screen():
9
  Create the RoBERTa sentiment analysis screen components
10
 
11
  Returns:
12
- tuple: (run_roberta_btn, roberta_output, other components...)
13
  """
14
  with gr.Column() as roberta_screen:
15
  gr.Markdown("## RoBERTa Sentiment Analysis")
@@ -42,14 +42,17 @@ def create_roberta_screen():
42
  # Run button in its own column for better visibility
43
  run_roberta_btn = gr.Button("Run Sentiment Analysis", variant="primary", size="large")
44
 
 
 
 
45
  # Hidden output to store raw analysis results
46
  roberta_output = gr.JSON(label="Sentiment Analysis Results", visible=False)
47
 
48
- # Pre-create visualization components (all initially hidden)
 
49
  visualization_container = gr.Markdown(visible=False)
50
- status_message = gr.Markdown(visible=False)
51
 
52
- return run_roberta_btn, roberta_output, sentence_level, visualization_style, visualization_container, status_message
53
 
54
  def process_roberta_request(dataset, sentence_level=True, visualization_style="Standard"):
55
  """
@@ -122,4 +125,4 @@ def process_roberta_request(dataset, sentence_level=True, visualization_style="S
122
  }
123
  }
124
  }
125
- }
 
9
  Create the RoBERTa sentiment analysis screen components
10
 
11
  Returns:
12
+ tuple: (run_roberta_btn, roberta_output, sentence_level, visualization_style, visualization_container, roberta_status)
13
  """
14
  with gr.Column() as roberta_screen:
15
  gr.Markdown("## RoBERTa Sentiment Analysis")
 
42
  # Run button in its own column for better visibility
43
  run_roberta_btn = gr.Button("Run Sentiment Analysis", variant="primary", size="large")
44
 
45
+ # Status message area
46
+ roberta_status = gr.Markdown(visible=False)
47
+
48
  # Hidden output to store raw analysis results
49
  roberta_output = gr.JSON(label="Sentiment Analysis Results", visible=False)
50
 
51
+ # Placeholder for visualization container - this won't be directly updated
52
+ # but is included for backward compatibility
53
  visualization_container = gr.Markdown(visible=False)
 
54
 
55
+ return run_roberta_btn, roberta_output, sentence_level, visualization_style, visualization_container, roberta_status
56
 
57
  def process_roberta_request(dataset, sentence_level=True, visualization_style="Standard"):
58
  """
 
125
  }
126
  }
127
  }
128
+ }
visualization/roberta_visualizer.py CHANGED
@@ -43,89 +43,83 @@ def create_sentiment_visualization(analysis_results):
43
  if len(models) >= 2:
44
  output_components.append(gr.Markdown(f"### RoBERTa Sentiment Analysis: Comparing {models[0]} and {models[1]}"))
45
 
46
- # Create a sentiment comparison chart
47
  sa_data = sentiment_results.get("sentiment_analysis", {})
48
  if sa_data and len(models) >= 2:
49
  # Extract sentiment scores and labels for comparison
50
  model_data = []
51
 
 
 
 
 
 
 
 
52
  for model_name in models:
53
  if model_name in sa_data:
54
  model_result = sa_data[model_name]
55
- model_data.append({
56
- "model": model_name,
57
- "sentiment_score": model_result.get("sentiment_score", 0),
58
- "label": model_result.get("label", "neutral"),
59
- "contradiction": model_result.get("scores", {}).get("contradiction", 0),
60
- "neutral": model_result.get("scores", {}).get("neutral", 0),
61
- "entailment": model_result.get("scores", {}).get("entailment", 0)
62
- })
 
 
 
 
 
 
 
 
63
 
64
- if model_data:
65
- df = pd.DataFrame(model_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- # Create gauge chart for sentiment scores
68
- fig = go.Figure()
69
 
70
- # Add gauge for each model
71
- for i, row in df.iterrows():
72
- # Set color based on sentiment
73
- color = "green" if row["sentiment_score"] > 0.5 else "red" if row["sentiment_score"] < -0.5 else "gray"
 
74
 
75
- fig.add_trace(go.Indicator(
76
- mode="gauge+number",
77
- value=row["sentiment_score"],
78
- title={"text": f"{row['model']}<br><span style='font-size:0.8em;color:{color}'>{row['label'].capitalize()}</span>"},
79
- gauge={
80
- "axis": {"range": [-2, 2], "tickmode": "array", "tickvals": [-2, -1, 0, 1, 2],
81
- "ticktext": ["Very Negative", "Negative", "Neutral", "Positive", "Very Positive"]},
82
- "bar": {"color": color},
83
- "threshold": {
84
- "line": {"color": "black", "width": 2},
85
- "thickness": 0.75,
86
- "value": row["sentiment_score"]
87
- },
88
- "steps": [
89
- {"range": [-2, -0.5], "color": "rgba(255, 0, 0, 0.2)"},
90
- {"range": [-0.5, 0.5], "color": "rgba(128, 128, 128, 0.2)"},
91
- {"range": [0.5, 2], "color": "rgba(0, 128, 0, 0.2)"}
92
- ]
93
- },
94
- domain={"row": 0, "column": i}
95
- ))
96
-
97
- # Layout adjustments
98
- fig.update_layout(
99
- title="Sentiment Score Comparison",
100
- grid={"rows": 1, "columns": len(df), "pattern": "independent"},
101
- height=300,
102
- margin=dict(t=70, b=30, l=30, r=30)
103
- )
104
-
105
- output_components.append(gr.Plot(value=fig))
106
-
107
- # Create detailed scores visualization
108
- fig2 = make_subplots(rows=1, cols=len(df),
109
- subplot_titles=[f"{row['model']} Detailed Scores" for i, row in df.iterrows()])
110
-
111
- for i, row in df.iterrows():
112
- fig2.add_trace(
113
- go.Bar(
114
- x=["Contradiction (Negative)", "Neutral", "Entailment (Positive)"],
115
- y=[row["contradiction"], row["neutral"], row["entailment"]],
116
- marker_color=["rgba(255, 0, 0, 0.6)", "rgba(128, 128, 128, 0.6)", "rgba(0, 128, 0, 0.6)"]
117
- ),
118
- row=1, col=i+1
119
- )
120
 
121
- fig2.update_layout(
122
- title="RoBERTa Classification Scores",
123
- showlegend=False,
124
- height=350,
125
- margin=dict(t=70, b=30, l=30, r=30)
126
- )
127
 
128
- output_components.append(gr.Plot(value=fig2))
129
 
130
  # Display comparison summary
131
  if "comparison" in sentiment_results:
@@ -237,4 +231,8 @@ def process_and_visualize_sentiment_analysis(analysis_results):
237
  import traceback
238
  error_msg = f"Sentiment visualization error: {str(e)}\n{traceback.format_exc()}"
239
  print(error_msg)
240
- return [gr.Markdown(f"**Error during sentiment visualization:**\n\n```\n{str(e)}\n```")]
 
 
 
 
 
43
  if len(models) >= 2:
44
  output_components.append(gr.Markdown(f"### RoBERTa Sentiment Analysis: Comparing {models[0]} and {models[1]}"))
45
 
46
+ # Create text-based summary of sentiment scores
47
  sa_data = sentiment_results.get("sentiment_analysis", {})
48
  if sa_data and len(models) >= 2:
49
  # Extract sentiment scores and labels for comparison
50
  model_data = []
51
 
52
+ summary_html = "<div style='margin: 20px 0; padding: 15px; background-color: #f8f9fa; border-radius: 5px;'>"
53
+ summary_html += "<h4 style='margin-top: 0;'>Sentiment Score Comparison</h4>"
54
+ summary_html += "<table style='width: 100%; border-collapse: collapse;'>"
55
+ summary_html += "<tr><th style='text-align: left; padding: 8px; border-bottom: 1px solid #ddd;'>Model</th>"
56
+ summary_html += "<th style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>Sentiment Score</th>"
57
+ summary_html += "<th style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>Label</th></tr>"
58
+
59
  for model_name in models:
60
  if model_name in sa_data:
61
  model_result = sa_data[model_name]
62
+ score = model_result.get("sentiment_score", 0)
63
+ label = model_result.get("label", "neutral").capitalize()
64
+
65
+ # Set color based on sentiment
66
+ if label.lower() == "positive":
67
+ color = "green"
68
+ elif label.lower() == "negative":
69
+ color = "red"
70
+ else:
71
+ color = "gray"
72
+
73
+ summary_html += f"<tr>"
74
+ summary_html += f"<td style='padding: 8px; border-bottom: 1px solid #ddd;'>{model_name}</td>"
75
+ summary_html += f"<td style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>{score:.2f}</td>"
76
+ summary_html += f"<td style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd; color: {color}; font-weight: bold;'>{label}</td>"
77
+ summary_html += f"</tr>"
78
 
79
+ summary_html += "</table></div>"
80
+ output_components.append(gr.HTML(summary_html))
81
+
82
+ # Create HTML-based score comparison gauge
83
+ model_scores = []
84
+ for model_name in models:
85
+ if model_name in sa_data:
86
+ score = sa_data[model_name].get("sentiment_score", 0)
87
+ model_scores.append((model_name, score))
88
+
89
+ if len(model_scores) >= 2:
90
+ gauge_html = "<div style='margin: 20px 0; padding: 15px; background-color: #f8f9fa; border-radius: 5px;'>"
91
+ gauge_html += "<h4 style='text-align: center; margin-top: 0;'>Sentiment Scale</h4>"
92
+ gauge_html += "<div style='display: flex; justify-content: space-between; margin-bottom: 5px;'>"
93
+ gauge_html += "<span>Very Negative (-2.0)</span>"
94
+ gauge_html += "<span>Neutral (0.0)</span>"
95
+ gauge_html += "<span>Very Positive (2.0)</span>"
96
+ gauge_html += "</div>"
97
 
98
+ # Create the gauge background
99
+ gauge_html += "<div style='position: relative; width: 100%; height: 30px; background: linear-gradient(to right, #d73027, #f46d43, #fdae61, #fee08b, #ffffbf, #d9ef8b, #a6d96a, #66bd63, #1a9850); border-radius: 5px;'>"
100
 
101
+ # Add model markers
102
+ for model_name, score in model_scores:
103
+ # Calculate position (0-100%)
104
+ position = ((score + 2.0) / 4.0) * 100
105
+ position = max(0, min(100, position)) # Clamp between 0-100%
106
 
107
+ # Calculate color
108
+ if score > 0.5:
109
+ color = "#006400" # Dark green
110
+ elif score < -0.5:
111
+ color = "#8B0000" # Dark red
112
+ else:
113
+ color = "#000000" # Black
114
+
115
+ gauge_html += f"<div style='position: absolute; left: {position}%; transform: translateX(-50%); top: 0;'>"
116
+ gauge_html += f"<div style='width: 3px; height: 30px; background-color: {color};'></div>"
117
+ gauge_html += f"<div style='position: absolute; top: 100%; left: 50%; transform: translateX(-50%); white-space: nowrap; font-weight: bold; color: {color};'>{model_name}: {score:.2f}</div>"
118
+ gauge_html += "</div>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
+ gauge_html += "</div></div>"
 
 
 
 
 
121
 
122
+ output_components.append(gr.HTML(gauge_html))
123
 
124
  # Display comparison summary
125
  if "comparison" in sentiment_results:
 
231
  import traceback
232
  error_msg = f"Sentiment visualization error: {str(e)}\n{traceback.format_exc()}"
233
  print(error_msg)
234
+ return [
235
+ gr.Markdown(f"**Error during sentiment visualization:**"),
236
+ gr.HTML(f"<div style='background-color: #FEE; padding: 10px; border-radius: 5px; border: 1px solid #F88;'>" +
237
+ f"<pre style='white-space: pre-wrap; overflow-wrap: break-word;'>{str(e)}</pre></div>")
238
+ ]