Spaces:
Sleeping
Sleeping
| <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 ; } | |
| .animate-floaty, .animate-shimmer, .animate-pulseSoft { animation: none ; } | |
| } | |
| </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, '<').replace(/>/g, '>'); | |
| 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> |