reach-vb HF Staff commited on
Commit
86a4e7b
·
verified ·
1 Parent(s): 0eb789f

Doesn't work - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +337 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Hugging Chat
3
- emoji: 🚀
4
- colorFrom: red
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: hugging-chat
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,337 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>HuggingChat | Minimal AI Interface</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/@huggingface/inference"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ .message-stream::after {
12
+ content: "";
13
+ width: 8px;
14
+ height: 20px;
15
+ background: #3b82f6;
16
+ display: inline-block;
17
+ animation: cursor-blink 1s infinite;
18
+ vertical-align: middle;
19
+ margin-left: 2px;
20
+ }
21
+
22
+ @keyframes cursor-blink {
23
+ 0% { opacity: 0; }
24
+ 50% { opacity: 1; }
25
+ 100% { opacity: 0; }
26
+ }
27
+
28
+ .gradient-bg {
29
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
30
+ }
31
+
32
+ .chat-container {
33
+ height: calc(100vh - 160px);
34
+ }
35
+
36
+ @media (max-width: 640px) {
37
+ .chat-container {
38
+ height: calc(100vh - 140px);
39
+ }
40
+ }
41
+ </style>
42
+ </head>
43
+ <body class="gradient-bg min-h-screen font-sans">
44
+ <div class="container mx-auto px-4 py-6 max-w-4xl">
45
+ <!-- Header -->
46
+ <header class="flex justify-between items-center mb-6">
47
+ <div class="flex items-center">
48
+ <img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" alt="Hugging Face" class="h-8 mr-3">
49
+ <h1 class="text-2xl font-bold text-gray-800">HuggingChat</h1>
50
+ </div>
51
+ <div id="auth-section">
52
+ <button id="login-btn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg flex items-center">
53
+ <i class="fas fa-sign-in-alt mr-2"></i> Login with Hugging Face
54
+ </button>
55
+ <div id="user-info" class="hidden items-center">
56
+ <img id="user-avatar" class="w-8 h-8 rounded-full mr-2" src="">
57
+ <span id="username" class="font-medium text-gray-700"></span>
58
+ <button id="logout-btn" class="ml-4 text-gray-500 hover:text-gray-700">
59
+ <i class="fas fa-sign-out-alt"></i>
60
+ </button>
61
+ </div>
62
+ </div>
63
+ </header>
64
+
65
+ <!-- Chat Container -->
66
+ <div class="bg-white rounded-xl shadow-lg overflow-hidden">
67
+ <div class="chat-container overflow-y-auto p-4" id="chat-messages">
68
+ <div class="text-center py-10 text-gray-400" id="empty-state">
69
+ <i class="fas fa-comments text-4xl mb-3"></i>
70
+ <p class="text-lg">Start a conversation with the AI</p>
71
+ <p class="text-sm mt-1">Your messages will appear here</p>
72
+ </div>
73
+ </div>
74
+
75
+ <!-- Input Area -->
76
+ <div class="border-t border-gray-200 p-4 bg-gray-50">
77
+ <div class="flex items-end">
78
+ <div class="flex-grow relative">
79
+ <textarea
80
+ id="message-input"
81
+ class="w-full border border-gray-300 rounded-lg px-4 py-3 pr-12 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
82
+ placeholder="Type your message..."
83
+ rows="1"
84
+ disabled
85
+ ></textarea>
86
+ <button id="send-btn" class="absolute right-3 bottom-3 text-blue-500 hover:text-blue-600 disabled:text-gray-400" disabled>
87
+ <i class="fas fa-paper-plane text-xl"></i>
88
+ </button>
89
+ </div>
90
+ </div>
91
+
92
+ <div class="mt-3 flex items-center justify-between">
93
+ <div class="flex items-center space-x-2">
94
+ <label for="model-select" class="text-sm text-gray-600">Model:</label>
95
+ <select id="model-select" class="text-sm border border-gray-300 rounded px-2 py-1 bg-white">
96
+ <option value="deepseek-ai/DeepSeek-R1-0528">DeepSeek-R1-0528</option>
97
+ <option value="meta-llama/Meta-Llama-3-8B-Instruct">Llama 3 8B</option>
98
+ <option value="mistralai/Mistral-7B-Instruct-v0.2">Mistral 7B</option>
99
+ </select>
100
+ </div>
101
+ <div class="text-xs text-gray-500">
102
+ <span id="token-counter">0 tokens</span>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <script>
110
+ // DOM Elements
111
+ const loginBtn = document.getElementById('login-btn');
112
+ const logoutBtn = document.getElementById('logout-btn');
113
+ const userInfo = document.getElementById('user-info');
114
+ const userAvatar = document.getElementById('user-avatar');
115
+ const username = document.getElementById('username');
116
+ const messageInput = document.getElementById('message-input');
117
+ const sendBtn = document.getElementById('send-btn');
118
+ const chatMessages = document.getElementById('chat-messages');
119
+ const emptyState = document.getElementById('empty-state');
120
+ const modelSelect = document.getElementById('model-select');
121
+ const tokenCounter = document.getElementById('token-counter');
122
+
123
+ // State
124
+ let hfClient = null;
125
+ let currentUser = null;
126
+ let currentStream = null;
127
+ let isGenerating = false;
128
+ let messageCount = 0;
129
+
130
+ // Initialize
131
+ checkAuth();
132
+
133
+ // Event Listeners
134
+ loginBtn.addEventListener('click', handleLogin);
135
+ logoutBtn.addEventListener('click', handleLogout);
136
+ sendBtn.addEventListener('click', sendMessage);
137
+ messageInput.addEventListener('keydown', (e) => {
138
+ if (e.key === 'Enter' && !e.shiftKey) {
139
+ e.preventDefault();
140
+ if (!isGenerating) sendMessage();
141
+ }
142
+ });
143
+
144
+ messageInput.addEventListener('input', () => {
145
+ // Auto-resize textarea
146
+ messageInput.style.height = 'auto';
147
+ messageInput.style.height = (messageInput.scrollHeight) + 'px';
148
+
149
+ // Enable/disable send button
150
+ sendBtn.disabled = messageInput.value.trim() === '' || isGenerating;
151
+ });
152
+
153
+ // Functions
154
+ function checkAuth() {
155
+ const token = localStorage.getItem('hf_token');
156
+ const user = localStorage.getItem('hf_user');
157
+
158
+ if (token && user) {
159
+ currentUser = JSON.parse(user);
160
+ setupAuthenticatedUI(token);
161
+ }
162
+ }
163
+
164
+ function handleLogin() {
165
+ // In a real app, you would use OAuth flow
166
+ // For demo purposes, we'll simulate it with a prompt
167
+ const token = prompt("Enter your Hugging Face token:");
168
+
169
+ if (token) {
170
+ // Simulate getting user info
171
+ const demoUser = {
172
+ name: "Demo User",
173
+ avatar: "https://ui-avatars.com/api/?name=Demo+User&background=3b82f6&color=fff"
174
+ };
175
+
176
+ localStorage.setItem('hf_token', token);
177
+ localStorage.setItem('hf_user', JSON.stringify(demoUser));
178
+ currentUser = demoUser;
179
+
180
+ setupAuthenticatedUI(token);
181
+ }
182
+ }
183
+
184
+ function handleLogout() {
185
+ localStorage.removeItem('hf_token');
186
+ localStorage.removeItem('hf_user');
187
+ currentUser = null;
188
+ hfClient = null;
189
+
190
+ // Reset UI
191
+ loginBtn.classList.remove('hidden');
192
+ userInfo.classList.add('hidden');
193
+ messageInput.disabled = true;
194
+ sendBtn.disabled = true;
195
+
196
+ // Clear chat
197
+ chatMessages.innerHTML = emptyState.outerHTML;
198
+ messageCount = 0;
199
+ }
200
+
201
+ function setupAuthenticatedUI(token) {
202
+ // Initialize HF client
203
+ hfClient = new HuggingFace.inference.InferenceApi(token);
204
+
205
+ // Update UI
206
+ loginBtn.classList.add('hidden');
207
+ userInfo.classList.remove('hidden');
208
+ userAvatar.src = currentUser.avatar;
209
+ username.textContent = currentUser.name;
210
+ messageInput.disabled = false;
211
+
212
+ // Show welcome message if first time
213
+ if (messageCount === 0) {
214
+ addMessage('assistant', "Hello! I'm an AI assistant. How can I help you today?");
215
+ }
216
+ }
217
+
218
+ async function sendMessage() {
219
+ const message = messageInput.value.trim();
220
+ if (!message || isGenerating) return;
221
+
222
+ // Add user message to chat
223
+ addMessage('user', message);
224
+ messageInput.value = '';
225
+ messageInput.style.height = 'auto';
226
+ sendBtn.disabled = true;
227
+
228
+ // Create loading message for AI
229
+ const loadingId = addMessage('assistant', '', true);
230
+
231
+ try {
232
+ isGenerating = true;
233
+
234
+ // Get selected model
235
+ const model = modelSelect.value;
236
+
237
+ // Prepare messages for API
238
+ const messages = getConversationHistory();
239
+
240
+ // Stream the response
241
+ const response = await hfClient.conversational({
242
+ model: model,
243
+ inputs: {
244
+ past_user_inputs: messages.filter(m => m.role === 'user').map(m => m.content),
245
+ generated_responses: messages.filter(m => m.role === 'assistant').map(m => m.content),
246
+ text: message
247
+ }
248
+ });
249
+
250
+ updateMessage(loadingId, response.generated_text);
251
+ chatMessages.scrollTop = chatMessages.scrollHeight;
252
+
253
+ // Update token count (approximate)
254
+ const tokens = Math.ceil(response.generated_text.length / 4);
255
+ tokenCounter.textContent = `${tokens} tokens`;
256
+
257
+ // Update token count (approximate)
258
+ const tokens = Math.ceil(fullResponse.length / 4);
259
+ tokenCounter.textContent = `${tokens} tokens`;
260
+
261
+ } catch (error) {
262
+ console.error("Error:", error);
263
+ updateMessage(loadingId, "Sorry, I encountered an error. Please try again.");
264
+ } finally {
265
+ isGenerating = false;
266
+ currentStream = null;
267
+ }
268
+ }
269
+
270
+ function addMessage(role, content, isLoading = false) {
271
+ // Hide empty state if first message
272
+ if (messageCount === 0 && emptyState.parentNode) {
273
+ chatMessages.removeChild(emptyState);
274
+ }
275
+
276
+ const messageId = 'msg-' + Date.now();
277
+ const messageDiv = document.createElement('div');
278
+ messageDiv.className = `mb-4 flex ${role === 'user' ? 'justify-end' : 'justify-start'}`;
279
+
280
+ const bubbleClass = role === 'user'
281
+ ? 'bg-blue-500 text-white rounded-l-xl rounded-tr-xl'
282
+ : 'bg-gray-100 text-gray-800 rounded-r-xl rounded-tl-xl';
283
+
284
+ const loadingClass = isLoading ? 'message-stream' : '';
285
+
286
+ messageDiv.innerHTML = `
287
+ <div class="max-w-[80%]">
288
+ <div class="${bubbleClass} px-4 py-3 ${loadingClass}" id="${messageId}">
289
+ ${content}
290
+ </div>
291
+ <div class="text-xs text-gray-500 mt-1 ${role === 'user' ? 'text-right' : 'text-left'}">
292
+ ${role === 'user' ? 'You' : 'AI'} • ${new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}
293
+ </div>
294
+ </div>
295
+ `;
296
+
297
+ chatMessages.appendChild(messageDiv);
298
+ chatMessages.scrollTop = chatMessages.scrollHeight;
299
+ messageCount++;
300
+
301
+ return messageId;
302
+ }
303
+
304
+ function updateMessage(id, content) {
305
+ const element = document.getElementById(id);
306
+ if (element) {
307
+ element.innerHTML = content;
308
+
309
+ // Remove streaming cursor if present
310
+ if (element.classList.contains('message-stream')) {
311
+ element.classList.remove('message-stream');
312
+ }
313
+ }
314
+ }
315
+
316
+ function getConversationHistory() {
317
+ const messages = [];
318
+ const messageElements = chatMessages.querySelectorAll('[id^="msg-"]');
319
+
320
+ messageElements.forEach(el => {
321
+ const bubble = el.closest('.mb-4');
322
+ const role = bubble.classList.contains('justify-end') ? 'user' : 'assistant';
323
+ const timeElement = bubble.querySelector('.text-xs');
324
+ const timeText = timeElement ? timeElement.textContent : '';
325
+
326
+ messages.push({
327
+ role: role,
328
+ content: el.textContent
329
+ });
330
+ });
331
+
332
+ return messages;
333
+ }
334
+
335
+ </script>
336
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=reach-vb/hugging-chat" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
337
+ </html>