import { showAlert } from './shared_functions.js'; let chatCount = 0; // Zähler für Chat-Sessions let currentChatId = null; // Aktuell angezeigte Chat-ID let useMarkdown = true; document.getElementById('newChatButton').addEventListener('click', () => { createNewChat(); }); document.getElementById('sendButton').addEventListener('click', () => { const chatBox = document.getElementById('chatBox'); const chatInput = document.getElementById('chatInput'); const messageText = chatInput.value.trim(); if (messageText !== '' && currentChatId !== null) { // Stelle sicher, dass eine Chat-ID vorhanden ist const messageElement = document.createElement('div'); messageElement.classList.add('chat-message', 'user'); //messageElement.innerText = messageText; if (useMarkdown) { messageElement.innerHTML = renderMarkdown(messageText); } else { messageElement.innerText = messageText; } chatBox.prepend(messageElement); // Nachricht speichern saveMessage(currentChatId, messageText); // Verwende die aktuelle Chat-ID // Sidebar-Button für den Chat-Verlauf erstellen, falls noch nicht vorhanden if (document.getElementById(`chatSession-${currentChatId}`) === null) { createChatSessionButton(currentChatId); } chatInput.value = ''; // Input-Feld leeren } }); function createNewChat() { // Erhöhe den Chat-Zähler und erstelle einen neuen Chat const newChatId = chatCount++; localStorage.setItem(`chatHistory-${newChatId}`, JSON.stringify([])); // Leeren Chat speichern createChatSessionButton(newChatId); // Button für den neuen Chat erstellen currentChatId = newChatId; // Setze die aktuelle Chat-ID loadChatHistory(currentChatId); // Lade den neuen Chat } async function saveMessage(chatId, message) { const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || []; chatHistory.push({ role: "user", content: message }); localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory)); // Aktualisiere den Button-Text in der Sidebar updateChatSessionButton(chatId); // Sende die Nachricht an den Chatbot const userMessage = getLastUserMessage(); if (userMessage) { let a = await stream_api_open_ai(userMessage); console.log("Komplette Nachricht: " + a) // Update progress bar: let consumption = await tokenize_api_open_ai() updateProgressBar(consumption.count, consumption.max_model_len); const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || []; chatHistory.push({ role: "assistant", content: a }); localStorage.setItem(`chatHistory-${chatId}`, JSON.stringify(chatHistory)); } } function updateChatSessionButton(chatId) { const button = document.getElementById(`chatSession-${chatId}`); if (button) { const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || []; // Hole die erste Nachricht oder lasse es leer, wenn keine vorhanden ist const chatName = chatHistory.length > 0 ? chatHistory[0].content.slice(0, 10) : ''; // Nimm die ersten 10 Zeichen der ersten Nachricht button.innerText = chatName + "..." || `Chat ${chatId + 1}`; // Falls leer, setze auf "Chat x" } } function createChatSessionButton(chatId) { const chatList = document.getElementById('chatList'); // Container für Chat-Button und Löschen-Button const buttonContainer = document.createElement('div'); buttonContainer.classList.add('chat-session-button-container'); // Chat-Button const button = document.createElement('button'); button.classList.add('chat-session-button'); button.id = `chatSession-${chatId}`; button.innerText = `Chat ${chatId + 1}`; // Vorläufiger Name button.addEventListener('click', () => { loadChatHistory(chatId); // Lade den Chat-Verlauf und setze die aktuelle Chat-ID currentChatId = chatId; // Setze die aktuelle Chat-ID auf die ausgewählte Chat-ID }); // Löschen-Button const deleteButton = document.createElement('button'); deleteButton.classList.add('delete-chat-button'); deleteButton.innerText = "✕"; deleteButton.addEventListener('click', (event) => { event.stopPropagation(); // Verhindert, dass der Chat geladen wird, wenn auf Löschen geklickt wird deleteChat(chatId, buttonContainer); clearChat(); }); // Elemente hinzufügen buttonContainer.appendChild(button); buttonContainer.appendChild(deleteButton); chatList.appendChild(buttonContainer); } function clearChat(){ const chatBox = document.getElementById('chatBox'); chatBox.innerHTML = ''; // Aktuellen Chat leeren } function loadChatHistory(chatId) { const chatBox = document.getElementById('chatBox'); chatBox.innerHTML = ''; // Aktuellen Chat leeren if (currentChatId === null) { return; // Wenn kein Chat ausgewählt ist, nichts laden } const chatHistory = JSON.parse(localStorage.getItem(`chatHistory-${chatId}`)) || []; chatHistory.forEach(entry => { const messageElement = document.createElement('div'); messageElement.classList.add('chat-message', entry.role); messageElement.innerHTML = renderMarkdown(entry.content); chatBox.prepend(messageElement); }); } function deleteChat(chatId, buttonContainer) { // Entferne den Chat-Verlauf aus dem LocalStorage localStorage.removeItem(`chatHistory-${chatId}`); // Entferne den Button aus der Sidebar buttonContainer.remove(); } // Lade alle Chat-Sitzungen beim Start function loadAllChatSessions() { Object.keys(localStorage).forEach((key) => { if (key.startsWith('chatHistory-')) { const chatId = parseInt(key.split('-')[1], 10); createChatSessionButton(chatId); chatCount = Math.max(chatCount, chatId + 1); // Chat-Zähler aktualisieren } }); for (let i = 0; i < chatCount; i++) {// Aktualisiere die Namen an der Seite updateChatSessionButton(i); } // Lade den neuesten Chat-Verlauf if (chatCount > 0) { loadChatHistory(chatCount - 1); currentChatId = chatCount - 1; // Setze die aktuelle Chat-ID } else { const chatBox = document.getElementById('chatBox'); chatBox.innerHTML = ''; // Chat-Box leer, wenn keine Chats existieren } } // Beim Laden der Seite alle Chat-Sitzungen laden window.addEventListener('DOMContentLoaded', loadAllChatSessions); const chatInput = document.getElementById('chatInput'); // Event-Listener für das Senden der Nachricht und das Erstellen eines Zeilenumbruchs chatInput.addEventListener('keydown', (event) => { if (event.key === 'Enter') { if (currentChatId == null){ createNewChat(); } // Prüfen, ob die Shift-Taste nicht gedrückt wird if (!event.shiftKey) { event.preventDefault(); // Verhindert das Standardverhalten (Absenden des Formulars) const messageText = chatInput.value.trim(); if (messageText !== '' && currentChatId !== null) { const messageElement = document.createElement('div'); messageElement.classList.add('chat-message', 'user'); messageElement.innerText = messageText; document.getElementById('chatBox').prepend(messageElement); // Nachricht speichern saveMessage(currentChatId, messageText); // Sidebar-Button für den Chat-Verlauf erstellen, falls noch nicht vorhanden if (document.getElementById(`chatSession-${currentChatId}`) === null) { createChatSessionButton(currentChatId); } chatInput.value = ''; // Input-Feld leeren } } else { // Shift + Enter: Zeilenumbruch chatInput.value += '\n'; // Zeilenumbruch in das Textfeld einfügen } } }); /* OpenAI zeug */ async function getModels() { try { const response = await fetch(`http://localhost:8015/v1/models`, { method: 'GET', headers: { 'Authorization': `Bearer YOUR_API_KEY`, 'Content-Type': 'application/json', } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const models = await response.json(); return models.data[0].id } catch (error) { if (error.message.includes('502')) { showAlert("Server Error: 502 \nMaybe the LLM is offline?") console.error('Bad Gateway: The server is acting as a gateway or proxy and received an invalid response from the upstream server.'); } else { // Handle other errors here console.error('Error fetching models:', error); } } } function getAllCurrentChatMessages() { const cookieData = JSON.parse(localStorage.getItem(`chatHistory-${currentChatId}`)) || []; return cookieData } function getLastUserMessage() { // Lade die Cookie-Daten (ersetze dies durch den tatsächlichen Weg zur Cookie-Datenstruktur) const cookieData = JSON.parse(localStorage.getItem(`chatHistory-${currentChatId}`)) || []; // Filter nur die User-Nachrichten heraus const userMessages = cookieData.filter(message => message.role === "user"); // Falls es User-Nachrichten gibt, die letzte davon zurückgeben if (userMessages.length > 0) { return userMessages[userMessages.length - 1].content; } return ''; // Rückgabe eines leeren Strings, falls keine Nachricht gefunden wird } function renderMarkdown(content) { return marked.parse(content); } async function stream_api_open_ai(userMessage) { // Neues div-Element für die Antwort des Chatbots erstellen const chatBox = document.getElementById('chatBox'); const botMessageDiv = document.createElement('div'); botMessageDiv.className = 'chat-message assistant'; chatBox.prepend(botMessageDiv); let send_message_system = [{ role: "system", content: "You are a knowledgeable assistant." }]; let send_message_user = getAllCurrentChatMessages(); let send_message_final = send_message_system.concat(send_message_user) console.log(send_message_final) const response = await fetch('http://localhost:8015/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer YOUR_API_KEY`, }, body: JSON.stringify({ model: await getModels(), messages: send_message_final, stream: true, temperature: 0.3 }) }); const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); let result = ''; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); const lines = chunk.split('\n'); for (const line of lines) { if (line && line.includes('data: ')) { const jsonStr = line.replace('data: ', '').trim(); if (jsonStr === '[DONE]'){ break; } try { const json = JSON.parse(jsonStr); if (json.choices[0].delta.content) { const token = json.choices[0].delta.content; result += token; if (useMarkdown) { botMessageDiv.innerHTML = renderMarkdown(result); } else { botMessageDiv.textContent = result; } } } catch (error) { console.error('Error parsing JSON:', error, 'Received:', jsonStr); } } } } return result; } function formatArrayToCustomString(array) { return '[' + array.map(dict => { return '{' + Object.entries(dict) .map(([key, value]) => `'${key}':'${value}'`) .join(', ') + '}'; }).join(', ') + ']'; } // Tokenizer async function tokenize_api_open_ai() { let send_message_system = [{ role: "system", content: "You are a knowledgeable assistant." }]; let send_message_user = getAllCurrentChatMessages(); let send_message_final = send_message_system.concat(send_message_user) let formattedString = `"${formatArrayToCustomString(send_message_final)}"`; console.log(formattedString) const response = await fetch('http://localhost:8015/tokenize', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer YOUR_API_KEY`, }, body: JSON.stringify({ model: await getModels(), prompt: formattedString, add_special_tokens: true }) }); // Check if the response is successful if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const json = await response.json(); // Await the response.json() promise console.log(json); // Log the parsed JSON response return json } // Progress Bar // Function to update the progress bar function updateProgressBar(currentUsage, maxUsage) { const percentage = (currentUsage / maxUsage) * 100; // Update the width of the progress bar const progressBar = document.getElementById('progress-bar'); progressBar.style.width = `${percentage}%`; // Update the text const usageText = document.getElementById('usage-text'); usageText.innerText = `${currentUsage} / ${maxUsage} used`; }