diff options
-rw-r--r-- | html/matt-chat/index.html | 180 |
1 files changed, 149 insertions, 31 deletions
diff --git a/html/matt-chat/index.html b/html/matt-chat/index.html index 2d93dfc..5747438 100644 --- a/html/matt-chat/index.html +++ b/html/matt-chat/index.html @@ -84,13 +84,14 @@ background-color: #007BFF; color: white; text-align: right; - margin-right: 20px; + margin-left: 20px; } .bot-message { background-color: #f0f0f0; color: #333; - margin-left: 20px; + text-align: left; + margin-right: 20px; } @media (max-width: 600px) { @@ -184,11 +185,18 @@ { value: "qwen2.5-coder:1.5b", label: "qwen2.5-coder:1.5b, fast coding" }, { value: "qwen2.5-coder:7b", label: "qwen2.5-coder:7b, fast-ish coding" } ], - contextWindowSize: 3, // Number of previous exchanges to remember - systemMessage: "You are a helpful assistant. If you don't know something you'll let me know. Your name is Matt." // Set the mood and personality for the LLM's responses + contextWindowSize: 6, // Number of previous exchanges to remember + systemMessage: "You are a helpful assistant. If you don't know something you'll let me know. Your name is Matt.", // Set the mood and personality for the LLM's responses + maxTokens: 4096, // Approximate max tokens for most models + summarizeThreshold: 3584, // When to trigger summarization + }; + + let conversationHistory = { + summary: null, + current: [], + full: [] }; - let conversationHistory = []; let isCatMode = false; // Flag to track cat mode function populateModelSelect() { @@ -306,10 +314,15 @@ return; } - addMessage(userMessage, "user"); - conversationHistory.push({ role: "user", content: userMessage }); // Add user message to history - userInput.value = ""; + if (userMessage.toLowerCase() === '/context') { + const context = viewCurrentContext(); + addMessage(`Current conversation has ${context.currentMessages} messages\nEstimated tokens: ${context.estimatedTokens}`, "bot"); + return; + } + addMessage(userMessage, "user"); + userInput.value = ""; // Add this line back to clear the input + // Reset the counter document.getElementById("char-count").textContent = "0"; document.getElementById("word-count").textContent = "0"; @@ -332,15 +345,7 @@ const retainHistory = document.getElementById("retain-history").checked; // Check the checkbox state // Prepare the messages for the API - const messagesToSend = [ - { role: "system", content: config.systemMessage }, - { role: "user", content: userMessage } - ]; - - // Include conversation history only if the checkbox is checked - if (retainHistory) { - messagesToSend.push(...conversationHistory.slice(-config.contextWindowSize * 2)); // Get the last few exchanges - } + const messagesToSend = await prepareMessages(userMessage); const response = await fetch(config.apiUrl, { method: "POST", @@ -362,25 +367,22 @@ if (data.choices && data.choices.length > 0) { const botResponse = data.choices[0].message.content; - - // Calculate the duration - const duration = Date.now() - startTime; // Time taken in milliseconds - + // Clear loading indicator clearInterval(animationInterval); loadingIndicator.remove(); - - // Add bot's response to chat + + // Add bot's response to chat and history addMessage(botResponse, "bot"); - conversationHistory.push({ role: "bot", content: botResponse }); // Add bot response to history + conversationHistory.current.push({ role: "assistant", content: botResponse }); - // Display the time taken + // Calculate and display duration + const duration = Date.now() - startTime; const timeTakenMessage = formatDuration(duration); const timeDisplay = document.createElement("div"); timeDisplay.classList.add("bot-time"); timeDisplay.textContent = `Response time: ${timeTakenMessage}`; - timeDisplay.style.textAlign = "center"; // Center the text - document.getElementById("chat-container").appendChild(timeDisplay); // Append the time display + document.getElementById("chat-container").appendChild(timeDisplay); } else { console.error("No response from API"); loadingIndicator.remove(); @@ -388,8 +390,8 @@ } // Optional: Limit the conversation history to the last 10 messages - if (conversationHistory.length > 10) { - conversationHistory.shift(); // Remove the oldest message + if (conversationHistory.current.length > 10) { + conversationHistory.current.shift(); // Remove the oldest message } } catch (error) { @@ -454,8 +456,12 @@ function clearChat() { const chatContainer = document.getElementById("chat-container"); - chatContainer.innerHTML = ""; // Clear all messages - conversationHistory = []; // Clear the conversation history + chatContainer.innerHTML = ""; + conversationHistory = { + summary: null, + current: [], + full: [] + }; } function displayHelp() { @@ -468,6 +474,118 @@ `; addMessage(helpMessage, "bot"); // Display help message as a bot message } + + function estimateTokens(text) { + // Rough estimation: ~4 chars per token for English text + return Math.ceil(text.length / 4); + } + + function getContextSize(messages) { + return messages.reduce((sum, msg) => sum + estimateTokens(msg.content), 0); + } + + async function summarizeConversation(messages) { + try { + const modelSelect = document.getElementById("model-select"); + const selectedModel = modelSelect.value; + + const response = await fetch(config.apiUrl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: selectedModel, + messages: messages, + }), + }); + + const data = await response.json(); + return data.choices[0].message.content; + } catch (error) { + console.error("Error summarizing conversation:", error); + return null; + } + } + + async function prepareMessages(userMessage) { + const messages = []; + + // Always start with system message + messages.push({ role: "system", content: config.systemMessage }); + + if (document.getElementById("retain-history").checked) { + // If we have a summary, add it more naturally + if (conversationHistory.summary) { + messages.push({ + role: "system", + content: `Previous discussion: ${conversationHistory.summary}` + }); + } + + // Add current conversation segment + messages.push(...conversationHistory.current); + } + + // We'll add the new message to history here, before we check for summarization + const newMessage = { role: "user", content: userMessage }; + conversationHistory.current.push(newMessage); + messages.push(newMessage); + + // Check if we need to summarize + const totalTokens = getContextSize(messages); + if (totalTokens > config.summarizeThreshold) { + // Move current messages to full history, except for the newest message + conversationHistory.full.push(...conversationHistory.current.slice(0, -1)); + + // Create a more natural summarization prompt + const summary = await summarizeConversation([ + { + role: "system", + content: "Summarize this conversation's key points and context that would be important for continuing the discussion naturally. Be concise but maintain essential details." + }, + ...conversationHistory.full + ]); + + if (summary) { + conversationHistory.summary = summary; + // Keep only the most recent messages for immediate context + conversationHistory.current = conversationHistory.current.slice(-4); + + // Rebuild messages array with new summary + return [ + { role: "system", content: config.systemMessage }, + { role: "system", content: `Previous discussion: ${summary}` }, + ...conversationHistory.current + ]; + } + } + + return messages; + } + + // Add a function to clean up old messages periodically + function pruneConversationHistory() { + if (conversationHistory.full.length > 100) { + // Keep only the last 100 messages in full history + conversationHistory.full = conversationHistory.full.slice(-100); + } + } + + // Call this after successful responses + setInterval(pruneConversationHistory, 60000); // Clean up every minute + + // Add these functions to help debug and manage context + function viewCurrentContext() { + const context = { + summary: conversationHistory.summary, + currentMessages: conversationHistory.current.length, + fullHistoryMessages: conversationHistory.full.length, + estimatedTokens: getContextSize(conversationHistory.current) + }; + console.log("Current Context:", context); + return context; + } </script> </body> </html> |