File size: 13,871 Bytes
7731b47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1403d1
7731b47
 
 
 
a1403d1
7731b47
 
a1403d1
 
 
7731b47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a92712
7731b47
 
4069671
7731b47
 
9a92712
 
 
 
 
 
 
7731b47
 
4973fc0
fe35cb2
 
 
 
 
 
9a92712
 
 
 
 
 
 
 
 
 
 
 
 
 
7731b47
9a92712
 
 
 
 
 
 
4973fc0
 
 
 
9a92712
 
 
 
 
 
 
 
 
7731b47
9a92712
 
7731b47
9a92712
 
 
 
 
7731b47
9a92712
 
 
 
 
 
 
 
 
 
 
 
7731b47
9a92712
7731b47
9a92712
7731b47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4973fc0
 
 
 
 
 
7731b47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9a92712
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
"""
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>")
        ]