import gradio as gr import plotly.graph_objects as go import plotly.express as px import pandas as pd def create_bias_visualization(analysis_results): """ Create visualizations for bias detection analysis results Args: analysis_results (dict): Analysis results from the bias detection Returns: list: List of gradio components with visualizations """ output_components = [] # Check if we have valid results if not analysis_results or "analyses" not in analysis_results: return [gr.Markdown("No analysis results found.")] # Process each prompt for prompt, analyses in analysis_results["analyses"].items(): # Process Bias Detection analysis if available if "bias_detection" in analyses: bias_results = analyses["bias_detection"] # Show models being compared models = bias_results.get("models", []) if len(models) >= 2: output_components.append(gr.Markdown(f"### Bias Analysis: Comparing responses from {models[0]} and {models[1]}")) # Check if there's an error if "error" in bias_results: output_components.append(gr.Markdown(f"**Error in bias detection:** {bias_results['error']}")) continue model1_name, model2_name = models[0], models[1] # Comparative results if "comparative" in bias_results: comparative = bias_results["comparative"] output_components.append(gr.Markdown("#### Comparative Bias Analysis")) # Create summary table summary_html = f""" """ # Sentiment row if "sentiment" in comparative: sent_sig = comparative["sentiment"].get("significant", False) summary_html += f""" """ # Partisan row if "partisan" in comparative: part_sig = comparative["partisan"].get("significant", False) summary_html += f""" """ # Framing row if "framing" in comparative: frame_diff = comparative["framing"].get("different_frames", False) summary_html += f""" """ # Overall row if "overall" in comparative: overall_sig = comparative["overall"].get("significant_bias_difference", False) summary_html += f""" """ summary_html += "
Bias Category {model1_name} {model2_name} Significant Difference?
Sentiment Bias {comparative["sentiment"].get(model1_name, "N/A").title()} {comparative["sentiment"].get(model2_name, "N/A").title()} {"Yes" if sent_sig else "No"}
Partisan Leaning {comparative["partisan"].get(model1_name, "N/A").title()} {comparative["partisan"].get(model2_name, "N/A").title()} {"Yes" if part_sig else "No"}
Dominant Frame {comparative["framing"].get(model1_name, "N/A").title().replace('_', ' ')} {comparative["framing"].get(model2_name, "N/A").title().replace('_', ' ')} {"Yes" if frame_diff else "No"}
Overall Bias Difference {comparative["overall"].get("difference", 0):.2f} / 1.0 {"Yes" if overall_sig else "No"}
" # Add the HTML table to the components output_components.append(gr.HTML(summary_html)) # Create detailed visualizations for each model if available for model_name in [model1_name, model2_name]: if model_name in bias_results: model_data = bias_results[model_name] # Sentiment visualization if "sentiment" in model_data: sentiment = model_data["sentiment"] if "sentiment_scores" in sentiment: # Create sentiment score chart sentiment_df = pd.DataFrame({ 'Score': [ sentiment["sentiment_scores"]["pos"], sentiment["sentiment_scores"]["neg"], sentiment["sentiment_scores"]["neu"] ], 'Category': ['Positive', 'Negative', 'Neutral'] }) fig = px.bar( sentiment_df, x='Category', y='Score', title=f"Sentiment Analysis for {model_name}", height=300 ) output_components.append(gr.Plot(value=fig)) # Partisan leaning visualization if "partisan" in model_data: partisan = model_data["partisan"] if "liberal_count" in partisan and "conservative_count" in partisan: # Create partisan terms chart partisan_df = pd.DataFrame({ 'Count': [partisan["liberal_count"], partisan["conservative_count"]], 'Category': ['Liberal Terms', 'Conservative Terms'] }) fig = px.bar( partisan_df, x='Category', y='Count', title=f"Partisan Term Usage for {model_name}", color='Category', color_discrete_map={ 'Liberal Terms': 'blue', 'Conservative Terms': 'red' }, height=300 ) output_components.append(gr.Plot(value=fig)) # Show example partisan terms if "liberal_terms" in partisan or "conservative_terms" in partisan: lib_terms = ", ".join(partisan.get("liberal_terms", [])) con_terms = ", ".join(partisan.get("conservative_terms", [])) if lib_terms or con_terms: terms_md = f"**Partisan Terms Used by {model_name}**\n\n" if lib_terms: terms_md += f"- Liberal terms: {lib_terms}\n" if con_terms: terms_md += f"- Conservative terms: {con_terms}\n" output_components.append(gr.Markdown(terms_md)) # Framing visualization if "framing" in model_data: framing = model_data["framing"] if "framing_distribution" in framing: # Create framing distribution chart frame_items = [] for frame, value in framing["framing_distribution"].items(): frame_items.append({ 'Frame': frame.replace('_', ' ').title(), 'Proportion': value }) frame_df = pd.DataFrame(frame_items) fig = px.pie( frame_df, values='Proportion', names='Frame', title=f"Issue Framing Distribution for {model_name}", height=400 ) output_components.append(gr.Plot(value=fig)) # Show example framing terms if "framing_examples" in framing: examples_md = f"**Example Framing Terms Used by {model_name}**\n\n" for frame, examples in framing["framing_examples"].items(): if examples: examples_md += f"- {frame.replace('_', ' ').title()}: {', '.join(examples)}\n" output_components.append(gr.Markdown(examples_md)) # If no components were added, show a message if len(output_components) <= 1: output_components.append(gr.Markdown("No detailed bias detection analysis found in results.")) return output_components def process_and_visualize_bias_analysis(analysis_results): """ Process the bias detection 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 bias detection analysis results") return create_bias_visualization(analysis_results) except Exception as e: import traceback error_msg = f"Bias detection visualization error: {str(e)}\n{traceback.format_exc()}" print(error_msg) return [gr.Markdown(f"**Error during bias detection visualization:**\n\n```\n{error_msg}\n```")]