|
import PipelineProgress from '../components/PipelineProgress'; |
|
import { useJobRunner } from '../hooks/JobRunnerProvider'; |
|
import { useMemo } from 'react'; |
|
|
|
export default function ResultsPage() { |
|
const { result, resp, loading, error, url } = useJobRunner(); |
|
|
|
|
|
const isExample = useMemo(() => { |
|
try { |
|
const draft = localStorage.getItem('cfgDraft'); |
|
if (!draft) return false; |
|
const parsed = JSON.parse(draft); |
|
return parsed?.dataset === 'example'; |
|
} catch { |
|
return false; |
|
} |
|
}, []); |
|
|
|
|
|
if (isExample) { |
|
const oriHtml = 'ori_sentiment_distribution.html'; |
|
const ftHtml = 'ft_sentiment_distribution.html'; |
|
const oriCsv = 'ori_generation_results.csv'; |
|
const ftCsv = 'finetune_aug_generation_result.csv'; |
|
|
|
return ( |
|
<div className="space-y-6"> |
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-2">Example Preview</h2> |
|
<p className="text-sm text-slate-600"> |
|
This is a fixed example preview. The pipeline was not executed. |
|
</p> |
|
</section> |
|
|
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-4">Distribution</h2> |
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> |
|
<figure className="rounded-xl overflow-hidden border bg-white"> |
|
<iframe |
|
src={oriHtml} |
|
title="Original distribution (Plotly)" |
|
className="w-full" |
|
style={{ height: 480, border: '0' }} |
|
/> |
|
<figcaption className="p-3 text-sm text-slate-600">Original</figcaption> |
|
</figure> |
|
|
|
<figure className="rounded-xl overflow-hidden border bg-white"> |
|
<iframe |
|
src={ftHtml} |
|
title="Counterfactual distribution (Plotly)" |
|
className="w-full" |
|
style={{ height: 480, border: '0' }} |
|
/> |
|
<figcaption className="p-3 text-sm text-slate-600">Counterfactual Augmented</figcaption> |
|
</figure> |
|
</div> |
|
</section> |
|
|
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-4">Download Report</h2> |
|
<ul className="space-y-2"> |
|
<li> |
|
<a |
|
className="text-indigo-600 hover:underline" |
|
href={oriCsv} |
|
target="_blank" |
|
rel="noreferrer" |
|
download |
|
> |
|
Original Generation CSV |
|
</a> |
|
</li> |
|
<li> |
|
<a |
|
className="text-indigo-600 hover:underline" |
|
href={ftCsv} |
|
target="_blank" |
|
rel="noreferrer" |
|
download |
|
> |
|
Counterfactual / Fine-tuned Generation CSV |
|
</a> |
|
</li> |
|
</ul> |
|
</section> |
|
</div> |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
const isHtml = (s: string) => /\.html?(?:$|\?)/i.test(s); |
|
|
|
|
|
const renderPlot = (srcRaw: string, title: string, alt: string) => { |
|
const src = url(srcRaw); |
|
if (isHtml(srcRaw)) { |
|
return ( |
|
<iframe |
|
src={src} |
|
title={title} |
|
className="w-full" |
|
style={{ height: 480, border: '0' }} |
|
/> |
|
); |
|
} |
|
return ( |
|
<img |
|
src={src} |
|
alt={alt} |
|
className="w-full h-auto" |
|
loading="lazy" |
|
onError={(e) => { |
|
e.currentTarget.alt = `${alt} loading failed`; |
|
}} |
|
/> |
|
); |
|
}; |
|
|
|
if (loading && !resp) { |
|
return ( |
|
<div className="space-y-6"> |
|
<PipelineProgress /> |
|
<section className="grid grid-cols-1 md:grid-cols-2 gap-6"> |
|
{[0, 1].map((i) => ( |
|
<div key={i} className="rounded-2xl border bg-white/70 backdrop-blur p-3"> |
|
<div className="w-full h-64 rounded-xl bg-gradient-to-b from-slate-200 to-slate-100 animate-pulse" /> |
|
<div className="mt-3 h-4 w-40 rounded bg-slate-200 animate-pulse" /> |
|
</div> |
|
))} |
|
</section> |
|
</div> |
|
); |
|
} |
|
|
|
if (error) { |
|
return ( |
|
<div className="p-6 rounded-2xl bg-red-50 border border-red-200 text-red-700"> |
|
{error} |
|
</div> |
|
); |
|
} |
|
|
|
if (!result || !resp) { |
|
return ( |
|
<div className="p-6 rounded-2xl bg-white/70 border border-white/40"> |
|
Task not executed yet |
|
</div> |
|
); |
|
} |
|
|
|
const m = result.metrics!; |
|
const plots = resp.results.plots; |
|
|
|
const r = resp.results as any; |
|
const links: { label: string; href: string }[] = []; |
|
|
|
if (r?.generation_file) { |
|
links.push({ label: 'Generation CSV', href: r.generation_file }); |
|
} |
|
if (r?.sentiment_subset_file) { |
|
links.push({ label: 'Original sentiment subset CSV', href: r.sentiment_subset_file }); |
|
} |
|
if (r?.cf_sentiment_subset_file) { |
|
links.push({ label: 'CF sentiment subset CSV', href: r.cf_sentiment_subset_file }); |
|
} |
|
if (r?.run_config_files?.markdown) { |
|
links.push({ label: 'Run Config (Markdown)', href: r.run_config_files.markdown }); |
|
} |
|
if (r?.run_config_files?.json) { |
|
links.push({ label: 'Run Config (JSON)', href: r.run_config_files.json }); |
|
} |
|
if (r?.finetuned_model_zip) { |
|
links.push({ label: 'Fine-tuned Model (ZIP)', href: r.finetuned_model_zip }); |
|
} else if (r?.finetuned_model_dir) { |
|
links.push({ label: 'Fine-tuned Model Folder', href: r.finetuned_model_dir }); |
|
} |
|
|
|
return ( |
|
<div className="space-y-6"> |
|
{loading && <PipelineProgress />} |
|
|
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-3">Metric</h2> |
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> |
|
<div className="p-4 rounded-xl bg-slate-50 border"> |
|
<div className="text-slate-500 text-sm">Original Difference</div> |
|
<div className="text-2xl font-bold">{m.finalMeanDiff.toFixed(4)}</div> |
|
</div> |
|
<div className="p-4 rounded-xl bg-slate-50 border"> |
|
<div className="text-slate-500 text-sm">CF Difference</div> |
|
<div className="text-2xl font-bold"> |
|
{resp.results.metrics.cfFinalMeanDiff.toFixed(4)} |
|
</div> |
|
</div> |
|
</div> |
|
</section> |
|
|
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-4">Distribution</h2> |
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> |
|
<figure className="rounded-xl overflow-hidden border bg-white"> |
|
{renderPlot(plots.original_sentiment, 'Original distribution (Plotly)', 'Original distribution')} |
|
<figcaption className="p-3 text-sm text-slate-600">Original</figcaption> |
|
</figure> |
|
|
|
<figure className="rounded-xl overflow-hidden border bg-white"> |
|
{renderPlot(plots.counterfactual_sentiment, 'Counterfactual distribution (Plotly)', 'Counterfactual distribution')} |
|
<figcaption className="p-3 text-sm text-slate-600">Counterfactual Augmented</figcaption> |
|
</figure> |
|
</div> |
|
</section> |
|
|
|
{links.length > 0 && ( |
|
<section className="p-6 rounded-2xl border border-white/40 bg-white/70 backdrop-blur"> |
|
<h2 className="text-lg font-semibold mb-4">Download Report</h2> |
|
<ul className="space-y-2"> |
|
{links.map((l) => ( |
|
<li key={l.label}> |
|
<a |
|
className="text-indigo-600 hover:underline" |
|
href={url(l.href)} |
|
target="_blank" |
|
rel="noreferrer" |
|
download |
|
> |
|
{l.label} |
|
</a> |
|
</li> |
|
))} |
|
</ul> |
|
</section> |
|
)} |
|
</div> |
|
); |
|
} |
|
|