Spaces:
Sleeping
Sleeping
""" | |
Visualization components for RoBERTa sentiment analysis | |
""" | |
import gradio as gr | |
import pandas as pd | |
import plotly.express as px | |
import plotly.graph_objects as go | |
from plotly.subplots import make_subplots | |
import numpy as np | |
import json | |
def create_sentiment_visualization(analysis_results): | |
""" | |
Create visualizations for RoBERTa sentiment analysis results | |
Args: | |
analysis_results (dict): Analysis results from the sentiment analysis | |
Returns: | |
list: List of gradio components with visualizations | |
""" | |
print("Starting create_sentiment_visualization function") | |
output_components = [] | |
# Check if we have valid results | |
if not analysis_results or "analyses" not in analysis_results: | |
print("No analysis results found.") | |
return [gr.Markdown("No analysis results found.")] | |
# Add debug print for each step | |
print(f"Number of prompts: {len(analysis_results['analyses'])}") | |
# Process each prompt | |
for prompt, analyses in analysis_results["analyses"].items(): | |
output_components.append(gr.Markdown(f"## Analysis of Prompt: \"{prompt[:100]}{'...' if len(prompt) > 100 else ''}\"")) | |
# Process RoBERTa sentiment analysis if available | |
if "roberta_sentiment" in analyses: | |
sentiment_results = analyses["roberta_sentiment"] | |
# Check if there's an error | |
if "error" in sentiment_results: | |
output_components.append(gr.Markdown(f"**Error in sentiment analysis:** {sentiment_results['error']}")) | |
continue | |
# Show models being compared | |
models = sentiment_results.get("models", []) | |
if len(models) >= 2: | |
output_components.append(gr.Markdown(f"### RoBERTa Sentiment Analysis: Comparing {models[0]} and {models[1]}")) | |
# Create text-based summary of sentiment scores | |
sa_data = sentiment_results.get("sentiment_analysis", {}) | |
if sa_data and len(models) >= 2: | |
# Extract sentiment scores and labels for comparison | |
model_data = [] | |
summary_html = "<div style='margin: 20px 0; padding: 15px; background-color: #f8f9fa; border-radius: 5px;'>" | |
summary_html += "<h4 style='margin-top: 0;'>Sentiment Score Comparison</h4>" | |
summary_html += "<table style='width: 100%; border-collapse: collapse;'>" | |
summary_html += "<tr><th style='text-align: left; padding: 8px; border-bottom: 1px solid #ddd;'>Model</th>" | |
summary_html += "<th style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>Sentiment Score</th>" | |
summary_html += "<th style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>Label</th></tr>" | |
for model_name in models: | |
if model_name in sa_data: | |
model_result = sa_data.get(model_name) | |
if model_result is not None: | |
score = model_result.get("sentiment_score", 0) | |
label = model_result.get("label", "neutral").capitalize() | |
else: | |
score = 0 | |
label = "Neutral" | |
# Set color based on sentiment | |
if label.lower() == "positive": | |
color = "green" | |
elif label.lower() == "negative": | |
color = "red" | |
else: | |
color = "gray" | |
summary_html += f"<tr>" | |
summary_html += f"<td style='padding: 8px; border-bottom: 1px solid #ddd;'>{model_name}</td>" | |
summary_html += f"<td style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd;'>{score:.2f}</td>" | |
summary_html += f"<td style='text-align: center; padding: 8px; border-bottom: 1px solid #ddd; color: {color}; font-weight: bold;'>{label}</td>" | |
summary_html += f"</tr>" | |
summary_html += "</table></div>" | |
output_components.append(gr.HTML(summary_html)) | |
# Create HTML-based score comparison gauge | |
model_scores = [] | |
for model_name in models: | |
if model_name in sa_data: | |
model_result = sa_data.get(model_name) | |
if model_result is not None: | |
score = model_result.get("sentiment_score", 0) | |
model_scores.append((model_name, score)) | |
if len(model_scores) >= 2: | |
gauge_html = "<div style='margin: 20px 0; padding: 15px; background-color: #f8f9fa; border-radius: 5px;'>" | |
gauge_html += "<h4 style='text-align: center; margin-top: 0;'>Sentiment Scale</h4>" | |
gauge_html += "<div style='display: flex; justify-content: space-between; margin-bottom: 5px;'>" | |
gauge_html += "<span>Very Negative (-2.0)</span>" | |
gauge_html += "<span>Neutral (0.0)</span>" | |
gauge_html += "<span>Very Positive (2.0)</span>" | |
gauge_html += "</div>" | |
# Create the gauge background | |
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;'>" | |
# Add model markers | |
for model_name, score in model_scores: | |
# Calculate position (0-100%) | |
position = ((score + 2.0) / 4.0) * 100 | |
position = max(0, min(100, position)) # Clamp between 0-100% | |
# Calculate color | |
if score > 0.5: | |
color = "#006400" # Dark green | |
elif score < -0.5: | |
color = "#8B0000" # Dark red | |
else: | |
color = "#000000" # Black | |
gauge_html += f"<div style='position: absolute; left: {position}%; transform: translateX(-50%); top: 0;'>" | |
gauge_html += f"<div style='width: 3px; height: 30px; background-color: {color};'></div>" | |
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>" | |
gauge_html += "</div>" | |
gauge_html += "</div></div>" | |
output_components.append(gr.HTML(gauge_html)) | |
# Display comparison summary | |
if "comparison" in sentiment_results: | |
comparison = sentiment_results["comparison"] | |
summary_html = """ | |
<div style="margin: 20px 0; padding: 15px; background-color: #f8f9fa; border-radius: 5px;"> | |
<h4 style="margin-top: 0;">Sentiment Comparison Summary</h4> | |
""" | |
# Add difference direction | |
if "difference_direction" in comparison: | |
summary_html += f""" | |
<p style="font-weight: 500; margin-bottom: 10px;"> | |
{comparison["difference_direction"]} | |
</p> | |
""" | |
# Add significance info | |
if "significant_difference" in comparison: | |
color = "red" if comparison["significant_difference"] else "green" | |
significance = "Significant" if comparison["significant_difference"] else "Minor" | |
summary_html += f""" | |
<p> | |
<span style="font-weight: bold; color: {color};">{significance} difference</span> in sentiment | |
(difference score: {comparison.get("sentiment_difference", 0):.2f}) | |
</p> | |
""" | |
summary_html += "</div>" | |
output_components.append(gr.HTML(summary_html)) | |
# Display sentence-level sentiment analysis for both responses | |
model_sentences = {} | |
for model_name in models: | |
if model_name in sa_data: | |
model_result = sa_data.get(model_name) | |
if model_result is not None and "sentence_scores" in model_result: | |
sentence_scores = model_result.get("sentence_scores") | |
if sentence_scores: | |
model_sentences[model_name] = sentence_scores | |
if model_sentences and any(len(sentences) > 0 for sentences in model_sentences.values()): | |
output_components.append(gr.Markdown("### Sentence-Level Sentiment Analysis")) | |
for model_name, sentences in model_sentences.items(): | |
if sentences: | |
output_components.append(gr.Markdown(f"#### {model_name} Response Breakdown")) | |
# Create HTML visualization for sentences with sentiment | |
sentences_html = """ | |
<div style="margin-bottom: 20px;"> | |
""" | |
for i, sentence in enumerate(sentences): | |
score = sentence.get("score", 0) | |
label = sentence.get("label", "neutral") | |
text = sentence.get("text", "") | |
# Skip very short sentences or empty text | |
if len(text.split()) < 3: | |
continue | |
# Color based on sentiment | |
if label == "positive": | |
color = f"rgba(0, 128, 0, {min(1.0, abs(score) * 0.5)})" | |
border = "rgba(0, 128, 0, 0.3)" | |
elif label == "negative": | |
color = f"rgba(255, 0, 0, {min(1.0, abs(score) * 0.5)})" | |
border = "rgba(255, 0, 0, 0.3)" | |
else: | |
color = "rgba(128, 128, 128, 0.1)" | |
border = "rgba(128, 128, 128, 0.3)" | |
sentences_html += f""" | |
<div style="padding: 10px; margin-bottom: 10px; background-color: {color}; | |
border-radius: 5px; border: 1px solid {border};"> | |
<div style="display: flex; justify-content: space-between;"> | |
<span>{text}</span> | |
<span style="margin-left: 10px; font-weight: bold;"> | |
{score:.2f} ({label.capitalize()}) | |
</span> | |
</div> | |
</div> | |
""" | |
sentences_html += "</div>" | |
output_components.append(gr.HTML(sentences_html)) | |
# If no components were added, show a message | |
if len(output_components) <= 1: | |
output_components.append(gr.Markdown("No detailed sentiment analysis found in results.")) | |
return output_components | |
def process_and_visualize_sentiment_analysis(analysis_results): | |
""" | |
Process the sentiment analysis results and create visualization components | |
Args: | |
analysis_results (dict): The analysis results | |
Returns: | |
list: List of gradio components for visualization | |
""" | |
try: | |
print(f"Starting visualization of sentiment analysis results") | |
components = create_sentiment_visualization(analysis_results) | |
return components | |
except Exception as e: | |
import traceback | |
error_msg = f"Sentiment visualization error: {str(e)}\n{traceback.format_exc()}" | |
print(error_msg) | |
return [ | |
gr.Markdown(f"**Error during sentiment visualization:**"), | |
gr.HTML(f"<div style='background-color: #FEE; padding: 10px; border-radius: 5px; border: 1px solid #F88;'>" + | |
f"<pre style='white-space: pre-wrap; overflow-wrap: break-word;'>{str(e)}</pre></div>") | |
] |