import gradio as gr import pandas as pd from transformers import pipeline # ------------------------------------------------ # Load Qwen 3B (instruction-following, concise) # ------------------------------------------------ generator = pipeline( "text-generation", model="Qwen/Qwen2.5-3B-Instruct", device_map="auto", trust_remote_code=True ) # ------------------------------------------------ # Generic fact quantization (NO domain logic) # ------------------------------------------------ def magnitude_bucket(x): if x < 0.05: return "low" elif x < 0.2: return "medium" else: return "high" def direction_bucket(diff): if diff > 0: return "increase" elif diff < 0: return "decrease" else: return "no_change" # ------------------------------------------------ # Core logic # ------------------------------------------------ def analyze_kpi(csv_file, top_n): df = pd.read_csv(csv_file.name) dates = df.columns[1:] prev_date, curr_date = dates[-2], dates[-1] df["diff"] = df[curr_date] - df[prev_date] df["abs_diff"] = df["diff"].abs() ranked = df.sort_values("abs_diff", ascending=False) top_kpis = ranked.head(3) other_kpis = ranked.iloc[3:] # ------------------------------- # Top 3 KPI FACT BLOCKS # ------------------------------- top_facts = [] for _, row in top_kpis.iterrows(): top_facts.append({ "KPI": row["Kpi"], "DIRECTION": direction_bucket(row["diff"]), "CHANGE_VALUE": round(row["abs_diff"], 2), "MAGNITUDE": magnitude_bucket(row["abs_diff"]), "UNIT": "percentage points" if "%" in row["Kpi"] else "units" }) # ------------------------------- # Remaining KPI AGGREGATED FACTS # ------------------------------- if len(other_kpis) > 0: other_facts = { "KPI_COUNT": len(other_kpis), "AVG_CHANGE": round(other_kpis["abs_diff"].mean(), 2), "MAGNITUDE": magnitude_bucket(other_kpis["abs_diff"].mean()), "DIRECTION_BALANCE": ( "mostly_increase" if (other_kpis["diff"] > 0).mean() > 0.7 else "mostly_decrease" if (other_kpis["diff"] > 0).mean() < 0.3 else "mixed" ) } else: other_facts = None # ------------------------------- # Model input = FACT BLOCK ONLY # (no narrative text embedded) # ------------------------------- model_input = ( "Write a short insight-style summary using only the facts below.\n\n" "TOP_KPI_FACTS:\n" f"{top_facts}\n\n" "OTHER_KPI_FACTS:\n" f"{other_facts}" ) # ------------------------------- # Controlled variation generation # ------------------------------- output = generator( model_input, max_new_tokens=120, do_sample=True, temperature=0.6, top_p=0.85, repetition_penalty=1.1 )[0]["generated_text"] return ranked.head(top_n)[["Kpi", "abs_diff"]], output # ------------------------------------------------ # Gradio UI (Hugging Face Space) # ------------------------------------------------ with gr.Blocks(title="Network Insight Summary") as demo: gr.Markdown("## 📊 Network Insight Summary") gr.Markdown( "Upload KPI CSV to generate a concise, insight-style summary " "highlighting the most significant KPI changes." ) csv_input = gr.File(file_types=[".csv"]) top_n_input = gr.Slider( minimum=3, maximum=6, value=5, step=1, label="KPIs to Display" ) btn = gr.Button("Generate Insight") table = gr.Dataframe(label="Top KPI Changes") summary = gr.Textbox(label="Insight Summary", lines=4) btn.click( analyze_kpi, inputs=[csv_input, top_n_input], outputs=[table, summary] ) demo.launch()