Spaces:
Runtime error
Runtime error
| <html lang="en" class="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Ling 2.6 · Reasoning Engine</title> | |
| <meta name="description" content="Experience Ling-2.6-1T, a 1-trillion parameter reasoning model by inclusionAI. High-fidelity intelligence at your fingertips."> | |
| <!-- Fonts & Icons --> | |
| <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=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> | |
| <script src="https://unpkg.com/lucide@latest"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| <style> | |
| :root { | |
| --bg: #0a0a0c; | |
| --sidebar: #111114; | |
| --surface: #16161a; | |
| --border: rgba(255, 255, 255, 0.08); | |
| --accent: #8b5cf6; | |
| --accent-glow: rgba(139, 92, 246, 0.3); | |
| --text-primary: #f8fafc; | |
| --text-secondary: #94a3b8; | |
| --text-muted: #64748b; | |
| --user-bubble: #2d2d35; | |
| --ai-bubble: transparent; | |
| --radius-lg: 20px; | |
| --radius-md: 12px; | |
| --font-sans: 'Plus Jakarta Sans', sans-serif; | |
| --font-mono: 'JetBrains Mono', monospace; | |
| --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| body { | |
| background: var(--bg); | |
| color: var(--text-primary); | |
| font-family: var(--font-sans); | |
| height: 100vh; | |
| display: flex; | |
| overflow: hidden; | |
| } | |
| /* --- Sidebar --- */ | |
| #sidebar { | |
| width: 280px; | |
| background: var(--sidebar); | |
| border-right: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| transition: var(--transition); | |
| z-index: 100; | |
| } | |
| @media (max-width: 768px) { | |
| #sidebar { | |
| position: fixed; | |
| left: -280px; | |
| height: 100%; | |
| } | |
| #sidebar.open { | |
| left: 0; | |
| box-shadow: 20px 0 50px rgba(0,0,0,0.5); | |
| } | |
| } | |
| .sidebar-header { | |
| padding: 24px; | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .brand-logo { | |
| width: 32px; | |
| height: 32px; | |
| background: linear-gradient(135deg, var(--accent), #d8b4fe); | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| box-shadow: 0 0 15px var(--accent-glow); | |
| } | |
| .brand-name { | |
| font-weight: 700; | |
| font-size: 1.1rem; | |
| letter-spacing: -0.02em; | |
| } | |
| .new-chat-btn { | |
| margin: 0 16px 20px; | |
| padding: 12px; | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| color: var(--text-primary); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| font-size: 0.9rem; | |
| font-weight: 500; | |
| } | |
| .new-chat-btn:hover { | |
| border-color: var(--accent); | |
| background: rgba(139, 92, 246, 0.05); | |
| } | |
| .sidebar-nav { | |
| flex: 1; | |
| padding: 0 16px; | |
| overflow-y: auto; | |
| } | |
| .nav-section { | |
| margin-bottom: 24px; | |
| } | |
| .nav-label { | |
| font-size: 0.7rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| color: var(--text-muted); | |
| margin-bottom: 12px; | |
| padding-left: 8px; | |
| } | |
| .nav-item { | |
| padding: 10px 12px; | |
| border-radius: 8px; | |
| color: var(--text-secondary); | |
| font-size: 0.85rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .nav-item:hover { | |
| background: rgba(255, 255, 255, 0.03); | |
| color: var(--text-primary); | |
| } | |
| .sidebar-footer { | |
| padding: 20px; | |
| border-top: 1px solid var(--border); | |
| } | |
| /* --- Main Content --- */ | |
| #main { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| position: relative; | |
| background: radial-gradient(circle at top right, rgba(139, 92, 246, 0.03), transparent 40%); | |
| } | |
| header { | |
| height: 64px; | |
| display: flex; | |
| align-items: center; | |
| padding: 0 24px; | |
| border-bottom: 1px solid var(--border); | |
| justify-content: space-between; | |
| backdrop-filter: blur(10px); | |
| z-index: 50; | |
| } | |
| .header-left { | |
| display: flex; | |
| align-items: center; | |
| gap: 16px; | |
| } | |
| #menu-toggle { | |
| display: none; | |
| cursor: pointer; | |
| color: var(--text-secondary); | |
| } | |
| @media (max-width: 768px) { | |
| #menu-toggle { display: block; } | |
| } | |
| .model-badge { | |
| background: rgba(139, 92, 246, 0.1); | |
| color: var(--accent); | |
| padding: 4px 10px; | |
| border-radius: 20px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| border: 1px solid rgba(139, 92, 246, 0.2); | |
| } | |
| /* --- Chat Messages --- */ | |
| #chat-container { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 40px 0; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| scroll-behavior: smooth; | |
| } | |
| .message-wrap { | |
| width: 100%; | |
| max-width: 800px; | |
| padding: 24px 20px; | |
| display: flex; | |
| gap: 20px; | |
| animation: fadeIn 0.4s ease-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .message-wrap.user { | |
| background: transparent; | |
| } | |
| .avatar { | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 8px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex-shrink: 0; | |
| } | |
| .user .avatar { | |
| background: #3b82f6; | |
| color: white; | |
| } | |
| .ai .avatar { | |
| background: var(--accent); | |
| color: white; | |
| } | |
| .message-content { | |
| flex: 1; | |
| font-size: 0.95rem; | |
| line-height: 1.6; | |
| color: var(--text-primary); | |
| } | |
| .message-content p { | |
| margin-bottom: 12px; | |
| } | |
| .message-content p:last-child { | |
| margin-bottom: 0; | |
| } | |
| /* Markdown Styling */ | |
| .message-content pre { | |
| background: #0d0d0f; | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 16px; | |
| margin: 16px 0; | |
| overflow-x: auto; | |
| } | |
| .message-content code { | |
| font-family: var(--font-mono); | |
| font-size: 0.85rem; | |
| background: rgba(255,255,255,0.05); | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| } | |
| .message-content pre code { | |
| background: none; | |
| padding: 0; | |
| } | |
| /* --- Empty State --- */ | |
| #empty-state { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| text-align: center; | |
| padding: 20px; | |
| } | |
| .empty-icon { | |
| width: 64px; | |
| height: 64px; | |
| background: var(--surface); | |
| border-radius: 20px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin-bottom: 24px; | |
| color: var(--accent); | |
| border: 1px solid var(--border); | |
| } | |
| .empty-title { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| margin-bottom: 12px; | |
| } | |
| .empty-subtitle { | |
| color: var(--text-secondary); | |
| max-width: 400px; | |
| line-height: 1.6; | |
| } | |
| /* --- Input Bar --- */ | |
| #input-area { | |
| padding: 20px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| background: linear-gradient(transparent, var(--bg) 50%); | |
| } | |
| .input-container { | |
| width: 100%; | |
| max-width: 800px; | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: 24px; | |
| padding: 8px 12px; | |
| display: flex; | |
| align-items: flex-end; | |
| gap: 12px; | |
| transition: var(--transition); | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.2); | |
| } | |
| .input-container:focus-within { | |
| border-color: rgba(139, 92, 246, 0.5); | |
| box-shadow: 0 10px 40px rgba(139, 92, 246, 0.1); | |
| } | |
| #user-input { | |
| flex: 1; | |
| background: none; | |
| border: none; | |
| outline: none; | |
| color: var(--text-primary); | |
| padding: 12px 8px; | |
| font-family: inherit; | |
| font-size: 1rem; | |
| resize: none; | |
| max-height: 200px; | |
| min-height: 24px; | |
| } | |
| .action-btn { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| border: none; | |
| background: transparent; | |
| color: var(--text-secondary); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: var(--transition); | |
| } | |
| .action-btn:hover { | |
| background: rgba(255,255,255,0.05); | |
| color: var(--text-primary); | |
| } | |
| .send-btn { | |
| background: var(--accent); | |
| color: white; | |
| } | |
| .send-btn:hover { | |
| background: #7c3aed; | |
| transform: scale(1.05); | |
| } | |
| .send-btn:disabled { | |
| background: var(--border); | |
| color: var(--text-muted); | |
| cursor: not-allowed; | |
| transform: none; | |
| } | |
| .input-footer { | |
| margin-top: 12px; | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| } | |
| /* --- Scrollbar --- */ | |
| ::-webkit-scrollbar { width: 6px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; } | |
| ::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.15); } | |
| /* Typing Indicator */ | |
| .typing { | |
| display: flex; | |
| gap: 4px; | |
| padding: 8px 0; | |
| } | |
| .dot { | |
| width: 4px; | |
| height: 4px; | |
| background: var(--text-muted); | |
| border-radius: 50%; | |
| animation: bounce 1.4s infinite ease-in-out both; | |
| } | |
| .dot:nth-child(1) { animation-delay: -0.32s; } | |
| .dot:nth-child(2) { animation-delay: -0.16s; } | |
| @keyframes bounce { | |
| 0%, 80%, 100% { transform: scale(0); } | |
| 40% { transform: scale(1.0); } | |
| } | |
| /* System Prompt Panel */ | |
| #system-panel { | |
| position: absolute; | |
| top: 70px; | |
| right: 24px; | |
| width: 320px; | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-md); | |
| padding: 16px; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.3); | |
| display: none; | |
| z-index: 1000; | |
| animation: fadeIn 0.2s ease; | |
| } | |
| #system-panel.show { display: block; } | |
| #system-panel h3 { font-size: 0.9rem; margin-bottom: 10px; } | |
| #system-input { | |
| width: 100%; | |
| background: var(--bg); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| color: var(--text-primary); | |
| padding: 10px; | |
| font-size: 0.85rem; | |
| resize: vertical; | |
| min-height: 80px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <aside id="sidebar"> | |
| <div class="sidebar-header"> | |
| <div class="brand-logo"> | |
| <i data-lucide="brain-circuit"></i> | |
| </div> | |
| <span class="brand-name">Ling Engine</span> | |
| </div> | |
| <button class="new-chat-btn" onclick="clearConversation()"> | |
| <i data-lucide="plus" size="18"></i> | |
| New Chat | |
| </button> | |
| <div class="sidebar-nav"> | |
| <div class="nav-section"> | |
| <div class="nav-label">Recent</div> | |
| <div id="history-list"> | |
| <!-- History items will appear here --> | |
| <div class="nav-item"> | |
| <i data-lucide="message-square" size="16"></i> | |
| <span>Introduction to Ling</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="sidebar-footer"> | |
| <div class="nav-item"> | |
| <i data-lucide="settings" size="16"></i> | |
| <span>Settings</span> | |
| </div> | |
| </div> | |
| </aside> | |
| <main id="main"> | |
| <header> | |
| <div class="header-left"> | |
| <div id="menu-toggle" onclick="toggleSidebar()"> | |
| <i data-lucide="menu"></i> | |
| </div> | |
| <div class="model-badge">Ling-2.6-1T</div> | |
| </div> | |
| <div class="header-right" style="display: flex; gap: 12px;"> | |
| <button class="action-btn" title="System Prompt" onclick="toggleSystemPanel()"> | |
| <i data-lucide="sliders"></i> | |
| </button> | |
| <button class="action-btn" title="Clear Chat" onclick="clearConversation()"> | |
| <i data-lucide="trash-2"></i> | |
| </button> | |
| </div> | |
| <div id="system-panel"> | |
| <h3>System Instructions</h3> | |
| <textarea id="system-input" placeholder="Configure the model's behavior..."></textarea> | |
| </div> | |
| </header> | |
| <div id="chat-container"> | |
| <div id="empty-state"> | |
| <div class="empty-icon"> | |
| <i data-lucide="sparkles" size="32"></i> | |
| </div> | |
| <h1 class="empty-title">How can I help you today?</h1> | |
| <p class="empty-subtitle">Ling-2.6-1T is a trillion-parameter reasoning model capable of complex problem solving, coding, and creative analysis.</p> | |
| <div style="display: flex; gap: 10px; margin-top: 32px; flex-wrap: wrap; justify-content: center;"> | |
| <div class="new-chat-btn" style="margin:0; padding: 12px 20px;" onclick="useSuggestion('Explain quantum entanglement')"> | |
| Quantum Physics | |
| </div> | |
| <div class="new-chat-btn" style="margin:0; padding: 12px 20px;" onclick="useSuggestion('Write a fast API with Rust')"> | |
| Coding Help | |
| </div> | |
| <div class="new-chat-btn" style="margin:0; padding: 12px 20px;" onclick="useSuggestion('Write a sci-fi short story')"> | |
| Creative Writing | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="input-area"> | |
| <div class="input-container"> | |
| <button class="action-btn"> | |
| <i data-lucide="paperclip" size="20"></i> | |
| </button> | |
| <textarea id="user-input" placeholder="Message Ling..." rows="1"></textarea> | |
| <button id="send-btn" class="action-btn send-btn" onclick="sendMessage()"> | |
| <i data-lucide="arrow-up" size="20"></i> | |
| </button> | |
| </div> | |
| <div class="input-footer"> | |
| Ling can make mistakes. Check important info. | |
| </div> | |
| </div> | |
| </main> | |
| <script> | |
| lucide.createIcons(); | |
| const chatContainer = document.getElementById('chat-container'); | |
| const userInput = document.getElementById('user-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const emptyState = document.getElementById('empty-state'); | |
| const systemInput = document.getElementById('system-input'); | |
| const sidebar = document.getElementById('sidebar'); | |
| let history = []; | |
| let isStreaming = false; | |
| // Auto-resize textarea | |
| userInput.addEventListener('input', () => { | |
| userInput.style.height = 'auto'; | |
| userInput.style.height = userInput.scrollHeight + 'px'; | |
| }); | |
| userInput.addEventListener('keydown', (e) => { | |
| if (e.key === 'Enter' && !e.shiftKey) { | |
| e.preventDefault(); | |
| sendMessage(); | |
| } | |
| }); | |
| function toggleSidebar() { | |
| sidebar.classList.toggle('open'); | |
| } | |
| function toggleSystemPanel() { | |
| document.getElementById('system-panel').classList.toggle('show'); | |
| } | |
| function useSuggestion(text) { | |
| userInput.value = text; | |
| userInput.style.height = 'auto'; | |
| userInput.style.height = userInput.scrollHeight + 'px'; | |
| sendMessage(); | |
| } | |
| function clearConversation() { | |
| history = []; | |
| chatContainer.innerHTML = ''; | |
| chatContainer.appendChild(emptyState); | |
| emptyState.style.display = 'flex'; | |
| } | |
| function appendMessage(role, content = '') { | |
| if (emptyState.style.display !== 'none') { | |
| emptyState.style.display = 'none'; | |
| } | |
| const wrap = document.createElement('div'); | |
| wrap.className = `message-wrap ${role}`; | |
| const avatar = document.createElement('div'); | |
| avatar.className = 'avatar'; | |
| avatar.innerHTML = role === 'user' ? '<i data-lucide="user" size="20"></i>' : '<i data-lucide="bot" size="20"></i>'; | |
| const msgContent = document.createElement('div'); | |
| msgContent.className = 'message-content'; | |
| if (role === 'ai' && content === '') { | |
| msgContent.innerHTML = '<div class="typing"><div class="dot"></div><div class="dot"></div><div class="dot"></div></div>'; | |
| } else { | |
| msgContent.innerHTML = marked.parse(content); | |
| } | |
| wrap.appendChild(avatar); | |
| wrap.appendChild(msgContent); | |
| chatContainer.appendChild(wrap); | |
| lucide.createIcons(); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| return msgContent; | |
| } | |
| async function sendMessage() { | |
| const text = userInput.value.trim(); | |
| if (!text || isStreaming) return; | |
| userInput.value = ''; | |
| userInput.style.height = 'auto'; | |
| isStreaming = true; | |
| sendBtn.disabled = true; | |
| appendMessage('user', text); | |
| history.push({ role: 'user', content: text }); | |
| const aiMsgEl = appendMessage('ai', ''); | |
| let accumulated = ''; | |
| try { | |
| const response = await fetch('/stream_chat', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| messages: history, | |
| system_prompt: systemInput.value | |
| }) | |
| }); | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder(); | |
| aiMsgEl.innerHTML = ''; // Remove typing indicator | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| const chunk = decoder.decode(value); | |
| const lines = chunk.split('\n\n'); | |
| for (const line of lines) { | |
| if (line.startsWith('data: ')) { | |
| const data = line.slice(6).trim(); | |
| if (data === '[DONE]') break; | |
| try { | |
| const parsed = JSON.parse(data); | |
| if (parsed.error) { | |
| accumulated = `<span style="color: #ef4444;">Error: ${parsed.error}</span>`; | |
| aiMsgEl.innerHTML = accumulated; | |
| break; | |
| } | |
| if (parsed.token) { | |
| accumulated += parsed.token; | |
| aiMsgEl.innerHTML = marked.parse(accumulated); | |
| chatContainer.scrollTop = chatContainer.scrollHeight; | |
| } | |
| } catch (e) {} | |
| } | |
| } | |
| } | |
| } catch (error) { | |
| aiMsgEl.innerHTML = '<span style="color: #ef4444;">Error: Connection failed</span>'; | |
| } finally { | |
| isStreaming = false; | |
| sendBtn.disabled = false; | |
| history.push({ role: 'assistant', content: accumulated }); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> | |