anycoder-24c18dca / index.js
akhaliq's picture
akhaliq HF Staff
Upload index.js with huggingface_hub
12525b4 verified
// index.js
class GemmaChatbot {
constructor() {
this.generator = null;
this.conversation = [
{ role: "system", content: "You are a helpful assistant." }
];
this.isGenerating = false;
this.device = 'cpu';
this.initElements();
this.bindEvents();
this.loadModel();
}
initElements() {
this.chatContainer = document.getElementById('chat-container');
this.messageInput = document.getElementById('message-input');
this.sendButton = document.getElementById('send-button');
this.loadingIndicator = document.getElementById('loading-indicator');
this.deviceSelect = document.getElementById('device-select');
this.errorToast = document.getElementById('error-toast');
this.errorMessage = document.getElementById('error-message');
}
bindEvents() {
this.sendButton.addEventListener('click', () => this.sendMessage());
this.messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
this.sendMessage();
}
});
this.messageInput.addEventListener('input', this.autoResize.bind(this));
this.deviceSelect.addEventListener('change', (e) => {
this.device = e.target.value;
this.loadModel();
});
}
async loadModel() {
try {
this.showLoading();
this.sendButton.disabled = true;
this.messageInput.disabled = true;
const config = {
dtype: "fp32"
};
if (this.device === 'webgpu') {
config.device = 'webgpu';
}
this.generator = await window.transformers.pipeline(
"text-generation",
"onnx-community/gemma-3-270m-it-ONNX",
config
);
this.hideLoading();
this.showMessage('system', 'Model loaded successfully! Ready to chat.', 'info');
} catch (error) {
console.error('Failed to load model:', error);
this.showError(`Failed to load model: ${error.message}. Try CPU mode or refresh the page.`);
if (this.device === 'webgpu') {
this.deviceSelect.value = 'cpu';
this.device = 'cpu';
}
} finally {
this.sendButton.disabled = false;
this.messageInput.disabled = false;
}
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message || this.isGenerating || !this.generator) return;
this.messageInput.value = '';
this.autoResize();
// Add user message
this.conversation.push({ role: "user", content: message });
this.addMessage('user', message);
this.isGenerating = true;
this.showLoading();
this.sendButton.disabled = true;
this.messageInput.disabled = true;
try {
const streamer = new window.transformers.TextStreamer(this.generator.tokenizer, {
skip_prompt: true,
skip_special_tokens: true,
});
const output = await this.generator(this.conversation, {
max_new_tokens: 512,
do_sample: false,
streamer: streamer,
});
const assistantMessage = output[0].generated_text.at(-1).content;
this.conversation.push({ role: "assistant", content: assistantMessage });
this.addMessage('assistant', assistantMessage);
} catch (error) {
console.error('Generation error:', error);
this.showError('Sorry, an error occurred while generating the response.');
this.addMessage('assistant', "Sorry, I encountered an error. Please try again.");
} finally {
this.isGenerating = false;
this.hideLoading();
this.sendButton.disabled = false;
this.messageInput.disabled = false;
this.messageInput.focus();
}
}
addMessage(role, content, type = 'default') {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${role}-message ${type}`;
const messageContent = document.createElement('div');
messageContent.className = 'message-content';
const roleName = role === 'user' ? 'You' : 'Gemma';
messageContent.innerHTML = `<strong>${roleName}:</strong> ${this.escapeHtml(content)}`;
messageDiv.appendChild(messageContent);
this.chatContainer.appendChild(messageDiv);
this.scrollToBottom();
}
showMessage(role, content, type) {
this.addMessage(role, content, type);
}
autoResize() {
this.messageInput.style.height = 'auto';
this.messageInput.style.height = Math.min(this.messageInput.scrollHeight, 120) + 'px';
}
scrollToBottom() {
this.chatContainer.scrollTop = this.chatContainer.scrollHeight;
}
showLoading() {
this.loadingIndicator.classList.remove('hidden');
}
hideLoading() {
this.loadingIndicator.classList.add('hidden');
}
showError(message) {
this.errorMessage.textContent = message;
this.errorToast.classList.remove('hidden');
setTimeout(() => {
this.errorToast.classList.add('hidden');
}, 5000);
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
// Initialize the chatbot when the page loads
document.addEventListener('DOMContentLoaded', () => {
new GemmaChatbot();
});