import streamlit as st import pandas as pd import plotly.express as px import matplotlib.pyplot as plt import json from typing import Dict, List, Any, Union import torch def display_json_as_table(data: Union[Dict, List]): """Display JSON data as a formatted table""" if isinstance(data, list): # Convert list of dicts to dataframe if possible try: df = pd.DataFrame(data) st.dataframe(df) except: # Fall back to JSON display st.json(data) else: # Convert dict to dataframe with keys and values as columns try: df = pd.DataFrame(list(data.items()), columns=['Key', 'Value']) st.dataframe(df) except: # Fall back to JSON display st.json(data) def format_sentiment_result(result: List[Dict]): """Format sentiment analysis result for display""" if not result: return {} # Get the first result (usually there's only one) item = result[0] # Create a dataframe for display df = pd.DataFrame({ 'Label': [item['label']], 'Score': [round(item['score'] * 100, 2)], }) # Add visual indicator based on sentiment is_positive = item['label'].lower() == 'positive' color = 'green' if is_positive else 'red' emoji = '😃' if is_positive else '😞' return { 'dataframe': df, 'color': color, 'emoji': emoji, 'score': round(item['score'] * 100, 2) } def plot_sentiment_gauge(score: float, color: str): """Create a gauge chart for sentiment score""" fig = px.pie( values=[score, 100-score], names=['Score', ''], color_discrete_sequence=[color, '#F0F2F6'], hole=0.7, ) fig.update_layout( annotations=[dict(text=f"{score}%", x=0.5, y=0.5, font_size=20, showarrow=False)], showlegend=False, margin=dict(l=20, r=20, t=20, b=20), height=200, ) return fig def format_ner_results(ner_results: List[Dict]): """Format NER results for display""" # Convert to DataFrame for easier display if not ner_results: return pd.DataFrame() entities_data = [] for entity in ner_results: entities_data.append({ 'Entity': entity['word'], 'Type': entity['entity_group'], 'Score': round(entity['score'] * 100, 2), 'Start': entity['start'], 'End': entity['end'] }) return pd.DataFrame(entities_data) def highlight_entities_in_text(text: str, entities: List[Dict]): """Highlight entities in text for display""" if not entities: return text # Sort entities by start position in reverse order # to avoid index shifting when replacing sorted_entities = sorted(entities, key=lambda x: x['start'], reverse=True) # Convert text to HTML with highlights html_text = text for entity in sorted_entities: start = entity['start'] end = entity['end'] entity_text = text[start:end] entity_type = entity['entity_group'] # Define color based on entity type color_map = { 'PER': '#FFD700', # Person - Gold 'ORG': '#98FB98', # Organization - Pale Green 'LOC': '#ADD8E6', # Location - Light Blue 'MISC': '#FFA07A' # Miscellaneous - Light Salmon } color = color_map.get(entity_type, '#D3D3D3') # Default to light gray # Replace text with highlighted version highlight = f'{entity_text}' html_text = html_text[:start] + highlight + html_text[end:] return html_text def plot_similarity_heatmap(query: str, texts: List[str], similarities: List[float]): """Create a bar chart for similarity scores""" # Create a DataFrame with the data df = pd.DataFrame({ 'Text': texts, 'Similarity': similarities }) # Sort by similarity score in descending order df = df.sort_values('Similarity', ascending=False) # Create the bar chart fig = px.bar( df, x='Similarity', y='Text', orientation='h', title=f'Similarity to: "{query}"', labels={'Similarity': 'Cosine Similarity', 'Text': 'Corpus Text'}, range_x=[0, 1] ) fig.update_layout( height=300, margin=dict(l=20, r=20, t=40, b=20), ) return fig def display_text_with_answer(context: str, answer: Dict): """Display context text with highlighted answer""" if not answer or 'start' not in answer or 'end' not in answer: return context start = answer['start'] end = answer['end'] answer_text = answer['answer'] # Replace the answer with a highlighted version highlighted_text = ( context[:start] + f'{answer_text}' + context[end:] ) return highlighted_text