akhaliq HF Staff commited on
Commit
c480f99
·
verified ·
1 Parent(s): 42b6b95

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +182 -61
index.js CHANGED
@@ -1,76 +1,197 @@
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
+ // DOM Elements
4
+ const chatMessages = document.getElementById('chatMessages');
5
+ const userInput = document.getElementById('userInput');
6
+ const sendButton = document.getElementById('sendButton');
7
+ const modelStatus = document.getElementById('modelStatus');
8
+ const statusText = document.getElementById('statusText');
9
+ const progressFill = document.getElementById('progressFill');
10
+
11
+ // State
12
+ let generator = null;
13
+ let conversationHistory = [
14
+ { role: "system", content: "You are a helpful, friendly AI assistant. Provide clear, concise, and accurate responses." }
15
+ ];
16
+ let isGenerating = false;
17
+
18
+ // Initialize the application
19
+ async function init() {
20
+ try {
21
+ updateStatus('Loading AI model...', 0);
22
+
23
+ // Create text generation pipeline with progress tracking
24
+ generator = await pipeline(
25
+ "text-generation",
26
+ "onnx-community/Llama-3.2-1B-Instruct-q4f16",
27
+ {
28
+ dtype: "q4f16",
29
+ device: "webgpu",
30
+ progress_callback: (progress) => {
31
+ if (progress.status === 'progress') {
32
+ const percentage = Math.round((progress.loaded / progress.total) * 100);
33
+ updateStatus(`Loading model: ${progress.file}`, percentage);
34
+ }
35
+ }
36
+ }
37
+ );
38
+
39
+ updateStatus('Model ready!', 100);
40
+
41
+ // Enable input after model is loaded
42
+ setTimeout(() => {
43
+ modelStatus.classList.add('ready');
44
+ userInput.disabled = false;
45
+ sendButton.disabled = false;
46
+ userInput.focus();
47
+ }, 500);
48
+
49
+ } catch (error) {
50
+ console.error('Error initializing model:', error);
51
+ updateStatus('Error loading model. Please refresh the page.', 0);
52
+ statusText.style.color = '#FF3B30';
53
+ }
54
+ }
55
 
56
+ // Update status display
57
+ function updateStatus(message, progress) {
58
+ statusText.textContent = message;
59
+ progressFill.style.width = `${progress}%`;
60
+ }
61
 
62
+ // Add message to chat
63
+ function addMessage(role, content, isStreaming = false) {
64
+ const messageDiv = document.createElement('div');
65
+ messageDiv.className = `message ${role}`;
66
+
67
+ const avatar = document.createElement('div');
68
+ avatar.className = 'message-avatar';
69
+ avatar.textContent = role === 'user' ? '👤' : '🤖';
70
+
71
+ const contentDiv = document.createElement('div');
72
+ contentDiv.className = 'message-content';
73
+
74
+ if (isStreaming) {
75
+ contentDiv.innerHTML = '<div class="typing-indicator">
76
+ <div class="typing-dot"></div>
77
+ <div class="typing-dot"></div>
78
+ <div class="typing-dot"></div>
79
+ </div>';
80
+ } else {
81
+ contentDiv.innerHTML = formatMessage(content);
82
+ }
83
 
84
+ messageDiv.appendChild(avatar);
85
+ messageDiv.appendChild(contentDiv);
 
 
86
 
87
+ // Remove welcome message if it exists
88
+ const welcomeMessage = chatMessages.querySelector('.welcome-message');
89
+ if (welcomeMessage) {
90
+ welcomeMessage.remove();
91
+ }
92
 
93
+ chatMessages.appendChild(messageDiv);
94
+ chatMessages.scrollTop = chatMessages.scrollHeight;
 
 
 
95
 
96
+ return contentDiv;
97
+ }
98
 
99
+ // Format message content
100
+ function formatMessage(text) {
101
+ // Simple formatting for line breaks
102
+ return text
103
+ .split('\n')
104
+ .map(line => line.trim() ? `<p>${escapeHtml(line)}</p>` : '')
105
+ .join('');
106
+ }
107
 
108
+ // Escape HTML to prevent XSS
109
+ function escapeHtml(text) {
110
+ const div = document.createElement('div');
111
+ div.textContent = text;
112
+ return div.innerHTML;
113
+ }
114
+
115
+ // Handle message sending
116
+ async function sendMessage() {
117
+ const message = userInput.value.trim();
118
+ if (!message || isGenerating || !generator) return;
119
+
120
+ // Add user message
121
+ addMessage('user', message);
122
+ conversationHistory.push({ role: "user", content: message });
123
+
124
+ // Clear input
125
+ userInput.value = '';
126
+ userInput.style.height = 'auto';
127
+
128
+ // Disable input while generating
129
+ isGenerating = true;
130
+ userInput.disabled = true;
131
+ sendButton.disabled = true;
132
+
133
+ try {
134
+ // Add assistant message placeholder with typing indicator
135
+ const assistantContentDiv = addMessage('assistant', '', true);
136
+ let fullResponse = '';
137
+
138
+ // Create streamer for real-time output
139
+ const streamer = new TextStreamer(generator.tokenizer, {
140
+ skip_prompt: true,
141
+ skip_special_tokens: true,
142
+ callback_function: (text) => {
143
+ fullResponse += text;
144
+ assistantContentDiv.innerHTML = formatMessage(fullResponse);
145
+ chatMessages.scrollTop = chatMessages.scrollHeight;
146
+ }
147
+ });
148
+
149
+ // Generate response
150
+ const output = await generator(conversationHistory, {
151
+ max_new_tokens: 512,
152
+ do_sample: true,
153
+ temperature: 0.7,
154
+ top_p: 0.9,
155
+ streamer: streamer
156
  });
157
 
158
+ // Get the final generated text
159
+ const finalResponse = output[0].generated_text.at(-1).content;
160
+
161
+ // Update conversation history
162
+ conversationHistory.push({ role: "assistant", content: finalResponse });
163
 
164
+ // Ensure final response is displayed
165
+ assistantContentDiv.innerHTML = formatMessage(finalResponse);
 
 
166
 
167
+ } catch (error) {
168
+ console.error('Error generating response:', error);
169
+ addMessage('assistant', 'Sorry, I encountered an error. Please try again.');
170
+ } finally {
171
+ // Re-enable input
172
+ isGenerating = false;
173
+ userInput.disabled = false;
174
+ sendButton.disabled = false;
175
+ userInput.focus();
176
+ }
177
  }
178
 
179
+ // Auto-resize textarea
180
+ userInput.addEventListener('input', function() {
181
+ this.style.height = 'auto';
182
+ this.style.height = Math.min(this.scrollHeight, 120) + 'px';
183
+ });
184
+
185
+ // Handle Enter key
186
+ userInput.addEventListener('keydown', (e) => {
187
+ if (e.key === 'Enter' && !e.shiftKey) {
188
+ e.preventDefault();
189
+ sendMessage();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
+ });
192
+
193
+ // Send button click
194
+ sendButton.addEventListener('click', sendMessage);
195
+
196
+ // Initialize app when page loads
197
+ init();