akhaliq HF Staff commited on
Commit
49d96e8
·
verified ·
1 Parent(s): 55e0982

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +217 -56
index.js CHANGED
@@ -1,76 +1,237 @@
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, env } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.0';
2
+
3
+ // Configure environment
4
+ env.allowLocalModels = false;
5
+
6
+ class ChatApp {
7
+ constructor() {
8
+ this.generator = null;
9
+ this.conversationHistory = [
10
+ { role: "system", content: "You are a helpful, friendly AI assistant. Provide clear, concise, and accurate responses." }
11
+ ];
12
+ this.isGenerating = false;
13
+
14
+ this.elements = {
15
+ loadingScreen: document.getElementById('loadingScreen'),
16
+ chatInterface: document.getElementById('chatInterface'),
17
+ messagesContainer: document.getElementById('messagesContainer'),
18
+ userInput: document.getElementById('userInput'),
19
+ sendButton: document.getElementById('sendButton'),
20
+ loadingStatus: document.getElementById('loadingStatus'),
21
+ progressFill: document.getElementById('progressFill'),
22
+ progressText: document.getElementById('progressText')
23
+ };
24
+
25
+ this.init();
26
+ }
27
 
28
+ async init() {
29
+ try {
30
+ await this.loadModel();
31
+ this.setupEventListeners();
32
+ this.showChatInterface();
33
+ } catch (error) {
34
+ console.error('Initialization error:', error);
35
+ this.showError('Failed to initialize the application. Please refresh the page.');
36
+ }
37
+ }
38
 
39
+ async loadModel() {
40
+ this.updateLoadingStatus('Downloading model...', 0);
41
+
42
+ try {
43
+ this.generator = await pipeline(
44
+ "text-generation",
45
+ "onnx-community/Qwen2.5-0.5B-Instruct",
46
+ {
47
+ dtype: "q8",
48
+ device: "webgpu",
49
+ progress_callback: (progress) => {
50
+ if (progress.status === 'progress') {
51
+ const percent = Math.round((progress.loaded / progress.total) * 100);
52
+ this.updateLoadingStatus(
53
+ `Loading ${progress.file}...`,
54
+ percent
55
+ );
56
+ } else if (progress.status === 'done') {
57
+ this.updateLoadingStatus('Model loaded successfully!', 100);
58
+ }
59
+ }
60
+ }
61
+ );
62
+ } catch (error) {
63
+ console.log('WebGPU not available, falling back to WASM');
64
+ this.generator = await pipeline(
65
+ "text-generation",
66
+ "onnx-community/Qwen2.5-0.5B-Instruct",
67
+ {
68
+ dtype: "q8",
69
+ progress_callback: (progress) => {
70
+ if (progress.status === 'progress') {
71
+ const percent = Math.round((progress.loaded / progress.total) * 100);
72
+ this.updateLoadingStatus(
73
+ `Loading ${progress.file}...`,
74
+ percent
75
+ );
76
+ }
77
+ }
78
+ }
79
+ );
80
+ }
81
+ }
82
 
83
+ updateLoadingStatus(message, percent) {
84
+ this.elements.loadingStatus.textContent = message;
85
+ this.elements.progressFill.style.width = `${percent}%`;
86
+ this.elements.progressText.textContent = `${percent}%`;
87
+ }
88
+
89
+ showChatInterface() {
90
+ setTimeout(() => {
91
+ this.elements.loadingScreen.style.display = 'none';
92
+ this.elements.chatInterface.style.display = 'flex';
93
+ this.elements.userInput.focus();
94
+ }, 500);
95
+ }
96
+
97
+ setupEventListeners() {
98
+ // Send button click
99
+ this.elements.sendButton.addEventListener('click', () => this.handleSend());
100
+
101
+ // Enter key to send (Shift+Enter for new line)
102
+ this.elements.userInput.addEventListener('keydown', (e) => {
103
+ if (e.key === 'Enter' && !e.shiftKey) {
104
+ e.preventDefault();
105
+ this.handleSend();
106
+ }
107
+ });
108
 
109
+ // Auto-resize textarea
110
+ this.elements.userInput.addEventListener('input', (e) => {
111
+ e.target.style.height = 'auto';
112
+ e.target.style.height = Math.min(e.target.scrollHeight, 120) + 'px';
113
+ this.elements.sendButton.disabled = !e.target.value.trim() || this.isGenerating;
114
  });
115
 
116
+ // Suggestion buttons
117
+ document.querySelectorAll('.suggestion-btn').forEach(btn => {
118
+ btn.addEventListener('click', (e) => {
119
+ const prompt = e.target.dataset.prompt;
120
+ this.elements.userInput.value = prompt;
121
+ this.elements.userInput.dispatchEvent(new Event('input'));
122
+ this.handleSend();
123
+ });
124
+ });
125
+ }
126
 
127
+ async handleSend() {
128
+ const message = this.elements.userInput.value.trim();
129
+ if (!message || this.isGenerating) return;
130
 
131
+ // Clear input
132
+ this.elements.userInput.value = '';
133
+ this.elements.userInput.style.height = 'auto';
134
+ this.elements.sendButton.disabled = true;
135
 
136
+ // Hide welcome message if present
137
+ const welcomeMsg = document.querySelector('.welcome-message');
138
+ if (welcomeMsg) welcomeMsg.remove();
139
+
140
+ // Add user message
141
+ this.addMessage(message, 'user');
142
+
143
+ // Add assistant message placeholder with typing indicator
144
+ const assistantMessageDiv = this.addMessage('', 'assistant', true);
145
+ const messageContent = assistantMessageDiv.querySelector('.message-content');
146
+
147
+ // Add to conversation history
148
+ this.conversationHistory.push({ role: "user", content: message });
149
+
150
+ this.isGenerating = true;
151
+
152
+ try {
153
+ let fullResponse = '';
154
+
155
+ // Create text streamer with callback
156
+ const streamer = new TextStreamer(this.generator.tokenizer, {
157
+ skip_prompt: true,
158
+ skip_special_tokens: true,
159
+ callback_function: (text) => {
160
+ fullResponse += text;
161
+ // Remove typing indicator if present
162
+ const typingIndicator = messageContent.querySelector('.typing-indicator');
163
+ if (typingIndicator) typingIndicator.remove();
164
+
165
+ // Update message content
166
+ messageContent.textContent = fullResponse;
167
+ this.scrollToBottom();
168
+ }
169
+ });
170
+
171
+ // Generate response
172
+ const output = await this.generator(this.conversationHistory, {
173
+ max_new_tokens: 512,
174
+ do_sample: false,
175
+ streamer: streamer,
176
  });
177
 
178
+ // Get final response
179
+ const finalResponse = output[0].generated_text.at(-1).content;
180
 
181
+ // Update conversation history
182
+ this.conversationHistory.push({ role: "assistant", content: finalResponse });
 
 
183
 
184
+ // Ensure final text is displayed
185
+ messageContent.textContent = finalResponse;
186
+
187
+ } catch (error) {
188
+ console.error('Generation error:', error);
189
+ messageContent.textContent = 'Sorry, I encountered an error generating a response. Please try again.';
190
+ } finally {
191
+ this.isGenerating = false;
192
+ this.elements.sendButton.disabled = false;
193
+ this.elements.userInput.focus();
194
+ this.scrollToBottom();
195
+ }
196
  }
197
 
198
+ addMessage(content, role, showTyping = false) {
199
+ const messageDiv = document.createElement('div');
200
+ messageDiv.className = `message ${role}-message`;
201
+
202
+ const avatar = document.createElement('div');
203
+ avatar.className = 'message-avatar';
204
+ avatar.textContent = role === 'user' ? '👤' : '🤖';
205
+
206
+ const messageContent = document.createElement('div');
207
+ messageContent.className = 'message-content';
208
+
209
+ if (showTyping) {
210
+ const typingIndicator = document.createElement('div');
211
+ typingIndicator.className = 'typing-indicator';
212
+ typingIndicator.innerHTML = '<span></span><span></span><span></span>';
213
+ messageContent.appendChild(typingIndicator);
214
+ } else {
215
+ messageContent.textContent = content;
216
+ }
217
 
218
+ messageDiv.appendChild(avatar);
219
+ messageDiv.appendChild(messageContent);
220
+ this.elements.messagesContainer.appendChild(messageDiv);
221
 
222
+ this.scrollToBottom();
223
+ return messageDiv;
224
+ }
 
 
 
 
 
 
 
225
 
226
+ scrollToBottom() {
227
+ this.elements.messagesContainer.scrollTop = this.elements.messagesContainer.scrollHeight;
228
+ }
 
 
229
 
230
+ showError(message) {
231
+ this.elements.loadingStatus.textContent = message;
232
+ this.elements.loadingStatus.style.color = '#FF3B30';
233
  }
234
+ }
235
+
236
+ // Initialize the app
237
+ new ChatApp();