akhaliq HF Staff commited on
Commit
7d29472
·
verified ·
1 Parent(s): a6ce108

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +237 -56
index.js CHANGED
@@ -1,76 +1,257 @@
1
- import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.7.6';
2
 
3
- // Reference the elements that we will need
4
- const status = document.getElementById('status');
5
- const fileUpload = document.getElementById('upload');
6
- const imageContainer = document.getElementById('container');
7
- const example = document.getElementById('example');
 
 
 
8
 
9
- const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/city-streets.jpg';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- // Create a new object detection pipeline
12
- status.textContent = 'Loading model...';
13
- const detector = await pipeline('object-detection', 'Xenova/detr-resnet-50');
14
- status.textContent = 'Ready';
 
15
 
16
- example.addEventListener('click', (e) => {
17
- e.preventDefault();
18
- detect(EXAMPLE_URL);
 
 
19
  });
20
 
21
- fileUpload.addEventListener('change', function (e) {
22
- const file = e.target.files[0];
23
- if (!file) {
24
- return;
25
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- const reader = new FileReader();
 
 
28
 
29
- // Set up a callback when the file is loaded
30
- reader.onload = e2 => detect(e2.target.result);
 
31
 
32
- reader.readAsDataURL(file);
 
 
 
 
 
33
  });
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- // Detect objects in the image
37
- async function detect(img) {
38
- imageContainer.innerHTML = '';
39
- imageContainer.style.backgroundImage = `url(${img})`;
40
 
41
- status.textContent = 'Analysing...';
42
- const output = await detector(img, {
43
- threshold: 0.5,
44
- percentage: true,
45
- });
46
- status.textContent = '';
47
- output.forEach(renderBox);
48
  }
49
 
50
- // Render a bounding box and label on the image
51
- function renderBox({ box, label }) {
52
- const { xmax, xmin, ymax, ymin } = box;
 
53
 
54
- // Generate a random color for the box
55
- const color = '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, 0);
 
56
 
57
- // Draw the box
58
- const boxElement = document.createElement('div');
59
- boxElement.className = 'bounding-box';
60
- Object.assign(boxElement.style, {
61
- borderColor: color,
62
- left: 100 * xmin + '%',
63
- top: 100 * ymin + '%',
64
- width: 100 * (xmax - xmin) + '%',
65
- height: 100 * (ymax - ymin) + '%',
66
- })
67
 
68
- // Draw label
69
- const labelElement = document.createElement('span');
70
- labelElement.textContent = label;
71
- labelElement.className = 'bounding-box-label';
72
- labelElement.style.backgroundColor = color;
73
 
74
- boxElement.appendChild(labelElement);
75
- imageContainer.appendChild(boxElement);
 
 
76
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.0';
2
 
3
+ class Chatbot {
4
+ constructor() {
5
+ this.generator = null;
6
+ this.isGenerating = false;
7
+ this.conversationHistory = [];
8
+ this.maxHistoryLength = 10;
9
+ this.currentModel = 'Xenova/distilgpt2';
10
+ this.currentDevice = 'wasm';
11
 
12
+ this.initializeElements();
13
+ this.attachEventListeners();
14
+ this.loadModel();
15
+ }
16
+
17
+ initializeElements() {
18
+ this.messagesContainer = document.getElementById('messages');
19
+ this.messageInput = document.getElementById('message-input');
20
+ this.sendButton = document.getElementById('send-button');
21
+ this.clearButton = document.getElementById('clear-chat');
22
+ this.modelSelect = document.getElementById('model-select');
23
+ this.deviceSelect = document.getElementById('device-select');
24
+ this.typingIndicator = document.getElementById('typing-indicator');
25
+ this.loadingOverlay = document.getElementById('loading-overlay');
26
+ this.errorToast = document.getElementById('error-toast');
27
+ this.errorMessage = document.getElementById('error-message');
28
+ this.charCount = document.getElementById('char-count');
29
+ this.dismissErrorBtn = document.getElementById('dismiss-error');
30
+ }
31
+
32
+ attachEventListeners() {
33
+ this.sendButton.addEventListener('click', () => this.sendMessage());
34
+ this.clearButton.addEventListener('click', () => this.clearChat());
35
+ this.modelSelect.addEventListener('change', (e) => this.changeModel(e.target.value));
36
+ this.deviceSelect.addEventListener('change', (e) => this.changeDevice(e.target.value));
37
 
38
+ this.messageInput.addEventListener('input', () => {
39
+ this.updateCharCount();
40
+ this.autoResizeTextarea();
41
+ this.sendButton.disabled = !this.messageInput.value.trim() || this.isGenerating;
42
+ });
43
 
44
+ this.messageInput.addEventListener('keydown', (e) => {
45
+ if (e.key === 'Enter' && !e.shiftKey) {
46
+ e.preventDefault();
47
+ this.sendMessage();
48
+ }
49
  });
50
 
51
+ this.dismissErrorBtn.addEventListener('click', () => this.hideError());
52
+
53
+ // Check for WebGPU support
54
+ this.checkWebGPUSupport();
55
+ }
56
+
57
+ async checkWebGPUSupport() {
58
+ if (!navigator.gpu) {
59
+ this.deviceSelect.querySelector('option[value="webgpu"]').disabled = true;
60
+ this.deviceSelect.value = 'wasm';
61
+ this.currentDevice = 'wasm';
62
+ }
63
+ }
64
+
65
+ async loadModel() {
66
+ this.showLoading();
67
+ try {
68
+ const config = {
69
+ device: this.currentDevice,
70
+ dtype: this.currentDevice === 'webgpu' ? 'fp16' : 'q4'
71
+ };
72
+
73
+ this.generator = await pipeline('text-generation', this.currentModel, config);
74
+ this.hideLoading();
75
+ this.sendButton.disabled = !this.messageInput.value.trim();
76
+ } catch (error) {
77
+ console.error('Error loading model:', error);
78
+ this.hideLoading();
79
+ this.showError('Failed to load model. Please try again or select a different model.');
80
+ this.sendButton.disabled = true;
81
+ }
82
+ }
83
+
84
+ async changeModel(modelName) {
85
+ if (modelName === this.currentModel) return;
86
+
87
+ this.currentModel = modelName;
88
+ await this.loadModel();
89
+ }
90
+
91
+ async changeDevice(device) {
92
+ if (device === this.currentDevice) return;
93
+
94
+ this.currentDevice = device;
95
+ await this.loadModel();
96
+ }
97
+
98
+ async sendMessage() {
99
+ const message = this.messageInput.value.trim();
100
+ if (!message || this.isGenerating) return;
101
+
102
+ this.addMessage(message, 'user');
103
+ this.messageInput.value = '';
104
+ this.updateCharCount();
105
+ this.autoResizeTextarea();
106
+ this.sendButton.disabled = true;
107
+ this.isGenerating = true;
108
+ this.showTypingIndicator();
109
+
110
+ try {
111
+ const prompt = this.buildPrompt(message);
112
+ const response = await this.generateResponse(prompt);
113
+ this.addMessage(response, 'bot');
114
+ } catch (error) {
115
+ console.error('Error generating response:', error);
116
+ this.showError('Failed to generate response. Please try again.');
117
+ } finally {
118
+ this.isGenerating = false;
119
+ this.hideTypingIndicator();
120
+ this.sendButton.disabled = !this.messageInput.value.trim();
121
+ }
122
+ }
123
+
124
+ buildPrompt(userMessage) {
125
+ let prompt = "You are a helpful AI assistant. Respond in a friendly and informative way.\n\n";
126
+
127
+ // Include recent conversation history
128
+ if (this.conversationHistory.length > 0) {
129
+ const recentHistory = this.conversationHistory.slice(-4);
130
+ recentHistory.forEach(msg => {
131
+ if (msg.role === 'user') {
132
+ prompt += `User: ${msg.content}\n`;
133
+ } else {
134
+ prompt += `Assistant: ${msg.content}\n`;
135
+ }
136
+ });
137
+ }
138
 
139
+ prompt += `User: ${userMessage}\nAssistant:`;
140
+ return prompt;
141
+ }
142
 
143
+ async generateResponse(prompt) {
144
+ const maxNewTokens = 100;
145
+ const temperature = 0.7;
146
 
147
+ const result = await this.generator(prompt, {
148
+ max_new_tokens: maxNewTokens,
149
+ temperature: temperature,
150
+ do_sample: true,
151
+ pad_token_id: 50256,
152
+ return_full_text: false
153
  });
154
 
155
+ let response = result[0].generated_text.trim();
156
+
157
+ // Clean up the response
158
+ response = response.replace(/^(Assistant:|AI:|Bot:)/i, '').trim();
159
+ response = response.split('\n')[0]; // Take only the first line
160
+
161
+ if (!response) {
162
+ response = "I'm not sure how to respond to that. Could you try rephrasing?";
163
+ }
164
+
165
+ return response;
166
+ }
167
+
168
+ addMessage(content, role) {
169
+ const messageDiv = document.createElement('div');
170
+ messageDiv.className = `message ${role}-message`;
171
+
172
+ const messageContent = document.createElement('div');
173
+ messageContent.className = 'message-content';
174
+ messageContent.innerHTML = `<p>${this.escapeHtml(content)}</p>`;
175
+
176
+ const messageTime = document.createElement('div');
177
+ messageTime.className = 'message-time';
178
+ messageTime.textContent = role === 'user' ? 'You' : 'Bot';
179
+
180
+ messageDiv.appendChild(messageContent);
181
+ messageDiv.appendChild(messageTime);
182
+
183
+ this.messagesContainer.appendChild(messageDiv);
184
+ this.scrollToBottom();
185
+
186
+ // Update conversation history
187
+ this.conversationHistory.push({ role, content });
188
+ if (this.conversationHistory.length > this.maxHistoryLength) {
189
+ this.conversationHistory.shift();
190
+ }
191
+ }
192
+
193
+ clearChat() {
194
+ this.messagesContainer.innerHTML = `
195
+ <div class="message bot-message">
196
+ <div class="message-content">
197
+ <p>Hello! I'm your AI assistant. How can I help you today?</p>
198
+ </div>
199
+ <div class="message-time">Bot</div>
200
+ </div>
201
+ `;
202
+ this.conversationHistory = [];
203
+ this.scrollToBottom();
204
+ }
205
 
206
+ updateCharCount() {
207
+ const length = this.messageInput.value.length;
208
+ this.charCount.textContent = `${length} / 500`;
209
+ }
210
 
211
+ autoResizeTextarea() {
212
+ this.messageInput.style.height = 'auto';
213
+ this.messageInput.style.height = Math.min(this.messageInput.scrollHeight, 120) + 'px';
 
 
 
 
214
  }
215
 
216
+ showTypingIndicator() {
217
+ this.typingIndicator.classList.remove('hidden');
218
+ this.scrollToBottom();
219
+ }
220
 
221
+ hideTypingIndicator() {
222
+ this.typingIndicator.classList.add('hidden');
223
+ }
224
 
225
+ showLoading() {
226
+ this.loadingOverlay.classList.remove('hidden');
227
+ }
 
 
 
 
 
 
 
228
 
229
+ hideLoading() {
230
+ this.loadingOverlay.classList.add('hidden');
231
+ }
 
 
232
 
233
+ showError(message) {
234
+ this.errorMessage.textContent = message;
235
+ this.errorToast.classList.remove('hidden');
236
+ setTimeout(() => this.hideError(), 5000);
237
  }
238
+
239
+ hideError() {
240
+ this.errorToast.classList.add('hidden');
241
+ }
242
+
243
+ scrollToBottom() {
244
+ this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
245
+ }
246
+
247
+ escapeHtml(text) {
248
+ const div = document.createElement('div');
249
+ div.textContent = text;
250
+ return div.innerHTML;
251
+ }
252
+ }
253
+
254
+ // Initialize the chatbot when the page loads
255
+ document.addEventListener('DOMContentLoaded', () => {
256
+ new Chatbot();
257
+ });