Spaces:
Sleeping
Sleeping
Download index.html from codeninja3d/askBot: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/spaces/codeninja3d/askBot/resolve/main/index.html
- Command line
-
hf download hf://spaces/codeninja3d/askBot/index.html
-
curl -L -o index.html https://huggingface.co/spaces/codeninja3d/askBot/resolve/main/index.html
10.4 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Ask Julia Assistant</title> | |
| <script> | |
| window.MathJax = { tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] } }; | |
| </script> | |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> | |
| <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> | |
| <style> | |
| :root { --sidebar-width: 450px; } | |
| body { font-family: 'Inter', sans-serif; background: #0f172a; color: #f8fafc; display: flex; height: 100vh; margin: 0; overflow: hidden; } | |
| #content-area { | |
| flex: 1; padding: 40px; overflow-y: auto; | |
| transition: padding-right 0.3s ease; | |
| } | |
| body.sidebar-active #content-area { | |
| padding-right: calc(var(--sidebar-width) + 40px); | |
| } | |
| #sidebar { | |
| position: fixed; right: 0; top: 0; height: 100%; | |
| width: var(--sidebar-width); background: #1e293b; | |
| display: flex; flex-direction: column; | |
| box-shadow: -5px 0 15px rgba(0,0,0,0.3); | |
| transform: translateX(100%); transition: transform 0.3s ease; | |
| z-index: 100; padding: 20px; box-sizing: border-box; | |
| } | |
| #sidebar.open { transform: translateX(0); } | |
| #sidebar-tab { | |
| position: absolute; left: -40px; top: 50%; transform: translateY(-50%); | |
| width: 40px; height: 70px; | |
| /* Sidebar match */ | |
| background: #1e293b; | |
| /* The blue color from your original design */ | |
| color: #38bdf8; | |
| border: none; border-radius: 8px 0 0 8px; cursor: pointer; | |
| box-shadow: -5px 0 10px rgba(0,0,0,0.1); display: flex; | |
| align-items: center; justify-content: center; font-size: 1.2rem; | |
| border-left: 1px solid #334155; border-top: 1px solid #334155; border-bottom: 1px solid #334155; | |
| padding: 0; transition: all 0.2s ease; | |
| } | |
| #sidebar-tab:hover { | |
| background: #334155; | |
| /* Brighter blue on hover */ | |
| color: #7dd3fc; | |
| /* Subtle blue glow */ | |
| box-shadow: -2px 0 15px rgba(56, 189, 248, 0.3); | |
| } | |
| h2 { color: #38bdf8; } | |
| .research-text { line-height: 1.8; font-size: 1.1rem; color: #cbd5e1; } | |
| #chat-output { flex: 1; overflow-y: auto; margin-bottom: 10px; font-size: 0.95rem; line-height: 1.6; border-bottom: 1px solid #334155; padding-bottom: 10px; } | |
| .ai-msg { background: #0f172a; padding: 15px; border-radius: 8px; margin-top: 10px; border-left: 4px solid #38bdf8; } | |
| ::selection { background: #38bdf8; color: #0f172a; } | |
| .cursor-blink { animation: blink 1s step-end infinite; color: #38bdf8; } | |
| @keyframes blink { 50% { opacity: 0; } } | |
| /* FOOLPROOF FLEXBOX INPUT LAYOUT */ | |
| .input-container { | |
| display: flex; | |
| align-items: flex-end; /* Keeps button at the bottom when typing long messages */ | |
| gap: 10px; | |
| margin-top: 10px; | |
| width: 100%; | |
| } | |
| #chat-input { | |
| flex: 1; | |
| background: #0f172a; border: 1px solid #334155; color: white; | |
| padding: 12px; | |
| border-radius: 8px; box-sizing: border-box; outline: none; | |
| resize: none; overflow-y: hidden; min-height: 45px; max-height: 150px; | |
| font-family: inherit; font-size: 0.95rem; | |
| } | |
| #chat-input:focus { border-color: #38bdf8; } | |
| #send-btn { | |
| flex-shrink: 0; /* Prevents button from shrinking */ | |
| background: #38bdf8; | |
| color: #0f172a; | |
| border: none; | |
| border-radius: 8px; | |
| width: 45px; | |
| height: 45px; /* Exactly matches the minimum height of the text area */ | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: transform 0.1s, background 0.2s, opacity 0.2s; | |
| } | |
| #send-btn:hover { background: #7dd3fc; } | |
| #send-btn:active { transform: scale(0.9); } | |
| /* Mobile Adjustment */ | |
| @media (max-width: 600px) { | |
| :root { --sidebar-width: 100%; } | |
| #sidebar-tab { width: 50px; height: 50px; left: -50px; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="content-area"> | |
| <h2>Research Material</h2> | |
| <div class="research-text"> | |
| <p>In Flow Matching, the transition is defined by the ODE: $dx = v_t(x)dt$. | |
| This vector field $v_t$ defines the velocity at each point in space-time to push samples from $p_0$ to $p_1$.</p> | |
| <p>The forward diffusion process adds noise $q(x_t | x_{t-1}) = \mathcal{N}(x_t; \sqrt{1-\beta_t}x_{t-1}, \beta_t I)$. | |
| As $t$ increases, the original structure of the image is lost to Gaussian randomness.</p> | |
| <p>Copy any text above and paste it into the sidebar with your question!</p> | |
| </div> | |
| </div> | |
| <div id="sidebar"> | |
| <button id="sidebar-tab" onclick="toggleSidebar()" title="Toggle Ask Julia"> | |
| <span id="tab-icon">◀</span> | |
| </button> | |
| <h3>Ask Julia</h3> | |
| <div id="chat-output"> </div> | |
| <div class="input-container"> | |
| <textarea id="chat-input" rows="1" placeholder="@bot explain..."></textarea> | |
| <button id="send-btn" onclick="askBot()" title="Send"> | |
| <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| const sidebar = document.getElementById('sidebar'); | |
| const output = document.getElementById('chat-output'); | |
| const input = document.getElementById('chat-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const tabIcon = document.getElementById('tab-icon'); | |
| function toggleSidebar() { | |
| sidebar.classList.toggle('open'); | |
| document.body.classList.toggle('sidebar-active'); | |
| if (sidebar.classList.contains('open')) { | |
| tabIcon.innerText = "▶"; | |
| } else { | |
| tabIcon.innerText = "◀"; | |
| } | |
| } | |
| input.addEventListener('input', function() { | |
| this.style.height = 'auto'; | |
| this.style.height = this.scrollHeight + 'px'; | |
| this.style.overflowY = this.scrollHeight > 150 ? 'auto' : 'hidden'; | |
| }); | |
| function renderTextWithMath(text) { | |
| const mathBlocks = []; | |
| const mathRegex = /(\\$\\$[\\s\\S]*?\\$\\$|\\$[^\\$]*?\\$|\\\\\\[[\\s\\S]*?\\\\\\]|\\\\\\([\\s\\S]*?\\\\\\))/g; | |
| let placeholderText = text.replace(mathRegex, (match) => { | |
| mathBlocks.push(match); | |
| return `@@MATH_BLOCK_${mathBlocks.length - 1}@@`; | |
| }); | |
| let html = marked.parse(placeholderText); | |
| mathBlocks.forEach((math, index) => { | |
| html = html.replace(`@@MATH_BLOCK_${index}@@`, math); | |
| }); | |
| return html; | |
| } | |
| function typeARResponse(text, element) { | |
| return new Promise((resolve) => { | |
| let i = 0; | |
| let currentText = ""; | |
| const speed = 10; | |
| const chunkSize = 2; | |
| const interval = setInterval(() => { | |
| currentText += text.substring(i, i + chunkSize); | |
| i += chunkSize; | |
| element.innerHTML = renderTextWithMath(currentText) + '<span class="cursor-blink">▌</span>'; | |
| output.scrollTop = output.scrollHeight; | |
| if (i >= text.length) { | |
| clearInterval(interval); | |
| element.innerHTML = renderTextWithMath(text); | |
| resolve(); | |
| } | |
| }, speed); | |
| }); | |
| } | |
| async function askBot() { | |
| const query = input.value.trim(); | |
| if(!query.includes('@bot')) return; | |
| // Disable UI while waiting for response | |
| sendBtn.style.opacity = "0.5"; | |
| sendBtn.disabled = true; | |
| input.disabled = true; | |
| output.innerHTML += `<div><b>You:</b> ${query}</div><div class="ai-msg" id="last-response">Thinking...</div>`; | |
| input.value = ""; | |
| input.style.height = 'auto'; | |
| output.scrollTop = output.scrollHeight; | |
| try { | |
| const res = await fetch('/explain', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ page_text: "Context provided in query.", user_query: query }) | |
| }); | |
| const data = await res.json(); | |
| const lastResponse = document.getElementById('last-response'); | |
| lastResponse.removeAttribute('id'); | |
| await typeARResponse(data.reply, lastResponse); | |
| if (window.MathJax) MathJax.typesetPromise([lastResponse]); | |
| } catch (err) { | |
| document.getElementById('last-response').innerHTML = "<span style='color: #f87171;'>Error: Could not connect to backend.</span>"; | |
| } | |
| // Re-enable UI | |
| sendBtn.style.opacity = "1"; | |
| sendBtn.disabled = false; | |
| input.disabled = false; | |
| input.focus(); | |
| output.scrollTop = output.scrollHeight; | |
| } | |
| input.addEventListener('keydown', (e) => { | |
| if(e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| askBot(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |