akhaliq HF Staff commited on
Commit
b767261
·
verified ·
1 Parent(s): f695f22

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +235 -56
index.js CHANGED
@@ -1,76 +1,255 @@
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, TextStreamer } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.0';
2
+
3
+ class ChatApp {
4
+ constructor() {
5
+ this.generator = null;
6
+ this.messages = [
7
+ { role: "system", content: "You are a helpful, friendly AI assistant. Provide clear, concise, and accurate responses." }
8
+ ];
9
+ this.isGenerating = false;
10
+
11
+ this.elements = {
12
+ loadingScreen: document.getElementById('loadingScreen'),
13
+ chatMessages: document.getElementById('chatMessages'),
14
+ messageInput: document.getElementById('messageInput'),
15
+ sendButton: document.getElementById('sendButton'),
16
+ progressBar: document.getElementById('progressFill'),
17
+ progressText: document.getElementById('progressText')
18
+ };
19
+
20
+ this.init();
21
+ }
22
+
23
+ async init() {
24
+ try {
25
+ await this.loadModel();
26
+ this.setupEventListeners();
27
+ this.hideLoading();
28
+ this.addWelcomeMessage();
29
+ } catch (error) {
30
+ console.error('Initialization error:', error);
31
+ this.showError('Failed to initialize the AI model. Please refresh the page.');
32
+ }
33
+ }
34
+
35
+ async loadModel() {
36
+ try {
37
+ this.updateProgress(0, 'Loading model...');
38
+
39
+ // Create a text generation pipeline with progress tracking
40
+ this.generator = await pipeline(
41
+ "text-generation",
42
+ "onnx-community/Llama-3.2-1B-Instruct-q4f16",
43
+ {
44
+ dtype: "q4f16",
45
+ device: "webgpu",
46
+ progress_callback: (progress) => {
47
+ if (progress.status === 'progress') {
48
+ const percent = Math.round((progress.loaded / progress.total) * 100);
49
+ this.updateProgress(percent, `Downloading model: ${progress.file}`);
50
+ } else if (progress.status === 'done') {
51
+ this.updateProgress(100, 'Model loaded successfully!');
52
+ }
53
+ }
54
+ }
55
+ );
56
+
57
+ console.log('Model loaded successfully!');
58
+ } catch (error) {
59
+ console.error('Model loading error:', error);
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ updateProgress(percent, text) {
65
+ this.elements.progressBar.style.width = `${percent}%`;
66
+ this.elements.progressText.textContent = `${percent}%`;
67
+
68
+ const loadingText = document.querySelector('.loading-text');
69
+ if (loadingText) {
70
+ loadingText.textContent = text;
71
+ }
72
+ }
73
 
74
+ hideLoading() {
75
+ this.elements.loadingScreen.classList.add('hidden');
76
+ this.elements.messageInput.disabled = false;
77
+ this.elements.sendButton.disabled = false;
78
+ this.elements.messageInput.focus();
79
+ }
80
 
81
+ setupEventListeners() {
82
+ this.elements.sendButton.addEventListener('click', () => this.sendMessage());
83
 
84
+ this.elements.messageInput.addEventListener('keydown', (e) => {
85
+ if (e.key === 'Enter' && !e.shiftKey) {
86
+ e.preventDefault();
87
+ this.sendMessage();
88
+ }
89
+ });
90
 
91
+ // Auto-resize textarea
92
+ this.elements.messageInput.addEventListener('input', () => {
93
+ this.elements.messageInput.style.height = 'auto';
94
+ this.elements.messageInput.style.height = this.elements.messageInput.scrollHeight + 'px';
95
  });
96
+ }
97
+
98
+ addWelcomeMessage() {
99
+ const welcomeMessage = {
100
+ role: 'assistant',
101
+ content: "Hello! I'm your AI assistant. How can I help you today? Feel free to ask me anything!" + "};
102
+ this.addMessageToChat(welcomeMessage);
103
+ }
104
+
105
+ async sendMessage() {
106
+ const userMessage = this.elements.messageInput.value.trim();
107
+
108
+ if (!userMessage || this.isGenerating) return;
109
+
110
+ // Add user message to chat
111
+ const userMsg = { role: 'user', content: userMessage };
112
+ this.messages.push(userMsg);
113
+ this.addMessageToChat(userMsg);
114
+
115
+ // Clear input
116
+ this.elements.messageInput.value = '';
117
+ this.elements.messageInput.style.height = 'auto';
118
+
119
+ // Disable input while generating
120
+ this.isGenerating = true;
121
+ this.elements.messageInput.disabled = true;
122
+ this.elements.sendButton.disabled = true;
123
+
124
+ // Show typing indicator
125
+ const typingIndicator = this.addTypingIndicator();
126
+
127
+ try {
128
+ // Generate response with streaming
129
+ let fullResponse = '';
130
+ let assistantMessageElement = null;
131
+
132
+ const streamer = new TextStreamer(this.generator.tokenizer, {
133
+ skip_prompt: true,
134
+ skip_special_tokens: true,
135
+ callback_function: (text) => {
136
+ fullResponse += text;
137
+
138
+ // Remove typing indicator on first token
139
+ if (!assistantMessageElement) {
140
+ typingIndicator.remove();
141
+ assistantMessageElement = this.addMessageToChat({
142
+ role: 'assistant',
143
+ content: ''
144
+ }, true);
145
+ }
146
 
147
+ // Update the message content
148
+ const contentElement = assistantMessageElement.querySelector('.message-content');
149
+ if (contentElement) {
150
+ contentElement.textContent = fullResponse;
151
+ this.scrollToBottom();
152
+ }
153
+ }
154
+ });
155
 
156
+ const output = await this.generator(this.messages, {
157
+ max_new_tokens: 512,
158
+ do_sample: false,
159
+ streamer: streamer,
160
+ });
161
 
162
+ // Add final response to messages history
163
+ const assistantResponse = output[0].generated_text.at(-1).content;
164
+ this.messages.push({ role: 'assistant', content: assistantResponse });
165
 
166
+ } catch (error) {
167
+ console.error('Generation error:', error);
168
+ typingIndicator.remove();
169
+ this.addMessageToChat({
170
+ role: 'assistant',
171
+ content: 'Sorry, I encountered an error. Please try again.'
172
  });
173
+ } finally {
174
+ this.isGenerating = false;
175
+ this.elements.messageInput.disabled = false;
176
+ this.elements.sendButton.disabled = false;
177
+ this.elements.messageInput.focus();
178
+ }
179
+ }
180
+
181
+ addMessageToChat(message, isStreaming = false) {
182
+ const messageDiv = document.createElement('div');
183
+ messageDiv.className = `message ${message.role}`;
184
 
185
+ const avatar = document.createElement('div');
186
+ avatar.className = 'message-avatar';
187
+ avatar.textContent = message.role === 'user' ? 'U' : 'AI';
188
 
189
+ const content = document.createElement('div');
190
+ content.className = 'message-content';
191
+ content.textContent = message.content;
 
192
 
193
+ messageDiv.appendChild(avatar);
194
+ messageDiv.appendChild(content);
195
+
196
+ this.elements.chatMessages.appendChild(messageDiv);
197
+ this.scrollToBottom();
198
+
199
+ return messageDiv;
200
  }
201
 
202
+ addTypingIndicator() {
203
+ const messageDiv = document.createElement('div');
204
+ messageDiv.className = 'message assistant';
205
+ messageDiv.id = 'typing-indicator';
206
+
207
+ const avatar = document.createElement('div');
208
+ avatar.className = 'message-avatar';
209
+ avatar.textContent = 'AI';
210
+
211
+ const content = document.createElement('div');
212
+ content.className = 'message-content';
213
+
214
+ const typingDiv = document.createElement('div');
215
+ typingDiv.className = 'typing-indicator';
216
+ typingDiv.innerHTML = '<div class="typing-dot"></div>
217
+ <div class="typing-dot"></div>
218
+ <div class="typing-dot"></div>';
219
 
220
+ content.appendChild(typingDiv);
221
+ messageDiv.appendChild(avatar);
222
+ messageDiv.appendChild(content);
223
 
224
+ this.elements.chatMessages.appendChild(messageDiv);
225
+ this.scrollToBottom();
 
 
 
 
 
 
 
 
226
 
227
+ return messageDiv;
228
+ }
229
+
230
+ scrollToBottom() {
231
+ this.elements.chatMessages.scrollTop = this.elements.chatMessages.scrollHeight;
232
+ }
233
 
234
+ showError(message) {
235
+ const errorDiv = document.createElement('div');
236
+ errorDiv.style.cssText = `
237
+ position: fixed;
238
+ top: 20px;
239
+ right: 20px;
240
+ background: #ff3b30;
241
+ color: white;
242
+ padding: 16px 24px;
243
+ border-radius: 12px;
244
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
245
+ z-index: 2000;
246
+ `;
247
+ errorDiv.textContent = message;
248
+ document.body.appendChild(errorDiv);
249
+
250
+ setTimeout(() => errorDiv.remove(), 5000);
251
  }
252
+ }
253
+
254
+ // Initialize the app
255
+ new ChatApp();