llm-evaluator / src /dashboard.py
zaid646's picture
Initial commit: LLM-as-a-Judge evaluator
0b84707
Raw
History Blame Contribute Delete
4.21 kB
import pandas as pd
import plotly.express as px
import streamlit as st
def render_ui(records_data: list[dict]):
df = pd.DataFrame(records_data)
tab1, tab2, tab3 = st.tabs(["Summary", "Per-Sample Breakdown", "Raw Data"])
with tab1:
col1, col2, col3, col4 = st.columns(4)
total = len(df)
passed = df["passed"].sum()
fail = total - passed
pass_rate = (passed / total * 100) if total > 0 else 0
col1.metric("Total Samples", total)
col2.metric("Passed", int(passed))
col3.metric("Failed", int(fail))
col4.metric("Pass Rate", f"{pass_rate:.1f}%")
st.divider()
score_cols = ["relevance", "hallucination", "toxicity"]
available = [c for c in score_cols if c in df.columns and df[c].notna().any()]
if available:
avg_scores = df[available].mean()
st.subheader("Average Scores")
score_df = pd.DataFrame({
"Criterion": [c.capitalize() for c in available],
"Average Score": [avg_scores[c] for c in available],
})
fig = px.bar(
score_df,
x="Criterion",
y="Average Score",
range_y=[0, 5],
text_auto=".2f",
color="Average Score",
color_continuous_scale="viridis",
)
st.plotly_chart(fig, use_container_width=True)
if "target_latency_ms" in df.columns:
st.subheader("Target Latency Distribution")
lat_df = df[df["target_latency_ms"].notna()]
if not lat_df.empty:
fig2 = px.histogram(
lat_df,
x="target_latency_ms",
nbins=20,
labels={"target_latency_ms": "Latency (ms)"},
)
st.plotly_chart(fig2, use_container_width=True)
if "judge_tokens" in df.columns:
total_judge_tokens = int(df["judge_tokens"].sum())
total_target_tokens = int(df["target_tokens"].sum()) if "target_tokens" in df.columns else 0
total_tokens = total_judge_tokens + total_target_tokens
cost_estimate = total_tokens * 0.000002
st.subheader("Token Usage & Cost")
tok_col1, tok_col2, tok_col3, tok_col4 = st.columns(4)
tok_col1.metric("Target Tokens", f"{total_target_tokens:,}")
tok_col2.metric("Judge Tokens", f"{total_judge_tokens:,}")
tok_col3.metric("Total Tokens", f"{total_tokens:,}")
tok_col4.metric("Est. Cost", f"${cost_estimate:.6f}")
with tab2:
for _, row in df.iterrows():
passed_icon = "PASS" if row["passed"] else "FAIL"
with st.expander(
f"[{passed_icon}] {row.get('sample_id', '?')}: {row['prompt'][:80]}...",
expanded=not row["passed"],
):
st.text_area("Prompt", row["prompt"], height=80, disabled=True)
st.text_area("Expected Answer", row["expected_answer"], height=80, disabled=True)
if row.get("target_output"):
st.text_area("Target Output", row["target_output"], height=100, disabled=True)
if row.get("target_error"):
st.error(f"Target Error: {row['target_error']}")
if row.get("relevance") is not None:
r, h, t = row["relevance"], row["hallucination"], row["toxicity"]
st.metric("Relevance", f"{r}/5")
st.metric("Hallucination (5=best)", f"{h}/5")
st.metric("Toxicity (5=best)", f"{t}/5")
if row.get("reasoning"):
st.caption(f"Judge reasoning: {row['reasoning']}")
st.caption(
f"Target latency: {row.get('target_latency_ms', 'N/A')}ms | "
f"Judge latency: {row.get('judge_latency_ms', 'N/A')}ms | "
f"Target tokens: {row.get('target_tokens', 'N/A')} | "
f"Judge tokens: {row.get('judge_tokens', 'N/A')}"
)
with tab3:
st.json(records_data)