CoolFace
Apppublic

samurvivor-07/llm-evaluation-framework

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
app.py245 linesDownload Raw Back to root
1import gradio as gr2import pandas as pd3import plotly.graph_objects as go4from plotly.subplots import make_subplots5 6# ── Load Results ───────────────────────────────────────────────7df = pd.read_csv("eval_results.csv")8 9# ── Build Dashboard ────────────────────────────────────────────10def build_dashboard():11    fig = make_subplots(12        rows=2, cols=2,13        subplot_titles=[14            "Overall ROUGE Score Comparison",15            "Performance by Category",16            "Question-level Improvement (Δ ROUGE)",17            "Win Rate Distribution"18        ],19        specs=[20            [{"type": "bar"}, {"type": "bar"}],21            [{"type": "bar"}, {"type": "pie"}]22        ],23        vertical_spacing=0.18,24        horizontal_spacing=0.1225    )26 27    colors = {"base": "#636EFA", "ft": "#00CC96", "pos": "#00CC96", "neg": "#EF553B"}28 29    # Plot 1 — Overall30    for name, col, key in [("Base Mistral 7B", colors["base"], "base"), ("Fine-tuned", colors["ft"], "ft")]:31        fig.add_trace(go.Bar(32            name=name,33            x=["ROUGE-1", "ROUGE-2", "ROUGE-L", "Avg"],34            y=[df[f'{key}_rouge1'].mean(), df[f'{key}_rouge2'].mean(),35               df[f'{key}_rougeL'].mean(), df[f'{key}_avg_rouge'].mean()],36            marker_color=col,37        ), row=1, col=1)38 39    # Plot 2 — Per category40    cat_groups = df.groupby('category').agg(41        base_avg=('base_avg_rouge', 'mean'),42        ft_avg=('ft_avg_rouge', 'mean')43    ).reset_index()44 45    fig.add_trace(go.Bar(name="Base Mistral 7B", x=cat_groups['category'],46        y=cat_groups['base_avg'], marker_color=colors["base"], showlegend=False), row=1, col=2)47    fig.add_trace(go.Bar(name="Fine-tuned", x=cat_groups['category'],48        y=cat_groups['ft_avg'], marker_color=colors["ft"], showlegend=False), row=1, col=2)49 50    # Plot 3 — Per question51    imp_colors = [colors["pos"] if x > 0 else colors["neg"] for x in df['improvement']]52    fig.add_trace(go.Bar(53        x=list(range(1, 21)), y=df['improvement'].tolist(),54        marker_color=imp_colors, showlegend=False,55        hovertext=[q[:50] for q in df['question']], hoverinfo="text+y"56    ), row=2, col=1)57 58    # Plot 4 — Win rate59    wins   = (df['improvement'] > 0).sum()60    losses = (df['improvement'] <= 0).sum()61    fig.add_trace(go.Pie(62        labels=["Fine-tuned Wins", "Base Wins"],63        values=[wins, losses],64        marker_colors=[colors["pos"], colors["neg"]],65        hole=0.4, textinfo="label+percent"66    ), row=2, col=2)67 68    fig.update_layout(69        height=650, barmode="group", template="plotly_dark",70        paper_bgcolor="#1e293b", plot_bgcolor="#1e293b",71        font={"color": "white", "size": 11},72        title={"text": "🔬 Medical LLM Evaluation — Base Mistral 7B vs Fine-tuned LoRA", "x": 0.5}73    )74    fig.update_xaxes(tickangle=-25, row=1, col=2)75    fig.update_xaxes(title_text="Question #", row=2, col=1)76 77    return fig78 79def get_details(question_idx):80    if question_idx is None:81        return "", "", ""82    row = df.iloc[int(question_idx)]83    q        = f"**Question:** {row['question']}"84    base_ans = f"**Base Model Answer:**\n\n{row['base_answer']}"85    ft_ans   = f"**Fine-tuned Answer:**\n\n{row['ft_answer']}\n\n---\n**ROUGE Improvement: {row['improvement']:+.4f}**"86    return q, base_ans, ft_ans87 88css = """89@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');90:root {91    --bg-primary:#ffffff;--bg-card:#ffffff;--bg-elevated:#f1f5f9;92    --border:rgba(0,0,0,0.08);--text-primary:#0f172a;--text-secondary:#475569;93    --text-tertiary:#94a3b8;--accent:#6366f1;--accent-dim:rgba(99,102,241,0.1);94    --positive:#10b981;--negative:#ef4444;95    --shadow:0 4px 6px -1px rgba(0,0,0,0.07);--shadow-lg:0 10px 15px -3px rgba(0,0,0,0.08);96    --radius:16px;97}98[data-theme="dark"] {99    --bg-primary:#0f172a;--bg-card:#1e293b;--bg-elevated:#334155;100    --border:rgba(255,255,255,0.08);--text-primary:#f1f5f9;101    --text-secondary:#94a3b8;--text-tertiary:#475569;102    --shadow:0 4px 6px -1px rgba(0,0,0,0.3);--shadow-lg:0 10px 15px -3px rgba(0,0,0,0.4);103}104* { font-family:"Inter",sans-serif !important; box-sizing:border-box; }105body,.gradio-container { background:var(--bg-primary) !important; color:var(--text-primary) !important; transition:all 0.3s ease; }106.gradio-container { max-width:1100px !important; margin:0 auto !important; padding:24px !important; }107.app-header { text-align:center; padding:52px 24px 36px; background:linear-gradient(135deg,var(--accent-dim),transparent); border-radius:var(--radius); border:1px solid var(--border); margin-bottom:28px; }108.app-header h1 { font-size:2.4em !important; font-weight:900 !important; background:linear-gradient(135deg,var(--accent),#8b5cf6,#10b981); -webkit-background-clip:text !important; -webkit-text-fill-color:transparent !important; margin-bottom:14px !important; }109.app-header p { color:var(--text-secondary) !important; font-size:1em !important; max-width:650px; margin:0 auto !important; line-height:1.8 !important; }110.badges { display:flex; justify-content:center; gap:10px; flex-wrap:wrap; margin-top:20px; }111.badge { padding:6px 16px; border-radius:20px; font-size:0.75em; font-weight:600; border:1px solid var(--border); background:var(--bg-elevated); color:var(--text-secondary); }112.badge.accent { background:var(--accent-dim); color:var(--accent); border-color:rgba(99,102,241,0.25); }113.badge.positive { background:rgba(16,185,129,0.1); color:#10b981; border-color:rgba(16,185,129,0.25); }114.stats-row { display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:28px; }115.stat-card { background:var(--bg-card); border:1px solid var(--border); border-radius:var(--radius); padding:20px 16px; text-align:center; box-shadow:var(--shadow); transition:all 0.2s ease; }116.stat-card:hover { transform:translateY(-2px); box-shadow:var(--shadow-lg); }117.stat-value { font-size:1.9em; font-weight:900; color:var(--accent); line-height:1; }118.stat-label { font-size:0.7em; color:var(--text-tertiary); font-weight:600; text-transform:uppercase; letter-spacing:0.8px; margin-top:6px; }119.card { background:var(--bg-card) !important; border:1px solid var(--border) !important; border-radius:var(--radius) !important; padding:24px !important; box-shadow:var(--shadow) !important; }120.theme-toggle { position:fixed !important; top:20px !important; right:20px !important; background:var(--bg-card) !important; border:1px solid var(--border) !important; border-radius:50% !important; width:46px !important; height:46px !important; cursor:pointer !important; font-size:1.2em !important; box-shadow:var(--shadow-lg) !important; transition:all 0.2s !important; z-index:1000 !important; }121.theme-toggle:hover { transform:scale(1.12) rotate(15deg) !important; }122label { color:var(--text-secondary) !important; font-weight:700 !important; font-size:0.78em !important; text-transform:uppercase !important; letter-spacing:1px !important; }123.footer { text-align:center; padding:28px; color:var(--text-tertiary); font-size:0.78em; border-top:1px solid var(--border); margin-top:36px; line-height:2; }124"""125 126js = """127function toggleTheme(){128    const root=document.documentElement;129    const btn=document.getElementById("theme-btn");130    const dark=root.getAttribute("data-theme")==="dark";131    root.setAttribute("data-theme",dark?"light":"dark");132    btn.textContent=dark?"🌙":"☀️";133    localStorage.setItem("eval-theme",dark?"light":"dark");134}135document.addEventListener("DOMContentLoaded",()=>{136    const saved=localStorage.getItem("eval-theme")||"light";137    document.documentElement.setAttribute("data-theme",saved);138    const btn=document.getElementById("theme-btn");139    if(btn)btn.textContent=saved==="dark"?"☀️":"🌙";140});141"""142 143with gr.Blocks(css=css, title="🔬 LLM Evaluation Framework") as demo:144 145    gr.HTML(f"""146    <button class="theme-toggle" id="theme-btn" onclick="toggleTheme()">🌙</button>147    <script>{js}</script>148    <div class="app-header">149        <h1>🔬 LLM Evaluation Framework</h1>150        <p>Research-grade evaluation comparing Base Mistral 7B vs LoRA Fine-tuned Medical AI151        across 20 questions in 5 clinical domains. Interactive results dashboard.</p>152        <div class="badges">153            <span class="badge accent">Mistral 7B</span>154            <span class="badge accent">LoRA Fine-tuned</span>155            <span class="badge positive">+17.8% ROUGE</span>156            <span class="badge positive">65% Win Rate</span>157            <span class="badge">5 Medical Domains</span>158            <span class="badge">20 Questions</span>159        </div>160    </div>161 162    <div class="stats-row">163        <div class="stat-card">164            <div class="stat-value">+17.8%</div>165            <div class="stat-label">ROUGE Improvement</div>166        </div>167        <div class="stat-card">168            <div class="stat-value">65%</div>169            <div class="stat-label">Win Rate</div>170        </div>171        <div class="stat-card">172            <div class="stat-value">20</div>173            <div class="stat-label">Questions Evaluated</div>174        </div>175        <div class="stat-card">176            <div class="stat-value">5</div>177            <div class="stat-label">Medical Domains</div>178        </div>179    </div>180    """)181 182    with gr.Column(elem_classes=["card"]):183        gr.Markdown("### 📊 Evaluation Dashboard")184        dashboard_plot = gr.Plot(value=build_dashboard())185 186    with gr.Column(elem_classes=["card"]):187        gr.Markdown("### 🔍 Question-level Analysis")188        question_slider = gr.Slider(189            minimum=0, maximum=19, step=1, value=0,190            label="Select Question (0-19)"191        )192        with gr.Row():193            question_out  = gr.Markdown()194        with gr.Row():195            base_out = gr.Markdown(label="Base Model")196            ft_out   = gr.Markdown(label="Fine-tuned Model")197 198    gr.HTML("""199    <div style="margin-top:28px;background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:28px;box-shadow:var(--shadow);">200        <h3 style="color:var(--text-primary);margin-bottom:20px;font-size:1em;font-weight:700;">📋 Evaluation Categories</h3>201        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;">202            <div style="padding:16px;background:var(--bg-elevated);border-radius:12px;text-align:center;">203                <div style="font-size:1.8em;margin-bottom:8px;">💊</div>204                <div style="font-weight:700;color:var(--text-primary);font-size:0.85em;">Pharmacology</div>205                <div style="color:var(--text-tertiary);font-size:0.75em;margin-top:4px;">4 questions</div>206            </div>207            <div style="padding:16px;background:var(--bg-elevated);border-radius:12px;text-align:center;">208                <div style="font-size:1.8em;margin-bottom:8px;">🩺</div>209                <div style="font-weight:700;color:var(--text-primary);font-size:0.85em;">Symptoms & Diagnosis</div>210                <div style="color:var(--text-tertiary);font-size:0.75em;margin-top:4px;">4 questions</div>211            </div>212            <div style="padding:16px;background:var(--bg-elevated);border-radius:12px;text-align:center;">213                <div style="font-size:1.8em;margin-bottom:8px;">🧬</div>214                <div style="font-weight:700;color:var(--text-primary);font-size:0.85em;">Pathophysiology</div>215                <div style="color:var(--text-tertiary);font-size:0.75em;margin-top:4px;">4 questions</div>216            </div>217            <div style="padding:16px;background:var(--bg-elevated);border-radius:12px;text-align:center;">218                <div style="font-size:1.8em;margin-bottom:8px;">💉</div>219                <div style="font-weight:700;color:var(--text-primary);font-size:0.85em;">Treatment</div>220                <div style="color:var(--text-tertiary);font-size:0.75em;margin-top:4px;">4 questions</div>221            </div>222            <div style="padding:16px;background:var(--bg-elevated);border-radius:12px;text-align:center;">223                <div style="font-size:1.8em;margin-bottom:8px;">🫀</div>224                <div style="font-weight:700;color:var(--text-primary);font-size:0.85em;">Anatomy & Physiology</div>225                <div style="color:var(--text-tertiary);font-size:0.75em;margin-top:4px;">4 questions</div>226            </div>227        </div>228    </div>229 230    <div class="footer">231        Base Mistral 7B vs LoRA Fine-tuned • ROUGE-1, ROUGE-2, ROUGE-L Metrics •232        20 Medical QA Questions • 5 Clinical Domains •233        <a href="https://github.com/Boatengs/llm-evaluation-framework" target="_blank" style="color:var(--accent);">GitHub</a> •234        <a href="https://huggingface.co/samboateng190/medical-mistral-lora" target="_blank" style="color:var(--accent);">Fine-tuned Model</a>235    </div>236    """)237 238    question_slider.change(239        fn=get_details,240        inputs=question_slider,241        outputs=[question_out, base_out, ft_out]242    )243 244demo.launch()245