'use client'; import { useState } from 'react'; import { Loader2, CheckCircle2, AlertCircle } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { QueryPanel } from '@/components/query/QueryPanel'; import { QueryMode } from '@/components/query/QueryPanel'; import { Button } from '@/components/ui/button'; import ReactMarkdown from 'react-markdown'; import api from '@/lib/axios'; interface ColResult { answer: string; confidence: number; timeMs: number; context: string; } interface ComparisonData { query: string; results: { graph: ColResult; vector: ColResult; hybrid: ColResult }; verdict: string; } const COL_META = [ { key: 'graph', label: 'Graph Only', accent: 'text-accent-violet', bar: 'bg-accent-violet' }, { key: 'vector', label: 'Vector Only', accent: 'text-accent-indigo', bar: 'bg-accent-indigo' }, { key: 'hybrid', label: 'Hybrid', accent: 'text-accent-cyan', bar: 'bg-accent-cyan' }, ] as const; function generateVerdict(comps: Record): string { const times: Record = {}; const hasAnswer: Record = {}; for (const mode of ['graph', 'vector', 'hybrid']) { times[mode] = comps[mode]?.response_time ?? 999; hasAnswer[mode] = !!(comps[mode]?.answer && comps[mode].answer.length > 10); } const fastest = Object.entries(times).sort((a, b) => a[1] - b[1])[0]?.[0] || 'hybrid'; const answered = Object.entries(hasAnswer).filter(([, v]) => v).map(([k]) => k); if (answered.length === 0) return 'No retrieval mode produced a valid answer.'; if (answered.includes('hybrid')) { return `Hybrid performed best — combines graph traversal with vector context for comprehensive answers. Fastest mode: ${fastest} (${Math.round(times[fastest] * 1000)}ms).`; } return `${answered[0]} produced the best result for this query. Fastest mode: ${fastest}.`; } function ConfidenceBar({ value, bar }: { value: number; bar: string }) { return (
Confidence {value}%
); } export function ComparisonView() { const [query, setQuery] = useState(''); const [mode, setMode] = useState('hybrid'); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [data, setData] = useState(null); async function compare() { if (!query.trim()) return; setLoading(true); setError(null); try { const { data: res } = await api.post('/query/compare/', { query }); const comps = res.comparisons || res.results || {}; const mapped: ComparisonData = { query, results: { graph: { answer: comps.graph?.answer || '', confidence: Math.round((comps.graph?.confidence ?? 0) * 100), timeMs: Math.round((comps.graph?.response_time ?? 0) * 1000), context: comps.graph?.context || comps.graph?.strategy || 'GRAPH', }, vector: { answer: comps.vector?.answer || '', confidence: Math.round((comps.vector?.confidence ?? 0) * 100), timeMs: Math.round((comps.vector?.response_time ?? 0) * 1000), context: comps.vector?.context || comps.vector?.strategy || 'VECTOR', }, hybrid: { answer: comps.hybrid?.answer || '', confidence: Math.round((comps.hybrid?.confidence ?? 0) * 100), timeMs: Math.round((comps.hybrid?.response_time ?? 0) * 1000), context: comps.hybrid?.context || comps.hybrid?.strategy || 'HYBRID', }, }, verdict: res.verdict || generateVerdict(comps), }; setData(mapped); } catch (err: any) { const msg = err?.response?.data?.error || 'Failed to compare retrieval modes.'; setError(msg); } finally { setLoading(false); } } return (
{loading && (
Running Graph, Vector & Hybrid retrieval...
)} {error && (
{error}
)} {data && ( <>

Comparison Metrics

{COL_META.map((c) => ( ))} {COL_META.map((c) => ( ))} {COL_META.map((c) => ( ))} {COL_META.map((c) => ( ))} {COL_META.map((c) => ( ))}
Metric {c.label}
Confidence {data.results[c.key].confidence}%
Response Time {data.results[c.key].timeMs}ms
Context Length {data.results[c.key].context.length} chars
Answer Length {data.results[c.key].answer.length} chars
{COL_META.map((c) => { const r = data.results[c.key]; return (

{c.label}

{r.answer}

Context: {r.context}

⏱️ {r.timeMs}ms

); })}

Verdict

{data.verdict}

)}
); }