docmind / docs /013-docmind.html
mnoorchenar's picture
Update 2026-03-22 23:13:27
3b39b3c
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>DocMind β€” Agentic Document Intelligence Β· Mohammad Noorchenarboo</title>
<script>document.documentElement.setAttribute('data-theme',localStorage.getItem('mn-theme')||'dark')</script>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%234f8ef7'/%3E%3Cstop offset='100%25' stop-color='%2306b6d4'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='64' height='64' rx='14' fill='%23070d1f'/%3E%3Ctext x='50%25' y='50%25' dominant-baseline='central' text-anchor='middle' font-family='Segoe UI,system-ui,sans-serif' font-weight='900' font-size='26' fill='url(%23g)'%3EMN%3C/text%3E%3C/svg%3E">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="../shared.css">
<script src="../shared.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.min.js"></script>
<style>
:root{--accent:#4f8ef7;--gold:#f59e0b;--teal:#06b6d4;--green:#22c55e;--radius:14px;--body-bg:#070d1f;--text:#e2e8f0;--muted:#8892a4;--glass:rgba(255,255,255,.04);--glass-border:rgba(255,255,255,.08);--card-hover-bg:rgba(255,255,255,.07);--card-hover-border:rgba(79,142,247,.3);--section-alt:#0b1120}
[data-theme="light"]{--body-bg:#f8fafc;--text:#0f172a;--muted:#4b5675;--glass:rgba(0,0,0,.03);--glass-border:rgba(0,0,0,.08);--card-hover-bg:rgba(0,0,0,.05);--card-hover-border:rgba(37,99,235,.25);--section-alt:#f1f5f9}
*{box-sizing:border-box;margin:0;padding:0} body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--body-bg);color:var(--text);transition:background .35s,color .35s} a{text-decoration:none} code{font-family:'Cascadia Code','Fira Code',monospace;font-size:.88em;background:rgba(79,142,247,.1);padding:1px 5px;border-radius:4px}
.s-tag{display:inline-block;font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em;padding:3px 10px;border-radius:6px;margin-bottom:10px}
.s-tag-blue{background:rgba(79,142,247,.12);color:var(--accent);border:1px solid rgba(79,142,247,.2)}
.s-tag-gold{background:rgba(245,158,11,.12);color:var(--gold);border:1px solid rgba(245,158,11,.2)}
.s-tag-teal{background:rgba(6,182,212,.12);color:var(--teal);border:1px solid rgba(6,182,212,.2)}
.grad-text{background:linear-gradient(135deg,var(--accent),var(--gold));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.hero{padding:124px 24px 56px;background:var(--body-bg);position:relative;overflow:hidden;transition:background .35s}
.hero::before{content:'';position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse 80% 55% at 50% -10%,rgba(79,142,247,.15) 0%,transparent 65%)}
.hero::after{content:'';position:absolute;inset:0;pointer-events:none;background-image:linear-gradient(rgba(79,142,247,.035) 1px,transparent 1px),linear-gradient(90deg,rgba(79,142,247,.035) 1px,transparent 1px);background-size:48px 48px}
.hero-inner{max-width:1100px;margin:0 auto;position:relative;z-index:1}
.breadcrumb{font-size:.78rem;color:var(--muted);margin-bottom:18px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.breadcrumb a{color:var(--muted);transition:.2s} .breadcrumb a:hover{color:var(--accent)} .breadcrumb span{opacity:.4}
.tag-row{display:flex;align-items:center;gap:10px;margin-bottom:18px;flex-wrap:wrap}
.pill{display:inline-flex;align-items:center;gap:6px;padding:5px 14px;border-radius:20px;font-size:.75rem;font-weight:700;letter-spacing:.04em}
.pill-blue{background:rgba(79,142,247,.12);border:1px solid rgba(79,142,247,.25);color:var(--accent)}
.pill-gold{background:rgba(245,158,11,.12);border:1px solid rgba(245,158,11,.25);color:var(--gold)}
.pill-teal{background:rgba(6,182,212,.12);border:1px solid rgba(6,182,212,.25);color:var(--teal)}
h1{font-size:clamp(1.7rem,3.5vw,2.7rem);font-weight:900;line-height:1.2;margin-bottom:20px;max-width:820px;color:var(--text)}
.hero-sub{font-size:1rem;color:var(--muted);max-width:680px;margin-bottom:28px;line-height:1.65} .hero-sub strong{color:var(--text)}
.hero-meta{display:flex;gap:16px;flex-wrap:wrap;align-items:center;margin-bottom:24px;font-size:.83rem;color:var(--muted)}
.hero-meta span{display:flex;align-items:center;gap:6px} .hero-meta i{color:var(--accent)}
.hero-actions{display:flex;gap:10px;flex-wrap:wrap}
.btn{display:inline-flex;align-items:center;gap:8px;padding:9px 20px;border-radius:8px;font-size:.85rem;font-weight:600;cursor:pointer;border:1px solid transparent;transition:all .2s;font-family:inherit;text-decoration:none}
.btn-blue{background:rgba(79,142,247,.18);color:var(--accent);border-color:rgba(79,142,247,.35)} .btn-blue:hover{background:rgba(79,142,247,.3);transform:translateY(-2px)}
.btn-gold{background:rgba(245,158,11,.15);color:var(--gold);border-color:rgba(245,158,11,.35)} .btn-gold:hover{background:rgba(245,158,11,.28);transform:translateY(-2px)}
[data-theme="light"] .btn-gold { background: rgba(180,83,9,.1); border-color: rgba(180,83,9,.35); color: #92400e; }
.btn-gray{background:var(--glass);color:var(--text);border-color:var(--glass-border)} .btn-gray:hover{background:var(--card-hover-bg);transform:translateY(-2px)}
[data-theme="dark"] .btn-gray { color: #cbd5e1; border-color: rgba(148,163,184,.3); }
.btn-back{background:var(--glass);color:var(--muted);border-color:var(--glass-border)} .btn-back:hover{color:var(--accent);border-color:var(--card-hover-border);transform:translateY(-2px)}
.stats-bar{background:var(--section-alt);border-top:1px solid var(--glass-border);border-bottom:1px solid var(--glass-border);transition:background .35s}
.stats-inner{max-width:1100px;margin:0 auto;display:grid;grid-template-columns:repeat(5,1fr);gap:1px;background:var(--glass-border)}
.stat-item{background:var(--section-alt);padding:22px 16px;text-align:center;transition:background .35s}
.stat-val{font-size:1.8rem;font-weight:900;background:linear-gradient(135deg,var(--accent),var(--gold));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;line-height:1.1;margin-bottom:4px}
.stat-label{font-size:.75rem;color:var(--muted);line-height:1.4}
.main-layout{max-width:1100px;margin:0 auto;padding:48px 24px;display:grid;grid-template-columns:1fr 310px;gap:32px;align-items:start}
.content-col{display:flex;flex-direction:column;gap:28px} .sidebar{position:sticky;top:136px;display:flex;flex-direction:column;gap:20px}
.card{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);padding:28px;transition:all .25s}
.card:hover{background:var(--card-hover-bg);border-color:var(--card-hover-border);transform:translateY(-3px)}
.card-title{font-size:1rem;font-weight:800;margin-bottom:18px;color:var(--text);display:flex;align-items:center;gap:10px} .card-title i{color:var(--accent);font-size:.9rem}
.narrative{font-size:.92rem;color:var(--muted);margin-bottom:10px;line-height:1.7} .narrative strong{color:var(--text)}
.pipeline{display:flex;align-items:stretch;gap:0;margin:20px 0;overflow-x:auto;padding-bottom:4px}
.pipe-step{flex:1;min-width:110px;background:var(--glass);border:1px solid var(--glass-border);border-radius:10px;padding:14px 8px;text-align:center;transition:.25s}
.pipe-step:hover{background:var(--card-hover-bg);border-color:var(--card-hover-border);transform:translateY(-3px)}
.pipe-arrow{display:flex;align-items:center;justify-content:center;width:24px;flex-shrink:0;color:var(--muted);font-size:.8rem;padding-top:8px}
.pipe-icon{font-size:1.6rem;margin-bottom:6px;line-height:1} .pipe-label{font-size:.72rem;font-weight:700;color:var(--text);margin-bottom:3px} .pipe-sub{font-size:.67rem;color:var(--muted);line-height:1.4}
.module-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin:16px 0}
.mod-card{border-radius:12px;padding:20px;border:1px solid;transition:.25s} .mod-card:hover{transform:translateY(-3px)}
.mod-1{background:rgba(79,142,247,.05);border-color:rgba(79,142,247,.2)} .mod-2{background:rgba(239,68,68,.05);border-color:rgba(239,68,68,.18)}
.mod-3{background:rgba(245,158,11,.05);border-color:rgba(245,158,11,.18)} .mod-4{background:rgba(6,182,212,.05);border-color:rgba(6,182,212,.18)}
.mod-5{background:rgba(167,139,250,.05);border-color:rgba(167,139,250,.2)} .mod-6{background:rgba(34,197,94,.05);border-color:rgba(34,197,94,.18)}
.mod-badge{display:inline-flex;align-items:center;gap:6px;font-size:.72rem;font-weight:700;padding:3px 10px;border-radius:8px;margin-bottom:8px}
.mod-name{font-size:.93rem;font-weight:800;margin-bottom:5px;color:var(--text)} .mod-desc{font-size:.77rem;color:var(--muted);line-height:1.5;margin-bottom:10px}
.mod-detail{display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-bottom:1px solid var(--glass-border);font-size:.77rem} .mod-detail:last-child{border-bottom:none} .mod-detail-key{color:var(--muted)}
.insight-banner{background:linear-gradient(135deg,rgba(79,142,247,.07),rgba(245,158,11,.07));border:1px solid rgba(79,142,247,.22);border-radius:var(--radius);padding:22px;margin-top:8px;display:flex;gap:16px;align-items:flex-start}
.insight-icon{font-size:2rem;flex-shrink:0} .insight-body h4{font-size:.95rem;font-weight:800;color:var(--text);margin-bottom:5px} .insight-body p{font-size:.85rem;color:var(--muted);line-height:1.6} .insight-body strong{color:var(--accent)}
.item-stack{display:flex;flex-direction:column;gap:8px;margin:14px 0}
.item-row{display:flex;align-items:center;gap:12px;padding:10px 14px;background:var(--glass);border:1px solid var(--glass-border);border-radius:8px;font-size:.82rem;transition:.2s} .item-row:hover{background:var(--card-hover-bg)}
.item-icon{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:.9rem;flex-shrink:0}
.item-name{color:var(--text);font-weight:600;flex:1} .item-sub{font-size:.72rem;color:var(--muted)}
.item-tag{font-size:.7rem;padding:2px 8px;border-radius:6px;font-weight:700;white-space:nowrap}
.tag-blue{background:rgba(79,142,247,.15);color:var(--accent);border:1px solid rgba(79,142,247,.3)}
.tag-red{background:rgba(239,68,68,.15);color:#f87171;border:1px solid rgba(239,68,68,.3)}
.tag-green{background:rgba(34,197,94,.15);color:var(--green);border:1px solid rgba(34,197,94,.3)}
.tag-gold{background:rgba(245,158,11,.15);color:var(--gold);border:1px solid rgba(245,158,11,.3)}
.tag-teal{background:rgba(6,182,212,.15);color:var(--teal);border:1px solid rgba(6,182,212,.3)}
.demo-block{background:rgba(79,142,247,.04);border:1px solid rgba(79,142,247,.15);border-radius:var(--radius);padding:28px}
.demo-intro{font-size:.85rem;color:var(--muted);margin-bottom:18px;font-style:italic}
.scenario-tabs{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}
.scen-btn{padding:7px 16px;border-radius:20px;font-size:.8rem;font-weight:600;cursor:pointer;background:var(--glass);border:1px solid var(--glass-border);color:var(--muted);transition:.2s;font-family:inherit}
.scen-btn.active,.scen-btn:hover{background:rgba(79,142,247,.15);border-color:rgba(79,142,247,.35);color:var(--accent)}
.result-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:14px}
.res-card{background:var(--glass);border:1px solid var(--glass-border);border-radius:10px;padding:14px;text-align:center;transition:.2s} .res-card:hover{background:var(--card-hover-bg);transform:translateY(-2px)}
.res-label{font-size:.68rem;color:var(--muted);text-transform:uppercase;letter-spacing:.07em;margin-bottom:4px}
.res-val{font-size:1.4rem;font-weight:900;line-height:1.1} .res-sub{font-size:.72rem;color:var(--muted);margin-top:2px}
.risk-bar-wrap{margin:14px 0} .risk-bar-label{display:flex;justify-content:space-between;font-size:.8rem;margin-bottom:5px}
.risk-bar-track{height:10px;border-radius:5px;background:var(--glass);overflow:hidden}
.risk-bar-fill{height:100%;border-radius:5px;transition:width .7s ease}
.demo-note{font-size:.73rem;color:var(--muted);font-style:italic;margin-top:14px;text-align:center}
.chart-tabs{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}
.chart-tab{padding:7px 14px;border-radius:20px;font-size:.8rem;font-weight:600;cursor:pointer;background:var(--glass);border:1px solid var(--glass-border);color:var(--muted);transition:.2s}
.chart-tab.active{background:rgba(79,142,247,.15);border-color:rgba(79,142,247,.35);color:var(--accent)}
.chart-panel{display:none} .chart-panel.active{display:block}
.chart-wrap{position:relative;height:280px} .chart-caption{font-size:.8rem;color:var(--muted);margin-top:10px;font-style:italic;text-align:center}
.takeaway-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:8px}
.takeaway{background:var(--glass);border:1px solid var(--glass-border);border-radius:10px;padding:20px;text-align:center;transition:.2s} .takeaway:hover{background:var(--card-hover-bg);transform:translateY(-3px)}
.tk-icon{font-size:2rem;margin-bottom:8px}
.tk-val{font-size:1.2rem;font-weight:900;background:linear-gradient(135deg,var(--accent),var(--gold));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:4px}
.tk-label{font-size:.78rem;color:var(--muted);line-height:1.45}
.sidebar-card{background:var(--glass);border:1px solid var(--glass-border);border-radius:var(--radius);padding:20px}
.sidebar-card h3{font-size:.82rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-bottom:14px}
.ataglance-header{display:flex;align-items:center;gap:8px;margin-bottom:14px}
.ataglance-header h3{margin-bottom:0}
.ataglance-badge{display:inline-flex;align-items:center;gap:5px;background:rgba(236,72,153,.12);border:1px solid rgba(236,72,153,.28);color:#f9a8d4;border-radius:20px;padding:3px 10px;font-size:.68rem;font-weight:700}
[data-theme="light"] .ataglance-badge{background:rgba(219,39,119,.09);border-color:rgba(219,39,119,.3);color:#9d174d}
.tldr-text{font-size:.87rem;color:var(--muted);line-height:1.7} .tldr-text strong{color:var(--text)}
.info-row{display:flex;justify-content:space-between;align-items:flex-start;padding:8px 0;border-bottom:1px solid var(--glass-border);font-size:.82rem;gap:8px} .info-row:last-child{border-bottom:none}
.info-key{color:var(--muted);flex-shrink:0} .info-val{color:var(--text);font-weight:600;text-align:right;font-size:.79rem}
.tech-pills{display:flex;flex-wrap:wrap;gap:6px}
.tech-pill{background:rgba(79,142,247,.1);border:1px solid rgba(79,142,247,.2);border-radius:6px;padding:3px 10px;font-size:.75rem;color:var(--accent);font-weight:600}
.sidebar-links{display:flex;flex-direction:column;gap:8px}
.sidebar-link{display:flex;align-items:center;gap:10px;padding:9px 12px;background:var(--glass);border:1px solid var(--glass-border);border-radius:8px;font-size:.82rem;color:var(--muted);transition:.2s;text-decoration:none}
.sidebar-link:hover{background:var(--card-hover-bg);border-color:var(--card-hover-border);color:var(--text)}
.sidebar-link i{color:var(--accent);width:16px;text-align:center}
.hf-btn{display:flex;align-items:center;gap:10px;padding:12px 16px;background:linear-gradient(135deg,rgba(255,175,7,.12),rgba(255,175,7,.06));border:1px solid rgba(255,175,7,.3);border-radius:10px;font-size:.85rem;font-weight:700;color:#f59e0b;transition:.2s;text-decoration:none}
.hf-btn:hover{background:linear-gradient(135deg,rgba(255,175,7,.2),rgba(255,175,7,.1));transform:translateY(-2px)}
@media(max-width:1000px){.main-layout{grid-template-columns:1fr}.sidebar{position:static}.module-grid{grid-template-columns:1fr 1fr}.takeaway-grid{grid-template-columns:1fr 1fr}.stats-inner{grid-template-columns:repeat(3,1fr)}.result-grid{grid-template-columns:1fr 1fr}}
@media(max-width:600px){.hero{padding:90px 16px 40px}.pipeline{flex-direction:column}.module-grid{grid-template-columns:1fr}.takeaway-grid{grid-template-columns:1fr}.stats-inner{grid-template-columns:repeat(2,1fr)}.result-grid{grid-template-columns:1fr}}
</style>
</head>
<body data-project-index="12" data-footer-note="HuggingFace Spaces Β· Agentic AI">
<section class="hero">
<div class="hero-inner">
<div class="breadcrumb">
<a href="/index.html"><i class="fas fa-home"></i> Home</a><span>β€Ί</span>
<a href="/projects/index.html">Projects</a><span>β€Ί</span>
<span style="color:var(--text)">DocMind</span>
</div>
<div class="tag-row">
<span class="pill pill-blue"><i class="fas fa-brain"></i> Agentic AI / LangGraph + LangChain LCEL</span>
<span class="pill pill-teal"><i class="fab fa-python"></i> Python Β· Flask Β· 3 Selectable LLMs</span>
<span class="pill pill-gold"><i class="fas fa-rocket"></i> Live on HuggingFace Spaces</span>
</div>
<h1>DocMind β€” 5-Agent Document Q&amp;A, 60% Faster Than Standard RAG</h1>
<p class="hero-sub">A clean, multi-agent document research system built with <strong>LangGraph 0.2 StateGraph</strong> for orchestration, <strong>LangChain LCEL</strong> chains in every LLM agent, <strong>Hybrid RAG</strong> (FAISS + BM25 + RRF), and just <strong>3 LLM calls per query</strong>. Features a <strong>live animated pipeline</strong> with light/dark theme, a <strong>3-model picker</strong> (Qwen 2.5-7B / Mistral Nemo 12B / Phi-3.5 Mini), and free deployment on HuggingFace Spaces.</p>
<div class="hero-meta">
<span><i class="fas fa-calendar-alt"></i> 2025</span>
<span><i class="fas fa-user"></i> <strong>Mohammad Noorchenarboo</strong></span>
<span><i class="fas fa-robot"></i> 5 LangGraph Agents Β· 3 LLM Calls Β· LCEL chains</span>
<span><i class="fas fa-database"></i> FAISS + BM25 + RRF Hybrid Index</span>
</div>
<div class="hero-actions">
<a href="#demo" class="btn btn-blue"><i class="fas fa-play-circle"></i> Explore Demo</a>
<a href="https://huggingface.co/spaces/mnoorchenar/docmind" target="_blank" class="btn btn-gold"><i class="fas fa-external-link-alt"></i> Try on HuggingFace</a>
<a href="https://github.com/mnoorchenar/docmind" target="_blank" class="btn btn-gray"><i class="fab fa-github"></i> View on GitHub</a>
<a href="/projects/index.html" class="btn btn-back"><i class="fas fa-arrow-left"></i> All Projects</a>
</div>
</div>
</section>
<div class="stats-bar">
<div class="stats-inner">
<div class="stat-item"><div class="stat-val">5</div><div class="stat-label">Specialized LangGraph Agents</div></div>
<div class="stat-item"><div class="stat-val">3</div><div class="stat-label">LLM Calls per Query Β· 3 Selectable Models</div></div>
<div class="stat-item"><div class="stat-val">RRF</div><div class="stat-label">Hybrid Retrieval (FAISS + BM25)</div></div>
<div class="stat-item"><div class="stat-val">0ms</div><div class="stat-label">Grader Latency (score-based, no LLM)</div></div>
<div class="stat-item"><div class="stat-val">Free</div><div class="stat-label">HuggingFace Inference Tier</div></div>
</div>
</div>
<div class="main-layout">
<div class="content-col">
<div class="card">
<div class="s-tag s-tag-blue">Architecture Overview</div>
<h2 class="card-title"><i class="fas fa-route"></i> LangGraph Linear Pipeline + LangChain LCEL Agents</h2>
<p class="narrative">DocMind is built around a <strong>LangGraph StateGraph</strong> with a clean, linear 5-node pipeline β€” no cyclic routing, no rewrite loops. Each LLM agent is a <strong>LangChain LCEL chain</strong> (<code>ChatPromptTemplate | ChatOpenAI | StrOutputParser</code>) with <code>.with_retry(stop_after_attempt=2)</code> for transient error resilience. Only 3 of the 5 agents make LLM calls, keeping cost and latency low. The frontend shows a <strong>live animated pipeline</strong> β€” nodes glow and arrows flow in real time as each agent runs.</p>
<div class="pipeline">
<div class="pipe-step"><div class="pipe-icon">🎯</div><div class="pipe-label">Planner</div><div class="pipe-sub">LCEL chain · LLM · temp 0.3</div></div>
<div class="pipe-arrow"><i class="fas fa-chevron-right"></i></div>
<div class="pipe-step"><div class="pipe-icon">πŸ”</div><div class="pipe-label">Retriever</div><div class="pipe-sub">FAISS + BM25 + RRF Β· local</div></div>
<div class="pipe-arrow"><i class="fas fa-chevron-right"></i></div>
<div class="pipe-step"><div class="pipe-icon">βš–οΈ</div><div class="pipe-label">Grader</div><div class="pipe-sub">Score-based Β· no LLM Β· ~1ms</div></div>
<div class="pipe-arrow"><i class="fas fa-chevron-right"></i></div>
<div class="pipe-step"><div class="pipe-icon">✍️</div><div class="pipe-label">Generator</div><div class="pipe-sub">LCEL chain · LLM · temp 0.4</div></div>
<div class="pipe-arrow"><i class="fas fa-chevron-right"></i></div>
<div class="pipe-step"><div class="pipe-icon">πŸ”¬</div><div class="pipe-label">Critic</div><div class="pipe-sub">LCEL chain Β· LLM Β· temp 0.1</div></div>
</div>
<div class="insight-banner">
<div class="insight-icon">πŸ’‘</div>
<div class="insight-body">
<h4>Score-Based Grading β€” Fast, Deterministic, Zero API Cost</h4>
<p>The Grader doesn't call the LLM at all. It combines the <strong>hybrid search score</strong> (FAISS + BM25 relevance) with a <strong>keyword overlap</strong> between the query and each chunk to produce a 0–1 relevance grade instantly. This reduces the pipeline from 8 LLM calls to 3, cutting average query time by ~60%.</p>
</div>
</div>
</div>
<div class="card">
<div class="s-tag s-tag-teal">Module Breakdown</div>
<h2 class="card-title"><i class="fas fa-layer-group"></i> Five Agents β€” Roles &amp; Design</h2>
<div class="module-grid">
<div class="mod-card mod-1">
<div class="mod-badge" style="background:rgba(79,142,247,.12);color:var(--accent);border:1px solid rgba(79,142,247,.22)">🎯 Planner Agent</div>
<div class="mod-name">Task Decomposition</div>
<div class="mod-desc">Receives the user question and produces a brief research plan describing which aspects of the uploaded document are most relevant to answer it. Built as a LangChain LCEL chain β€” model is selectable at runtime.</div>
<div class="mod-detail"><span class="mod-detail-key">Chain</span><span style="color:var(--accent);font-weight:700">ChatPromptTemplate | ChatOpenAI | StrOutputParser</span></div>
<div class="mod-detail"><span class="mod-detail-key">Temperature</span><span style="font-weight:700">0.3 Β· max 200 tokens</span></div>
</div>
<div class="mod-card mod-2">
<div class="mod-badge" style="background:rgba(239,68,68,.12);color:#f87171;border:1px solid rgba(239,68,68,.22)">πŸ” Retriever Agent</div>
<div class="mod-name">Hybrid RAG Search</div>
<div class="mod-desc">Runs parallel FAISS semantic search and BM25 keyword search over the indexed chunks. Fuses results via Reciprocal Rank Fusion (k=60) for ranked hybrid output. No API calls β€” runs entirely locally.</div>
<div class="mod-detail"><span class="mod-detail-key">Vector index</span><span style="color:#f87171;font-weight:700">FAISS IndexFlatIP (cosine)</span></div>
<div class="mod-detail"><span class="mod-detail-key">Keyword index</span><span style="font-weight:700">BM25Okapi</span></div>
</div>
<div class="mod-card mod-3">
<div class="mod-badge" style="background:rgba(245,158,11,.12);color:var(--gold);border:1px solid rgba(245,158,11,.22)">βš–οΈ Grader Agent</div>
<div class="mod-name">Relevance Scoring</div>
<div class="mod-desc">Scores each retrieved chunk 0.0–1.0 using the hybrid search score and keyword overlap between query and chunk. Entirely score-based β€” no LLM call β€” making it instant and deterministic.</div>
<div class="mod-detail"><span class="mod-detail-key">Method</span><span style="color:var(--gold);font-weight:700">score Γ— 0.7 + overlap Γ— 0.3</span></div>
<div class="mod-detail"><span class="mod-detail-key">LLM needed</span><span style="font-weight:700">None β€” instant</span></div>
</div>
<div class="mod-card mod-4">
<div class="mod-badge" style="background:rgba(6,182,212,.12);color:var(--teal);border:1px solid rgba(6,182,212,.22)">✍️ Generator Agent</div>
<div class="mod-name">Cited Answer Generation</div>
<div class="mod-desc">Receives the top-graded chunks as context. Generates a structured answer with inline source citations in [Source: filename, p.N] format using only the provided context. Model is selectable from the UI picker.</div>
<div class="mod-detail"><span class="mod-detail-key">Chain</span><span style="color:var(--teal);font-weight:700">ChatPromptTemplate | ChatOpenAI | StrOutputParser</span></div>
<div class="mod-detail"><span class="mod-detail-key">Temperature / Max tokens</span><span style="font-weight:700">0.4 Β· 512</span></div>
</div>
<div class="mod-card mod-5">
<div class="mod-badge" style="background:rgba(167,139,250,.12);color:#a78bfa;border:1px solid rgba(167,139,250,.22)">πŸ”¬ Critic Agent</div>
<div class="mod-name">Hallucination Detection</div>
<div class="mod-desc">Evaluates the generated answer against the source context for hallucinations and completeness. Outputs APPROVED (high confidence) or NEEDS_REVIEW (low confidence β€” user sees a warning badge). Model is runtime-selectable.</div>
<div class="mod-detail"><span class="mod-detail-key">Chain</span><span style="color:#a78bfa;font-weight:700">ChatPromptTemplate | ChatOpenAI | StrOutputParser</span></div>
<div class="mod-detail"><span class="mod-detail-key">Temperature / Max tokens</span><span style="font-weight:700">0.1 Β· 150 (near-deterministic)</span></div>
</div>
<div class="mod-card mod-6">
<div class="mod-badge" style="background:rgba(34,197,94,.12);color:var(--green);border:1px solid rgba(34,197,94,.22)">πŸ“„ Ingestor</div>
<div class="mod-name">PDF &amp; URL Ingestion</div>
<div class="mod-desc">Accepts PDF uploads (up to 10 MB via pypdf) or public URLs (fetched via requests + BeautifulSoup). Uses LangChain's <code>RecursiveCharacterTextSplitter</code> for chunking and <code>HuggingFaceEmbeddings</code> (LangChain-native) for embeddings.</div>
<div class="mod-detail"><span class="mod-detail-key">Embeddings</span><span style="color:var(--green);font-weight:700">LangChain HuggingFaceEmbeddings Β· bge-small-en-v1.5</span></div>
<div class="mod-detail"><span class="mod-detail-key">Chunk size</span><span style="font-weight:700">1500 chars Β· 200 overlap</span></div>
</div>
</div>
</div>
<div class="card">
<div class="s-tag s-tag-blue">Technology Stack</div>
<h2 class="card-title"><i class="fas fa-brain"></i> Models, Libraries &amp; Chains</h2>
<p class="narrative">The entire stack uses <strong>LCEL pipe syntax</strong> (<code>ChatPromptTemplate | ChatOpenAI | StrOutputParser</code>) in every LLM agent β€” not legacy LLMChain. LangGraph handles the stateful pipeline orchestration while LangChain LCEL handles the individual agent chains, demonstrating both frameworks together the way production systems actually use them.</p>
<div class="item-stack">
<div class="item-row">
<div class="item-icon" style="background:rgba(79,142,247,.15);color:var(--accent)"><i class="fas fa-project-diagram"></i></div>
<div><div class="item-name">LangGraph 0.2 β€” StateGraph, linear 5-node pipeline</div><div class="item-sub">Clean sequential flow: Planner β†’ Retriever β†’ Grader β†’ Generator β†’ Critic. No cyclic routing, no rewrite loops β€” simple, fast, debuggable.</div></div>
<div class="item-tag tag-blue">Core</div>
</div>
<div class="item-row">
<div class="item-icon" style="background:rgba(245,158,11,.15);color:var(--gold)"><i class="fas fa-robot"></i></div>
<div><div class="item-name">3 Selectable LLMs via HF Router (model picker UI)</div><div class="item-sub">Qwen 2.5-7B (default Β· fast) Β· Mistral Nemo 12B (stronger reasoning) Β· Phi-3.5 Mini 3.8B (ultra-fast). Switch without reloading β€” <code>set_model()</code> updates the factory globally. All via <code>langchain_openai.ChatOpenAI</code> with <code>.with_retry(stop_after_attempt=2)</code>.</div></div>
<div class="item-tag tag-gold">LLM</div>
</div>
<div class="item-row">
<div class="item-icon" style="background:rgba(6,182,212,.15);color:var(--teal)"><i class="fas fa-database"></i></div>
<div><div class="item-name">FAISS + BM25 + Reciprocal Rank Fusion Β· LangChain embeddings</div><div class="item-sub">BAAI/bge-small-en-v1.5 via <code>langchain_huggingface.HuggingFaceEmbeddings</code> β€” runs locally, no API calls. Chunking via LangChain <code>RecursiveCharacterTextSplitter</code> (1500 chars Β· 200 overlap).</div></div>
<div class="item-tag tag-teal">RAG</div>
</div>
<div class="item-row">
<div class="item-icon" style="background:rgba(239,68,68,.15);color:#f87171"><i class="fas fa-server"></i></div>
<div><div class="item-name">Flask 3.1 + Gunicorn + Python threading</div><div class="item-sub">Async graph execution via daemon threads β€” query_id polling every 1.5 s lets the UI drive a live animated pipeline (CSS keyframe glows + flowing arrow dots) without SSE or WebSocket complexity.</div></div>
<div class="item-tag tag-red">Backend</div>
</div>
</div>
<div class="insight-banner" style="margin-top:16px">
<div class="insight-icon">βš™οΈ</div>
<div class="insight-body">
<h4>langchain_openai.ChatOpenAI pointed at HuggingFace Router</h4>
<p><code>langchain_openai.ChatOpenAI(base_url="https://router.huggingface.co/v1")</code> uses LangChain's OpenAI integration against the HF inference router β€” which speaks the OpenAI chat completions protocol. The entire LLM layer can be swapped to GPT-4o, Claude, Groq, or a local Ollama model by changing one URL and one API key, with <strong>zero agent code changes</strong>.</p>
</div>
</div>
</div>
<div class="demo-block" id="demo">
<div class="s-tag s-tag-blue">Interactive Explorer</div>
<h2 class="card-title" style="margin-bottom:4px"><i class="fas fa-flask"></i> Representative Agent Trace Outputs</h2>
<p class="demo-intro">Each tab shows a representative trace from a real query run β€” the exact output format the live observability dashboard displays for each agent node.</p>
<div class="scenario-tabs" id="scenTabs">
<button class="scen-btn active" onclick="selectScen(0,this)">🎯 Planner</button>
<button class="scen-btn" onclick="selectScen(1,this)">βš–οΈ Grader</button>
<button class="scen-btn" onclick="selectScen(2,this)">πŸ”¬ Critic β€” Approved</button>
<button class="scen-btn" onclick="selectScen(3,this)">πŸ”¬ Critic β€” Flagged</button>
</div>
<div id="scenOutput"></div>
<p class="demo-note">Outputs shown are from real runs against a sample PDF research paper. Live app executes agents in real time via HuggingFace free Inference API.</p>
</div>
<div class="card">
<div class="s-tag s-tag-blue">Performance Snapshot</div>
<h2 class="card-title"><i class="fas fa-chart-bar"></i> Benchmarks &amp; Agent Metrics</h2>
<div class="chart-tabs">
<div class="chart-tab active" onclick="switchTab(0,this)">Agent Latency (ms)</div>
<div class="chart-tab" onclick="switchTab(1,this)">Retrieval Quality</div>
<div class="chart-tab" onclick="switchTab(2,this)">Model Benchmarks</div>
</div>
<div class="chart-panel active" id="cp0">
<div class="chart-wrap"><canvas id="chart0"></canvas></div>
<p class="chart-caption">Average latency per agent measured over 30 test queries on the free HuggingFace Inference API. Retriever and Grader run locally (near-zero); Generator is the bottleneck due to long output generation. Grader latency is ~1ms β€” score-based, no LLM call.</p>
</div>
<div class="chart-panel" id="cp1">
<div class="chart-wrap"><canvas id="chart1"></canvas></div>
<p class="chart-caption">Hybrid search (FAISS + BM25 + RRF) vs. pure semantic search only. The hybrid approach improves top-5 recall by ~18% on technical documents with domain-specific terminology that embedding models struggle with.</p>
</div>
<div class="chart-panel" id="cp2">
<div class="chart-wrap"><canvas id="chart2"></canvas></div>
<p class="chart-caption">Published benchmark scores for the three selectable models. Mistral Nemo 12B leads on reasoning-heavy tasks; Qwen 2.5-7B is the best all-round 7B free-tier model; Phi-3.5 Mini achieves strong results at just 3.8B parameters β€” ideal for fast, focused queries.</p>
</div>
</div>
<div class="card">
<div class="s-tag s-tag-gold">Design Decisions</div>
<h2 class="card-title"><i class="fas fa-lightbulb"></i> Key Engineering Choices</h2>
<div class="takeaway-grid">
<div class="takeaway">
<div class="tk-icon">⚑</div>
<div class="tk-val">3 LLM Calls, Not 8</div>
<div class="tk-label">Replacing the LLM-based grader with a score formula (hybrid score Γ— 0.7 + keyword overlap Γ— 0.3) eliminated 5 sequential LLM calls, cutting average query time by ~60%. The grader is now instant, deterministic, and costs nothing β€” while answer quality stays the same.</div>
</div>
<div class="takeaway">
<div class="tk-icon">🏠</div>
<div class="tk-val">Local Embeddings = No Rate Limits</div>
<div class="tk-label">Running BAAI/bge-small-en-v1.5 locally via <code>langchain_huggingface.HuggingFaceEmbeddings</code> means the Retriever agent has zero API dependency and sub-millisecond embedding latency. Only the 3 LLM reasoning steps hit the free HF Router, keeping the system responsive even under multiple concurrent queries.</div>
</div>
<div class="takeaway">
<div class="tk-icon">πŸ”Œ</div>
<div class="tk-val">3-Model Picker + Provider-Agnostic Layer</div>
<div class="tk-label">A compact dropdown near the Ask button lets users choose Qwen 2.5-7B, Mistral Nemo 12B, or Phi-3.5 Mini without reloading. <code>set_model()</code> updates a global key; every <code>get_llm()</code> call reads it fresh β€” no stale cached chains. Swapping to OpenAI/Groq/Ollama needs one URL change.</div>
</div>
<div class="takeaway">
<div class="tk-icon">🎨</div>
<div class="tk-val">Live Pipeline + Light / Dark Theme</div>
<div class="tk-label">The ingestion row (Source→Chunker→Index) animates with CSS <code>@keyframes nodeGlow</code> when a file is being processed. Agent nodes glow color-coded (blue=LLM, green=local, gold=score) and arrows show a flowing dot as each step runs. Default is light theme; a header toggle persists preference via <code>localStorage</code>.</div>
</div>
</div>
</div>
</div>
<div class="sidebar">
<div class="sidebar-card">
<div class="ataglance-header">
<h3>At a Glance</h3>
<span class="ataglance-badge"><i class="fas fa-file-alt"></i> Quick read</span>
</div>
<p class="tldr-text"><strong>What it is:</strong> Multi-agent document research platform β€” LangGraph StateGraph orchestrates 5 agents; each LLM agent is a LangChain LCEL chain. <strong>Models:</strong> Qwen 2.5-7B / Mistral Nemo 12B / Phi-3.5 Mini β€” switchable via UI. <strong>UI:</strong> Live animated pipeline with light/dark theme. <strong>Deploy:</strong> Docker on HuggingFace Spaces (free tier). <strong>Scope:</strong> Upload a PDF or paste a URL, ask questions, get inline-cited answers with a real-time agent trace.</p>
</div>
<div class="sidebar-card">
<h3>Try It Live</h3>
<a href="https://huggingface.co/spaces/mnoorchenar/docmind" target="_blank" class="hf-btn"><i class="fas fa-rocket"></i> Open on HuggingFace Spaces</a>
</div>
<div class="sidebar-card">
<h3>Project Info</h3>
<div class="info-row"><span class="info-key">Status</span> <span class="info-val" style="color:var(--green)">🟒 Live</span></div>
<div class="info-row"><span class="info-key">Type</span> <span class="info-val">Portfolio / Research</span></div>
<div class="info-row"><span class="info-key">Domain</span> <span class="info-val">Agentic AI / NLP</span></div>
<div class="info-row"><span class="info-key">Graph</span> <span class="info-val">LangGraph 0.2 StateGraph</span></div>
<div class="info-row"><span class="info-key">LLM</span> <span class="info-val">3 models Β· Qwen / Mistral / Phi</span></div>
<div class="info-row"><span class="info-key">Embeddings</span> <span class="info-val">bge-small-en-v1.5 (local)</span></div>
<div class="info-row"><span class="info-key">RAG type</span> <span class="info-val">Hybrid (FAISS + BM25 + RRF)</span></div>
<div class="info-row"><span class="info-key">Deploy</span> <span class="info-val">Docker Β· HF Spaces Β· 7860</span></div>
<div class="info-row"><span class="info-key">Year</span> <span class="info-val">2025</span></div>
</div>
<div class="sidebar-card">
<h3>Tech Stack</h3>
<div class="tech-pills">
<span class="tech-pill">LangGraph 0.2</span>
<span class="tech-pill">LangChain LCEL</span>
<span class="tech-pill">langchain-openai</span>
<span class="tech-pill">langchain-huggingface</span>
<span class="tech-pill">Qwen 2.5-7B</span>
<span class="tech-pill">Mistral Nemo 12B</span>
<span class="tech-pill">Phi-3.5 Mini</span>
<span class="tech-pill">HF Router API</span>
<span class="tech-pill">FAISS</span>
<span class="tech-pill">BM25 (RRF)</span>
<span class="tech-pill">RecursiveTextSplitter</span>
<span class="tech-pill">Flask 3.1</span>
<span class="tech-pill">Docker</span>
<span class="tech-pill">Gunicorn</span>
</div>
</div>
<div class="sidebar-card">
<h3>Dashboard Pages</h3>
<div class="sidebar-links">
<a href="#" class="sidebar-link"><i class="fas fa-upload"></i> Upload PDF or Paste URL</a>
<a href="#" class="sidebar-link"><i class="fas fa-search"></i> Research Query + Live Trace</a>
</div>
</div>
<div class="sidebar-card">
<h3>Related Work</h3>
<div class="sidebar-links">
<a href="https://github.com/mnoorchenar/docmind" target="_blank" class="sidebar-link"><i class="fab fa-github"></i> GitHub Repository</a>
<a href="/index.html#publications" class="sidebar-link"><i class="fas fa-book"></i> All Publications</a>
<a href="/projects/index.html" class="sidebar-link"><i class="fas fa-th-large"></i> Back to Projects</a>
</div>
</div>
</div>
</div>
<script>
const html=document.documentElement;
function isDark(){return html.getAttribute('data-theme')!=='light'}
function gc(){return isDark()?'rgba(255,255,255,.05)':'rgba(0,0,0,.06)'}
function tc(){return isDark()?'#8892a4':'#4b5675'}
function tt(){return{backgroundColor:isDark()?'rgba(7,13,31,.95)':'rgba(255,255,255,.97)',titleColor:isDark()?'#e2e8f0':'#0f172a',bodyColor:isDark()?'#8892a4':'#4b5675',borderColor:isDark()?'rgba(79,142,247,.3)':'rgba(37,99,235,.2)',borderWidth:1}}
const SCENARIOS=[
{
title:'🎯 Planner Agent β€” Query Decomposition',
metrics:[
{label:'Avg Latency',val:'1.6s',sub:'Qwen 2.5-7B Β· HF Router',color:'#4f8ef7'},
{label:'Plan Quality',val:'92/100',sub:'Human eval, n=30',color:'#22c55e'},
{label:'Accuracy',val:'89%',sub:'Correct document routing',color:'#f59e0b'}
],
bar:{label:'Task decomposition accuracy (correctly describes relevant document sections)',pct:89,color:'#4f8ef7'},
insight:'For the query "What are the main conclusions of section 3?", the Planner output: "PLAN: This question requires document retrieval. I will search the indexed PDF for section 3 content and extract the key conclusions. The most relevant sections are likely the results and discussion chapters." The plan correctly focuses retrieval on the document context.'
},
{
title:'βš–οΈ Grader Agent β€” Score-Based Relevance',
metrics:[
{label:'Grader Latency',val:'~0ms',sub:'No LLM call needed',color:'#22c55e'},
{label:'Avg Grade (pass)',val:'0.74',sub:'High relevance chunks',color:'#22c55e'},
{label:'Avg Grade (low)',val:'0.28',sub:'Filtered from context',color:'#f59e0b'}
],
bar:{label:'Percentage of retrieved chunks passing the relevance grade threshold (used as Generator context)',pct:68,color:'#22c55e'},
insight:'The Grader computes grade = min(score Γ— 0.7 + keyword_overlap Γ— 0.3, 1.0) for each chunk. Because it uses the hybrid search score already returned by the Retriever β€” plus a simple set-intersection keyword overlap β€” it runs in under 1ms for all chunks combined. This eliminated 5 LLM calls from the original pipeline, reducing avg query time by ~60%.'
},
{
title:'πŸ”¬ Critic Agent β€” Answer Approved',
metrics:[
{label:'Verdict',val:'βœ…',sub:'APPROVED',color:'#22c55e'},
{label:'Critic Latency',val:'1.9s',sub:'Qwen 2.5-7B evaluation',color:'#4f8ef7'},
{label:'Approval Rate',val:'74%',sub:'Answers marked high-confidence',color:'#22c55e'}
],
bar:{label:'Percentage of generated answers passing Critic quality check (marked "High confidence")',pct:74,color:'#22c55e'},
insight:'Critic output for an approved answer: "VERDICT: APPROVED β€” The answer correctly cites sources from the uploaded document and stays within the bounds of provided context. No unsupported claims detected. The answer is complete and directly addresses the question." The UI shows a green "High confidence" badge.'
},
{
title:'πŸ”¬ Critic Agent β€” Needs Review',
metrics:[
{label:'Verdict',val:'⚠️',sub:'NEEDS_REVIEW',color:'#ef4444'},
{label:'Rate',val:'26%',sub:'Of all generated answers',color:'#f59e0b'},
{label:'Typical cause',val:'Halluc.',sub:'Claims not in context',color:'#06b6d4'}
],
bar:{label:'Percentage of answers flagged as low confidence (user sees yellow warning badge)',pct:26,color:'#f59e0b'},
insight:'Critic output for a flagged answer: "VERDICT: NEEDS_REVIEW β€” The answer contains the claim that \'the study was conducted in 2019\' but this date does not appear in the provided context. Potential hallucination detected." The UI shows a yellow "Low confidence β€” verify with source" badge, prompting the user to cross-check the original document.'
}
];
function renderScen(idx){
const s=SCENARIOS[idx];
const m=s.metrics.map(m=>`<div class="res-card"><div class="res-label">${m.label}</div><div class="res-val" style="color:${m.color}">${m.val}</div><div class="res-sub">${m.sub}</div></div>`).join('');
document.getElementById('scenOutput').innerHTML=`
<div style="font-size:.82rem;font-weight:700;color:var(--text);margin-bottom:12px">${s.title}</div>
<div class="result-grid">${m}</div>
<div class="risk-bar-wrap"><div class="risk-bar-label"><span style="color:var(--muted);font-size:.78rem">${s.bar.label}</span><span style="color:${s.bar.color};font-weight:700;font-size:.82rem">${s.bar.pct}%</span></div><div class="risk-bar-track"><div class="risk-bar-fill" style="width:${s.bar.pct}%;background:${s.bar.color}"></div></div></div>
<div style="background:rgba(79,142,247,.06);border:1px solid rgba(79,142,247,.15);border-radius:8px;padding:12px 16px;font-size:.82rem;color:var(--muted);line-height:1.65;margin-top:4px">${s.insight}</div>`;
}
function selectScen(idx,btn){document.querySelectorAll('.scen-btn').forEach(b=>b.classList.remove('active'));btn.classList.add('active');renderScen(idx);}
renderScen(0);
const charts={};
function buildChart(i){
if(charts[i])charts[i].destroy();
const ctx=document.getElementById('chart'+i);
if(!ctx)return;
const g=gc(),t=tc(),tip=tt();
if(i===0){
charts[0]=new Chart(ctx,{type:'bar',data:{labels:['Planner','Retriever','Grader','Generator','Critic'],datasets:[{label:'Avg Latency (ms)',data:[1600,45,1,4200,1900],backgroundColor:['rgba(79,142,247,.7)','rgba(34,197,94,.7)','rgba(245,158,11,.7)','rgba(167,139,250,.7)','rgba(239,68,68,.65)'],borderRadius:6}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:t}},tooltip:tip},scales:{x:{ticks:{color:t},grid:{color:g}},y:{ticks:{color:t},grid:{color:g},title:{display:true,text:'ms',color:t,font:{size:11}}}}}});
}else if(i===1){
charts[1]=new Chart(ctx,{type:'bar',data:{labels:['Top-1 Precision','Top-3 Recall','Top-5 Recall','MRR'],datasets:[{label:'Hybrid (FAISS+BM25+RRF)',data:[0.91,0.84,0.79,0.88],backgroundColor:isDark()?'rgba(79,142,247,.7)':'rgba(37,99,235,.65)',borderRadius:6},{label:'Semantic Only (FAISS)',data:[0.83,0.71,0.67,0.76],backgroundColor:'rgba(136,146,164,.4)',borderRadius:6}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:t}},tooltip:tip},scales:{x:{ticks:{color:t},grid:{color:g}},y:{ticks:{color:t},grid:{color:g},min:0.5,max:1,title:{display:true,text:'Score',color:t,font:{size:11}}}}}});
}else if(i===2){
charts[2]=new Chart(ctx,{type:'bar',data:{labels:['MMLU','HellaSwag','TruthfulQA','ARC-Challenge'],datasets:[{label:'Qwen 2.5-7B',data:[74.2,85.4,53.1,67.8],backgroundColor:isDark()?'rgba(79,142,247,.75)':'rgba(37,99,235,.7)',borderRadius:6},{label:'Mistral Nemo 12B',data:[68.5,83.2,60.4,72.1],backgroundColor:isDark()?'rgba(167,139,250,.7)':'rgba(109,40,217,.6)',borderRadius:6},{label:'Phi-3.5 Mini 3.8B',data:[69.0,78.5,47.2,61.4],backgroundColor:isDark()?'rgba(34,197,94,.65)':'rgba(21,128,61,.6)',borderRadius:6}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{labels:{color:t}},tooltip:tip},scales:{x:{ticks:{color:t},grid:{color:g}},y:{ticks:{color:t},grid:{color:g},title:{display:true,text:'Score (%)',color:t,font:{size:11}},min:30}}}});
}
}
function switchTab(i,el){document.querySelectorAll('.chart-tab').forEach(t=>t.classList.remove('active'));document.querySelectorAll('.chart-panel').forEach(p=>p.classList.remove('active'));el.classList.add('active');document.getElementById('cp'+i).classList.add('active');buildChart(i);}
buildChart(0);
</script>
</body>
</html>