akhaliq HF Staff commited on
Commit
c2096ea
·
verified ·
1 Parent(s): 7a21348

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +197 -56
index.js CHANGED
@@ -1,76 +1,217 @@
1
- import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/[email protected]';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ class ChatbotApp {
2
+ constructor() {
3
+ this.generator = null;
4
+ this.messages = [
5
+ { role: "system", content: "You are a helpful assistant. Be concise and friendly." }
6
+ ];
7
+ this.isGenerating = false;
8
+ this.init();
9
+ }
10
+
11
+ async init() {
12
+ this.setupElements();
13
+ this.setupEventListeners();
14
+ await this.loadModel();
15
+ }
16
 
17
+ setupElements() {
18
+ this.chatMessages = document.getElementById('chatMessages');
19
+ this.messageInput = document.getElementById('messageInput');
20
+ this.sendButton = document.getElementById('sendButton');
21
+ this.status = document.getElementById('status');
22
+ this.loadingIndicator = document.getElementById('loadingIndicator');
23
+ this.progressFill = document.getElementById('progressFill');
24
+ this.progressText = document.getElementById('progressText');
25
+ this.charCount = document.getElementById('charCount');
26
+ }
27
 
28
+ setupEventListeners() {
29
+ // Send button click
30
+ this.sendButton.addEventListener('click', () => this.sendMessage());
31
+
32
+ // Enter key to send (Shift+Enter for new line)
33
+ this.messageInput.addEventListener('keydown', (e) => {
34
+ if (e.key === 'Enter' && !e.shiftKey) {
35
+ e.preventDefault();
36
+ this.sendMessage();
37
+ }
38
+ });
39
 
40
+ // Character count
41
+ this.messageInput.addEventListener('input', () => {
42
+ const length = this.messageInput.value.length;
43
+ this.charCount.textContent = `${length} / 1000`;
44
 
45
+ // Auto-resize textarea
46
+ this.messageInput.style.height = 'auto';
47
+ this.messageInput.style.height = Math.min(this.messageInput.scrollHeight, 120) + 'px';
48
  });
49
 
50
+ // Initialize worker
51
+ this.setupWorker();
52
+ }
53
+
54
+ setupWorker() {
55
+ // Create worker from separate file
56
+ this.worker = new Worker('worker.js');
57
+
58
+ this.worker.addEventListener('message', (e) => {
59
+ switch(e.data.type) {
60
+ case 'progress':
61
+ this.updateProgress(e.data.progress);
62
+ break;
63
+ case 'modelLoaded':
64
+ this.onModelLoaded(e.data.generator);
65
+ break;
66
+ case 'error':
67
+ this.onError(e.data.error);
68
+ break;
69
+ }
70
+ });
71
+ }
72
+
73
+ async loadModel() {
74
+ this.status.textContent = 'Downloading model...';
75
+ this.loadingIndicator.classList.remove('hidden');
76
+ this.worker.postMessage({ type: 'loadModel' });
77
+ }
78
 
79
+ updateProgress(progress) {
80
+ this.progressFill.style.width = `${progress}%`;
81
+ this.progressText.textContent = `${Math.round(progress)}%`;
82
+ }
83
 
84
+ onModelLoaded(generator) {
85
+ this.generator = generator;
86
+ this.loadingIndicator.classList.add('hidden');
87
+ this.status.textContent = 'Ready';
88
+ this.messageInput.disabled = false;
89
+ this.sendButton.disabled = false;
90
+ this.messageInput.focus();
91
+ }
92
 
93
+ onError(error) {
94
+ this.loadingIndicator.classList.add('hidden');
95
+ this.status.textContent = 'Error loading model';
96
+ this.addMessage('system', `Error: ${error}. Please refresh the page to try again.`);
97
+ }
98
+
99
+ async sendMessage() {
100
+ const message = this.messageInput.value.trim();
101
+ if (!message || this.isGenerating || !this.generator) return;
102
+
103
+ // Add user message
104
+ this.addMessage('user', message);
105
+ this.messages.push({ role: "user", content: message });
106
+
107
+ // Clear input
108
+ this.messageInput.value = '';
109
+ this.messageInput.style.height = 'auto';
110
+ this.charCount.textContent = '0 / 1000';
111
+
112
+ // Disable input
113
+ this.isGenerating = true;
114
+ this.messageInput.disabled = true;
115
+ this.sendButton.disabled = true;
116
+ this.status.textContent = 'Thinking...';
117
+
118
+ // Add AI message with typing indicator
119
+ const aiMessageId = this.addMessage('ai', '', true);
120
+
121
+ try {
122
+ // Generate response with streaming
123
+ const streamer = new transformers.TextStreamer(this.generator.tokenizer, {
124
+ skip_prompt: true,
125
+ skip_special_tokens: true,
126
+ callback_function: (text) => {
127
+ this.updateMessage(aiMessageId, text);
128
+ }
129
  });
130
 
131
+ const output = await this.generator(this.messages, {
132
+ max_new_tokens: 512,
133
+ do_sample: false,
134
+ streamer: streamer,
135
+ });
136
 
137
+ // Add the AI response to messages
138
+ const aiResponse = output[0].generated_text.at(-1).content;
139
+ this.messages.push({ role: "assistant", content: aiResponse });
140
+
141
+ } catch (error) {
142
+ this.updateMessage(aiMessageId, 'Sorry, I encountered an error. Please try again.');
143
+ console.error('Generation error:', error);
144
+ } finally {
145
+ // Re-enable input
146
+ this.isGenerating = false;
147
+ this.messageInput.disabled = false;
148
+ this.sendButton.disabled = false;
149
+ this.status.textContent = 'Ready';
150
+ this.messageInput.focus();
151
+ }
152
+ }
153
 
154
+ addMessage(role, content, isTyping = false) {
155
+ const messageId = 'msg-' + Date.now();
156
+ const messageDiv = document.createElement('div');
157
+ messageDiv.className = `message ${role}`;
158
+ messageDiv.id = messageId;
159
+
160
+ const avatar = document.createElement('div');
161
+ avatar.className = role === 'user' ? 'user-avatar' : 'ai-avatar';
162
+ avatar.innerHTML = role === 'user'
163
+ ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
164
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
165
+ <circle cx="12" cy="7" r="4"></circle>
166
+ </svg>'
167
+ : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
168
+ <path d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z" />
169
+ <path d="M12 8v4" />
170
+ <circle cx="12" cy="16" r="1" />
171
+ </svg>';
172
+
173
+ const messageContent = document.createElement('div');
174
+ messageContent.className = 'message-content';
175
+
176
+ const bubble = document.createElement('div');
177
+ bubble.className = 'message-bubble';
178
+
179
+ if (isTyping) {
180
+ bubble.innerHTML = '<div class="typing-indicator">
181
+ <div class="typing-dot"></div>
182
+ <div class="typing-dot"></div>
183
+ <div class="typing-dot"></div>
184
+ </div>';
185
+ } else {
186
+ bubble.textContent = content;
187
  }
188
 
189
+ const time = document.createElement('div');
190
+ time.className = 'message-time';
191
+ time.textContent = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
192
 
193
+ messageContent.appendChild(bubble);
194
+ messageContent.appendChild(time);
195
+ messageDiv.appendChild(avatar);
196
+ messageDiv.appendChild(messageContent);
197
 
198
+ this.chatMessages.appendChild(messageDiv);
199
+ this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
 
 
 
 
 
 
 
 
200
 
201
+ return messageId;
202
+ }
 
 
 
203
 
204
+ updateMessage(messageId, content) {
205
+ const messageElement = document.getElementById(messageId);
206
+ if (messageElement) {
207
+ const bubble = messageElement.querySelector('.message-bubble');
208
+ bubble.textContent = content;
209
+ this.chatMessages.scrollTop = this.chatMessages.scrollHeight;
210
  }
211
+ }
212
+ }
213
+
214
+ // Initialize the app when DOM is loaded
215
+ document.addEventListener('DOMContentLoaded', () => {
216
+ new ChatbotApp();
217
+ });