/* INSPECTION VIEW — trace a real query through the retrieval pipeline. Runs POST /query and shows the actual route decision, the ranked candidates with their real scores, and the assembled context. The pipeline strip labels each stage with real values; stages the backend doesn't expose internals for (embedding, the gate distribution) are described, not fabricated. */ function inspToCand(c) { const pages = c.page_numbers || []; return { chunk_id: c.chunk_id, paper: c.paper_id, page: pages[0], score: typeof c.score === "number" ? c.score : 0, kind: c.source === "visual" ? "visual" : "text", bbox: (c.metadata && c.metadata.bbox) || null, text: c.text || "", }; } function Stage({ icon, label, value, sub, last, selected, onClick }) { return ( {!last &&
}
); } function InspRow({ c, onOpen, scoreMin, scoreMax }) { // Min-max scaled within the result set — logits carry any sign. const rel = scoreMax === scoreMin ? 1 : ((c.score || 0) - scoreMin) / (scoreMax - scoreMin); return (
onOpen(c)} title="View source region on page">
{c.kind === "visual" ? "IMG" : "TXT"} {c.paper} · p.{c.page}
relevance {c.score.toFixed(3)}
{c.text &&
{clip(c.text, 150)}
}
); } function InspectionView({ settings, papers, routingAvailable }) { const [draft, setDraft] = useState(window.RAG.SUGGESTIONS[0].q); const [busy, setBusy] = useState(false); const [status, setStatus] = useState(""); const [result, setResult] = useState(null); // { query, cands, routing } const [activeStage, setActiveStage] = useState(null); const [pageItem, setPageItem] = useState(null); const paperTitle = useCallback( (id) => { const p = (papers || []).find((x) => x.paper_id === id); return (p && p.title) || id; }, [papers] ); const trace = useCallback(async (text) => { const v = (text != null ? text : draft).trim(); if (!v || busy) return; setBusy(true); setStatus(""); setActiveStage(null); try { const { results, routing } = await window.RAG.retrieve(v, { topK: settings.topk, forceRoute: settings.route === "text" ? "text" : settings.route === "visual" ? "hybrid" : "", routingMode: settings.routingMode || "", paperId: settings.paper || "", onStatus: setStatus, }); setStatus(""); setResult({ query: v, cands: results.map(inspToCand), routing }); } catch (err) { setStatus(`Trace failed: ${(err && err.message) || err}`); setResult(null); } finally { setBusy(false); } }, [draft, busy, settings]); const cands = result ? result.cands : []; const textCands = cands.filter((c) => c.kind === "text"); const visCands = cands.filter((c) => c.kind === "visual"); // Min-max scale within the set: rerank logits carry any sign, and an // all-negative set must not render every bar empty. const allScores = cands.map((c) => c.score || 0); const scoreMax = allScores.length ? Math.max(...allScores) : 0; const scoreMin = allScores.length ? Math.min(...allScores) : 0; const routeLabel = result ? window.RAG.routeLabel(result.routing) : "text"; const stageInfo = { query: { icon: "text", title: "Query", body: result ? `Normalized query: “${result.query}”` : "The turn, resolved against conversation history and classified by intent." }, embed: { icon: "layers", title: "Embed", body: "Encoded with bge-m3 into a 1024-d dense vector (L2-normalized) for nearest-neighbour search. The raw vector isn't surfaced by the API." }, route: { icon: "route", title: "Route gate", body: routingAvailable === false ? "No router on this deployment — every query retrieves text-side. The gate runs where the GPU visual leg is built." : result ? `Routing mode: ${result.routing?.mode || settings.routingMode || "default"} · path: ${result.routing?.path || "text"}${result.routing?.forced ? " · forced" : ""}${result.routing?.category ? " · category: " + result.routing.category : ""}` : "A gate predicts which store(s) hold the answer." }, retrieve: { icon: "search", title: "Retrieve", body: result ? `Top ${cands.length} after reranking the hybrid BM25 + dense (RRF-fused) candidate pool (${textCands.length} text, ${visCands.length} visual).` : "Pulls top-k candidates from each enabled store." }, rerank: { icon: "filter", title: "Rerank", body: "A MiniLM cross-encoder re-scores the candidate pool; the score shown on each row is the post-rerank relevance." }, assemble: { icon: "check", title: "Assemble", body: result ? `Top ${cands.length} chunks packed into the generation context (budget ${settings.topk}).` : "Greedily packs the highest-scoring chunks under a token budget." }, }; return (
setDraft(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") trace(); }} />
{result && routingAvailable !== false && } {settings.paper && filter: {settings.paper} }
EXAMPLES
{window.RAG.SUGGESTIONS.map((s, i) => ( ))}
{status &&
{status}
} {!result && !status &&
Run a trace to see the real routing decision, ranked candidates, and assembled context.
} {result && (
setActiveStage((a) => a === "query" ? null : "query")} /> setActiveStage((a) => a === "embed" ? null : "embed")} /> setActiveStage((a) => a === "route" ? null : "route")} /> setActiveStage((a) => a === "retrieve" ? null : "retrieve")} /> setActiveStage((a) => a === "rerank" ? null : "rerank")} /> setActiveStage((a) => a === "assemble" ? null : "assemble")} />
{activeStage && stageInfo[activeStage] && (

{stageInfo[activeStage].title}

{stageInfo[activeStage].body}

)}

Text store{textCands.length}

{textCands.length ? textCands.map((c, i) => ) :
No text candidates.
}

Visual store{routingAvailable === false ? "off" : visCands.length}

{visCands.length ? visCands.map((c, i) => ) :
{routingAvailable === false ? Not built on this deployment — the visual leg needs a GPU. Offline it measures +35% recall@10 over text-only retrieval (results); here retrieval runs text-side and figure questions are answered from page images at generation time. : "No visual candidates passed the gate for this query."}
}

Assembled context {cands.length} chunks

{cands.map((c, i) => (
setPageItem(c)} title="View source region on page"> {i + 1} {c.kind === "visual" ? "IMG" : "TXT"} {c.paper} · p.{c.page}
region {c.score.toFixed(3)}
))}
)}
setPageItem(null)} paperTitle={paperTitle} />
); } window.InspectionView = InspectionView;