diff --git a/app.py b/app.py index e79a44f6..9b91f864 100644 --- a/app.py +++ b/app.py @@ -87,6 +87,10 @@ class Gpt4AllWebUI: self.add_endpoint( "/message_rank_down", "message_rank_down", self.message_rank_down, methods=["GET"] ) + self.add_endpoint( + "/delete_message", "delete_message", self.delete_message, methods=["GET"] + ) + self.add_endpoint( "/update_model_params", "update_model_params", self.update_model_params, methods=["POST"] @@ -103,6 +107,13 @@ class Gpt4AllWebUI: self.add_endpoint( "/training", "training", self.training, methods=["GET"] ) + self.add_endpoint( + "/main", "main", self.main, methods=["GET"] + ) + + self.add_endpoint( + "/settings", "settings", self.settings, methods=["GET"] + ) self.add_endpoint( "/help", "help", self.help, methods=["GET"] @@ -358,6 +369,12 @@ GPT4All:Welcome! I'm here to assist you with anything you need. What can I do fo new_rank = self.current_discussion.message_rank_down(discussion_id) return jsonify({"new_rank": new_rank}) + def delete_message(self): + discussion_id = request.args.get("id") + new_rank = self.current_discussion.delete_message(discussion_id) + return jsonify({"new_rank": new_rank}) + + def new_discussion(self): title = request.args.get("title") self.current_discussion = self.db.create_discussion(title) @@ -402,6 +419,12 @@ GPT4All:Welcome! I'm here to assist you with anything you need. What can I do fo def get_config(self): return jsonify(self.config) + def main(self): + return render_template("main.html") + + def settings(self): + return render_template("settings.html") + def help(self): return render_template("help.html") @@ -459,7 +482,7 @@ if __name__ == "__main__": help="launch Flask server in debug mode", ) parser.add_argument( - "--host", type=str, default="localhost", help="the hostname to listen on" + "--host", type=str, default=None, help="the hostname to listen on" ) parser.add_argument("--port", type=int, default=None, help="the port to listen on") parser.add_argument( diff --git a/db.py b/db.py index 4f4a4cf0..11d32fad 100644 --- a/db.py +++ b/db.py @@ -90,7 +90,7 @@ class DiscussionsDB: return cursor.fetchone() - def delete(self, query): + def delete(self, query, params=None): """ Execute the specified SQL delete query on the database, with optional parameters. @@ -98,7 +98,10 @@ class DiscussionsDB: """ with sqlite3.connect(self.db_path) as conn: cursor = conn.cursor() - cursor.execute(query) + if params is None: + cursor.execute(query) + else: + cursor.execute(query, params) conn.commit() def insert(self, query, params=None): @@ -276,5 +279,14 @@ class Discussion: f"UPDATE message SET rank = ? WHERE id = ?",(new_rank,message_id) ) return new_rank + + def delete_message(self, message_id): + """Delete the message + + Args: + message_id (int): The id of the message to be deleted + """ + # Retrieve current rank value for message_id + self.discussions_db.delete("DELETE FROM message WHERE id=?", (message_id,)) # ======================================================================================================================== diff --git a/static/images/refresh.png b/static/images/refresh.png new file mode 100644 index 00000000..eba88e28 Binary files /dev/null and b/static/images/refresh.png differ diff --git a/static/images/thumb_down.png b/static/images/thumb_down.png new file mode 100644 index 00000000..d493eb68 Binary files /dev/null and b/static/images/thumb_down.png differ diff --git a/static/images/thumb_up.png b/static/images/thumb_up.png new file mode 100644 index 00000000..1c7953a9 Binary files /dev/null and b/static/images/thumb_up.png differ diff --git a/static/js/chat.js b/static/js/chat.js index c8a2a564..52d76a7d 100644 --- a/static/js/chat.js +++ b/static/js/chat.js @@ -1,279 +1,236 @@ -const chatWindow = document.getElementById('chat-window'); -const chatForm = document.getElementById('chat-form'); -const userInput = document.getElementById('user-input'); - -chatForm.addEventListener('submit', event => { - event.preventDefault(); - - // get user input and clear input field - message = userInput.value; - userInput.value = ''; - - // add user message to chat window - const sendbtn = document.querySelector("#submit-input") - const waitAnimation = document.querySelector("#wait-animation") - sendbtn.style.display="none"; - waitAnimation.style.display="block"; - fetch('/bot', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ message }) - }).then(function(response) { - const stream = new ReadableStream({ - start(controller) { - const reader = response.body.getReader(); - function push() { - reader.read().then(function(result) { - if (result.done) { - sendbtn.style.display="block"; - waitAnimation.style.display="none"; - controller.close(); - return; - } - controller.enqueue(result.value); - push(); - }) - } - push(); - } - }); - const textDecoder = new TextDecoder(); - const readableStreamDefaultReader = stream.getReader(); - let entry_counter = 0 - function readStream() { - readableStreamDefaultReader.read().then(function(result) { - if (result.done) { - return; - } - - text = textDecoder.decode(result.value); - - // The server will first send a json containing information about the message just sent - if(entry_counter==0) - { - // We parse it and - infos = JSON.parse(text) - addMessage('User', infos.message, infos.id, 0, can_edit=true); - elements = addMessage('GPT4ALL', '', infos.response_id, 0, can_edit=true); - messageTextElement=elements['messageTextElement']; - hiddenElement=elements['hiddenElement']; - entry_counter ++; - } - else{ - // For the other enrtries, these are just the text of the chatbot - for (const char of text) { - txt = hiddenElement.innerHTML; - if (char != '\f') { - txt += char - hiddenElement.innerHTML = txt - messageTextElement.innerHTML = txt.replace(/\n/g, "
") - } - - // scroll to bottom of chat window - chatWindow.scrollTop = chatWindow.scrollHeight; - } - entry_counter ++; - } - - readStream(); - }); - } - readStream(); - }); - -}); - - function addMessage(sender, message, id, rank=0, can_edit=false) { - console.log(id) - const messageElement = document.createElement('div'); - messageElement.classList.add('bg-secondary', 'drop-shadow-sm', 'p-4', 'mx-6', 'my-4', 'flex', 'flex-col', 'space-x-2', 'rounded-lg', 'shadow-lg', 'bg-gray-800', 'hover:bg-gray-700', 'transition-colors', 'duration-300'); + const chatWindow = document.getElementById('chat-window'); + const chatForm = document.getElementById('chat-form'); + const userInput = document.getElementById('user-input'); - //messageElement.classList.add(sender); - messageElement.setAttribute('id', id); - - const senderElement = document.createElement('div'); - senderElement.classList.add('font-normal', 'underline', 'text-sm'); - senderElement.innerHTML = sender; - - const messageTextElement = document.createElement('div'); - messageTextElement.classList.add('font-medium', 'text-md'); - messageTextElement.innerText = message; - // Create a hidden div element needed to buffer responses before commiting them to the visible message - const hiddenElement = document.createElement('div'); - hiddenElement.style.display = 'none'; - hiddenElement.innerHTML = ''; - - messageElement.appendChild(senderElement); - messageElement.appendChild(messageTextElement); - if(can_edit) - { - // Create buttons container - const buttonsContainer = document.createElement('div'); - // Add the 'flex' class to the div - buttonsContainer.classList.add('flex'); - - // Add the 'justify-end' class to the div - buttonsContainer.classList.add('justify-end'); - - // Set the width and height of the container to 100% - buttonsContainer.style.width = '100%'; - buttonsContainer.style.height = '100%'; - - const editButton = document.createElement('button'); - editButton.classList.add('my-1','mx-1','outline-none','px-4','bg-accent','text-white','rounded-md','hover:bg-[#7ba0ea]','active:bg-blue-100','transition-colors','ease-in-out'); - editButton.style.float = 'right'; // set the float property to right - editButton.style.display='inline-block' - editButton.innerHTML = 'Edit'; - editButton.addEventListener('click', () => { - const inputField = document.createElement('input'); - inputField.type = 'text'; - inputField.classList.add('font-medium', 'text-md', 'border', 'border-gray-300', 'p-1'); - inputField.value = messageTextElement.innerHTML; - - buttonsContainer.style.display="none" + console.log(id) + const messageElement = document.createElement('div'); + messageElement.classList.add('bg-secondary', 'drop-shadow-sm', 'p-4', 'mx-6', 'my-4', 'flex', 'flex-col', 'space-x-2', 'rounded-lg', 'shadow-lg', 'bg-gray-800', 'hover:bg-gray-700', 'transition-colors', 'duration-300'); + + //messageElement.classList.add(sender); + messageElement.setAttribute('id', id); - const saveButton = document.createElement('button'); - saveButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-2', 'px-4', 'rounded', 'my-2', 'ml-2'); - saveButton.innerHTML = 'Save'; - saveButton.addEventListener('click', () => { - const newText = inputField.value; - messageTextElement.innerHTML = newText; - // make request to update message - const url = `/update_message?id=${id}&message=${newText}`; - fetch(url) - .then(response => { - if (!response.ok) { - throw new Error('Network response was not ok'); - } - else{ - console.log("Updated") - } - }) - .catch(error => { - console.error('There was a problem updating the message:', error); - }); - buttonsContainer.style.display='inline-block' - messageElement.replaceChild(messageTextElement, inputField); - //messageElement.removeChild(inputField); - messageElement.removeChild(saveButton); - }); + const senderElement = document.createElement('div'); + senderElement.classList.add('font-normal', 'underline', 'text-sm'); + senderElement.innerHTML = sender; + + const messageTextElement = document.createElement('div'); + messageTextElement.classList.add('font-medium', 'text-md'); + messageTextElement.innerText = message; + // Create a hidden div element needed to buffer responses before commiting them to the visible message + const hiddenElement = document.createElement('div'); + hiddenElement.style.display = 'none'; + hiddenElement.innerHTML = ''; + + messageElement.appendChild(senderElement); + messageElement.appendChild(messageTextElement); + if(can_edit) + { + // Create buttons container + const buttonsContainer = document.createElement('div'); + // Add the 'flex' class to the div + buttonsContainer.classList.add('flex'); + + // Add the 'justify-end' class to the div + buttonsContainer.classList.add('justify-end'); + + // Set the width and height of the container to 100% + buttonsContainer.style.width = '100%'; + buttonsContainer.style.height = '100%'; + + const editButton = document.createElement('button'); + editButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); + editButton.style.float = 'right'; // set the float property to right + editButton.style.display='inline-block' + editButton.innerHTML = ''; + const editImg = document.createElement('img'); + editImg.src = "/static/images/edit_discussion.png"; + editImg.classList.add('py-1', 'px-1', 'rounded', 'w-10', 'h-10'); + editButton.appendChild(editImg) + + editButton.addEventListener('click', () => { + const inputField = document.createElement('input'); + inputField.type = 'text'; + inputField.classList.add('font-medium', 'text-md', 'border', 'border-gray-300', 'p-1'); + inputField.value = messageTextElement.innerHTML; + + buttonsContainer.style.display="none" + + const saveButton = document.createElement('button'); + saveButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-2', 'px-4', 'rounded', 'my-2', 'ml-2'); + saveButton.innerHTML = 'Save'; + saveButton.addEventListener('click', () => { + const newText = inputField.value; + messageTextElement.innerHTML = newText; + // make request to update message + const url = `/update_message?id=${id}&message=${newText}`; + fetch(url) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + else{ + console.log("Updated") + } + }) + .catch(error => { + console.error('There was a problem updating the message:', error); + }); + buttonsContainer.style.display='inline-block' + messageElement.replaceChild(messageTextElement, inputField); + //messageElement.removeChild(inputField); + messageElement.removeChild(saveButton); + }); + + messageElement.replaceChild(inputField, messageTextElement); + messageElement.appendChild(saveButton); + inputField.focus(); + }); + + const deleteButton = document.createElement('button'); + deleteButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); + deleteButton.style.float = 'right'; // set the float property to right + deleteButton.style.display='inline-block' + deleteButton.innerHTML = ''; + const deleteImg = document.createElement('img'); + deleteImg.src = "/static/images/delete_discussion.png"; + deleteImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15'); + deleteButton.appendChild(deleteImg) + deleteButton.addEventListener('click', () => { + const url = `/delete_message?id=${id}`; + fetch(url) + .then(response => response.json()) + .then(data => { + console.log(data.new_rank) + messageElement.style.display="none" + }) + .catch(error => { + console.error('There was a problem updating the message:', error); + }); + }); + const rank_up = document.createElement('button'); + rank_up.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); + rank_up.style.float = 'right'; // set the float property to right + rank_up.style.display='inline-block' + rank_up.innerHTML = ''; + const thumbUpImg = document.createElement('img'); + thumbUpImg.src = "/static/images/thumb_up.png"; + thumbUpImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15'); + rank_up.appendChild(thumbUpImg) + const thumbUpBadge = document.createElement('span'); + thumbUpBadge.innerText = ""; + thumbUpBadge.classList.add('inline-flex', 'items-center', 'justify-center', 'h-4', 'w-4', 'rounded-full', 'bg-red-500', 'text-white', 'text-xs', 'top-0', 'right-0'); + rank_up.appendChild(thumbUpBadge) + + rank_up.addEventListener('click', () => { + const url = `/message_rank_up?id=${id}`; + fetch(url) + .then(response => response.json()) + .then(data => { + console.log(data.new_rank) + if(data.new_rank>0){ + thumbUpBadge.innerText=`${data.new_rank}` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`block` + thumbDownBadge.display='none' + } + else if(data.new_rank<0){ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`${data.new_rank}` + thumbUpBadge.display=`none` + thumbDownBadge.display='block' + } + else{ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`none` + thumbDownBadge.display='none' + } + }) + .catch(error => { + console.error('There was a problem updating the message:', error); + }); + }); + + const rank_down = document.createElement('button'); + rank_down.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); + rank_down.style.float = 'right'; // set the float property to right + rank_down.style.display='inline-block' + rank_down.innerHTML = ''; + const thumbDownImg = document.createElement('img'); + thumbDownImg.src = "/static/images/thumb_down.png"; + thumbDownImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15'); + rank_down.appendChild(thumbDownImg) + const thumbDownBadge = document.createElement('span'); + thumbDownBadge.innerText = ""; + thumbDownBadge.classList.add('inline-flex', 'items-center', 'justify-center', 'h-4', 'w-4', 'rounded-full', 'bg-red-500', 'text-white', 'text-xs', 'top-0', 'right-0'); + rank_down.appendChild(thumbDownBadge) + + rank_down.addEventListener('click', () => { + const url = `/message_rank_down?id=${id}`; + fetch(url) + .then(response => response.json()) + .then(data => { + console.log(data) + if(data.new_rank>0){ + thumbUpBadge.innerText=`${data.new_rank}` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`block` + thumbDownBadge.display='none' + } + else if(data.new_rank<0){ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`${data.new_rank}` + thumbUpBadge.display=`none` + thumbDownBadge.display='block' + } + else{ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`none` + thumbDownBadge.display='none' + } + }) + .catch(error => { + console.error('There was a problem updating the message:', error); + }); + }); + + buttonsContainer.appendChild(editButton); + buttonsContainer.appendChild(deleteButton); + + buttonsContainer.appendChild(rank_up); + buttonsContainer.appendChild(rank_down); + messageElement.appendChild(buttonsContainer); + if(rank>0){ + thumbUpBadge.innerText=`${rank}` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`block` + thumbDownBadge.display='none' + } + else if(rank<0){ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`${rank}` + thumbUpBadge.display=`none` + thumbDownBadge.display='block' + } + else{ + thumbUpBadge.innerText=`` + thumbDownBadge.innerText=`` + thumbUpBadge.display=`none` + thumbDownBadge.display='none' + } - messageElement.replaceChild(inputField, messageTextElement); - messageElement.appendChild(saveButton); - inputField.focus(); - }); - - const rank_up = document.createElement('button'); - rank_up.classList.add('my-1','mx-1','outline-none','px-4','bg-accent','text-white','rounded-md','hover:bg-[#7ba0ea]','active:bg-[#3d73e1]','transition-colors','ease-in-out'); - rank_up.style.float = 'right'; // set the float property to right - rank_up.style.display='inline-block' - rank_up.innerHTML = 'Up'; - rank_up.addEventListener('click', () => { - const url = `/message_rank_up?id=${id}`; - fetch(url) - .then(response => response.json()) - .then(data => { - console.log(data.new_rank) - if(data.new_rank>0){ - rank_up.innerText=`Up(${data.new_rank})` - rank_down.innerText=`Down` - } - else if(data.new_rank<0){ - rank_up.innerText=`Up` - rank_down.innerText=`Down(${data.new_rank})` - } - else{ - rank_up.innerText=`Up` - rank_down.innerText=`Down` - } - }) - .catch(error => { - console.error('There was a problem updating the message:', error); - }); - }); - - const rank_down = document.createElement('button'); - rank_down.classList.add('my-1','mx-1','outline-none','px-4','bg-accent','text-white','rounded-md','hover:bg-[#7ba0ea]','active:bg-[#3d73e1]','transition-colors','ease-in-out'); - rank_down.style.float = 'right'; // set the float property to right - rank_down.style.display='inline-block' - rank_down.innerHTML = 'Down'; - rank_down.addEventListener('click', () => { - const url = `/message_rank_down?id=${id}`; - fetch(url) - .then(response => response.json()) - .then(data => { - console.log(data) - if(data.new_rank>0){ - rank_up.innerText=`Up(${data.new_rank})` - rank_down.innerText=`Down` - } - else if(data.new_rank<0){ - rank_up.innerText=`Up` - rank_down.innerText=`Down(${data.new_rank})` - } - }) - .catch(error => { - console.error('There was a problem updating the message:', error); - }); - }); - - buttonsContainer.appendChild(editButton); - buttonsContainer.appendChild(rank_up); - buttonsContainer.appendChild(rank_down); - messageElement.appendChild(buttonsContainer); - if(rank>0){ - rank_up.innerText=`Up(${rank})` - rank_down.innerText=`Down` } - else if(rank<0){ - rank_up.innerText=`Up` - rank_down.innerText=`Down(${rank})` + chatWindow.appendChild(messageElement); + chatWindow.appendChild(hiddenElement); + + // scroll to bottom of chat window + chatWindow.scrollTop = chatWindow.scrollHeight; + + // Return all needed stuff + return { + 'messageTextElement':messageTextElement, + 'hiddenElement':hiddenElement } - - } - chatWindow.appendChild(messageElement); - chatWindow.appendChild(hiddenElement); - - // scroll to bottom of chat window - chatWindow.scrollTop = chatWindow.scrollHeight; - - // Return all needed stuff - return {'messageTextElement':messageTextElement, 'hiddenElement':hiddenElement} -} - -const welcome_message = ` -This is a very early testing Web UI of GPT4All chatbot. -Keep in mind that this is a 7B parameters model running on your own PC's CPU. It is literally 24 times smaller than GPT-3 in terms of parameter count. -While it is still new and not as powerful as GPT-3.5 or GPT-4, it can still be useful for many applications. -Many people are building models out there and you can try the models and compare them yourself. -Any feedback and contribution is welcomed. -This Web UI is a binding to the GPT4All model that allows you to test a chatbot locally on your machine. Feel free to ask questions or give instructions. - -Examples: - -- A color description has been provided. Find the CSS code associated with that color. A light red color with a medium light shade of pink. -- Come up with an interesting idea for a new movie plot. Your plot should be described with a title and a summary. -- Reverse a string in python. -- List 10 dogs. -- Write me a poem about the fall of Julius Ceasar into a ceasar salad in iambic pentameter. -- What is a three word topic describing the following keywords: baseball, football, soccer. -- Act as ChefAI an AI that has the ability to create recipes for any occasion. Instruction: Give me a recipe for my next anniversary. -- who is Abraham Lincoln?. -- write a letter to my collegue and tell him I can't make it to work today. Make it humorous. -- write a poem about love between two AIs. -Welcome! I'm here to assist you with anything you need. What can I do for you today? -`; - -addMessage("GPT4ALL",welcome_message,0,0,false); - -// Code for collapsable text -const collapsibles = document.querySelectorAll('.collapsible'); -function uncollapse(id){ - console.log("uncollapsing") - const content = document.querySelector(`#${id}`); - content.classList.toggle('active'); -} - +} \ No newline at end of file diff --git a/static/js/discussions.js b/static/js/discussions.js index 5484d2ea..97020482 100644 --- a/static/js/discussions.js +++ b/static/js/discussions.js @@ -13,7 +13,7 @@ function populate_discussions_list() buttonWrapper.classList.add('flex', 'items-center', 'mt-2', 'px-2', 'py-1', 'text-left'); const renameButton = document.createElement('button'); - renameButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-2', 'px-2', 'rounded', 'ml-2', 'mr-2',"w-20","h-20"); + renameButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); const renameImg = document.createElement('img'); renameImg.src = "/static/images/edit_discussion.png"; renameImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15'); @@ -77,7 +77,7 @@ function populate_discussions_list() dialog.showModal(); }); const deleteButton = document.createElement('button'); - deleteButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'rounded', 'ml-2', 'mr-2', "w-20", "h-20"); + deleteButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10"); const deleteImg = document.createElement('img'); deleteImg.src = "/static/images/delete_discussion.png"; deleteImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15'); @@ -110,7 +110,7 @@ function populate_discussions_list() }); const discussionButton = document.createElement('button'); - discussionButton.classList.add('bg-blue-500', 'hover:bg-blue-700', 'text-white', 'font-bold', 'rounded', 'ml-2', 'w-full', 'h-20'); + discussionButton.classList.add('bg-green-500', 'hover:bg-green-700', 'text-white', 'font-bold', 'py-2', 'px-4', 'rounded', 'ml-2', 'w-full'); discussionButton.textContent = discussion.title; discussionButton.addEventListener('click', () => { // send query with discussion id to reveal discussion messages diff --git a/static/js/main.js b/static/js/main.js new file mode 100644 index 00000000..41ca8f4e --- /dev/null +++ b/static/js/main.js @@ -0,0 +1,104 @@ +function update_main(){ + const chatWindow = document.getElementById('chat-window'); + const chatForm = document.getElementById('chat-form'); + const userInput = document.getElementById('user-input'); + + chatForm.addEventListener('submit', event => { + event.preventDefault(); + + // get user input and clear input field + message = userInput.value; + userInput.value = ''; + + // add user message to chat window + const sendbtn = document.querySelector("#submit-input") + const waitAnimation = document.querySelector("#wait-animation") + sendbtn.style.display="none"; + waitAnimation.style.display="block"; + fetch('/bot', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ message }) + }).then(function(response) { + const stream = new ReadableStream({ + start(controller) { + const reader = response.body.getReader(); + function push() { + reader.read().then(function(result) { + if (result.done) { + sendbtn.style.display="block"; + waitAnimation.style.display="none"; + controller.close(); + return; + } + controller.enqueue(result.value); + push(); + }) + } + push(); + } + }); + const textDecoder = new TextDecoder(); + const readableStreamDefaultReader = stream.getReader(); + let entry_counter = 0 + function readStream() { + readableStreamDefaultReader.read().then(function(result) { + if (result.done) { + return; + } + + text = textDecoder.decode(result.value); + + // The server will first send a json containing information about the message just sent + if(entry_counter==0) + { + // We parse it and + infos = JSON.parse(text) + addMessage('User', infos.message, infos.id, 0, can_edit=true); + elements = addMessage('GPT4ALL', '', infos.response_id, 0, can_edit=true); + messageTextElement=elements['messageTextElement']; + hiddenElement=elements['hiddenElement']; + entry_counter ++; + } + else{ + // For the other enrtries, these are just the text of the chatbot + for (const char of text) { + txt = hiddenElement.innerHTML; + if (char != '\f') { + txt += char + hiddenElement.innerHTML = txt + messageTextElement.innerHTML = txt.replace(/\n/g, "
") + } + + // scroll to bottom of chat window + chatWindow.scrollTop = chatWindow.scrollHeight; + } + entry_counter ++; + } + + readStream(); + }); + } + readStream(); + }); + + }); + + const welcome_message = ` + Welcome! I'm here to assist you with anything you need. What can I do for you today? + `; + + addMessage("GPT4ALL",welcome_message,0,0,false); + +} +fetch('/main') +.then(response => response.text()) +.then(html => { + document.getElementById('main').innerHTML = html; + update_main(); +}) +.catch(error => { + console.error('Error loading main page:', error); +}); diff --git a/static/js/settings.js b/static/js/settings.js index 8e24cfde..e31048b2 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -1,3 +1,121 @@ + +fetch('/settings') +.then(response => response.text()) +.then(html => { + document.getElementById('settings').innerHTML = html; + + modelInput = document.getElementById('model'); + seedInput = document.getElementById('seed'); + tempInput = document.getElementById('temp'); + nPredictInput = document.getElementById('n-predict'); + topKInput = document.getElementById('top-k'); + topPInput = document.getElementById('top-p'); + repeatPenaltyInput = document.getElementById('repeat-penalty'); + repeatLastNInput = document.getElementById('repeat-last-n'); + + temperatureValue = document.getElementById('temperature-value'); + n_predictValue = document.getElementById('n-predict-value'); + topkValue = document.getElementById('top-k-value'); + toppValue = document.getElementById('top-p-value'); + + repeatPenaltyValue = document.getElementById('repeat-penalty-value'); + repeatLastNValue = document.getElementById('repeat-last-n'); + + tempInput.addEventListener('input',() => { + temperatureValue.textContent =`Temperature(${tempInput.value})` + }) + + nPredictInput.addEventListener('input',() => { + n_predictValue.textContent =`N Predict(${nPredictInput.value})` + }) + + topKInput.addEventListener('input',() => { + topkValue.textContent =`Top-K(${topKInput.value})` + }) + + topPInput.addEventListener('input',() => { + toppValue.textContent =`Top-P(${topPInput.value})` + }) + + repeatPenaltyInput.addEventListener('input',() => { + repeatPenaltyValue.textContent =`Repeat penalty(${repeatPenaltyInput.value})` + }) + + repeatLastNInput.addEventListener('input',() => { + repeatLastNValue.textContent =`Repeat last N(${repeatLastNInput.value})` + }) + + + + fetch('/get_config') + .then((response) => response.json()) + .then((data) => { + console.log(data); + modelInput.value = data["model"] + seedInput.value = data["seed"] + tempInput.value = data["temp"] + nPredictInput.value = data["n_predict"] + topKInput.value = data["top_k"] + topPInput.value = data["top_p"] + + repeatPenaltyInput.textContent = data["repeat_penalty"] + repeatLastNInput.textContent = data["repeat_last_n"] + + temperatureValue.textContent =`Temperature(${data["temp"]})` + n_predictValue.textContent =`N Predict(${data["n_predict"]})` + + topkValue.textContent =`Top-K(${data["top_k"]})` + toppValue.textContent =`Top-P(${data["top_p"]})` + + repeatPenaltyValue.textContent =`Repeat penalty(${data["repeat_penalty"]})` + repeatLastNValue.textContent =`Repeat last N(${data["repeat_last_n"]})` + }) + .catch((error) => { + console.error('Error:', error); + }); + + + const submitButton = document.getElementById('submit-model-params'); + submitButton.addEventListener('click', (event) => { + // Prevent default form submission + event.preventDefault(); + + // Get form values and put them in an object + const formValues = { + model: modelInput.value, + seed: seedInput.value, + temp: tempInput.value, + nPredict: nPredictInput.value, + topK: topKInput.value, + topP: topPInput.value, + repeatPenalty: repeatPenaltyInput.value, + repeatLastN: repeatLastNInput.value + }; + console.log(formValues); + // Use fetch to send form values to Flask endpoint + fetch('/update_model_params', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(formValues), + }) + .then((response) => response.json()) + .then((data) => { + console.log(data); + }) + .catch((error) => { + console.error('Error:', error); + }); + }); + + + +}) +.catch(error => { + console.error('Error loading settings page:', error); +}); + function populate_models(){ // Get a reference to the - - - +
@@ -119,15 +45,17 @@ - + + + + + + - - - diff --git a/templates/help.html b/templates/help.html index 6092bf3c..c83ff0bf 100644 --- a/templates/help.html +++ b/templates/help.html @@ -29,6 +29,7 @@
  • Credits
  • How to use
  • FAQ
  • +
  • Examples
  • @@ -82,6 +83,33 @@ +
    +

    Usage examples

    +
    +
    +
    Casual discussion
    +
    Hello, my name is (put your name here).
    +
    Color picker for css
    +
    What is the hex code for the color pink.
    +
    Movie plot
    +
    Come up with an interesting idea for a new movie plot. Your plot should be described with a title and a summary.
    +
    Programming questions
    +
    Write a python function that reverses a string.
    +
    Ask about dogs
    +
    List 10 dogs.
    +
    Weird stuff
    +
    Write me a poem about the fall of Julius Ceasar into a ceasar salad in iambic pentameter.
    +
    Culinary help
    +
    Act as ChefAI an AI that has the ability to create recipes for any occasion. Instruction: Give me a recipe for my next anniversary.
    +
    General culture
    +
    Who is Abraham Lincoln?
    +
    Writing a letter
    +
    write a letter to my collegue and tell him I can't make it to work today. Make it humorous.
    +
    Love poem
    +
    write a poem about love between two AIs.
    +
    +
    +
    diff --git a/templates/main.html b/templates/main.html new file mode 100644 index 00000000..100971c9 --- /dev/null +++ b/templates/main.html @@ -0,0 +1,35 @@ +
    + +
    +
    +

    Chat box

    +
    +
    + +
    +
    + + + +
    +
    + +
    \ No newline at end of file diff --git a/templates/settings.html b/templates/settings.html new file mode 100644 index 00000000..e29088b0 --- /dev/null +++ b/templates/settings.html @@ -0,0 +1,40 @@ +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +