diff --git a/app/(main)/evaluations/[id]/page.tsx b/app/(main)/evaluations/[id]/page.tsx
index 535a88a..15c5ec6 100644
--- a/app/(main)/evaluations/[id]/page.tsx
+++ b/app/(main)/evaluations/[id]/page.tsx
@@ -20,6 +20,8 @@ import {
hasSummaryScores,
isNewScoreObjectV2,
getScoreObject,
+ getOverallScore,
+ getAiSummary,
normalizeToIndividualScores,
isGroupedFormat,
} from "@/app/lib/utils/evaluation";
@@ -29,9 +31,11 @@ import {
} from "@/app/lib/utils/evaluationExport";
import Sidebar from "@/app/components/Sidebar";
import {
+ AiSummaryNote,
CategoryMetricsTable,
DetailedResultsTable,
MetricsOverview,
+ OverallScoreCard,
RunModeBadge,
} from "@/app/components/evaluations";
import {
@@ -266,6 +270,8 @@ export default function EvaluationReport() {
scoreObject && isNewScoreObjectV2(scoreObject)
? (scoreObject.category_metrics ?? [])
: [];
+ const overallScore = getOverallScore(scoreObject);
+ const aiSummary = getAiSummary(scoreObject);
const isJobInProgress =
job.status.toLowerCase() !== "completed" &&
@@ -391,6 +397,7 @@ export default function EvaluationReport() {
{hasScore && isNewFormat ? (
<>
+ {overallScore &&
}
+ {aiSummary && !isFormatSwitching && (
+
+ )}
Detailed Results
diff --git a/app/components/evaluations/AiSummaryNote.tsx b/app/components/evaluations/AiSummaryNote.tsx
new file mode 100644
index 0000000..a948973
--- /dev/null
+++ b/app/components/evaluations/AiSummaryNote.tsx
@@ -0,0 +1,16 @@
+"use client";
+
+import { InfoIcon } from "@/app/components/icons";
+
+interface AiSummaryNoteProps {
+ summary: string;
+}
+
+export default function AiSummaryNote({ summary }: AiSummaryNoteProps) {
+ return (
+
+ );
+}
diff --git a/app/components/evaluations/OverallScoreCard.tsx b/app/components/evaluations/OverallScoreCard.tsx
new file mode 100644
index 0000000..735e04c
--- /dev/null
+++ b/app/components/evaluations/OverallScoreCard.tsx
@@ -0,0 +1,75 @@
+"use client";
+
+import type { OverallScore } from "@/app/lib/types/evaluation";
+import { getVerdictColor } from "@/app/lib/utils/evaluation";
+
+interface OverallScoreCardProps {
+ overall: OverallScore;
+}
+
+function VerdictBadge({ verdict }: { verdict: string }) {
+ const color = getVerdictColor(verdict);
+ return (
+
+ {verdict}
+
+ );
+}
+
+export default function OverallScoreCard({ overall }: OverallScoreCardProps) {
+ return (
+
+
+
+
+ Overall Score
+
+
+ {overall.overall_score.toFixed(3)}
+
+
+
+
+
+ {overall.breakdown.length > 0 && (
+
+ {overall.breakdown.map((item) => (
+
+
+
+ {item.name}
+
+
+
+
+
+ {item.score.toFixed(3)}
+
+
+ weight {item.weight.toFixed(2)}
+
+
+ {typeof item.delta === "number" && (
+
= 0
+ ? "text-status-success-text"
+ : "text-status-error-text"
+ }`}
+ >
+ {item.delta >= 0 ? "▲" : "▼"}{" "}
+ {Math.abs(item.delta).toFixed(3)}
+
+ )}
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/app/components/evaluations/index.ts b/app/components/evaluations/index.ts
index 6f2fa03..3ee4091 100644
--- a/app/components/evaluations/index.ts
+++ b/app/components/evaluations/index.ts
@@ -1,3 +1,4 @@
+export { default as AiSummaryNote } from "./AiSummaryNote";
export { default as CategoryMetricsTable } from "./CategoryMetricsTable";
export { default as CreateDatasetForm } from "./CreateDatasetForm";
export { default as DatasetCard } from "./DatasetCard";
@@ -10,6 +11,7 @@ export { default as EvalRunsList } from "./EvalRunsList";
export { default as EvaluationsTab } from "./EvaluationsTab";
export { default as GroupedResultsTable } from "./GroupedResultsTable";
export { default as MetricsOverview } from "./MetricsOverview";
+export { default as OverallScoreCard } from "./OverallScoreCard";
export { default as RunEvaluationForm } from "./RunEvaluationForm";
export { default as RunModeBadge } from "./RunModeBadge";
export { default as ScoreDisplay } from "./ScoreDisplay";
diff --git a/app/lib/types/evaluation.ts b/app/lib/types/evaluation.ts
index 5b0eb7f..dd6e858 100644
--- a/app/lib/types/evaluation.ts
+++ b/app/lib/types/evaluation.ts
@@ -60,10 +60,26 @@ export interface SummaryScore {
distribution?: Record; // For categorical data
}
+export interface ScoreBreakdownItem {
+ name: string;
+ score: number;
+ weight: number;
+ delta?: number | null;
+ verdict: string;
+}
+
+export interface OverallScore {
+ overall_score: number;
+ verdict: string;
+ breakdown: ScoreBreakdownItem[];
+}
+
export interface NewScoreObjectV2 {
summary_scores: SummaryScore[];
traces: TraceItem[] | GroupedTraceItem[];
category_metrics?: CategoryMetric[];
+ overall?: OverallScore | null;
+ ai_summary?: string | null;
}
export interface PerItemScore {
diff --git a/app/lib/utils/evaluation.ts b/app/lib/utils/evaluation.ts
index 1403499..20d5b96 100644
--- a/app/lib/utils/evaluation.ts
+++ b/app/lib/utils/evaluation.ts
@@ -4,6 +4,7 @@ import type {
IndividualScore,
NewScoreObjectV2,
BasicScoreObject,
+ OverallScore,
ScoreObject,
TraceItem,
} from "@/app/lib/types/evaluation";
@@ -33,6 +34,69 @@ export function isGroupedFormat(
return "llm_answers" in traces[0] && Array.isArray(traces[0].llm_answers);
}
+export function getOverallScore(
+ score: ScoreObject | null | undefined,
+): OverallScore | null {
+ if (!score || !isNewScoreObjectV2(score)) return null;
+ return score.overall ?? null;
+}
+
+export function getAiSummary(
+ score: ScoreObject | null | undefined,
+): string | null {
+ if (!score || !isNewScoreObjectV2(score)) return null;
+ return score.ai_summary ?? null;
+}
+
+type VerdictTone = "success" | "warning" | "error" | "default";
+
+const VERDICT_TONE_MAP: Record = {
+ pass: "success",
+ passed: "success",
+ excellent: "success",
+ good: "success",
+ warning: "warning",
+ moderate: "warning",
+ fail: "error",
+ failed: "error",
+ poor: "error",
+ critical: "error",
+};
+
+export function getVerdictColor(verdict: string): {
+ bg: string;
+ border: string;
+ text: string;
+} {
+ const tone = VERDICT_TONE_MAP[verdict.toLowerCase()] ?? "default";
+ switch (tone) {
+ case "success":
+ return {
+ bg: "bg-status-success-bg",
+ border: "border-status-success-border",
+ text: "text-status-success-text",
+ };
+ case "warning":
+ return {
+ bg: "bg-status-warning-bg",
+ border: "border-status-warning-border",
+ text: "text-status-warning-text",
+ };
+ case "error":
+ return {
+ bg: "bg-status-error-bg",
+ border: "border-status-error-border",
+ text: "text-status-error-text",
+ };
+ default:
+ return {
+ bg: "bg-status-default-bg",
+ border: "border-status-default-border",
+ text: "text-status-default-text",
+ };
+ }
+}
+
export function normalizeToIndividualScores(
score: ScoreObject | null | undefined,
): IndividualScore[] {