// Main application logic class ChatAssistant { constructor() { this.pipeline = null; this.isModelLoaded = false; this.worker = null; this.messageHistory = []; this.initializeElements(); this.setupEventListeners(); this.loadModel(); } initializeElements() { this.chatMessages = document.getElementById('chatMessages'); this.userInput = document.getElementById('userInput'); this.sendButton = document.getElementById('sendButton'); this.modelStatus = document.getElementById('modelStatus'); this.progressFill = document.getElementById('progressFill'); this.progressText = document.getElementById('progressText'); } setupEventListeners() { this.sendButton.addEventListener('click', () => this.sendMessage()); this.userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); this.sendMessage(); } }); } async loadModel() { try { this.modelStatus.textContent = 'Loading model...'; this.updateProgress(0, 'Initializing...'); // Create a Web Worker for model loading this.worker = new Worker('worker.js'); // Listen for messages from the worker this.worker.onmessage = (event) => { const { type, data, progress } = event.data; if (type === 'progress') { this.updateProgress(progress * 100, `Downloading: ${Math.round(progress * 100)}%`); } else if (type === 'ready') { this.pipeline = data; this.isModelLoaded = true; this.modelStatus.textContent = 'Ready'; this.updateProgress(100, 'Model loaded!'); this.addMessage('assistant', 'Hola! I\'m ready to chat. How can I help you today?'); } else if (type === 'error') { this.handleError(data); } }; // Start model loading in worker this.worker.postMessage({ type: 'loadModel' }); } catch (error) { this.handleError(error); } } updateProgress(percentage, text) { this.progressFill.style.width = `${percentage}%`; this.progressText.textContent = text; } async sendMessage() { const userInput = this.userInput.value.trim(); if (!userInput || !this.isModelLoaded) return; // Add user message to chat this.addMessage('user', userInput); this.userInput.value = ''; this.userInput.disabled = true; this.sendButton.disabled = true; try { // Show typing indicator const typingIndicator = this.addTypingIndicator(); // Generate response const response = await this.generateResponse(userInput); // Remove typing indicator and add response typingIndicator.remove(); this.addMessage('assistant', response); } catch (error) { this.handleError(error); this.userInput.disabled = false; this.sendButton.disabled = false; } this.userInput.disabled = false; this.sendButton.disabled = false; this.userInput.focus(); } async generateResponse(input) { if (!this.pipeline) { throw new Error('Model not loaded'); } try { const result = await this.pipeline(input, { max_new_tokens: 100, temperature: 0.7, top_p: 0.9, do_sample: true, return_full_text: false }); return result[0].generated_text.trim(); } catch (error) { throw new Error('Failed to generate response: ' + error.message); } } addMessage(sender, content) { const messageDiv = document.createElement('div'); messageDiv.className = `message ${sender}`; const messageContent = document.createElement('div'); messageContent.className = 'message-content'; messageContent.textContent = content; messageDiv.appendChild(messageContent); this.chatMessages.appendChild(messageDiv); // Scroll to bottom this.chatMessages.scrollTop = this.chatMessages.scrollHeight; this.messageHistory.push({ sender, content }); } addTypingIndicator() { const typingDiv = document.createElement('div'); typingDiv.className = 'message assistant'; const typingContent = document.createElement('div'); typingContent.className = 'message-content typing'; const dots = document.createElement('span'); dots.textContent = '...'; typingContent.appendChild(dots); typingDiv.appendChild(typingContent); this.chatMessages.appendChild(typingDiv); this.chatMessages.scrollTop = this.chatMessages.scrollHeight; return typingDiv; } handleError(error) { console.error('Error:', error); this.modelStatus.textContent = 'Error'; this.addMessage('assistant', 'Sorry, I encountered an error. Please try again later.'); // Show error message to user const errorMessage = document.createElement('div'); errorMessage.className = 'error-message'; errorMessage.textContent = 'An error occurred: ' + error.message; this.chatMessages.appendChild(errorMessage); } } // Initialize the application when DOM is loaded document.addEventListener('DOMContentLoaded', () => { new ChatAssistant(); });