Spaces:
Sleeping
Sleeping
import gradio as gr | |
import logging | |
import traceback | |
import matplotlib.pyplot as plt | |
import numpy as np | |
import plotly.graph_objects as go | |
from plotly.subplots import make_subplots | |
import io | |
import base64 | |
# Set up logging | |
logger = logging.getLogger('gradio_app.processors.bias') | |
def process_bias_detection(analysis_results, prompt, analyses): | |
""" | |
Process Bias Detection analysis and return UI updates | |
Args: | |
analysis_results (dict): Complete analysis results | |
prompt (str): The prompt being analyzed | |
analyses (dict): Analysis data for the prompt | |
Returns: | |
tuple: UI component updates | |
""" | |
logger.info("Processing Bias Detection visualization") | |
models = analyses["bias_detection"].get("models", ["Model 1", "Model 2"]) | |
logger.info(f"Bias models: {models}") | |
try: | |
# Get the bias detection results | |
bias_results = analyses["bias_detection"] | |
# Create markdown components for text description | |
results_markdown = f""" | |
## Bias Analysis Results | |
### Sentiment Analysis | |
- {models[0]}: {bias_results[models[0]]['sentiment']['bias_direction']} (strength: {bias_results[models[0]]['sentiment']['bias_strength']:.2f}) | |
- {models[1]}: {bias_results[models[1]]['sentiment']['bias_direction']} (strength: {bias_results[models[1]]['sentiment']['bias_strength']:.2f}) | |
- Difference: {bias_results['comparative']['sentiment']['difference']:.2f} | |
### Partisan Leaning | |
- {models[0]}: {bias_results[models[0]]['partisan']['leaning']} (score: {bias_results[models[0]]['partisan']['lean_score']:.2f}) | |
- {models[1]}: {bias_results[models[1]]['partisan']['leaning']} (score: {bias_results[models[1]]['partisan']['lean_score']:.2f}) | |
- Difference: {bias_results['comparative']['partisan']['difference']:.2f} | |
### Framing Analysis | |
- {models[0]} dominant frame: {bias_results[models[0]]['framing']['dominant_frame']} | |
- {models[1]} dominant frame: {bias_results[models[1]]['framing']['dominant_frame']} | |
- Different frames: {'Yes' if bias_results['comparative']['framing']['different_frames'] else 'No'} | |
### Liberal Terms Found | |
- {models[0]}: {', '.join(bias_results[models[0]]['partisan']['liberal_terms'][:10])} | |
- {models[1]}: {', '.join(bias_results[models[1]]['partisan']['liberal_terms'][:10])} | |
### Conservative Terms Found | |
- {models[0]}: {', '.join(bias_results[models[0]]['partisan']['conservative_terms'][:10])} | |
- {models[1]}: {', '.join(bias_results[models[1]]['partisan']['conservative_terms'][:10])} | |
### Overall Comparison | |
The overall bias difference is {bias_results['comparative']['overall']['difference']:.2f}, which is | |
{'significant' if bias_results['comparative']['overall']['significant_bias_difference'] else 'not significant'}. | |
""" | |
# Create visual components | |
# 1. Sentiment Analysis Visualization | |
fig1 = go.Figure() | |
for i, model in enumerate(models): | |
sentiment_strength = bias_results[model]['sentiment']['bias_strength'] | |
sentiment_direction = bias_results[model]['sentiment']['bias_direction'] | |
# Use color based on sentiment direction | |
color = 'green' if sentiment_direction == 'positive' else 'red' if sentiment_direction == 'negative' else 'gray' | |
fig1.add_trace(go.Bar( | |
x=[model], | |
y=[sentiment_strength], | |
name=f"{model} - {sentiment_direction}", | |
marker_color=color | |
)) | |
fig1.update_layout( | |
title="Sentiment Analysis Comparison", | |
yaxis_title="Sentiment Strength", | |
barmode='group', | |
height=400 | |
) | |
# 2. Partisan Leaning Visualization | |
fig2 = go.Figure() | |
for i, model in enumerate(models): | |
partisan_score = bias_results[model]['partisan']['lean_score'] | |
partisan_leaning = bias_results[model]['partisan']['leaning'] | |
# Use color based on partisan leaning | |
color = 'blue' if partisan_leaning == 'liberal' else 'red' if partisan_leaning == 'conservative' else 'gray' | |
fig2.add_trace(go.Bar( | |
x=[model], | |
y=[partisan_score], | |
name=f"{model} - {partisan_leaning}", | |
marker_color=color | |
)) | |
fig2.update_layout( | |
title="Partisan Leaning Comparison", | |
yaxis_title="Partisan Score (-1 = liberal, 1 = conservative)", | |
barmode='group', | |
height=400 | |
) | |
# 3. Framing Analysis Visualization | |
frames = ['economic', 'moral', 'security', 'social_welfare'] | |
# Create subplots with 1 row and 2 columns for side-by-side comparison | |
fig3 = make_subplots(rows=1, cols=2, subplot_titles=models) | |
for i, model in enumerate(models): | |
# Fix: Instead of directly accessing 'frame_counts', extract counts from frame_counts data | |
# Check if the data structure has 'frame_counts' key, otherwise use 'frames' directly | |
if 'frame_counts' in bias_results[model]['framing']: | |
frame_counts = bias_results[model]['framing']['frame_counts'] | |
else: | |
# Assuming frames data is available directly in the 'framing' section | |
frame_data = bias_results[model]['framing'].get('frames', {}) | |
# If not found, try to reconstruct from log data | |
if not frame_data: | |
# Use the information from logs to construct a minimal frame counts | |
frame_counts = {} | |
for frame in frames: | |
# Default to 0 or try to get count from other available sources | |
frame_counts[frame] = bias_results[model]['framing'].get(frame, 0) | |
else: | |
frame_counts = frame_data | |
# Add trace for each model | |
fig3.add_trace( | |
go.Bar( | |
x=list(frame_counts.keys()), | |
y=list(frame_counts.values()), | |
name=model | |
), | |
row=1, col=i + 1 | |
) | |
fig3.update_layout( | |
title="Framing Analysis Comparison", | |
height=400 | |
) | |
# Create individual components for results rather than trying to return a Column | |
markdown_component = results_markdown | |
plot1 = fig1 | |
plot2 = fig2 | |
plot3 = fig3 | |
return ( | |
analysis_results, # analysis_results_state | |
False, # analysis_output visibility | |
True, # visualization_area_visible | |
gr.update(visible=True), # analysis_title | |
gr.update(visible=True, value=f"## Analysis of Prompt: \"{prompt[:100]}...\""), # prompt_title | |
gr.update(visible=True, value=f"### Comparing responses from {models[0]} and {models[1]}"), | |
# models_compared | |
gr.update(visible=True, value="#### Bias detection visualization is available below"), # model1_title | |
gr.update(visible=True, | |
value="The detailed bias analysis includes sentiment analysis, partisan term detection, and framing analysis."), | |
# model1_words | |
gr.update(visible=False), # model2_title | |
gr.update(visible=False), # model2_words | |
gr.update(visible=False), # similarity_metrics_title | |
gr.update(visible=False), # similarity_metrics | |
False, # status_message_visible | |
gr.update(visible=False), # status_message | |
markdown_component, # Instead of returning a list, return individual components | |
plot1, | |
plot2, | |
plot3 | |
) | |
except Exception as e: | |
logger.error(f"Error generating bias visualization: {str(e)}\n{traceback.format_exc()}") | |
return ( | |
analysis_results, | |
True, # Show raw JSON for debugging | |
False, | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
gr.update(visible=False), | |
True, | |
gr.update(visible=True, value=f"❌ **Error generating bias visualization:** {str(e)}"), | |
"", # Return empty strings for visualization components instead of None | |
None, | |
None, | |
None | |
) |