Introduction / index.html
BinKhoaLe1812's picture
Upd mobile rend
3e00f57 verified
<!DOCTYPE html>
<html lang="en" class="scroll-smooth dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MedSwin — Project Introduction</title>
<meta name="description" content="MedSwin: evidence-constrained, auditable multi-agent clinical QA with two-stage biomedical retrieval, calibrated reranking, and distilled 7B medical LLM for deployable decision support." />
<link rel="icon" href="assets/logo.svg">
<!-- Tailwind (CDN) -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
if (typeof tailwind !== 'undefined') {
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
fontFamily: { inter: ['Inter', 'ui-sans-serif', 'system-ui'] },
boxShadow: {
glow: '0 0 18px rgba(99,102,241,0.28), 0 0 48px rgba(56,189,248,0.10)',
glass: '0 10px 30px rgba(0,0,0,0.35)'
},
backgroundImage: {
'grid': 'linear-gradient(to right, rgba(255,255,255,0.06) 1px, transparent 1px), linear-gradient(to bottom, rgba(255,255,255,0.06) 1px, transparent 1px)',
'radial': 'radial-gradient(closest-side, rgba(99,102,241,0.22), transparent)',
'noise': "url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22120%22 height=%22120%22%3E%3Cfilter id=%22n%22%3E%3CfeTurbulence type=%22fractalNoise%22 baseFrequency=%220.8%22 numOctaves=%223%22 stitchTiles=%22stitch%22/%3E%3C/filter%3E%3Crect width=%22120%22 height=%22120%22 filter=%22url(%23n)%22 opacity=%220.22%22/%3E%3C/svg%3E')"
},
keyframes: {
floaty: {
'0%, 100%': { transform: 'translateY(0px)' },
'50%': { transform: 'translateY(-10px)' }
},
shimmer: {
'0%': { backgroundPosition: '0% 50%' },
'100%': { backgroundPosition: '100% 50%' }
},
pulseSoft: {
'0%, 100%': { opacity: 0.55 },
'50%': { opacity: 0.9 }
},
marquee: {
'0%': { transform: 'translateX(0)' },
'100%': { transform: 'translateX(-50%)' }
}
},
animation: {
floaty: 'floaty 6s ease-in-out infinite',
shimmer: 'shimmer 8s ease-in-out infinite',
pulseSoft: 'pulseSoft 4.2s ease-in-out infinite',
marquee: 'marquee 22s linear infinite'
}
}
}
};
}
</script>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
<!-- Load mermaid first, prevent default DOM -->
<script>
window.mermaid = { startOnLoad: false };
</script>
<script defer src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<!-- AOS (Animate On Scroll) -->
<link href="https://unpkg.com/aos@2.3.4/dist/aos.css" rel="stylesheet" />
<script defer src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
<!-- Lucide Icons -->
<script defer src="https://unpkg.com/lucide@latest"></script>
<!-- Mermaid -->
<script defer src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<!-- KaTeX (math rendering) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"></script>
<!-- GSAP -->
<script defer src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<!-- Vanilla Tilt -->
<script defer src="https://unpkg.com/vanilla-tilt@1.8.1/dist/vanilla-tilt.min.js"></script>
<!-- Optional external styles (kept for backward compatibility) -->
<!-- <link rel="stylesheet" href="assets/styles.css"> -->
<style>
:root { color-scheme: dark; }
.container { max-width: 80rem; margin: 0 auto; padding: 0 1rem; }
.section { padding: 5rem 0; }
@media (min-width: 1024px) { .section { padding: 6.5rem 0; } }
.glass {
background: rgba(15, 23, 42, 0.60);
border: 1px solid rgba(255,255,255,0.10);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow: 0 10px 30px rgba(0,0,0,0.25);
}
.chip {
display: inline-flex; align-items: center; gap: .5rem;
padding: .45rem .75rem; border-radius: 999px;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(2, 6, 23, 0.35);
color: rgba(226, 232, 240, 0.92);
transition: transform .15s ease, border-color .15s ease, background .15s ease;
}
.chip:hover { transform: translateY(-1px); border-color: rgba(99,102,241,0.45); background: rgba(99,102,241,0.12); }
.link { color: rgba(226,232,240,0.88); transition: color .15s ease, opacity .15s ease; }
.link:hover { color: rgba(129,140,248,1); }
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
padding: .75rem 1rem; border-radius: .9rem; font-weight: 700;
border: 1px solid rgba(255,255,255,0.12);
transition: transform .15s ease, box-shadow .15s ease, background .15s ease, border-color .15s ease;
user-select: none;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary {
background: linear-gradient(90deg, rgba(99,102,241,0.95), rgba(56,189,248,0.9), rgba(217,70,239,0.85));
background-size: 200% 200%;
animation: shimmer 8s ease-in-out infinite;
box-shadow: 0 10px 30px rgba(99,102,241,0.18);
border-color: rgba(99,102,241,0.28);
}
.btn-primary:hover { box-shadow: 0 18px 46px rgba(99,102,241,0.26); }
.btn-ghost {
background: rgba(2, 6, 23, 0.35);
}
.btn-icon {
width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
border-radius: 14px; border: 1px solid rgba(255,255,255,0.12);
background: rgba(2,6,23,0.35);
transition: transform .15s ease, border-color .15s ease, background .15s ease;
}
.btn-icon:hover { transform: translateY(-1px); border-color: rgba(99,102,241,0.45); background: rgba(99,102,241,0.10); }
.icon { width: 18px; height: 18px; }
.card { border-radius: 1.25rem; overflow: hidden; }
.card-body { padding: 1.5rem; }
.card-title { font-weight: 800; letter-spacing: -0.02em; }
.muted { color: rgba(148,163,184,0.92); }
.kbd {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 12px; padding: .2rem .45rem; border-radius: .5rem;
border: 1px solid rgba(255,255,255,0.14); background: rgba(2,6,23,0.55); color: rgba(226,232,240,0.9);
}
.tab {
padding: .55rem .85rem; border-radius: 999px;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(2,6,23,0.35);
font-weight: 700; font-size: 0.92rem;
transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.tab:hover { transform: translateY(-1px); border-color: rgba(99,102,241,0.45); }
.tab.active { background: rgba(99,102,241,0.14); border-color: rgba(99,102,241,0.45); }
.accordion-btn { width: 100%; text-align: left; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.accordion-panel { max-height: 0; overflow: hidden; transition: max-height .25s ease; }
.accordion-item.open .accordion-panel { max-height: 520px; }
.codeblock {
position: relative;
border: 1px solid rgba(255,255,255,0.12);
border-radius: 1rem;
background: rgba(2,6,23,0.55);
overflow: hidden;
}
.codeblock pre { padding: 1.1rem 1.1rem 1.2rem; overflow: auto; font-size: 0.88rem; color: rgba(226,232,240,0.92); }
.copy-btn {
position: absolute; top: .75rem; right: .75rem;
display: inline-flex; align-items: center; gap: .45rem;
font-size: .78rem;
padding: .35rem .55rem;
border-radius: .7rem;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(2,6,23,0.55);
color: rgba(226,232,240,0.9);
transition: transform .15s ease, border-color .15s ease;
}
.copy-btn:hover { transform: translateY(-1px); border-color: rgba(56,189,248,0.45); }
.badge {
display: inline-flex; align-items: center; gap: .45rem;
padding: .25rem .6rem; border-radius: 999px;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(2,6,23,0.35);
font-size: .78rem; font-weight: 700;
color: rgba(226,232,240,0.92);
}
.toast {
position: fixed;
bottom: 1.25rem;
left: 50%;
transform: translateX(-50%);
z-index: 80;
padding: .75rem 1rem;
border-radius: 1rem;
border: 1px solid rgba(255,255,255,0.14);
background: rgba(2,6,23,0.7);
backdrop-filter: blur(10px);
display: none;
color: rgba(226,232,240,0.92);
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto !important; }
.animate-floaty, .animate-shimmer, .animate-pulseSoft { animation: none !important; }
}
</style>
</head>
<body class="bg-slate-950 text-slate-100 font-inter overflow-x-hidden">
<!-- Skip link -->
<a href="#main" class="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-[100] focus:bg-slate-900 focus:text-white focus:px-4 focus:py-2 focus:rounded-lg">
Skip to content
</a>
<!-- Scroll progress -->
<div class="fixed top-0 left-0 right-0 z-[70] h-[3px] bg-white/10">
<div id="progressBar" class="h-full w-0 bg-gradient-to-r from-indigo-400 via-sky-400 to-fuchsia-400"></div>
</div>
<!-- Background decoration -->
<div class="fixed inset-0 -z-10 overflow-hidden pointer-events-none">
<div class="absolute inset-0 opacity-[0.12] bg-noise"></div>
<div class="absolute inset-0 bg-grid [mask-image:radial-gradient(ellipse_at_center,black_55%,transparent_75%)]"></div>
<div class="absolute -top-48 -left-48 w-[64rem] h-[64rem] rounded-full bg-gradient-to-tr from-indigo-500/30 via-sky-400/16 to-cyan-300/10 blur-3xl animate-pulseSoft"></div>
<div class="absolute -bottom-56 -right-56 w-[66rem] h-[66rem] rounded-full bg-gradient-to-tr from-fuchsia-500/18 via-indigo-500/10 to-sky-400/10 blur-3xl animate-pulseSoft"></div>
<div class="absolute top-[18%] left-[52%] w-[32rem] h-[32rem] rounded-full bg-radial blur-2xl opacity-[0.38] animate-floaty"></div>
</div>
<!-- Navbar -->
<header class="sticky top-0 z-50 backdrop-blur supports-[backdrop-filter]:bg-slate-900/55 border-b border-white/10" role="banner">
<div class="max-w-7xl mx-auto px-4 py-3 flex items-center justify-between gap-4">
<div class="flex items-center gap-3 min-w-[220px]">
<img src="assets/logo.svg" class="w-9 h-9" alt="MedSwin logo" width="36" height="36" />
<div class="flex flex-col leading-tight">
<span class="font-extrabold tracking-tight text-lg sm:text-xl">MedSwin</span>
<span class="text-xs text-slate-400">Multi-Agent Biomedical QA</span>
</div>
</div>
<nav class="hidden lg:flex items-center gap-6 text-sm" role="navigation" aria-label="Main navigation">
<a href="#overview" class="link navlink" data-spy="overview">Overview</a>
<a href="#contributions" class="link navlink" data-spy="contributions">Contributions</a>
<a href="#architecture" class="link navlink" data-spy="architecture">Architecture</a>
<a href="#retrieval" class="link navlink" data-spy="retrieval">Retrieval</a>
<a href="#training" class="link navlink" data-spy="training">Training</a>
<a href="#evaluation" class="link navlink" data-spy="evaluation">Evaluation</a>
<a href="#team" class="link navlink" data-spy="team">Team</a>
</nav>
<div class="flex items-center gap-3">
<a href="https://github.com/MedSwin/RAG" target="_blank" rel="noopener noreferrer" class="btn btn-primary">
<i data-lucide="sparkles" class="icon" aria-hidden="true"></i>
RAG Repo
</a>
<button id="paperBtn" class="btn btn-ghost hidden sm:inline-flex" type="button" aria-haspopup="dialog">
<i data-lucide="file-text" class="icon" aria-hidden="true"></i>
Paper
</button>
<button id="themeToggle" aria-label="Toggle theme" class="btn-icon" type="button">
<i data-lucide="sun-medium" class="icon" aria-hidden="true"></i>
</button>
<button id="mobileMenuBtn" aria-label="Open menu" class="btn-icon lg:hidden" type="button">
<i data-lucide="menu" class="icon" aria-hidden="true"></i>
</button>
</div>
</div>
<!-- Mobile menu -->
<div id="mobileMenu" class="lg:hidden hidden border-t border-white/10 bg-slate-950/70 backdrop-blur">
<div class="max-w-7xl mx-auto px-4 py-4 flex flex-col gap-3 text-sm">
<a href="#overview" class="link navlink">Overview</a>
<a href="#contributions" class="link navlink">Contributions</a>
<a href="#architecture" class="link navlink">Architecture</a>
<a href="#retrieval" class="link navlink">Retrieval</a>
<a href="#training" class="link navlink">Training</a>
<a href="#evaluation" class="link navlink">Evaluation</a>
<a href="#team" class="link navlink">Team</a>
</div>
</div>
</header>
<main id="main">
<!-- Hero -->
<section class="relative overflow-x-clip" aria-labelledby="hero-title" style="overflow-x: clip;">
<div class="max-w-7xl mx-auto px-4 py-16 lg:py-24">
<div class="grid lg:grid-cols-2 gap-10 items-center">
<!-- Left -->
<div class="min-w-0" data-aos="fade-right" data-aos-duration="700">
<div class="flex flex-wrap items-center gap-2 mb-4">
<span class="badge"><i data-lucide="shield-check" class="icon" aria-hidden="true"></i> Evidence-first</span>
<span class="badge"><i data-lucide="search" class="icon" aria-hidden="true"></i> Two-stage retrieval</span>
<span class="badge"><i data-lucide="fingerprint" class="icon" aria-hidden="true"></i> Auditable traces</span>
<span class="badge"><i data-lucide="cpu" class="icon" aria-hidden="true"></i> Distilled 7B</span>
</div>
<h1 id="hero-title" class="text-4xl lg:text-6xl font-extrabold leading-tight tracking-tight break-words">
Multi-Agent <span class="text-indigo-300">Biomedical</span> Reasoning
<span class="block text-slate-200">Grounded in EMR & Guidelines</span>
</h1>
<p class="mt-5 text-slate-300 text-lg max-w-2xl break-words">
MedSwin is an <span class="text-slate-100 font-semibold">evidence-constrained</span> clinical QA stack:
specialised agents coordinate retrieval, EMR summarisation, guideline synthesis, and safety critique—while a
<span class="text-slate-100 font-semibold">calibrated reranker</span> enforces evidence sufficiency under a token budget.
</p>
<div class="mt-8 flex flex-wrap gap-3">
<a class="btn btn-primary" href="https://github.com/MedSwin/RAG" target="_blank" rel="noopener noreferrer">
<i data-lucide="rocket" class="icon" aria-hidden="true"></i>
Open Demo
</a>
<a class="btn btn-ghost" href="#architecture">
<i data-lucide="network" class="icon" aria-hidden="true"></i>
Explore Architecture
</a>
<button class="btn btn-ghost" id="openQuickTour" type="button">
<i data-lucide="play-circle" class="icon" aria-hidden="true"></i>
Quick Tour
</button>
</div>
<div class="mt-6 flex flex-wrap items-center gap-4 text-sm text-slate-400">
<span class="inline-flex items-center gap-2"><i data-lucide="graduation-cap" class="icon" aria-hidden="true"></i> MedSwin</span>
<span class="inline-flex items-center gap-2"><i data-lucide="lock" class="icon" aria-hidden="true"></i> Local-deployable by design</span>
<span class="inline-flex items-center gap-2"><i data-lucide="clipboard-check" class="icon" aria-hidden="true"></i> Provenance-aware output</span>
</div>
<!-- Marquee (fixed: no w-max overflow) -->
<div class="mt-8 overflow-hidden w-full rounded-2xl border border-white/10 bg-slate-950/40">
<div class="flex gap-6 whitespace-nowrap px-6 py-3 text-xs text-slate-300 will-change-transform">
<div class="flex gap-6 animate-marquee min-w-full">
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="git-branch" class="icon"></i> Replayable traces</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="list-checks" class="icon"></i> Evidence sufficiency checks</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="sliders" class="icon"></i> Token budget control</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="scan-search" class="icon"></i> Hybrid ANN + BM25</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="badge-check" class="icon"></i> Calibrated reranker</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="activity" class="icon"></i> Multi-agent coordination (MAC)</span>
</div>
<!-- second lane for seamless loop -->
<div class="flex gap-6 animate-marquee min-w-full" aria-hidden="true">
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="git-branch" class="icon"></i> Replayable traces</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="list-checks" class="icon"></i> Evidence sufficiency checks</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="sliders" class="icon"></i> Token budget control</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="scan-search" class="icon"></i> Hybrid ANN + BM25</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="badge-check" class="icon"></i> Calibrated reranker</span>
<span class="inline-flex items-center gap-2 shrink-0"><i data-lucide="activity" class="icon"></i> Multi-agent coordination (MAC)</span>
</div>
</div>
</div>
</div>
<!-- Hero right: interactive "Trust stack" -->
<div class="relative" data-aos="fade-left" data-aos-duration="700">
<div class="card glass shadow-glow">
<div class="p-6">
<div class="flex items-start justify-between gap-4">
<div>
<h3 class="text-lg font-extrabold tracking-tight">Trust Stack</h3>
<p class="text-sm text-slate-400 mt-1">Design primitives for clinical deployment readiness</p>
</div>
<span class="badge"><i data-lucide="sparkles" class="icon"></i> System</span>
</div>
<div class="mt-5 grid sm:grid-cols-2 gap-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-bold"><i data-lucide="fingerprint" class="icon"></i> Auditability</div>
<p class="text-sm text-slate-300 mt-2">
Typed artifacts + explicit provenance (document IDs, sections, timestamps, chunk offsets) enable replay and review.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-bold"><i data-lucide="layers" class="icon"></i> Evidence sufficiency</div>
<p class="text-sm text-slate-300 mt-2">
Retrieval is accepted only when EMR/CPG coverage targets are met under a strict token budget.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-bold"><i data-lucide="filter" class="icon"></i> Calibrated ranking</div>
<p class="text-sm text-slate-300 mt-2">
Long-context biomedical reranker outputs calibrated probabilities for deterministic inclusion policies.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-bold"><i data-lucide="shield-alert" class="icon"></i> Safety critique</div>
<p class="text-sm text-slate-300 mt-2">
Critic checks missing evidence, contraindications, and unsafe advice—then routes “retrieve-more” when needed.
</p>
</div>
</div>
<div class="mt-5 flex flex-wrap gap-2">
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/MedSwin">
<i data-lucide="box" class="icon"></i> Org
</a>
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/collections/MedSwin/model">
<i data-lucide="database" class="icon"></i> Model Asset
</a>
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/collections/MedSwin/rag">
<i data-lucide="database" class="icon"></i> Rag Data
</a>
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/collections/MedSwin/finetuning">
<i data-lucide="wand-2" class="icon"></i> Finetune Data
</a>
</div>
</div>
<div class="border-t border-white/10 p-4 text-xs text-slate-400">
<span class="inline-flex items-center gap-2">
<i data-lucide="info" class="icon" aria-hidden="true"></i>
Research prototype — not a substitute for professional medical advice.
</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Overview -->
<section id="overview" class="section">
<div class="container">
<div class="grid lg:grid-cols-5 gap-8 items-start">
<!-- Left: narrative -->
<div class="lg:col-span-3" data-aos="fade-up">
<h2 class="text-3xl lg:text-4xl font-extrabold tracking-tight">Overview</h2>
<p class="mt-4 text-slate-300 leading-relaxed">
MedSwin frames clinical QA as an <span class="font-semibold text-slate-100">evidence-constrained decision pipeline</span>.
Every answer is gated by evidence sufficiency, bounded by a strict context budget, and accompanied by a
replayable trace suitable for audit and safety review.
</p>
<div class="mt-6 grid sm:grid-cols-3 gap-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="message-square" class="icon"></i> Answer
</div>
<p class="text-sm text-slate-300 mt-2">
Clinically phrased, uncertainty-aware output generated only when evidence gates are satisfied.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="files" class="icon"></i> Evidence bundle
</div>
<p class="text-sm text-slate-300 mt-2">
Compact EMR + guideline passages selected under token and diversity constraints.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="route" class="icon"></i> Trace
</div>
<p class="text-sm text-slate-300 mt-2">
Structured artifact log: retrieval, ranking, policies, safety checks.
</p>
</div>
</div>
</div>
<!-- Right: compact system summary -->
<aside class="lg:col-span-2 rounded-3xl border border-white/10 bg-slate-950/40 p-6" data-aos="fade-up">
<div class="font-extrabold text-lg tracking-tight mb-3">Why MedSwin is different</div>
<ul class="space-y-3 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Refuses to answer when evidence is insufficient</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Explicit EMR + CPG coverage requirements</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Deterministic retrieval policies (no silent guessing)</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Local-deployable, auditable by design</li>
</ul>
</aside>
</div>
</div>
</section>
<!-- Contributions -->
<section id="contributions" class="section">
<div class="container">
<div class="grid lg:grid-cols-3 gap-6">
<div class="card glass" data-tilt data-tilt-max="7" data-aos="fade-up">
<div class="card-body">
<div class="flex items-center justify-between gap-3">
<h3 class="card-title text-xl">1) Auditable Multi-Agent Orchestration</h3>
<i data-lucide="fingerprint" class="icon" aria-hidden="true"></i>
</div>
<p class="mt-3 text-slate-300">
Every agent produces artifacts with provenance metadata and logs tool calls + selected evidence. This creates a
structured audit trail suitable for review and replay.
</p>
<ul class="mt-4 space-y-2 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Typed artifacts: ids, sections, timestamps, offsets</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Deterministic “retrieve-more” instead of guessing</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Critique + safety checks before finalisation</li>
</ul>
</div>
</div>
<div class="card glass" data-tilt data-tilt-max="7" data-aos="fade-up" data-aos-delay="120">
<div class="card-body">
<div class="flex items-center justify-between gap-3">
<h3 class="card-title text-xl">2) Two-Stage Retrieval with Calibrated Reranking</h3>
<i data-lucide="search-check" class="icon" aria-hidden="true"></i>
</div>
<p class="mt-3 text-slate-300">
Stage-1 retrieves candidates via dense retrieval + BM25 union. Stage-2 reranks with a long-context biomedical reranker
(LoRA-adapted) and outputs calibrated probabilities used by policy constraints.
</p>
<ul class="mt-4 space-y-2 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Hybrid candidate pool: ANN + lexical coverage</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Evidence sufficiency thresholds for EMR/CPG</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Budgeted, diverse selection (MMR-style)</li>
</ul>
</div>
</div>
<div class="card glass" data-tilt data-tilt-max="7" data-aos="fade-up" data-aos-delay="240">
<div class="card-body">
<div class="flex items-center justify-between gap-3">
<h3 class="card-title text-xl">3) Distilled 7B Medical LLM Pipeline</h3>
<i data-lucide="cpu" class="icon" aria-hidden="true"></i>
</div>
<p class="mt-3 text-slate-300">
A compact student is built with SFT on augmented biomedical QA, then refined using hard+soft KD from a larger instructor.
This targets deployability while preserving calibrated reasoning behavior.
</p>
<ul class="mt-4 space-y-2 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Large-scale augmentation with semantic checks</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> Hard labels expand coverage; soft labels preserve uncertainty</li>
<li class="flex gap-2"><i data-lucide="check" class="icon text-emerald-300"></i> PEFT (QLoRA/LoRA) enables modest GPU training</li>
</ul>
</div>
</div>
</div>
<!-- Quick “how it feels” steps -->
<div class="mt-10 grid lg:grid-cols-5 gap-3" data-aos="fade-up">
<div class="lg:col-span-2 rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<h3 class="text-xl font-extrabold tracking-tight">From question → audited answer</h3>
<p class="mt-2 text-slate-300">
MedSwin outputs an answer only when the evidence bundle is sufficient. Otherwise it asks clarifying questions or expands retrieval.
</p>
<div class="mt-4 flex flex-wrap gap-2">
<span class="badge"><i data-lucide="message-square" class="icon"></i> Clarify</span>
<span class="badge"><i data-lucide="scan-search" class="icon"></i> Retrieve-more</span>
<span class="badge"><i data-lucide="shield-check" class="icon"></i> Safe final</span>
</div>
</div>
<div class="lg:col-span-3 rounded-3xl border border-white/10 bg-slate-950/40 p-6">
<ol class="grid md:grid-cols-3 gap-4">
<li class="rounded-2xl border border-white/10 bg-slate-950/35 p-4">
<div class="flex items-center gap-2 font-extrabold"><span class="badge">1</span> Normalise</div>
<p class="text-sm text-slate-300 mt-2">Canonicalise terms, expand abbreviations, form retrieval probes.</p>
</li>
<li class="rounded-2xl border border-white/10 bg-slate-950/35 p-4">
<div class="flex items-center gap-2 font-extrabold"><span class="badge">2</span> Retrieve + Rank</div>
<p class="text-sm text-slate-300 mt-2">Hybrid candidates, rerank with calibrated probabilities, enforce sufficiency.</p>
</li>
<li class="rounded-2xl border border-white/10 bg-slate-950/35 p-4">
<div class="flex items-center gap-2 font-extrabold"><span class="badge">3</span> Synthesize + Critique</div>
<p class="text-sm text-slate-300 mt-2">Summarise EMR, synthesise guideline actions, run safety critique, then answer.</p>
</li>
</ol>
</div>
</div>
</div>
</section>
<!-- Architecture -->
<section id="architecture" class="section" aria-labelledby="architecture-title">
<div class="container">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-6 mb-10" data-aos="fade-up">
<div>
<h2 id="architecture-title" class="text-3xl lg:text-4xl font-extrabold tracking-tight">Architecture Explorer</h2>
<p class="mt-3 text-slate-300 max-w-3xl">
Explore MedSwin layers: multi-agent workflow, two-stage retrieval, evidence sufficiency checks, and MAC coordination.
</p>
</div>
<div class="flex flex-wrap gap-2">
<span class="badge"><i data-lucide="route" class="icon"></i> Orchestrated</span>
<span class="badge"><i data-lucide="file-check" class="icon"></i> Provenance</span>
<span class="badge"><i data-lucide="sliders" class="icon"></i> Budgeted</span>
</div>
</div>
<div class="flex flex-wrap gap-2 mb-6" role="tablist" aria-label="Architecture tabs">
<button class="tab active" data-tab="arch-system" role="tab" aria-selected="true">System</button>
<button class="tab" data-tab="arch-agents" role="tab" aria-selected="false">Agents & Artifacts</button>
<button class="tab" data-tab="arch-mac" role="tab" aria-selected="false">MAC Coordination</button>
<button class="tab" data-tab="arch-seq" role="tab" aria-selected="false">Sequence</button>
</div>
<div class="grid lg:grid-cols-5 gap-6">
<div class="lg:col-span-3">
<div class="card glass">
<div class="card-body">
<div id="arch-system" class="tabpanel">
<div class="flex items-center justify-between gap-4 mb-4">
<h3 class="text-xl font-extrabold tracking-tight">High-Level System Diagram</h3>
<span class="text-xs text-slate-400">Mermaid · interactive tab</span>
</div>
<pre class="mermaid text-sm">
flowchart LR
U["Clinician UI / EMR"] -->|q + patient context| ORCH["Orchestrator (MAC)\nplanning · policy checks · logging"]
ORCH --> QN["Query Normaliser"]
ORCH --> RET["Evidence Retriever"]
ORCH --> EMRS["EMR Summariser"]
ORCH --> GS["Guideline Synthesiser"]
ORCH --> SC["Safety Critic"]
subgraph IR["Two-Stage Retrieval (Budgeted)"]
DENSE["Stage 1: Dense ANN (MedEmbed)"] --> CAND["Candidates (dense OR BM25)"]
BM25["Stage 1: Lexical (BM25)"] --> CAND
CAND --> RER["Stage 2: Long-context Reranker\n(LoRA-adapted, calibrated)"]
RER --> SEL["Policy-aware selection\nMMR + sufficiency constraints"]
end
RET --> IR
SEL --> EVID["Evidence bundle M\nEMR + CPG + metadata"]
EMRS --> STATE["Clinical state summary"]
GS --> ACTIONS["Guideline actions + contraindications"]
SC --> FLAGS["Safety flags / missing evidence"]
EVID --> FUSE["Evidence-constrained synthesis"]
STATE --> FUSE
ACTIONS --> FUSE
FLAGS --> FUSE
FUSE --> OUT["Final answer + citations + cautions\n+ structured trace"]
</pre>
</div>
<div id="arch-agents" class="tabpanel hidden">
<div class="flex items-center justify-between gap-4 mb-4">
<h3 class="text-xl font-extrabold tracking-tight">Agents Exchange Typed Artifacts</h3>
<span class="text-xs text-slate-400">Selectable “focus” cards</span>
</div>
<div class="grid md:grid-cols-2 gap-4">
<button class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-left hover:border-indigo-400/40 transition focus:outline-none agentFocus" data-agent="Query Normaliser">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="spell-check" class="icon"></i> Query Normaliser</div>
<p class="text-sm text-slate-300 mt-2">Canonicalises terminology, expands abbreviations, generates retrieval probes.</p>
</button>
<button class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-left hover:border-indigo-400/40 transition focus:outline-none agentFocus" data-agent="Evidence Retriever">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="scan-search" class="icon"></i> Evidence Retriever</div>
<p class="text-sm text-slate-300 mt-2">Finds candidate EMR/CPG passages, returns ids, sections, scores, timestamps.</p>
</button>
<button class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-left hover:border-indigo-400/40 transition focus:outline-none agentFocus" data-agent="EMR Summariser">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="scan-text" class="icon"></i> EMR Summariser</div>
<p class="text-sm text-slate-300 mt-2">Compresses longitudinal records into a structured clinical state for reasoning.</p>
</button>
<button class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-left hover:border-indigo-400/40 transition focus:outline-none agentFocus" data-agent="Guideline Synthesiser">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="book-open-check" class="icon"></i> Guideline Synthesiser</div>
<p class="text-sm text-slate-300 mt-2">Extracts actionable steps + contraindications from guidelines with provenance.</p>
</button>
<button class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-left hover:border-indigo-400/40 transition focus:outline-none agentFocus md:col-span-2" data-agent="Safety Critic">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="shield-alert" class="icon"></i> Safety Critic</div>
<p class="text-sm text-slate-300 mt-2">Checks conflicts, missing evidence, unsafe recommendations; triggers retrieve-more actions.</p>
</button>
</div>
<div class="mt-5 rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center justify-between gap-3">
<div class="font-extrabold tracking-tight" id="artifactTitle">Artifact: EvidenceBundle</div>
<span class="badge"><i data-lucide="fingerprint" class="icon"></i> provenance</span>
</div>
<div class="codeblock mt-3">
<button class="copy-btn" data-copy="#artifactJson"><i data-lucide="copy" class="icon"></i> Copy</button>
<pre id="artifactJson"><code>{
"type": "EvidenceBundle",
"query": "clinical question + patient context",
"budget_tokens": 8192,
"selected": [
{"doc_id": "CPG:xyz", "section": "Recommendations", "timestamp": "YYYY-MM-DD", "chunk": [120, 420], "p_cal": 0.86},
{"doc_id": "EMR:abc", "section": "Meds/Labs", "timestamp": "YYYY-MM-DD", "chunk": [0, 260], "p_cal": 0.81}
],
"coverage": {"CPG": 1.0, "EMR": 1.0},
"trace_id": "trace_...",
"notes": ["deduped", "PII-scrubbed", "MMR-diversified"]
}</code></pre>
</div>
</div>
</div>
<div id="arch-mac" class="tabpanel hidden">
<div class="flex items-center justify-between gap-4 mb-4">
<h3 class="text-xl font-extrabold tracking-tight">MAC: Multi-Agent Coordination</h3>
<span class="text-xs text-slate-400">Parallel retrieval hypotheses</span>
</div>
<pre class="mermaid text-sm">
flowchart TB
Q["Query q + patient context"] --> O["MAC Orchestrator"]
subgraph A["Specialised Probes"]
E["Exploration Agent\n(recall-normalised)"]
P["Policy Agent\n(guideline coverage)"]
S["Safety Agent\n(contraindications)"]
end
O --> E
O --> P
O --> S
E --> CE["Candidate C_e + scores"]
P --> CP["Candidate C_p + scores"]
S --> CS["Candidate C_s + scores"]
CE --> U["Weighted union + re-rank\nω_i · S_i(q,d)"]
CP --> U
CS --> U
U --> M["Meta-bundle M_MAC\n(token budget B + sufficiency checks)"]
M --> OUT["Evidence for synthesis + critique"]
</pre>
<div class="mt-5 grid md:grid-cols-2 gap-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="activity" class="icon"></i> Why MAC helps</div>
<p class="text-sm text-slate-300 mt-2">
Instead of a single retrieval hypothesis, multiple agents explore different constraints and then fuse evidence,
preserving disagreements as inspectable signals.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center gap-2 font-extrabold"><i data-lucide="bar-chart-3" class="icon"></i> Agent weights</div>
<p class="text-sm text-slate-300 mt-2">
Agents accumulate track-record weights (e.g., sufficiency compliance) to influence future selection in a transparent way.
</p>
</div>
</div>
</div>
<div id="arch-seq" class="tabpanel hidden">
<div class="flex items-center justify-between gap-4 mb-4">
<h3 class="text-xl font-extrabold tracking-tight">Single-Turn Sequence</h3>
<span class="text-xs text-slate-400">Retrieval → policy checks → synthesis</span>
</div>
<pre class="mermaid text-sm">
sequenceDiagram
autonumber
participant C as Clinician
participant O as Orchestrator (MAC)
participant QN as Query Normaliser
participant IR as Two-stage Retrieval
participant EMR as EMR Summariser
participant GL as Guideline Synthesiser
participant SC as Safety Critic
participant L as LLM (Distilled 7B)
C->>O: query + patient context
O->>QN: normalise + expand probes
QN-->>O: canonical query
O->>IR: retrieve candidates + rerank
IR-->>O: evidence bundle M + p_cal + provenance
O->>EMR: build clinical state summary
O->>GL: extract actions + contraindications
O->>SC: check evidence sufficiency + safety
alt Insufficient evidence
SC-->>O: retrieve-more / clarify request
O-->>C: request clarification / expand search
else Sufficient evidence
SC-->>O: ok + cautions
O->>L: synthesize answer with citations
L-->>C: answer + citations + trace
end
</pre>
</div>
</div>
</div>
</div>
<!-- Right panel: interactive budget simulator -->
<aside class="lg:col-span-2">
<div class="card glass" data-aos="fade-up">
<div class="card-body">
<div class="flex items-start justify-between gap-4">
<div>
<h3 class="text-xl font-extrabold tracking-tight">Evidence Budget Simulator</h3>
<p class="text-sm text-slate-400 mt-1">
Illustrative UI to explain budgeted selection + sufficiency thresholds.
</p>
</div>
<span class="badge"><i data-lucide="sliders" class="icon"></i> interactive</span>
</div>
<div class="mt-5">
<label class="text-sm font-bold">Token budget (B)</label>
<input id="budgetSlider" type="range" min="2048" max="16384" step="512" value="8192"
class="w-full mt-2 accent-indigo-400" />
<div class="mt-2 flex items-center justify-between text-sm text-slate-300">
<span>2048</span>
<span class="font-extrabold text-slate-100" id="budgetValue">8192</span>
<span>16384</span>
</div>
</div>
<div class="mt-5 grid grid-cols-3 gap-3">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-center">
<div class="text-2xl font-extrabold" id="passagesCount">8</div>
<div class="text-xs text-slate-400">passages</div>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-center">
<div class="text-2xl font-extrabold" id="cpgCoverage">1.0</div>
<div class="text-xs text-slate-400">CPG κ</div>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4 text-center">
<div class="text-2xl font-extrabold" id="emrCoverage">1.0</div>
<div class="text-xs text-slate-400">EMR κ</div>
</div>
</div>
<div class="mt-5 rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="flex items-center justify-between">
<div class="font-extrabold tracking-tight">Policy status</div>
<span class="badge" id="policyBadge"><i data-lucide="check-circle" class="icon"></i> Accepted</span>
</div>
<p class="text-sm text-slate-300 mt-2" id="policyText">
Evidence sufficiency met → synthesis allowed.
</p>
</div>
<div class="mt-5 text-xs text-slate-400">
Note: values are explanatory placeholders; the paper defines κ and sufficiency acceptance logic conceptually.
</div>
</div>
</div>
<!-- Safety banner -->
<div class="mt-6 rounded-3xl border border-amber-400/25 bg-amber-400/10 p-5" data-aos="fade-up" data-aos-delay="120">
<div class="flex items-start gap-3">
<i data-lucide="alert-triangle" class="icon text-amber-200 mt-0.5"></i>
<div>
<div class="font-extrabold">Safety Notice</div>
<p class="text-sm text-slate-200/90 mt-1">
MedSwin is for research and education. It must not be used as a stand-alone medical decision maker.
Always involve qualified clinicians and local governance when trialing clinical AI.
</p>
</div>
</div>
</div>
</aside>
</div>
</div>
</section>
<!-- Retrieval -->
<section id="retrieval" class="section">
<div class="container">
<div class="grid lg:grid-cols-5 gap-8 items-start">
<div class="lg:col-span-3" data-aos="fade-up">
<h2 class="text-3xl lg:text-4xl font-extrabold tracking-tight">
Two-Stage Retrieval & Calibrated Reranking
</h2>
<p class="mt-4 text-slate-300 leading-relaxed">
Evidence selection is separated into recall-oriented candidate generation and precision-oriented reranking.
This avoids early truncation while enabling deterministic, policy-aware inclusion decisions.
</p>
<div class="mt-6 space-y-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="scan-search" class="icon"></i> Stage 1 — Candidate generation
</div>
<p class="text-sm text-slate-300 mt-2">
Dense ANN retrieval is unioned with BM25 to preserve rare clinical terms, abbreviations, and lab-specific phrasing.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="badge-check" class="icon"></i> Stage 2 — Long-context reranking
</div>
<p class="text-sm text-slate-300 mt-2">
A biomedical LLM reranker scores each passage and outputs calibrated probabilities usable as policy thresholds.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="sliders" class="icon"></i> Policy-aware selection
</div>
<p class="text-sm text-slate-300 mt-2">
Final selection enforces EMR + guideline sufficiency, diversity (MMR-style), and a strict token budget.
</p>
</div>
</div>
</div>
<!-- Right: sufficiency gate -->
<aside class="lg:col-span-2 rounded-3xl border border-white/10 bg-slate-950/40 p-6" data-aos="fade-up">
<div class="font-extrabold text-lg tracking-tight mb-3">Evidence acceptance gate</div>
<ul class="space-y-3 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="book-open-check" class="icon"></i> Required guideline recommendations present</li>
<li class="flex gap-2"><i data-lucide="file-heart" class="icon"></i> Patient-specific EMR signals included</li>
<li class="flex gap-2"><i data-lucide="layers" class="icon"></i> Redundancy reduced under budget</li>
<li class="flex gap-2"><i data-lucide="shield-alert" class="icon"></i> Safety critic approves synthesis</li>
</ul>
</aside>
</div>
</div>
</section>
<!-- Section spacer -->
<div class="h-20 lg:h-28"></div>
<!-- Training -->
<section id="training" class="section">
<div class="container">
<div class="grid lg:grid-cols-5 gap-8 items-start">
<div class="lg:col-span-3" data-aos="fade-up">
<h2 class="text-3xl lg:text-4xl font-extrabold tracking-tight">
Data, Training & Distillation
</h2>
<p class="mt-4 text-slate-300 leading-relaxed">
MedSwin’s deployable 7B model is trained for reliability rather than raw scale,
combining large-scale augmentation, supervised fine-tuning, and knowledge distillation.
</p>
<div class="mt-6 space-y-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold">A · Data augmentation</div>
<p class="text-sm text-slate-300 mt-2">
Paraphrasing, formatting variants, deduplication, and medical consistency checks expand coverage without semantic drift.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold">B · Supervised fine-tuning</div>
<p class="text-sm text-slate-300 mt-2">
Aligns the student to clinical instruction style, tone control, and structured answers.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold">C · Knowledge distillation</div>
<p class="text-sm text-slate-300 mt-2">
Hard labels expand task coverage; soft labels preserve calibration and uncertainty from a larger instructor.
</p>
</div>
</div>
</div>
<!-- Right: why KD -->
<aside class="lg:col-span-2 rounded-3xl border border-white/10 bg-slate-950/40 p-6" data-aos="fade-up">
<div class="font-extrabold text-lg tracking-tight mb-3">Why distillation?</div>
<ul class="space-y-3 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="cpu" class="icon"></i> Enables local inference on modest GPUs</li>
<li class="flex gap-2"><i data-lucide="shield-check" class="icon"></i> Preserves calibrated reasoning behaviour</li>
<li class="flex gap-2"><i data-lucide="settings" class="icon"></i> PEFT-friendly (LoRA / QLoRA)</li>
<li class="flex gap-2"><i data-lucide="lock" class="icon"></i> Institution-controlled deployment</li>
</ul>
</aside>
</div>
</div>
</section>
<!-- Section spacer -->
<div class="h-20 lg:h-28"></div>
<!-- Evaluation -->
<section id="evaluation" class="section">
<div class="container">
<div class="grid lg:grid-cols-5 gap-8 items-start">
<div class="lg:col-span-3" data-aos="fade-up">
<h2 class="text-3xl lg:text-4xl font-extrabold tracking-tight">
Evaluation & Safety
</h2>
<p class="mt-4 text-slate-300 leading-relaxed">
MedSwin evaluates clinical QA systems beyond answer accuracy, focusing on evidence quality,
guideline compliance, and runtime safety behaviour.
</p>
<div class="mt-6 grid sm:grid-cols-3 gap-4">
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="search" class="icon"></i> Retrieval quality
</div>
<p class="text-sm text-slate-300 mt-2">
Evidence relevance and coverage under a fixed token budget.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="book-open-check" class="icon"></i> Guideline coverage
</div>
<p class="text-sm text-slate-300 mt-2">
Presence of actionable recommendations and contraindications.
</p>
</div>
<div class="rounded-2xl border border-white/10 bg-slate-950/40 p-4">
<div class="font-extrabold inline-flex items-center gap-2">
<i data-lucide="check-check" class="icon"></i> Faithfulness
</div>
<p class="text-sm text-slate-300 mt-2">
Final answers remain grounded in cited evidence only.
</p>
</div>
</div>
</div>
<!-- Right: safety behaviour -->
<aside class="lg:col-span-2 rounded-3xl border border-white/10 bg-slate-950/40 p-6" data-aos="fade-up">
<div class="font-extrabold text-lg tracking-tight mb-3">Runtime safety behaviour</div>
<ul class="space-y-3 text-sm text-slate-300">
<li class="flex gap-2"><i data-lucide="help-circle" class="icon"></i> Clarifies when evidence is missing</li>
<li class="flex gap-2"><i data-lucide="quote" class="icon"></i> Enforces citation-required answers</li>
<li class="flex gap-2"><i data-lucide="shield-alert" class="icon"></i> Safety critic checks contraindications</li>
<li class="flex gap-2"><i data-lucide="users" class="icon"></i> Designed for human-in-the-loop use</li>
</ul>
</aside>
</div>
</div>
</section>
<!-- Team -->
<section id="team" class="section">
<div class="container">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-6 mb-10" data-aos="fade-up">
<div>
<h2 class="text-3xl lg:text-4xl font-extrabold tracking-tight">Team</h2>
<p class="mt-3 text-slate-300 max-w-3xl">
A multidisciplinary research team building an auditable medical AI system.
</p>
</div>
<div class="flex flex-wrap gap-2">
<span class="badge"><i data-lucide="graduation-cap" class="icon"></i> Swinburne</span>
<span class="badge"><i data-lucide="users" class="icon"></i> Multi-role</span>
</div>
</div>
<div class="grid md:grid-cols-2 lg:grid-cols-5 gap-4">
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5 text-center" data-aos="zoom-in" data-aos-delay="0">
<div class="text-3xl">🎖️</div>
<div class="mt-2 font-extrabold">Liam</div>
<div class="text-xs text-slate-400">Leader</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5 text-center" data-aos="zoom-in" data-aos-delay="120">
<div class="text-3xl">🧪</div>
<div class="mt-2 font-extrabold">Henry</div>
<div class="text-xs text-slate-400">LLM</div>
</div>
<div class="rounded-3xl border border-white/10 bg-slate-950/40 p-5 text-center" data-aos="zoom-in" data-aos-delay="240">
<div class="text-3xl">🔗</div>
<div class="mt-2 font-extrabold">Hai</div>
<div class="text-xs text-slate-400">System</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="py-12 border-t border-white/10 text-center text-slate-400">
<div class="container">
<div class="flex flex-wrap justify-center gap-4 mb-4">
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/MedSwin"><i data-lucide="box" class="icon"></i> HF Org</a>
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://github.com/MedSwin/RAG"><i data-lucide="app-window" class="icon"></i> RAG Repo</a>
<a class="chip" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/spaces/MedSwin/Augmentation"><i data-lucide="filter" class="icon"></i> Data Processing</a>
</div>
<div class="text-xs max-w-3xl mx-auto">
© 2025 Swinburne University · MedSwin. Research & educational use only.
This system does not provide medical advice. For medical concerns, consult qualified professionals.
</div>
<div class="mt-4 text-xs text-slate-500">
Tip: Press <span class="kbd">/</span> to open the quick command palette.
</div>
</div>
</footer>
</main>
<!-- Toast -->
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<!-- Modal (generic) -->
<div id="modal" class="fixed inset-0 z-[90] hidden" aria-hidden="true">
<div class="absolute inset-0 bg-black/60"></div>
<div class="absolute inset-0 flex items-center justify-center p-4">
<div class="w-full max-w-2xl rounded-3xl border border-white/10 bg-slate-950/80 backdrop-blur shadow-glow">
<div class="p-5 border-b border-white/10 flex items-center justify-between gap-4">
<div>
<div id="modalTitle" class="font-extrabold text-lg">Modal</div>
<div id="modalSubtitle" class="text-sm text-slate-400"></div>
</div>
<button id="modalClose" class="btn-icon" aria-label="Close modal" type="button">
<i data-lucide="x" class="icon"></i>
</button>
</div>
<div class="p-5">
<div id="modalBody" class="text-slate-200 text-sm leading-relaxed"></div>
<div class="mt-5 flex flex-wrap justify-end gap-2">
<button id="modalOk" class="btn btn-primary" type="button"><i data-lucide="check" class="icon"></i> OK</button>
</div>
</div>
</div>
</div>
</div>
<!-- Command palette -->
<div id="cmd" class="fixed inset-0 z-[95] hidden" aria-hidden="true">
<div class="absolute inset-0 bg-black/60"></div>
<div class="absolute inset-0 flex items-start justify-center p-4 pt-20">
<div class="w-full max-w-xl rounded-3xl border border-white/10 bg-slate-950/80 backdrop-blur shadow-glow overflow-hidden">
<div class="p-4 border-b border-white/10 flex items-center gap-3">
<i data-lucide="command" class="icon"></i>
<input id="cmdInput" class="w-full bg-transparent outline-none text-slate-100 placeholder:text-slate-500"
placeholder="Type a command… (e.g., 'architecture', 'retrieval', 'demo')" />
<span class="kbd">Esc</span>
</div>
<div id="cmdList" class="p-2 max-h-[50vh] overflow-auto"></div>
</div>
</div>
</div>
<!-- Optional external script -->
<!-- <script src="assets/app.js"></script> -->
<script>
// ---------- Helpers ----------
const $ = (sel, root = document) => root.querySelector(sel);
const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));
const MERMAID_SRC = new WeakMap();
function cacheMermaidSources() {
document.querySelectorAll('.mermaid').forEach(el => {
if (!MERMAID_SRC.has(el)) {
MERMAID_SRC.set(el, (el.textContent || '').trim());
}
});
}
// Cache mermaid src (before any render)
window.addEventListener('DOMContentLoaded', cacheMermaidSources);
function showToast(msg) {
const t = $('#toast');
if (!t) return;
t.textContent = msg;
t.style.display = 'block';
clearTimeout(showToast._to);
showToast._to = setTimeout(() => (t.style.display = 'none'), 1800);
}
function openModal({ title, subtitle, body }) {
const modal = $('#modal');
modal.classList.remove('hidden');
modal.setAttribute('aria-hidden', 'false');
$('#modalTitle').textContent = title || 'Modal';
$('#modalSubtitle').textContent = subtitle || '';
$('#modalBody').innerHTML = body || '';
}
function closeModal() {
const modal = $('#modal');
modal.classList.add('hidden');
modal.setAttribute('aria-hidden', 'true');
}
function openCmd() {
const cmd = $('#cmd');
cmd.classList.remove('hidden');
cmd.setAttribute('aria-hidden', 'false');
$('#cmdInput').value = '';
$('#cmdInput').focus();
renderCmdList('');
}
function closeCmd() {
const cmd = $('#cmd');
cmd.classList.add('hidden');
cmd.setAttribute('aria-hidden', 'true');
}
const COMMANDS = [
{ label: 'RAG repo', hint: 'Launch live HuggingFace Space', action: () => window.open('https://github.com/MedSwin/RAG', '_blank') },
{ label: 'Go to architecture', hint: 'Jump to architecture explorer', action: () => location.hash = '#architecture' },
{ label: 'Go to retrieval', hint: 'Jump to two-stage retrieval', action: () => location.hash = '#retrieval' },
{ label: 'Go to training', hint: 'Jump to distillation pipeline', action: () => location.hash = '#training' },
{ label: 'Open safety note', hint: 'Modal with safety principles', action: () => $('#openSafety').click() },
{ label: 'Open glossary', hint: 'Modal with key terms', action: () => $('#openGlossary').click() },
{ label: 'Open paper', hint: 'Modal with paper summary', action: () => $('#paperBtn').click() },
];
function renderCmdList(q) {
const list = $('#cmdList');
const query = (q || '').trim().toLowerCase();
const filtered = COMMANDS.filter(c => (c.label + ' ' + c.hint).toLowerCase().includes(query));
list.innerHTML = filtered.map((c, idx) => `
<button class="w-full text-left px-3 py-3 rounded-2xl hover:bg-white/5 border border-transparent hover:border-white/10 transition cmdItem" data-idx="${idx}">
<div class="font-extrabold">${c.label}</div>
<div class="text-xs text-slate-400 mt-1">${c.hint}</div>
</button>
`).join('');
$$('.cmdItem', list).forEach(btn => {
btn.addEventListener('click', () => {
const cmd = filtered[Number(btn.dataset.idx)];
closeCmd();
cmd?.action?.();
});
});
}
// ---------- Mermaid ----------
let _mermaidRendering = false;
async function renderMermaid() {
if (!window.mermaid) return;
if (_mermaidRendering) return;
_mermaidRendering = true;
try {
const isDark = document.documentElement.classList.contains('dark');
mermaid.initialize({
startOnLoad: false,
theme: isDark ? 'dark' : 'default',
securityLevel: 'loose',
fontFamily: 'Inter, ui-sans-serif, system-ui',
flowchart: { useMaxWidth: true, htmlLabels: true }
});
const blocks = document.querySelectorAll('.mermaid');
let idx = 0;
for (const el of blocks) {
const code = (MERMAID_SRC.get(el) || '').trim();
if (!code) continue;
const id = `mmd-${idx++}-${Date.now()}`;
try {
const { svg, bindFunctions } = await mermaid.render(id, code);
el.innerHTML = svg;
if (typeof bindFunctions === 'function') bindFunctions(el);
} catch (err) {
console.error('Mermaid render error:', err, code);
const safe = String(err).replace(/</g, '&lt;').replace(/>/g, '&gt;');
el.innerHTML = `<div class="text-red-300 text-sm">Mermaid render failed: ${safe}</div>`;
}
}
} finally {
_mermaidRendering = false;
}
}
// ---------- KaTeX ----------
function renderMath() {
if (!window.renderMathInElement) return;
renderMathInElement(document.body, {
delimiters: [
{ left: "$$", right: "$$", display: true },
{ left: "\\(", right: "\\)", display: false }
],
throwOnError: false
});
}
// ---------- Tabs ----------
function initTabs() {
$$('.tab').forEach(btn => {
btn.addEventListener('click', () => {
const group = btn.closest('[role="tablist"]') || btn.parentElement;
const tabId = btn.dataset.tab;
$$('.tab', group).forEach(t => t.classList.remove('active'));
btn.classList.add('active');
const root = group.closest('.card-body') || document;
$$('.tabpanel', root).forEach(p => p.classList.add('hidden'));
const panel = document.getElementById(tabId);
if (panel) panel.classList.remove('hidden');
requestAnimationFrame(() => { renderMermaid(); });
});
});
}
// ---------- Accordion ----------
function initAccordion() {
$$('.accordion-item').forEach(item => {
const btn = $('.accordion-btn', item);
btn?.addEventListener('click', () => {
item.classList.toggle('open');
});
});
}
// ---------- Copy buttons ----------
function initCopy() {
$$('.copy-btn').forEach(btn => {
btn.addEventListener('click', async () => {
const sel = btn.getAttribute('data-copy');
const el = $(sel);
const txt = el ? el.textContent : '';
try {
await navigator.clipboard.writeText(txt.trim());
showToast('Copied');
} catch {
showToast('Copy failed');
}
});
});
}
// ---------- Counters ----------
function initCounters() {
const counters = $$('.metric-value');
if (!('IntersectionObserver' in window)) return;
const io = new IntersectionObserver(entries => {
entries.forEach(e => {
if (!e.isIntersecting) return;
const el = e.target;
io.unobserve(el);
const end = Number(el.getAttribute('data-count')) || 0;
const duration = 900;
const start = 0;
const t0 = performance.now();
function tick(t) {
const p = Math.min(1, (t - t0) / duration);
const v = Math.floor(start + (end - start) * (1 - Math.pow(1 - p, 3)));
el.textContent = v.toLocaleString();
if (p < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
});
}, { threshold: 0.35 });
counters.forEach(c => io.observe(c));
}
// ---------- Theme ----------
function setThemeIcon() {
const isDark = document.documentElement.classList.contains('dark');
const icon = $('#themeToggle i');
if (!icon) return;
icon.setAttribute('data-lucide', isDark ? 'sun-medium' : 'moon');
if (window.lucide) lucide.createIcons();
}
function initTheme() {
const saved = localStorage.getItem('theme');
if (saved === 'light') document.documentElement.classList.remove('dark');
if (saved === 'dark') document.documentElement.classList.add('dark');
setThemeIcon();
$('#themeToggle')?.addEventListener('click', () => {
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
setThemeIcon();
renderMermaid();
});
}
// ---------- Scroll progress + scrollspy ----------
function initScrollUI() {
const pb = $('#progressBar');
const sections = ['overview','contributions','architecture','retrieval','training','evaluation','opensource','team']
.map(id => ({ id, el: document.getElementById(id) }))
.filter(x => x.el);
function onScroll() {
const h = document.documentElement;
const sc = h.scrollTop || document.body.scrollTop;
const max = (h.scrollHeight - h.clientHeight) || 1;
const pct = Math.min(1, sc / max);
if (pb) pb.style.width = (pct * 100).toFixed(2) + '%';
// scrollspy
const y = window.scrollY + 120;
let active = sections[0]?.id;
for (const s of sections) {
if (s.el.offsetTop <= y) active = s.id;
}
$$('.navlink').forEach(a => {
const key = a.getAttribute('data-spy');
if (!key) return;
a.classList.toggle('text-indigo-300', key === active);
a.classList.toggle('font-extrabold', key === active);
});
}
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
}
// ---------- Budget simulator (illustrative) ----------
function initBudgetSimulator() {
const slider = $('#budgetSlider');
if (!slider) return;
const out = $('#budgetValue');
const passages = $('#passagesCount');
const cpg = $('#cpgCoverage');
const emr = $('#emrCoverage');
const badge = $('#policyBadge');
const text = $('#policyText');
const compute = (B) => {
// Simple explanatory mapping: more budget -> more passages & safer coverage
const p = Math.max(4, Math.min(14, Math.round(B / 1024)));
const cpgK = Math.min(1.0, 0.65 + (B - 2048) / (16384 - 2048) * 0.45);
const emrK = Math.min(1.0, 0.62 + (B - 2048) / (16384 - 2048) * 0.48);
const accepted = cpgK >= 0.95 && emrK >= 0.95 && B >= 6144;
return { p, cpgK, emrK, accepted };
};
function render() {
const B = Number(slider.value);
const r = compute(B);
out.textContent = B.toLocaleString();
passages.textContent = r.p;
cpg.textContent = r.cpgK.toFixed(2);
emr.textContent = r.emrK.toFixed(2);
if (r.accepted) {
badge.innerHTML = '<i data-lucide="check-circle" class="icon"></i> Accepted';
badge.className = 'badge';
text.textContent = 'Evidence sufficiency met → synthesis allowed.';
} else {
badge.innerHTML = '<i data-lucide="alert-circle" class="icon"></i> Retrieve-more';
badge.className = 'badge';
text.textContent = 'Sufficiency not met → expand retrieval or request clarification before answering.';
}
if (window.lucide) lucide.createIcons();
}
slider.addEventListener('input', render);
render();
}
// ---------- Mobile menu ----------
function initMobileMenu() {
$('#mobileMenuBtn')?.addEventListener('click', () => {
$('#mobileMenu')?.classList.toggle('hidden');
});
$$('#mobileMenu a').forEach(a => a.addEventListener('click', () => $('#mobileMenu')?.classList.add('hidden')));
}
// ---------- Modals content ----------
function initModals() {
$('#modalClose')?.addEventListener('click', closeModal);
$('#modalOk')?.addEventListener('click', closeModal);
$('#modal')?.addEventListener('click', (e) => {
if (e.target === $('#modal').firstElementChild) closeModal();
});
$('#paperBtn')?.addEventListener('click', () => openModal({
title: 'Paper (MedSwin)',
subtitle: 'Summary of the system explanation',
body: `
<div class="space-y-3">
<p><b>MedSwin</b> is a multi-agent biomedical QA architecture grounded in EMR and clinical practice guidelines.</p>
<ul class="list-disc pl-5 space-y-2">
<li><b>Auditable orchestration</b>: specialised agents exchange typed artifacts with explicit provenance.</li>
<li><b>Two-stage retrieval</b>: hybrid candidate generation + long-context biomedical reranker with calibrated probabilities.</li>
<li><b>Deployable LLM</b>: a compact 7B model trained via SFT + KD using PEFT.</li>
<li><b>MAC coordination</b>: multiple retrieval hypotheses are fused under a shared token budget and policy constraints.</li>
</ul>
<p class="text-slate-300 text-xs">Use this website section structure to present the paper content clearly to staff and evaluators.</p>
</div>
`
}));
$('#openGlossary')?.addEventListener('click', () => openModal({
title: 'Glossary',
subtitle: 'Key MedSwin terms used on this page',
body: `
<div class="space-y-3">
<div><b>Evidence bundle (M)</b>: the selected set of EMR/CPG passages under a token budget.</div>
<div><b>Token budget (B)</b>: maximum context size used for evidence selection + synthesis.</div>
<div><b>Calibrated probability</b>: reranker output transformed for threshold-based inclusion policies.</div>
<div><b>Evidence sufficiency</b>: acceptance gate requiring adequate EMR and guideline coverage.</div>
<div><b>MAC</b>: multi-agent coordination that fuses multiple retrieval hypotheses.</div>
</div>
`
}));
$('#openSafety')?.addEventListener('click', () => openModal({
title: 'Safety Principles',
subtitle: 'How MedSwin reduces unsafe behaviour',
body: `
<div class="space-y-3">
<p>MedSwin prioritises <b>evidence sufficiency</b> and <b>auditability</b> over fluent answers.</p>
<ul class="list-disc pl-5 space-y-2">
<li>Refuses or asks clarification when evidence is insufficient.</li>
<li>Pairs outputs with citations and provenance fields (doc ids, sections, timestamps).</li>
<li>Runs a safety critique step for contraindications and missing evidence.</li>
<li>Encourages human-in-the-loop oversight for real deployments.</li>
</ul>
</div>
`
}));
$('#openContact')?.addEventListener('click', () => openModal({
title: 'Contact',
subtitle: 'Project links',
body: `
<div class="space-y-3">
<p>Use the quick links below:</p>
<ul class="list-disc pl-5 space-y-2">
<li><a class="underline" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/MedSwin">HuggingFace Org</a></li>
<li><a class="underline" target="_blank" rel="noopener noreferrer" href="https://github.com/MedSwin/RAG">RAG Repo</a></li>
<li><a class="underline" target="_blank" rel="noopener noreferrer" href="https://huggingface.co/spaces/MedSwin/Augmentation">Data Processing</a></li>
</ul>
</div>
`
}));
$('#openQuickTour')?.addEventListener('click', () => openModal({
title: 'Quick Tour',
subtitle: 'How to read this page',
body: `
<ol class="list-decimal pl-5 space-y-2">
<li>Start at <b>Contributions</b> to understand what’s unique about MedSwin.</li>
<li>Use the <b>Architecture Explorer</b> tabs to see system layers.</li>
<li>Open <b>Two-Stage Retrieval</b> accordions to learn how evidence is selected under budget.</li>
<li>Review <b>Training</b> to see SFT + KD producing a deployable 7B model.</li>
<li>Finish at <b>Evaluation & Safety</b> to understand what is measured and how risks are reduced.</li>
</ol>
`
}));
}
// ---------- Agent focus updates ----------
function initAgentFocus() {
$$('.agentFocus').forEach(btn => {
btn.addEventListener('click', () => {
const a = btn.getAttribute('data-agent') || 'Agent';
$('#artifactTitle').textContent = `Artifact: ${a} Output`;
showToast(`${a} selected`);
});
});
}
// ---------- Command palette hotkeys ----------
function initCmd() {
$('#cmdInput')?.addEventListener('input', (e) => renderCmdList(e.target.value));
$('#cmd')?.addEventListener('click', (e) => { if (e.target === $('#cmd').firstElementChild) closeCmd(); });
window.addEventListener('keydown', (e) => {
if (e.key === '/' && !/input|textarea/i.test(document.activeElement?.tagName || '')) {
e.preventDefault();
openCmd();
}
if (e.key === 'Escape') {
closeCmd();
closeModal();
}
});
}
// ---------- GSAP polish ----------
function initGSAP() {
if (!window.gsap || !window.ScrollTrigger) return;
gsap.registerPlugin(ScrollTrigger);
gsap.from('h1', { y: 14, opacity: 0, duration: 0.8, ease: 'power3.out' });
$$('.card').forEach((card) => {
gsap.from(card, {
scrollTrigger: { trigger: card, start: 'top 85%', toggleActions: 'play none none none' },
y: 18, opacity: 0, duration: 0.55, ease: 'power2.out'
});
});
}
// ---------- Init on load ----------
window.addEventListener('load', () => {
if (window.AOS) AOS.init({ duration: 700, once: true, offset: 90, easing: 'ease-in-out' });
if (window.lucide) lucide.createIcons();
if (window.VanillaTilt) VanillaTilt.init(document.querySelectorAll("[data-tilt]"), { glare: true, "max-glare": 0.15 });
initTheme();
initMobileMenu();
initTabs();
initAccordion();
initCopy();
initCounters();
initScrollUI();
initBudgetSimulator();
initModals();
initAgentFocus();
initCmd();
// Render math + mermaid after libs load
setTimeout(() => {
renderMath();
renderMermaid();
}, 0);
initGSAP();
});
</script>
</body>
</html>