import pandas as pd import gradio as gr import matplotlib.pyplot as plt import io from PIL import Image from transformers import pipeline # ---------------------------- # Load AI Models # ---------------------------- sentiment_model = pipeline( "sentiment-analysis", model="distilbert-base-uncased-finetuned-sst-2-english" ) theme_model = pipeline( "zero-shot-classification", model="valhalla/distilbart-mnli-12-3" ) THEMES = [ "product quality", "delivery", "price", "packaging", "taste", "customer service" ] # ---------------------------- # Analyze One Review # ---------------------------- def analyze_review(text): text = str(text)[:512] sentiment_result = sentiment_model(text)[0] label = sentiment_result["label"] confidence = round(sentiment_result["score"] * 100, 1) theme_result = theme_model(text, THEMES) top_theme = theme_result["labels"][0] theme_score = round(theme_result["scores"][0] * 100, 1) return label, confidence, top_theme, theme_score # ---------------------------- # Build Charts # ---------------------------- def build_chart(df): fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4)) sentiment_counts = df["Sentiment"].value_counts() color_map = { "POSITIVE": "#22c55e", "NEGATIVE": "#ef4444", "NEUTRAL": "#94a3b8" } colors = [color_map.get(label, "#94a3b8") for label in sentiment_counts.index] ax1.pie( sentiment_counts.values, labels=sentiment_counts.index, autopct="%1.0f%%", colors=colors, startangle=90, wedgeprops=dict(width=0.5) ) ax1.set_title("Sentiment Split") theme_counts = df["Top Theme"].value_counts() ax2.barh(theme_counts.index, theme_counts.values) ax2.set_title("Top Themes") ax2.invert_yaxis() plt.tight_layout() buf = io.BytesIO() plt.savefig(buf, format="png") plt.close(fig) buf.seek(0) return Image.open(buf) # ---------------------------- # Analyze Uploaded Excel File # ---------------------------- def analyze_excel(file): df = pd.read_excel(file.name) if "review_text" not in df.columns: if "Text" in df.columns: df = df.rename(columns={"Text": "review_text"}) else: return ( None, "❌ Excel file must contain a 'review_text' or 'Text' column.", None ) df = df.dropna(subset=["review_text"]) results = [] for _, row in df.iterrows(): label, confidence, theme, theme_confidence = analyze_review( row["review_text"] ) results.append( { "Review": str(row["review_text"])[:100] + "...", "Sentiment": label, "Confidence %": confidence, "Top Theme": theme, "Theme Confidence %": theme_confidence } ) output_df = pd.DataFrame(results) positive_pct = round( (output_df["Sentiment"] == "POSITIVE").mean() * 100, 1 ) summary = ( f"✅ Successfully analyzed {len(output_df)} reviews.\n" f"Positive Reviews: {positive_pct}%" ) chart = build_chart(output_df) return output_df, summary, chart # ---------------------------- # Gradio UI # ---------------------------- with gr.Blocks(title="Customer Feedback Analyzer") as app: gr.Markdown( """ # 🧠 AI Customer Feedback Analyzer Upload an Excel (.xlsx) file containing customer reviews. The app automatically predicts: - Sentiment - Confidence - Top Theme - Theme Confidence """ ) file_input = gr.File( label="Upload Excel File (.xlsx)", file_types=[".xlsx"] ) analyze_button = gr.Button("Analyze") summary_output = gr.Textbox(label="Summary") chart_output = gr.Image(label="Charts") table_output = gr.Dataframe(label="Analysis Results") analyze_button.click( analyze_excel, inputs=file_input, outputs=[ table_output, summary_output, chart_output ] ) app.launch()