akhaliq HF Staff commited on
Commit
e5ed48c
·
1 Parent(s): 47e787a

feat: add UI and project configuration for Ling-2.6-1T chat interface

Browse files
Files changed (3) hide show
  1. README.md +16 -4
  2. index.html +308 -0
  3. requirements.txt +2 -0
README.md CHANGED
@@ -1,8 +1,8 @@
1
  ---
2
  title: Ling 2.6 1T
3
- emoji: 🏆
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: gradio
7
  sdk_version: 6.14.0
8
  python_version: '3.13'
@@ -10,4 +10,16 @@ app_file: app.py
10
  pinned: false
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Ling 2.6 1T
3
+ emoji: 🧠
4
+ colorFrom: purple
5
+ colorTo: blue
6
  sdk: gradio
7
  sdk_version: 6.14.0
8
  python_version: '3.13'
 
10
  pinned: false
11
  ---
12
 
13
+ # Ling 2.6 · 1T Chat
14
+
15
+ Chat interface for [inclusionAI/Ling-2.6-1T](https://huggingface.co/inclusionAI/Ling-2.6-1T) routed via Hugging Face Inference Router.
16
+
17
+ ## Setup
18
+
19
+ Set the `HF_TOKEN` secret in your Space settings.
20
+
21
+ ## Architecture
22
+
23
+ - **Backend**: `gradio.Server` (FastAPI + Gradio queuing)
24
+ - **Frontend**: Custom HTML/CSS/JS with SSE streaming
25
+ - **Model**: `inclusionAI/Ling-2.6-1T:novita` via HF Router
index.html ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8"/>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
6
+ <title>Ling 2.6 1T · Chat</title>
7
+ <meta name="description" content="Chat with inclusionAI Ling-2.6-1T, a powerful 1-trillion parameter reasoning model, via Hugging Face Inference."/>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com"/>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"/>
10
+ <style>
11
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
12
+ :root{
13
+ --bg:#08090c;
14
+ --surface:#10121a;
15
+ --glass:rgba(255,255,255,0.04);
16
+ --border:rgba(255,255,255,0.08);
17
+ --accent:#7c6aff;
18
+ --accent2:#a78bfa;
19
+ --glow:rgba(124,106,255,0.25);
20
+ --text:#e8eaf0;
21
+ --muted:#6b7280;
22
+ --user-bg:rgba(124,106,255,0.15);
23
+ --ai-bg:rgba(255,255,255,0.04);
24
+ --radius:16px;
25
+ --font:'Inter',sans-serif;
26
+ --mono:'JetBrains Mono',monospace;
27
+ }
28
+ html,body{height:100%;background:var(--bg);color:var(--text);font-family:var(--font);overflow:hidden}
29
+
30
+ /* animated gradient orbs */
31
+ body::before,body::after{
32
+ content:'';position:fixed;border-radius:50%;filter:blur(120px);pointer-events:none;z-index:0;
33
+ }
34
+ body::before{width:600px;height:600px;background:radial-gradient(circle,rgba(124,106,255,.18),transparent 70%);top:-150px;left:-100px;animation:drift1 18s ease-in-out infinite alternate}
35
+ body::after{width:500px;height:500px;background:radial-gradient(circle,rgba(99,200,255,.12),transparent 70%);bottom:-100px;right:-80px;animation:drift2 22s ease-in-out infinite alternate}
36
+ @keyframes drift1{to{transform:translate(80px,60px)}}
37
+ @keyframes drift2{to{transform:translate(-60px,-40px)}}
38
+
39
+ /* layout */
40
+ #app{position:relative;z-index:1;display:flex;flex-direction:column;height:100vh;max-width:900px;margin:0 auto;padding:0 16px}
41
+
42
+ /* header */
43
+ header{display:flex;align-items:center;gap:14px;padding:20px 0 16px;border-bottom:1px solid var(--border);flex-shrink:0}
44
+ .logo{width:42px;height:42px;border-radius:12px;background:linear-gradient(135deg,var(--accent),#a78bfa);display:flex;align-items:center;justify-content:center;font-size:20px;box-shadow:0 0 24px var(--glow)}
45
+ .header-text h1{font-size:1.15rem;font-weight:700;background:linear-gradient(90deg,#fff,var(--accent2));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
46
+ .header-text p{font-size:.75rem;color:var(--muted);margin-top:2px}
47
+ .badge{margin-left:auto;font-size:.65rem;font-weight:600;padding:4px 10px;border-radius:20px;border:1px solid var(--accent);color:var(--accent2);letter-spacing:.05em;text-transform:uppercase;white-space:nowrap}
48
+
49
+ /* system prompt toggle */
50
+ #sys-toggle-wrap{padding:10px 0 4px;flex-shrink:0}
51
+ #sys-toggle{background:none;border:1px solid var(--border);color:var(--muted);font-size:.78rem;font-family:var(--font);padding:6px 14px;border-radius:8px;cursor:pointer;transition:all .2s;display:flex;align-items:center;gap:6px}
52
+ #sys-toggle:hover{border-color:var(--accent);color:var(--accent2)}
53
+ #sys-panel{display:none;margin-top:8px;background:var(--glass);border:1px solid var(--border);border-radius:var(--radius);padding:12px;backdrop-filter:blur(12px)}
54
+ #sys-panel.open{display:block}
55
+ #system-prompt{width:100%;background:transparent;border:none;color:var(--text);font-family:var(--font);font-size:.82rem;resize:none;outline:none;min-height:60px;line-height:1.6}
56
+ #system-prompt::placeholder{color:var(--muted)}
57
+
58
+ /* messages */
59
+ #messages{flex:1;overflow-y:auto;padding:16px 0 8px;display:flex;flex-direction:column;gap:14px;scroll-behavior:smooth}
60
+ #messages::-webkit-scrollbar{width:4px}
61
+ #messages::-webkit-scrollbar-track{background:transparent}
62
+ #messages::-webkit-scrollbar-thumb{background:var(--border);border-radius:4px}
63
+
64
+ .msg{display:flex;gap:12px;animation:fadeUp .3s ease}
65
+ @keyframes fadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
66
+ .msg.user{flex-direction:row-reverse}
67
+ .avatar{width:34px;height:34px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0;align-self:flex-start;margin-top:2px}
68
+ .msg.user .avatar{background:linear-gradient(135deg,var(--accent),#a78bfa)}
69
+ .msg.ai .avatar{background:var(--glass);border:1px solid var(--border)}
70
+ .bubble{max-width:78%;padding:12px 16px;border-radius:var(--radius);font-size:.88rem;line-height:1.7;white-space:pre-wrap;word-break:break-word}
71
+ .msg.user .bubble{background:var(--user-bg);border:1px solid rgba(124,106,255,.3);border-top-right-radius:4px}
72
+ .msg.ai .bubble{background:var(--ai-bg);border:1px solid var(--border);border-top-left-radius:4px}
73
+
74
+ /* code blocks inside bubbles */
75
+ .bubble code{font-family:var(--mono);font-size:.8rem;background:rgba(0,0,0,.4);padding:2px 6px;border-radius:4px;color:#a5f3fc}
76
+ .bubble pre{background:rgba(0,0,0,.5);border:1px solid var(--border);border-radius:10px;padding:12px;margin:8px 0;overflow-x:auto}
77
+ .bubble pre code{background:none;padding:0}
78
+
79
+ /* typing cursor */
80
+ .cursor{display:inline-block;width:2px;height:1em;background:var(--accent2);margin-left:2px;animation:blink .7s step-end infinite;vertical-align:text-bottom}
81
+ @keyframes blink{0%,100%{opacity:1}50%{opacity:0}}
82
+
83
+ /* empty state */
84
+ #empty{display:flex;flex-direction:column;align-items:center;justify-content:center;flex:1;gap:12px;color:var(--muted);text-align:center;pointer-events:none;user-select:none}
85
+ #empty .big-icon{font-size:48px;opacity:.4}
86
+ #empty p{font-size:.85rem;max-width:320px;line-height:1.7}
87
+ #empty.hidden{display:none}
88
+
89
+ /* suggestions */
90
+ #suggestions{display:flex;flex-wrap:wrap;gap:8px;padding:8px 0;flex-shrink:0}
91
+ .sug{background:var(--glass);border:1px solid var(--border);border-radius:10px;padding:8px 14px;font-size:.78rem;color:var(--muted);cursor:pointer;transition:all .2s;line-height:1.4}
92
+ .sug:hover{border-color:var(--accent);color:var(--accent2);background:rgba(124,106,255,.08)}
93
+ #suggestions.hidden{display:none}
94
+
95
+ /* input bar */
96
+ #input-wrap{flex-shrink:0;padding:12px 0 20px}
97
+ #input-box{display:flex;align-items:flex-end;gap:10px;background:var(--glass);border:1px solid var(--border);border-radius:20px;padding:12px 14px;backdrop-filter:blur(16px);transition:border-color .2s,box-shadow .2s}
98
+ #input-box:focus-within{border-color:rgba(124,106,255,.5);box-shadow:0 0 0 3px rgba(124,106,255,.1)}
99
+ #user-input{flex:1;background:none;border:none;outline:none;color:var(--text);font-family:var(--font);font-size:.9rem;resize:none;max-height:160px;line-height:1.6;overflow-y:auto}
100
+ #user-input::placeholder{color:var(--muted)}
101
+ #send-btn{width:38px;height:38px;border-radius:12px;background:linear-gradient(135deg,var(--accent),#a78bfa);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:transform .15s,box-shadow .2s;box-shadow:0 0 16px var(--glow)}
102
+ #send-btn:hover:not(:disabled){transform:scale(1.07);box-shadow:0 0 24px var(--glow)}
103
+ #send-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
104
+ #send-btn svg{width:18px;height:18px;fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
105
+
106
+ /* clear btn */
107
+ #clear-btn{background:none;border:1px solid var(--border);color:var(--muted);font-size:.75rem;font-family:var(--font);padding:5px 12px;border-radius:8px;cursor:pointer;transition:all .2s;flex-shrink:0;align-self:center}
108
+ #clear-btn:hover{border-color:#ef4444;color:#f87171}
109
+
110
+ /* footer */
111
+ footer{text-align:center;font-size:.68rem;color:var(--muted);padding-bottom:8px;flex-shrink:0}
112
+ footer a{color:var(--accent2);text-decoration:none}
113
+ </style>
114
+ </head>
115
+ <body>
116
+ <div id="app">
117
+ <header>
118
+ <div class="logo">🧠</div>
119
+ <div class="header-text">
120
+ <h1>Ling 2.6 · 1T</h1>
121
+ <p>inclusionAI · via Hugging Face Router</p>
122
+ </div>
123
+ <div class="badge">novita</div>
124
+ <button id="clear-btn" title="Clear conversation">Clear</button>
125
+ </header>
126
+
127
+ <div id="sys-toggle-wrap">
128
+ <button id="sys-toggle">⚙️ System prompt <span id="sys-arrow">▾</span></button>
129
+ <div id="sys-panel">
130
+ <textarea id="system-prompt" rows="3" placeholder="Optional system instructions… e.g. 'You are a concise coding assistant.'"></textarea>
131
+ </div>
132
+ </div>
133
+
134
+ <div id="messages">
135
+ <div id="empty">
136
+ <div class="big-icon">💬</div>
137
+ <p>Ask Ling-2.6-1T anything — math, reasoning, code, or open-ended questions.</p>
138
+ </div>
139
+ </div>
140
+
141
+ <div id="suggestions">
142
+ <div class="sug" onclick="useSuggestion(this)">🔢 Prove that √2 is irrational</div>
143
+ <div class="sug" onclick="useSuggestion(this)">🐍 Write a binary search in Python</div>
144
+ <div class="sug" onclick="useSuggestion(this)">🌍 What is the capital of France?</div>
145
+ <div class="sug" onclick="useSuggestion(this)">🧩 Explain attention in transformers</div>
146
+ </div>
147
+
148
+ <div id="input-wrap">
149
+ <div id="input-box">
150
+ <textarea id="user-input" placeholder="Message Ling…" rows="1" id="user-input"></textarea>
151
+ <button id="send-btn" title="Send">
152
+ <svg viewBox="0 0 24 24"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
153
+ </button>
154
+ </div>
155
+ </div>
156
+ <footer>Powered by <a href="https://huggingface.co/inclusionAI/Ling-2.6-1T" target="_blank">inclusionAI/Ling-2.6-1T</a> · Gradio Server</footer>
157
+ </div>
158
+
159
+ <script>
160
+ const messagesEl = document.getElementById('messages');
161
+ const inputEl = document.getElementById('user-input');
162
+ const sendBtn = document.getElementById('send-btn');
163
+ const emptyEl = document.getElementById('empty');
164
+ const sugsEl = document.getElementById('suggestions');
165
+ const sysToggle = document.getElementById('sys-toggle');
166
+ const sysPanel = document.getElementById('sys-panel');
167
+ const sysArrow = document.getElementById('sys-arrow');
168
+ const sysInput = document.getElementById('system-prompt');
169
+ const clearBtn = document.getElementById('clear-btn');
170
+
171
+ let history = []; // [{role,content}]
172
+ let streaming = false;
173
+
174
+ // System prompt toggle
175
+ sysToggle.addEventListener('click', () => {
176
+ sysPanel.classList.toggle('open');
177
+ sysArrow.textContent = sysPanel.classList.contains('open') ? '▴' : '▾';
178
+ });
179
+
180
+ // Auto-resize textarea
181
+ inputEl.addEventListener('input', () => {
182
+ inputEl.style.height = 'auto';
183
+ inputEl.style.height = Math.min(inputEl.scrollHeight, 160) + 'px';
184
+ });
185
+
186
+ // Send on Enter (Shift+Enter = newline)
187
+ inputEl.addEventListener('keydown', e => {
188
+ if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); }
189
+ });
190
+ sendBtn.addEventListener('click', sendMessage);
191
+ clearBtn.addEventListener('click', clearConversation);
192
+
193
+ function useSuggestion(el) {
194
+ inputEl.value = el.textContent.replace(/^[^\s]+\s/, '');
195
+ inputEl.focus();
196
+ sendMessage();
197
+ }
198
+
199
+ function clearConversation() {
200
+ history = [];
201
+ messagesEl.innerHTML = '<div id="empty"><div class="big-icon">💬</div><p>Ask Ling-2.6-1T anything — math, reasoning, code, or open-ended questions.</p></div>';
202
+ emptyEl && (emptyEl.classList.remove('hidden'));
203
+ sugsEl.classList.remove('hidden');
204
+ }
205
+
206
+ function appendMsg(role, content = '') {
207
+ const empt = document.getElementById('empty');
208
+ if (empt) empt.remove();
209
+ sugsEl.classList.add('hidden');
210
+
211
+ const wrap = document.createElement('div');
212
+ wrap.className = `msg ${role}`;
213
+ const av = document.createElement('div');
214
+ av.className = 'avatar';
215
+ av.textContent = role === 'user' ? '🧑' : '🤖';
216
+ const bub = document.createElement('div');
217
+ bub.className = 'bubble';
218
+ bub.textContent = content;
219
+ wrap.appendChild(av);
220
+ wrap.appendChild(bub);
221
+ messagesEl.appendChild(wrap);
222
+ messagesEl.scrollTop = messagesEl.scrollHeight;
223
+ return bub;
224
+ }
225
+
226
+ function setBubbleContent(bub, text) {
227
+ // Simple markdown: code fences and inline code
228
+ let escaped = text
229
+ .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
230
+ // code fences
231
+ escaped = escaped.replace(/```([\w]*)\n?([\s\S]*?)```/g,
232
+ (_,lang,code) => `<pre><code>${code.trimEnd()}</code></pre>`);
233
+ // inline code
234
+ escaped = escaped.replace(/`([^`]+)`/g, '<code>$1</code>');
235
+ // bold
236
+ escaped = escaped.replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>');
237
+ bub.innerHTML = escaped;
238
+ }
239
+
240
+ async function sendMessage() {
241
+ const text = inputEl.value.trim();
242
+ if (!text || streaming) return;
243
+
244
+ inputEl.value = '';
245
+ inputEl.style.height = 'auto';
246
+ sendBtn.disabled = true;
247
+ streaming = true;
248
+
249
+ history.push({ role: 'user', content: text });
250
+ appendMsg('user', text);
251
+
252
+ const aiBub = appendMsg('ai', '');
253
+ const cursor = document.createElement('span');
254
+ cursor.className = 'cursor';
255
+ aiBub.appendChild(cursor);
256
+
257
+ let accumulated = '';
258
+
259
+ try {
260
+ const resp = await fetch('/stream_chat', {
261
+ method: 'POST',
262
+ headers: { 'Content-Type': 'application/json' },
263
+ body: JSON.stringify({
264
+ messages: history,
265
+ system_prompt: sysInput.value,
266
+ }),
267
+ });
268
+
269
+ const reader = resp.body.getReader();
270
+ const decoder = new TextDecoder();
271
+ let buf = '';
272
+
273
+ while (true) {
274
+ const { done, value } = await reader.read();
275
+ if (done) break;
276
+ buf += decoder.decode(value, { stream: true });
277
+ const parts = buf.split('\n\n');
278
+ buf = parts.pop();
279
+ for (const part of parts) {
280
+ if (!part.startsWith('data:')) continue;
281
+ const raw = part.slice(5).trim();
282
+ if (raw === '[DONE]') break;
283
+ try {
284
+ const { token } = JSON.parse(raw);
285
+ accumulated += token;
286
+ cursor.remove();
287
+ setBubbleContent(aiBub, accumulated);
288
+ aiBub.appendChild(cursor);
289
+ messagesEl.scrollTop = messagesEl.scrollHeight;
290
+ } catch {}
291
+ }
292
+ }
293
+ } catch (err) {
294
+ accumulated = '⚠️ Error: ' + err.message;
295
+ setBubbleContent(aiBub, accumulated);
296
+ }
297
+
298
+ cursor.remove();
299
+ setBubbleContent(aiBub, accumulated);
300
+ history.push({ role: 'assistant', content: accumulated });
301
+ streaming = false;
302
+ sendBtn.disabled = false;
303
+ inputEl.focus();
304
+ messagesEl.scrollTop = messagesEl.scrollHeight;
305
+ }
306
+ </script>
307
+ </body>
308
+ </html>
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio>=5.0.0
2
+ openai>=1.0.0