const $ = (selector, scope = document) => scope.querySelector(selector); const $$ = (selector, scope = document) => [...scope.querySelectorAll(selector)]; const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; const data = { architecture: [ ['Input', 'Clinician input and case question are normalised before retrieval.'], ['Patient context', 'EMR history, medications, labs, allergies, and provenance metadata shape the query.'], ['Guidelines', 'CPG passages are retrieved with section, version, and update metadata.'], ['Orchestrator', 'Typed artifacts coordinate retrieval sets, summaries, guideline extracts, and safety critiques.'], ['Candidate pool', 'Dense ANN and BM25 lexical recall are unioned to protect rare terms and semantic matches.'], ['Reranking', 'A long-context biomedical reranker scores each query-passage pair and supports calibrated thresholds.'], ['Sufficiency', 'Facet coverage, entropy, contradictions, and marginal utility govern retrieve-more evidence actions.'], ['Answer', 'Final output includes a grounded answer.'] ], datasets: [ ['HealthCareMagic', 100, 'forum QA'], ['iCliniq', 10, 'forum QA'], ['PubMedQA labelled', 1, 'research QA'], ['PubMedQA unlabelled', 61.2, 'KD prompts'], ['PubMedQA synthetic', 211.3, 'multi-variant'] ], merges: [ ['Task arithmetic', 'Adds SFT and KD deltas with magnitude control.', '#33d7ff', 'θ = θ₀ + λ(ΔSFT + ΔKD)', 'Vector addition preserves both task updates but can amplify shared directions.'], ['NuSLERP', 'Interpolates normalised update directions to reduce norm dominance.', '#5ef7d8', 'θ = θ₀ + slerp(norm(ΔSFT), norm(ΔKD); t)', 'Normalise first, then follow the spherical arc between update directions.'], ['DARE', 'Drops and rescales redundant update coordinates.', '#ffd166', 'θ = θ₀ + m ⊙ Δ / p', 'A Bernoulli mask removes coordinates, then rescales the survivors to preserve expectation.'], ['TIES', 'Trims weak updates and resolves sign conflicts.', '#9b7cff', 'θᵢ = θ₀ᵢ + sign_vote(top_k(Δᵢ))', 'Weak coordinates are trimmed; conflicting signs are resolved by consensus before merging.'], ['DARE–TIES', 'Combines stochastic sparsity with sign consensus.', '#ff6f91', 'θ = θ₀ + TIES(DARE(ΔSFT), DARE(ΔKD))', 'Sparsify noisy updates first, then merge only the agreed surviving directions.'] ], retrievalStages: [ { key: 'Candidate pool', title: 'Stage 1: dense + lexical recall', body: 'The system retrieves a broad candidate set with dense ANN search and BM25 union. This protects exact clinical terms while preserving semantic recall.', nodes: [ ['Clinical query q', 70, 190], ['Dense ANN', 370, 105], ['BM25 lexical', 370, 275], ['Union C(q)', 660, 190] ], lines: [[225, 220, 360, 140], [225, 220, 360, 308], [520, 135, 650, 205], [520, 300, 650, 225]] }, { key: 'Biomedical rerank', title: 'Stage 2: long-context pointwise reranking', body: 'Each query-passage pair receives a logit and calibrated relevance probability, enabling auditable thresholds instead of uncalibrated top-K truncation.', nodes: [ ['q + passage d', 80, 160], ['LLM reranker', 350, 205], ['Temp scaling', 620, 135], ['p̂θ(q,d)', 650, 285] ], lines: [[250, 190, 340, 230], [510, 230, 610, 168], [510, 245, 640, 315]] }, { key: 'Evidence grade', title: 'Evidence hierarchy + source validity', body: 'Guidelines, systematic reviews, RCTs, observational evidence, case evidence, EMR evidence, and safety evidence are separated so patient context is not confused with generalisable treatment efficacy.', nodes: [ ['CPG / SR / RCT', 85, 115], ['EMR applicability', 105, 295], ['gEBM(d)', 410, 205], ['noise penalty', 660, 250] ], lines: [[255, 145, 405, 218], [285, 320, 405, 255], [555, 230, 650, 270]] }, { key: 'Budgeted bundle', title: 'Utility selection under token budget B', body: 'The bundle maximises clinical utility: facet coverage, source quality, safety relevance, contradiction resolution, and redundancy penalties under a hard token budget.', nodes: [ ['Facet set F(q)', 90, 150], ['Utility U(q,M)', 390, 185], ['M* bundle', 650, 145], ['Audit trace', 650, 290] ], lines: [[250, 180, 380, 215], [550, 215, 640, 180], [550, 225, 640, 320]] } ], facets: [ ['Guideline concordance', 42, true], ['Contraindications', 35, true], ['Patient applicability', 40, true], ['Medication interactions', 28, true], ['Outcome evidence', 52, false], ['Audit provenance', 58, false] ], retrievalEvents: [ 'Guideline agent retrieved a current CPG recommendation with section and version metadata.', 'Safety agent added contraindication evidence with severity tags.', 'Patient-context agent aligned lab trend and comorbidity constraints from EMR.', 'Contradiction critic preserved a population-exclusion conflict for adjudication.', 'Evidence-quality agent upgraded source grade using systematic-review support.', 'Orchestrator accepted bundle after marginal utility saturated under token budget.' ], agents: [ ['⌁', 'Exploration agent', 'Maximises recall through dense retrieval, lexical retrieval, synonym expansion, abbreviation expansion, and specialty reformulation.', 84], ['§', 'Guideline agent', 'Prioritises CPG and consensus recommendations, extracting strength, population, exclusions, and update date.', 91], ['◆', 'Evidence-quality agent', 'Assigns EBM grade, study design, provenance, sample relevance, outcome relevance, and recency.', 87], ['◈', 'Patient-context agent', 'Aligns evidence with EMR-derived comorbidities, demographics, medications, allergies, labs, and prior treatment history.', 85], ['!', 'Safety agent', 'Searches for contraindications, adverse events, drug-drug interactions, dose restrictions, and exclusion criteria.', 93], ['⇄', 'Contradiction critic', 'Separates true clinical conflict from population mismatch and routes unresolved high-severity conflicts forward.', 88] ], qa: { medquad: [ { model: 'DaRE-TIES-KD-0.7', rouge: 0.17, bert: 0.8501, tok: 0.22, uni: 0.47, bi: 0.14 }, { model: 'NuSL-KD-0.7', rouge: 0.17, bert: 0.8500, tok: 0.21, uni: 0.47, bi: 0.11 }, { model: 'DaRE-Linear-KD-0.7', rouge: 0.17, bert: 0.8494, tok: 0.22, uni: 0.45, bi: 0.14 }, { model: 'TA-SFT-0.7', rouge: 0.16, bert: 0.8491, tok: 0.18, uni: 0.51, bi: 0.20 }, { model: '7B-KD', rouge: 0.18, bert: 0.8441, tok: 0.26, uni: 0.46, bi: 0.12 }, { model: '7B-SFT', rouge: 0.15, bert: 0.8396, tok: 0.18, uni: 0.52, bi: 0.21 }, { model: 'KD-SFT-PubMed-l', rouge: 0.17, bert: 0.8341, tok: 0.24, uni: 0.44, bi: 0.11 }, { model: 'KD-SFT-PubMed-map', rouge: 0.17, bert: 0.8297, tok: 0.22, uni: 0.47, bi: 0.12 }, { model: 'MedGemma-27b-it', rouge: 0.19, bert: 0.8465, tok: 0.27, uni: 0.40, bi: 0.09 }, { model: 'MedGemma-1.5-4b', rouge: 0.18, bert: 0.8449, tok: 0.26, uni: 0.40, bi: 0.08 }, { model: 'Gemini 3.1', rouge: 0.15, bert: 0.8490, tok: 0.26, uni: 0.36, bi: 0.08 }, { model: 'Gemini 2.5 Flash', rouge: 0.09, bert: 0.8390, tok: 0.11, uni: 0.55, bi: 0.28 }, { model: 'GPT 5.4', rouge: 0.13, bert: 0.8450, tok: 0.21, uni: 0.31, bi: 0.05 }, { model: 'Claude Sonnet 4.6', rouge: 0.12, bert: 0.8470, tok: 0.19, uni: 0.28, bi: 0.05 }, { model: 'Mistral Small', rouge: 0.14, bert: 0.8450, tok: 0.23, uni: 0.34, bi: 0.07 }, { model: 'BioMistral-7B', rouge: 0.18, bert: 0.8460, tok: 0.25, uni: 0.45, bi: 0.11 }, { model: 'MediPhi', rouge: 0.18, bert: 0.8479, tok: 0.27, uni: 0.40, bi: 0.09 }, { model: 'Meditron-7B', rouge: 0.16, bert: 0.8240, tok: 0.22, uni: 0.47, bi: 0.13 }, { model: 'MedAlpaca-7B', rouge: 0.16, bert: 0.8196, tok: 0.18, uni: 0.50, bi: 0.20 } ], healthbench: [ { model: 'TIES-KD-0.7-0.6', rouge: 0.16, bert: 0.8411, tok: 0.22, uni: 0.35, bi: 0.08 }, { model: 'TA-SFT-0.7', rouge: 0.16, bert: 0.8410, tok: 0.23, uni: 0.35, bi: 0.08 }, { model: 'NuSL-KD-0.7', rouge: 0.16, bert: 0.8403, tok: 0.24, uni: 0.34, bi: 0.07 }, { model: 'DaRE-TIES-KD-0.7', rouge: 0.16, bert: 0.8392, tok: 0.24, uni: 0.34, bi: 0.07 }, { model: 'DaRE-Linear-KD-0.7', rouge: 0.16, bert: 0.8388, tok: 0.24, uni: 0.34, bi: 0.07 }, { model: '7B-KD', rouge: 0.15, bert: 0.8314, tok: 0.23, uni: 0.32, bi: 0.06 }, { model: '7B-SFT', rouge: 0.13, bert: 0.8299, tok: 0.17, uni: 0.31, bi: 0.07 }, { model: 'KD-SFT-PubMed-l', rouge: 0.13, bert: 0.8186, tok: 0.20, uni: 0.32, bi: 0.06 }, { model: 'KD-SFT-PubMed-map', rouge: 0.12, bert: 0.8088, tok: 0.16, uni: 0.31, bi: 0.06 }, { model: 'MedGemma-27b-it', rouge: 0.17, bert: 0.8342, tok: 0.26, uni: 0.32, bi: 0.07 }, { model: 'MedGemma-1.5-4b', rouge: 0.16, bert: 0.8326, tok: 0.25, uni: 0.32, bi: 0.06 }, { model: 'Gemini 3.1', rouge: 0.14, bert: 0.8480, tok: 0.26, uni: 0.33, bi: 0.06 }, { model: 'Gemini 2.5 Flash', rouge: 0.08, bert: 0.8230, tok: 0.13, uni: 0.47, bi: 0.18 }, { model: 'GPT 5.4', rouge: 0.12, bert: 0.8460, tok: 0.22, uni: 0.27, bi: 0.04 }, { model: 'Claude Sonnet 4.6', rouge: 0.11, bert: 0.8440, tok: 0.20, uni: 0.24, bi: 0.04 }, { model: 'Mistral Small', rouge: 0.13, bert: 0.8470, tok: 0.23, uni: 0.30, bi: 0.06 }, { model: 'BioMistral-7B', rouge: 0.16, bert: 0.8404, tok: 0.23, uni: 0.35, bi: 0.08 }, { model: 'Meditron-7B', rouge: 0.12, bert: 0.8068, tok: 0.15, uni: 0.31, bi: 0.06 }, { model: 'MedAlpaca-7B', rouge: 0.11, bert: 0.7946, tok: 0.21, uni: 0.34, bi: 0.07 } ] }, reranker: [ ['MRR@10', '0.9771', 97.71, 'Relevant passages are placed extremely close to the top.'], ['nDCG@10', '0.9826', 98.26, 'Position-sensitive ranking quality remains high after biomedical adaptation.'], ['Recall@10', '1.0000', 100, 'The positive passage is present in the first ten results.'], ['MAP@10', '0.9771', 97.71, 'Average precision across the ranked evidence set is high.'], ['p95 latency', '3895.1 ms', 74, 'Long-context scoring trades latency for calibrated clinical auditability.'] ], audit: [ ['Facet recall', 92], ['Citation precision', 88], ['Trace completeness', 96], ['Sufficiency decision', 90], ['Groundedness proxy', 86], ['Unsafe omission control', 84] ], release: [ ['01', 'Data engineering filters', 'License-aware fetchers, PHI scrubbing, MD5 deduplication, medically invariant augmentation filters, and dataset manifests.'], ['02', 'Teacher-label utilities', 'Logged prompts and decoding parameters for hard-label generation plus top-k soft-label serialization.'], ['03', 'QLoRA training scripts', '4-bit NF4, LoRA rank configuration, optimizer schedules, gradient checkpointing, early stopping, and checkpoint reconstruction.'], ['04', 'Merge specifications', 'MergeKit YAML recipes for TA, SLERP, NuSLERP, DARE, TIES, and DARE-TIES.'], ['05', 'Retrieval policy package', 'Dense + lexical union, long-context biomedical reranker inference, calibrated scoring hooks, evidence hierarchy, and index parameters.'], ['06', 'Evaluation and audit harness', 'Deterministic prompting, benchmarks, trace export, policy rates, penalties, and MSAS reporting.'] ] }; let activeStage = 0; let activeMerge = 4; let retrievalStep = 0; const coverageHistory = [34]; function setHTML(el, html) { if (el) el.innerHTML = html; } function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); } function fmtScore(value, metric) { if (metric === 'bert') return `${(value * 100).toFixed(2)}%`; return value.toFixed(3); } function initCanvas() { const canvas = $('#abyssCanvas'); if (!canvas || prefersReducedMotion) return; const ctx = canvas.getContext('2d'); let w = 0, h = 0, dpr = 1; const particles = Array.from({ length: 130 }, () => ({ x: Math.random(), y: Math.random(), r: Math.random() * 1.7 + .35, vx: (Math.random() - .5) * .00008, vy: Math.random() * .00012 + .000035, a: Math.random() * .45 + .12 })); const caustics = Array.from({ length: 10 }, (_, i) => ({ y: .12 + i * .095, speed: .00016 + Math.random() * .00018, amp: 8 + Math.random() * 14, alpha: .018 + Math.random() * .024 })); function resize() { dpr = Math.min(window.devicePixelRatio || 1, 2); w = canvas.width = Math.floor(innerWidth * dpr); h = canvas.height = Math.floor(innerHeight * dpr); canvas.style.width = `${innerWidth}px`; canvas.style.height = `${innerHeight}px`; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); w = innerWidth; h = innerHeight; } function draw(t) { ctx.clearRect(0, 0, w, h); const grad = ctx.createLinearGradient(0, 0, 0, h); grad.addColorStop(0, '#04142b'); grad.addColorStop(.48, '#020b1b'); grad.addColorStop(1, '#00040d'); ctx.fillStyle = grad; ctx.fillRect(0, 0, w, h); // Motivation vs Logic: the page theme should feel like deep water, but the animation must stay calm enough for reading. We layer slow caustic curves and small particulate drift instead of large distracting motion. caustics.forEach((line, i) => { ctx.beginPath(); ctx.strokeStyle = `rgba(101,231,255,${line.alpha})`; ctx.lineWidth = i % 3 === 0 ? 1.4 : .8; const base = h * line.y; for (let x = 0; x <= w; x += 18) { const y = base + Math.sin(x * .006 + t * line.speed + i) * line.amp + Math.sin(x * .019 + t * .00011) * 3; x ? ctx.lineTo(x, y) : ctx.moveTo(x, y); } ctx.stroke(); }); particles.forEach(p => { p.x += p.vx; p.y += p.vy; if (p.x < 0) p.x = 1; if (p.x > 1) p.x = 0; if (p.y > 1) p.y = 0; ctx.beginPath(); ctx.fillStyle = `rgba(224,250,255,${p.a})`; ctx.arc(p.x * w, p.y * h, p.r, 0, Math.PI * 2); ctx.fill(); }); requestAnimationFrame(draw); } resize(); addEventListener('resize', resize, { passive: true }); requestAnimationFrame(draw); } function initNavigation() { const navToggle = $('#navToggle'); const nav = $('#siteNav'); navToggle?.addEventListener('click', () => { const open = nav.classList.toggle('open'); navToggle.setAttribute('aria-expanded', open ? 'true' : 'false'); }); const links = [...$$('.nav a'), ...$$('.depth-map a')]; const sections = links.map(a => $(a.getAttribute('href'))).filter(Boolean); const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) return; links.forEach(a => a.classList.toggle('active', a.getAttribute('href') === `#${entry.target.id}`)); }); }, { rootMargin: '-40% 0px -55% 0px', threshold: 0.01 }); sections.forEach(s => observer.observe(s)); addEventListener('scroll', () => { const max = document.documentElement.scrollHeight - innerHeight; $('#readProgress').style.width = `${max > 0 ? (scrollY / max) * 100 : 0}%`; }, { passive: true }); // Root Cause vs Logic: anchor jumps could land headings under the sticky header or leave hash targets unrevealed after a deep link. CSS sets the normal margin; this correction settles hash targets after layout finishes. function settleHashTarget() { const id = decodeURIComponent(location.hash.slice(1)); if (!id) return; const target = document.getElementById(id); if (!target) return; const header = $('.site-header'); const offset = (header?.getBoundingClientRect().height || 0) + 34 + (id === 'architecture' ? 120 : 0); const top = target.getBoundingClientRect().top + scrollY - offset; window.scrollTo({ top: Math.max(0, top), behavior: prefersReducedMotion ? 'auto' : 'smooth' }); $$('.reveal', target).forEach(el => el.classList.add('visible')); } addEventListener('hashchange', () => setTimeout(settleHashTarget, 60)); setTimeout(settleHashTarget, 180); } function initRevealAndCounters() { const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) return; entry.target.classList.add('visible'); observer.unobserve(entry.target); }); }, { threshold: 0.12 }); $$('.reveal').forEach(el => observer.observe(el)); const countObserver = new IntersectionObserver(entries => { entries.forEach(entry => { if (!entry.isIntersecting) return; const el = entry.target; const target = Number(el.dataset.target || 0); const duration = 1100; const start = performance.now(); function tick(now) { const p = clamp((now - start) / duration, 0, 1); const eased = 1 - Math.pow(1 - p, 3); el.textContent = Math.round(target * eased).toString(); if (p < 1) requestAnimationFrame(tick); } requestAnimationFrame(tick); countObserver.unobserve(el); }); }, { threshold: .3 }); $$('.counter').forEach(el => countObserver.observe(el)); } function initSonar() { const readout = $('#sonarReadout'); $$('.sonar-node').forEach(btn => { const update = () => { readout.textContent = btn.dataset.copy; }; btn.addEventListener('mouseenter', update); btn.addEventListener('focus', update); }); } function initArchitecture() { const caption = $('#archCaption'); const notes = $('#architectureNotes'); const paths = $$('#architectureSvg .flow-path'); const nodes = $$('#architectureSvg .arch-node'); const evidenceFlows = $$('#architectureSvg .arch-evidence-flow'); let step = 1; let timer = null; function render(next = step) { step = next; paths.forEach(p => p.classList.toggle('active', Number(p.dataset.step) <= step)); nodes.forEach(n => n.classList.toggle('active', Number(n.dataset.step) <= step)); evidenceFlows.forEach(flow => flow.classList.toggle('active', Number(flow.dataset.step) <= step)); caption.textContent = data.architecture[step - 1]?.[1] || 'Grounded answer leaves with audit trace.'; const cards = data.architecture.slice(Math.max(0, step - 4), step).map(([title, body]) => `
${title}${body}
`).join(''); setHTML(notes, cards); } $('#playArchitecture')?.addEventListener('click', () => { clearInterval(timer); step = 1; render(step); timer = setInterval(() => { step += 1; render(step); if (step >= 8) clearInterval(timer); }, prefersReducedMotion ? 0 : 720); }); $('#resetArchitecture')?.addEventListener('click', () => { clearInterval(timer); render(1); }); nodes.forEach(n => n.addEventListener('click', () => render(Number(n.dataset.step)))); render(1); } function initDatasets() { const max = Math.max(...data.datasets.map(d => d[1])); setHTML($('#datasetBars'), data.datasets.map(([name, value, note]) => `
${name}
${note}
${value}k
`).join('')); setTimeout(() => $$('.dataset-fill').forEach(el => el.style.width = `${el.dataset.width}%`), 150); } function renderMerge() { const svg = $('#mergeSvg'); const op = data.merges[activeMerge]; const color = op[2]; const values = [ [68, 76, 64, 82, 58, 70], [54, 68, 62, 64, 60, 66], [0, 84, 0, 76, 0, 70], [58, 0, 72, 0, 66, 0], [0, 78, 0, 82, 62, 0] ][activeMerge]; const wrap = (text, x, y, width = 30, cls = 'merge-sub') => { const words = text.split(' '); const lines = words.reduce((acc, word) => { const last = acc[acc.length - 1] || ''; if (`${last} ${word}`.trim().length > width) acc.push(word); else acc[acc.length - 1] = `${last} ${word}`.trim(); return acc; }, ['']); return `${lines.map((line, i) => `${line}`).join('')}`; }; const miniBars = values.map((v, i) => { const x = 720 + i * 34; return ``; }).join(''); const mechanism = [ ['Add deltas', 'Sum both update vectors, then scale the total update before applying it to the base model.'], ['Normalize direction', 'Convert updates to directions, interpolate on the sphere, then restore a controlled magnitude.'], ['Drop + rescale', 'Mask redundant coordinates and rescale the surviving coordinates to preserve the expected update.'], ['Trim + sign vote', 'Keep strong coordinates, resolve sign conflicts, and merge only the agreed directions.'], ['Sparse consensus', 'Apply DARE sparsity first, then use TIES sign consensus on the surviving update set.'] ][activeMerge]; // Motivation vs Logic: the merge panel needs to teach the operator rather than decorate it. Each mode now shows a formula, weight coordinates, and the exact transformation metaphor used by that merge technique. svg.innerHTML = ` Input update ΔSFT format instruction Input update ΔKD teacher semantics Merge operator ${op[0]} ${wrap(op[3], 392, 212, 30, 'merge-formula')} ${mechanism[0]} ${wrap(mechanism[1], 392, 306, 32)} Merged model θ specialist ${miniBars} conflict-aware 7B update Selected operator: ${op[0]} · ${op[1]}`; } function initMerge() { const controls = $('#mergeControls'); setHTML(controls, data.merges.map((m, i) => ``).join('')); controls.addEventListener('click', e => { const btn = e.target.closest('.merge-button'); if (!btn) return; activeMerge = Number(btn.dataset.i); $$('.merge-button', controls).forEach(b => b.classList.toggle('active', b === btn)); renderMerge(); }); renderMerge(); } function renderRetrievalStage() { const stage = data.retrievalStages[activeStage]; $$('.stage-tab').forEach((btn, i) => btn.classList.toggle('active', i === activeStage)); $('#stageCaption').innerHTML = `${stage.title}${stage.body}`; const svg = $('#retrievalSvg'); svg.innerHTML = ` ${stage.lines.map((l, i) => ``).join('')} ${stage.nodes.map((n, i) => `${n[0]}${stage.key}`).join('')}`; } function initRetrieval() { const tabs = $('#retrievalTabs'); setHTML(tabs, data.retrievalStages.map((s, i) => ``).join('')); tabs.addEventListener('click', e => { const btn = e.target.closest('.stage-tab'); if (!btn) return; activeStage = Number(btn.dataset.i); renderRetrievalStage(); }); renderRetrievalStage(); } function renderFacets() { const threshold = 80; setHTML($('#facetBars'), data.facets.map(([name, value, critical]) => `
${name}${critical ? ' critical' : ''}${Math.round(value)}%
`).join('')); renderCoverage(); const accepted = data.facets.filter(f => f[2]).every(f => f[1] >= threshold); const status = $('#policyStatus'); status.classList.toggle('accepted', accepted); status.textContent = accepted ? 'Evidence bundle accepted: critical facets clear threshold and marginal utility is saturated.' : 'Critical facets are still below acceptance threshold; targeted retrieve-more action required.'; } function renderCoverage() { const svg = $('#coverageSvg'); const values = coverageHistory; const w = 760, h = 210, pad = 34; const x = i => pad + (i / Math.max(1, values.length - 1)) * (w - pad * 2); const y = v => h - pad - (v / 100) * (h - pad * 2); const points = values.map((v, i) => `${x(i)},${y(v)}`).join(' '); const bars = values.map((v, i) => ``).join(''); svg.innerHTML = ` 80% threshold ${bars} ${values.map((v,i)=>``).join('')}`; } function initSufficiency() { renderFacets(); const list = $('#bundleList'); $('#retrieveMore')?.addEventListener('click', () => { retrievalStep += 1; data.facets.forEach((f, i) => { f[1] = clamp(f[1] + [12, 15, 13, 14, 8, 7][i], 0, 96); }); coverageHistory.push(Math.round(data.facets.reduce((s, f) => s + f[1], 0) / data.facets.length)); const message = data.retrievalEvents[Math.min(retrievalStep - 1, data.retrievalEvents.length - 1)]; list.insertAdjacentHTML('afterbegin', `
Step ${retrievalStep}: ${message}
`); renderFacets(); }); } function initAgents() { setHTML($('#agentHive'), data.agents.map(([icon, name, text, rel]) => `
${icon}

${name}

${text}

`).join('')); } function metricScale(metric, rows) { const values = rows.map(r => r[metric]); if (metric === 'bert') return { min: 0.80, max: 0.86 }; if (metric === 'uni') return { min: 0.20, max: 0.58 }; if (metric === 'bi') return { min: 0.00, max: 0.30 }; const min = Math.max(0, Math.floor((Math.min(...values) - 0.02) * 100) / 100); const max = Math.ceil((Math.max(...values) + 0.03) * 100) / 100; return { min, max }; } function renderQA() { const dataset = $('#datasetSelect').value; const metric = $('#metricSort').value; const lowFirst = metric === 'uni' || metric === 'bi'; const rows = [...data.qa[dataset]].sort((a, b) => lowFirst ? a[metric] - b[metric] : b[metric] - a[metric]); const { min, max } = metricScale(metric, rows); const metricNames = { bert: 'BERTScore-F1', rouge: 'ROUGE-L F1', tok: 'Token F1', uni: 'Unigram precision', bi: 'Bigram precision' }; const tick = metric === 'bert' ? v => `${(v * 100).toFixed(0)}%` : v => v.toFixed(2); $('#chartMeta').innerHTML = `${metricNames[metric]}${lowFirst ? ' · lower better' : ' · higher better'}`; const axis = `
${tick(min)}${tick((min+max)/2)}${tick(max)}
`; const bars = rows.slice(0, 10).map((r, i) => { const pct = clamp(((r[metric] - min) / (max - min)) * 100, 0, 100); return `
${i + 1}. ${r.model}
${fmtScore(r[metric], metric)}
`; }).join(''); $('#metricBars').innerHTML = axis + bars; requestAnimationFrame(() => $$('#metricBars .bar-fill').forEach((el, i) => { el.style.transitionDelay = `${i * 70}ms`; el.style.width = `${el.dataset.width}%`; })); $('#qaTable tbody').innerHTML = rows.map(r => `${r.model}${r.rouge.toFixed(2)}${r.bert.toFixed(4)}${r.tok.toFixed(2)}${r.uni.toFixed(2)}${r.bi.toFixed(2)}`).join(''); } function renderReranker() { setHTML($('#rerankGrid'), data.reranker.map(([metric, value, score, text]) => `

${metric}

${value}

${text}

`).join('')); } function renderAudit() { const svg = $('#auditSvg'); const cx = 280, cy = 260, r = 185; const angles = data.audit.map((_, i) => -Math.PI / 2 + i * Math.PI * 2 / data.audit.length); const point = (val, angle) => [cx + Math.cos(angle) * r * val / 100, cy + Math.sin(angle) * r * val / 100]; const rings = [20,40,60,80,100].map(v => { const pts = angles.map(a => point(v, a).join(',')).join(' '); return ``; }).join(''); const axes = angles.map((a,i) => { const [x,y] = point(100, a); const [lx,ly] = point(115, a); return `${data.audit[i][0]}`; }).join(''); const pts = data.audit.map(([_, v], i) => point(v, angles[i]).join(',')).join(' '); svg.innerHTML = `${rings}${axes}${data.audit.map(([_, v], i) => { const [x,y]=point(v,angles[i]); return ``; }).join('')}`; $('#auditMetrics').innerHTML = data.audit.map(([name, v]) => `
  • ${name}: ${v}%
  • `).join(''); } function initEvaluation() { $$('.tab').forEach(btn => btn.addEventListener('click', () => { $$('.tab').forEach(b => { b.classList.toggle('active', b === btn); b.setAttribute('aria-selected', b === btn ? 'true' : 'false'); }); $$('.tab-panel').forEach(p => p.classList.toggle('active', p.id === `tab-${btn.dataset.tab}`)); $('#qaControls').style.display = btn.dataset.tab === 'qa' ? '' : 'none'; if (btn.dataset.tab === 'qa') renderQA(); if (btn.dataset.tab === 'rerank') renderReranker(); if (btn.dataset.tab === 'audit') renderAudit(); })); $('#datasetSelect').addEventListener('change', renderQA); $('#metricSort').addEventListener('change', renderQA); renderQA(); renderReranker(); renderAudit(); } function initRelease() { setHTML($('#releaseTimeline'), data.release.map(([num, title, text]) => `
    ${num}

    ${title}

    ${text}

    `).join('')); } function init() { initCanvas(); initNavigation(); initRevealAndCounters(); initSonar(); initArchitecture(); initDatasets(); initMerge(); initRetrieval(); initSufficiency(); initAgents(); initEvaluation(); initRelease(); } document.addEventListener('DOMContentLoaded', init);