Prism / frontend /src /components /EvalPanel.jsx
benroshan's picture
feat: RAGAS benchmark driven by JSON, local runner script
c549f0b
Raw
History Blame Contribute Delete
3.68 kB
import benchmark from "../data/ragas_benchmark.json";
const METRIC_META = [
{
key: "faithfulness",
label: "Faithfulness",
info: "Are claims in the answer supported by the retrieved documents? High = answer stays grounded in sources, doesn't hallucinate.",
},
{
key: "answer_relevancy",
label: "Answer Relevancy",
info: "Does the answer actually address the question? High = on-topic, concise. Low = vague or off-topic response.",
},
{
key: "context_precision",
label: "Context Precision",
info: "Were the retrieved chunks useful? High = retrieved docs were relevant to the question. Requires labeled ground truth dataset.",
},
{
key: "context_recall",
label: "Context Recall",
info: "Did retrieval find all the relevant chunks? High = nothing important was missed. Requires labeled ground truth dataset.",
},
];
const METRICS = METRIC_META.map((m) => ({ ...m, value: benchmark[m.key] }));
function ScoreBar({ value }) {
if (value === null || value === undefined) {
return <span className="text-xs text-gray-400">N/A — needs ground truth</span>;
}
const pct = Math.round(value * 100);
const color =
pct >= 70 ? "bg-green-500" : pct >= 50 ? "bg-yellow-500" : "bg-red-500";
return (
<div className="flex items-center gap-2">
<div className="flex-1 bg-gray-200 rounded-full h-1.5">
<div className={`${color} h-1.5 rounded-full`} style={{ width: `${pct}%` }} />
</div>
<span className="text-xs font-semibold text-gray-700 w-8 text-right">
{pct}%
</span>
</div>
);
}
export default function EvalPanel() {
return (
<div className="bg-gray-50/80 rounded-xl p-3.5">
<div className="flex items-center gap-1.5 mb-2.5">
<h3 className="text-xs font-semibold text-indigo-500 uppercase tracking-wider">
RAGAS Benchmark
</h3>
<span className="group relative">
<svg className="w-3 h-3 text-gray-400 cursor-help" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
</svg>
<span className="pointer-events-none absolute bottom-5 left-0 z-10 w-56 rounded-lg bg-gray-800 px-2.5 py-2 text-xs text-white opacity-0 group-hover:opacity-100 transition-opacity shadow-lg">
RAGAS (Retrieval Augmented Generation Assessment) scores measuring answer quality across 4 dimensions — faithfulness, relevancy, and retrieval precision/recall.
</span>
</span>
</div>
<div className="space-y-2">
{METRICS.map(({ key, label, value, info }) => (
<div key={key}>
<div className="flex items-center gap-1 mb-0.5">
<span className="text-xs text-gray-500">{label}</span>
<span className="group relative">
<svg className="w-3 h-3 text-gray-400 cursor-help" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
</svg>
<span className="pointer-events-none absolute bottom-5 left-0 z-10 w-52 rounded-lg bg-gray-800 px-2.5 py-2 text-xs text-white opacity-0 group-hover:opacity-100 transition-opacity shadow-lg">
{info}
</span>
</span>
</div>
<ScoreBar value={value} />
</div>
))}
</div>
</div>
);
}