Spaces:
Sleeping
Sleeping
| <html lang="en" data-theme="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Cortex RAG</title> | |
| <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&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script> | |
| <link rel="stylesheet" href="/static/styles.css" /> | |
| <link rel="icon" type="image/svg+xml" href="/static/favicon.svg"> | |
| </head> | |
| <body> | |
| <div class="mobile-overlay" id="mobileOverlay"></div> | |
| <div class="shell"> | |
| <nav class="sidebar" id="sidebar"> | |
| <div class="logo"> | |
| <svg width="24" height="24" viewBox="0 0 200 200" fill="none" style="flex-shrink:0" xmlns="http://www.w3.org/2000/svg"> | |
| <circle cx="100" cy="100" r="90" stroke="#E2E8F0" stroke-width="2" stroke-dasharray="4 4" /> | |
| <path d="M100 30C61.3401 30 30 61.3401 30 100C30 138.66 61.3401 170 100 170" | |
| stroke="url(#paint0_linear)" stroke-width="12" stroke-linecap="round" /> | |
| <circle cx="100" cy="30" r="8" fill="#6366F1" /> | |
| <circle cx="140" cy="60" r="8" fill="#4F46E5" /> | |
| <circle cx="160" cy="100" r="8" fill="#3B82F6" /> | |
| <circle cx="140" cy="140" r="8" fill="#06B6D4" /> | |
| <circle cx="100" cy="170" r="8" fill="#22D3EE" /> | |
| <rect x="85" y="85" width="30" height="30" rx="6" fill="url(#paint0_linear)" transform="rotate(45 100 100)" /> | |
| <path d="M100 85V115M85 100H115" stroke="white" stroke-width="3" stroke-linecap="round" /> | |
| <defs> | |
| <linearGradient id="paint0_linear" x1="30" y1="30" x2="170" y2="170" gradientUnits="userSpaceOnUse"> | |
| <stop stop-color="#6366F1" /> | |
| <stop offset="1" stop-color="#22D3EE" /> | |
| </linearGradient> | |
| </defs> | |
| </svg> | |
| <div class="logo-text"> | |
| <div class="logo-mark">CORTEX</div> | |
| <div class="logo-sub">RAG · v1.0</div> | |
| </div> | |
| </div> | |
| <div class="nav-section"> | |
| <div class="nav-item active" data-tab="chat"> | |
| <svg class="nav-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 10.5a2 2 0 01-2 2H5l-3 2.5V4a2 2 0 012-2h8a2 2 0 012 2v6.5z"/></svg> | |
| <span class="nav-label">Chat</span> | |
| </div> | |
| <div class="nav-item" data-tab="ingest"> | |
| <svg class="nav-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 2v8m0 0l-3-3m3 3l3-3M2 12v1a1 1 0 001 1h10a1 1 0 001-1v-1"/></svg> | |
| <span class="nav-label">Ingest</span> | |
| </div> | |
| <div class="nav-item" data-tab="eval"> | |
| <svg class="nav-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="10" width="3" height="4" rx="0.5"/><rect x="6.5" y="6" width="3" height="8" rx="0.5"/><rect x="11" y="2" width="3" height="12" rx="0.5"/></svg> | |
| <span class="nav-label">Evaluation</span> | |
| </div> | |
| <div class="nav-item" data-tab="system"> | |
| <svg class="nav-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="2.5"/><path d="M8 1.5v1.8M8 12.7v1.8M1.5 8h1.8M12.7 8h1.8M3.6 3.6l1.3 1.3M11.1 11.1l1.3 1.3M11.1 4.9l-1.3 1.3M4.9 11.1l-1.3 1.3"/></svg> | |
| <span class="nav-label">System</span> | |
| </div> | |
| </div> | |
| <div class="sidebar-footer"> | |
| <div class="footer-row"> | |
| <div class="status-row"> | |
| <span class="status-dot" id="statusDot"></span> | |
| <span class="status-label" id="statusLabel">checking…</span> | |
| </div> | |
| <button class="theme-btn" id="themeBtn" title="Toggle theme">☀</button> | |
| </div> | |
| <button class="sidebar-toggle" id="sidebarToggle" title="Collapse">◀</button> | |
| </div> | |
| </nav> | |
| <div class="main"> | |
| <div class="tab-panel active" id="tab-chat"> | |
| <div class="panel-header"> | |
| <div style="display:flex; align-items:center; gap:10px;"> | |
| <button class="mobile-nav-toggle" aria-label="Open Menu">☰</button> | |
| <span class="panel-title">/ Cortex</span> | |
| </div> | |
| <div class="panel-actions"> | |
| <button class="btn btn-ghost mobile-sources-btn" id="mobileSourcesBtn" style="display:none">sources</button> | |
| <!-- Model selector pill --> | |
| <div class="model-selector" id="modelSelector"> | |
| <div class="model-pill" id="modelPill" title="Select LLM provider and model"> | |
| <span class="model-pill-dot" id="modelDot"></span> | |
| <span class="model-pill-text" id="modelPillLabel">loading…</span> | |
| <span class="model-pill-caret">▾</span> | |
| </div> | |
| <div class="model-popover" id="modelPopover"> | |
| <div class="pop-header"> | |
| <span>LLM provider & model</span> | |
| <button class="pop-close" id="popCloseBtn" title="Close">✕</button> | |
| </div> | |
| <div class="pop-body"> | |
| <!-- Provider --> | |
| <div> | |
| <div class="pop-section-label">provider</div> | |
| <div class="provider-grid" id="providerGrid"></div> | |
| </div> | |
| <!-- Model --> | |
| <div> | |
| <div class="pop-section-label">model</div> | |
| <select class="pop-select" id="modelSelect"></select> | |
| <input class="pop-input" id="modelCustomInput" placeholder="model id (e.g. meta/llama-3.1-8b-instruct)" style="display:none;margin-top:6px"> | |
| </div> | |
| <!-- Custom base URL (shown only for custom provider) --> | |
| <div class="custom-base-row" id="customBaseRow"> | |
| <div class="pop-section-label">base url</div> | |
| <input class="pop-input" id="customBaseInput" placeholder="http://localhost:11434/v1"> | |
| </div> | |
| <!-- API key override --> | |
| <div> | |
| <div class="pop-section-label">api key override <span style="color:var(--muted);font-size:9px">(optional — uses .env if blank)</span></div> | |
| <input class="pop-input" id="apiKeyInput" type="password" placeholder="sk-… or nvapi-…"> | |
| </div> | |
| </div> | |
| <div class="pop-footer"> | |
| <span class="pop-footer-info" id="popFooterInfo"></span> | |
| <button class="btn btn-primary" id="applyModelBtn">apply</button> | |
| </div> | |
| </div> | |
| </div> | |
| <button class="btn btn-ghost" id="clearChatBtn">clear</button> | |
| </div> | |
| </div> | |
| <div class="chat-wrap"> | |
| <div class="chat-messages" id="chatMessages"> | |
| <div class="message"> | |
| <div class="msg-avatar ai">cx</div> | |
| <div class="msg-body"> | |
| <div class="msg-role">CORTEX</div> | |
| <div class="msg-text">Ready. Ask anything about your ingested documents — multi-hop questions work well.</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="sources-panel collapsed" id="sourcesPanel"> | |
| <div class="sources-header"> | |
| <span class="sources-title">Sources</span> | |
| <button class="sources-toggle" id="sourcesToggle" title="Expand">◀</button> | |
| </div> | |
| <div class="sources-list" id="sourcesList"> | |
| <div class="empty-sources"> | |
| <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg> | |
| <span>Retrieved sources will appear here</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="chat-input-area"> | |
| <div class="chat-input-row"> | |
| <textarea class="chat-textarea" id="chatInput" placeholder="Ask anything about your documents..." rows="1"></textarea> | |
| <button class="btn btn-primary" id="sendBtn">send</button> | |
| </div> | |
| <div class="stream-status" id="streamStatus"></div> | |
| </div> | |
| </div> | |
| <div class="tab-panel" id="tab-ingest"> | |
| <div class="panel-header"> | |
| <div style="display:flex; align-items:center; gap:10px;"> | |
| <button class="mobile-nav-toggle" aria-label="Open Menu">☰</button> | |
| <span class="panel-title">/ ingest</span> | |
| </div> | |
| </div> | |
| <div class="ingest-body"> | |
| <div class="ingest-tabs"> | |
| <div class="ingest-tab active" data-section="upload">upload files</div> | |
| <div class="ingest-tab" data-section="path">server path</div> | |
| </div> | |
| <div class="ingest-section active" id="ingest-section-upload"> | |
| <div class="form-card"> | |
| <h3>upload_files()</h3> | |
| <input type="file" id="fileInput" multiple accept=".pdf,.html,.htm,.txt,.md" style="display:none"> | |
| <div class="drop-zone" id="dropZone"> | |
| <div class="drop-zone-icon">📄</div> | |
| <div class="drop-zone-title">Drop files here or click to browse</div> | |
| <div class="drop-zone-sub">PDF · HTML · TXT · Markdown — multiple files allowed</div> | |
| </div> | |
| <div class="file-list" id="fileList"></div> | |
| <div class="upload-actions"> | |
| <button class="btn btn-primary" id="uploadBtn" disabled>upload & ingest</button> | |
| <span class="upload-count" id="uploadCount"></span> | |
| <button class="btn btn-ghost" id="clearFilesBtn" style="display:none">clear</button> | |
| </div> | |
| <div class="progress-wrap" id="uploadProgress"><div class="progress-bar"></div></div> | |
| </div> | |
| </div> | |
| <div class="ingest-section" id="ingest-section-path"> | |
| <div class="form-card"> | |
| <h3>ingest_path()</h3> | |
| <div class="form-group"> | |
| <label class="form-label">server path — file or directory</label> | |
| <input class="form-input" type="text" id="ingestPath" placeholder="data/documents or /path/to/paper.pdf"> | |
| </div> | |
| <label class="checkbox-row"> | |
| <input type="checkbox" id="ingestRecursive" checked> | |
| <span>recursive (include subdirectories)</span> | |
| </label> | |
| <div class="progress-wrap" id="ingestProgress"><div class="progress-bar"></div></div> | |
| <div style="margin-top:13px"><button class="btn btn-primary" id="ingestBtn">run ingestion</button></div> | |
| </div> | |
| </div> | |
| <div class="ingest-result" id="ingestResult"></div> | |
| <div class="ingest-log-section"> | |
| <h4>ingestion log</h4> | |
| <div class="ingest-log" id="ingestLogList"></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="tab-panel" id="tab-eval"> | |
| <div class="panel-header"> | |
| <div style="display:flex; align-items:center; gap:10px;"> | |
| <button class="mobile-nav-toggle" aria-label="Open Menu">☰</button> | |
| <span class="panel-title">/ evaluation</span> | |
| </div> | |
| <div class="panel-actions"> | |
| <button class="btn btn-ghost" id="refreshMetrics">refresh</button> | |
| <button class="btn btn-danger" id="flushCache">flush cache</button> | |
| </div> | |
| </div> | |
| <div class="eval-body" id="evalBody"> | |
| <div style="color:var(--muted);font-family:var(--mono);font-size:12px;padding:40px 0;text-align:center">loading metrics…</div> | |
| </div> | |
| </div> | |
| <div class="tab-panel" id="tab-system"> | |
| <div class="panel-header"> | |
| <div style="display:flex; align-items:center; gap:10px;"> | |
| <button class="mobile-nav-toggle" aria-label="Open Menu">☰</button> | |
| <span class="panel-title">/ system</span> | |
| </div> | |
| <div class="panel-actions"><button class="btn btn-ghost" id="refreshSystem">refresh</button></div> | |
| </div> | |
| <div class="system-body" id="systemBody"> | |
| <div style="color:var(--muted);font-family:var(--mono);font-size:12px;padding:40px 0;text-align:center">loading…</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="toast" id="toast"></div> | |
| <script src="/static/script.js"></script> | |
| </body> | |
| </html> |