From 057f3dd92d27affd97630bd3c7df1db229d27d58 Mon Sep 17 00:00:00 2001 From: ebolam Date: Sun, 26 Jun 2022 21:06:06 -0400 Subject: [PATCH] back, redo, retry functional --- aiserver.py | 46 ++++++-- koboldai_settings.py | 24 ++--- requirements.txt | 3 +- static/koboldai.css | 28 ++++- static/koboldai.js | 226 ++++++++++++++++++++++++++------------- templates/index_new.html | 12 ++- 6 files changed, 232 insertions(+), 107 deletions(-) diff --git a/aiserver.py b/aiserver.py index 81a3eb3b..da4a7c73 100644 --- a/aiserver.py +++ b/aiserver.py @@ -3407,6 +3407,9 @@ def actionsubmit(data, actionmode=0, force_submit=False, force_prompt_gen=False, for i in range(model_settings.numseqs): genout.append({"generated_text": system_settings.lua_koboldbridge.outputs[i+1]}) assert type(genout[-1]["generated_text"]) is str + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] if(len(genout) == 1): genresult(genout[0]["generated_text"], flash=False) refresh_story() @@ -3466,6 +3469,9 @@ def actionsubmit(data, actionmode=0, force_submit=False, force_prompt_gen=False, for i in range(model_settings.numseqs): genout.append({"generated_text": system_settings.lua_koboldbridge.outputs[i+1]}) assert type(genout[-1]["generated_text"]) is str + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] if(len(genout) == 1): genresult(genout[0]["generated_text"]) if(not system_settings.abort and system_settings.lua_koboldbridge.restart_sequence is not None): @@ -3893,6 +3899,9 @@ def generate(txt, minimum, maximum, found_entries=None): else: genout = [{"generated_text": utils.decodenewlines(tokenizer.decode(tokens[-already_generated:]))} for tokens in genout] + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] if(len(genout) == 1): genresult(genout[0]["generated_text"]) else: @@ -3947,11 +3956,7 @@ def genselect(genout): print("{0}[Result {1}]\n{2}{3}".format(colors.CYAN, i, result["generated_text"], colors.END)) i += 1 - story_settings.actions.clear_unused_options() - story_settings.actions.append_options([x["generated_text"] for x in genout]) - genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options_no_edits()] - # Store sequences in memory until selection is made story_settings.genseqs = genout @@ -4046,7 +4051,11 @@ def sendtocolab(txt, min, max): genout.append(system_settings.lua_koboldbridge.outputs[i+1]) assert type(genout[-1]) is str + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] if(len(genout) == 1): + genresult(genout[0]) else: # Convert torch output format to transformers @@ -4195,13 +4204,16 @@ def tpumtjgenerate(txt, minimum, maximum, found_entries=None): else: genout = [{"generated_text": utils.decodenewlines(tokenizer.decode(txt))} for txt in genout] - if(len(genout) == 1): - genresult(genout[0]["generated_text"]) + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] + if(len(story_settings.actions.get_current_options()) == 1): + genresult(story_settings.actions.get_current_options()[0]) else: if(system_settings.lua_koboldbridge.restart_sequence is not None and system_settings.lua_koboldbridge.restart_sequence > 0): genresult(genout[system_settings.lua_koboldbridge.restart_sequence-1]["generated_text"]) else: - genselect(genout) + genselect([{"generated_text": x} for x in story_settings.actions.get_current_options()]) set_aibusy(0) @@ -4943,7 +4955,9 @@ def oairequest(txt, min, max): {"generated_text": utils.decodenewlines(txt)} for txt in outputs] - + story_settings.actions.clear_unused_options() + story_settings.actions.append_options([x["generated_text"] for x in genout]) + genout = [{"generated_text": x['text']} for x in story_settings.actions.get_current_options()] if (len(genout) == 1): genresult(genout[0]["generated_text"]) else: @@ -5794,7 +5808,7 @@ def new_ui_index(): @socketio.on('Set Selected Text') def UI_2_Set_Selected_Text(data): print("Updating Selected Text: {}".format(data)) - story_settings.actions.use_option(int(data['chunk']), int(data['option'])) + story_settings.actions.use_option(int(data['option']), action_step=int(data['chunk'])) #==================================================================# # Event triggered when user clicks the submit button @@ -5820,6 +5834,7 @@ def UI_2_Pinning(data): #==================================================================# @socketio.on('back') def UI_2_back(data): + print("back") ignore = story_settings.actions.pop() #==================================================================# @@ -5827,8 +5842,19 @@ def UI_2_back(data): #==================================================================# @socketio.on('redo') def UI_2_redo(data): - pass + if len(story_settings.actions.get_current_options()) == 1: + story_settings.actions.use_option(0) +#==================================================================# +# Event triggered when user clicks the redo button +#==================================================================# +@socketio.on('retry') +def UI_2_retry(data): + story_settings.actions.clear_unused_options() + system_settings.lua_koboldbridge.feedback = None + story_settings.recentrng = story_settings.recentrngm = None + actionsubmit("", actionmode=story_settings.actionmode) + #==================================================================# # Event triggered to rely a message #==================================================================# diff --git a/koboldai_settings.py b/koboldai_settings.py index ee783061..34f89152 100644 --- a/koboldai_settings.py +++ b/koboldai_settings.py @@ -22,9 +22,8 @@ def process_variable_changes(classname, name, value, old_value, debug_message=No if value != old_value: #Special Case for KoboldStoryRegister if isinstance(value, KoboldStoryRegister): - print("We got a story register") - print(value) socketio.emit("reset_story", {}, broadcast=True, room="UI_2") + socketio.emit("var_changed", {"classname": "actions", "name": "Action Count", "old_value": None, "value":value.action_count}, broadcast=True, room="UI_2") for i in range(len(value.actions)): socketio.emit("var_changed", {"classname": "actions", "name": "Selected Text", "old_value": None, "value": {"id": i, "text": value[i]}}, include_self=True, broadcast=True, room="UI_2") socketio.emit("var_changed", {"classname": "actions", "name": "Options", "old_value": None, "value": {"id": i, "options": value.actions[i]['Options']}}, include_self=True, broadcast=True, room="UI_2") @@ -34,24 +33,19 @@ def process_variable_changes(classname, name, value, old_value, debug_message=No if threading.get_ident() in rely_clients: sio = rely_clients[threading.get_ident()] else: - start_time = time.time() - print("getting client") sio = socketio_client.Client() @sio.event def connect(): - print("I'm connected!") + pass sio.connect('http://localhost:5000/?rely=true') rely_clients[threading.get_ident()] = sio - print("got client, took {}".format(time.time()-start_time)) #release no longer used clients for thread in rely_clients: if thread not in [x.ident for x in threading.enumerate()]: del rely_clients[thread] - sio.emit("relay", {"emit": "var_changed", "data": {"classname": classname, "name": name, "old_value": clean_var_for_emit(old_value), "value": clean_var_for_emit(value)}, "include_self":True, "broadcast":True, "room":"UI_2"}) + sio.emit("relay", ["var_changed", {"classname": classname, "name": name, "old_value": clean_var_for_emit(old_value), "value": clean_var_for_emit(value)}, {"include_self":True, "broadcast":True, "room":"UI_2"}]) else: socketio.emit("var_changed", {"classname": classname, "name": name, "old_value": clean_var_for_emit(old_value), "value": clean_var_for_emit(value)}, include_self=True, broadcast=True, room="UI_2") - #eventlet.sleep() - #socketio.sleep(0) class settings(object): @@ -350,17 +344,15 @@ class KoboldStoryRegister(object): process_variable_changes("actions", "Selected Text", {"id": self.action_count, "text": text}, None) def append_options(self, option_list): - print("appending options for {}".format(self.action_count+1)) if self.action_count+1 in self.actions: old_options = self.actions[self.action_count+1]["Options"].copy() self.actions[self.action_count+1]['Options'].extend([{"text": x, "Pinned": False, "Previous Selection": False, "Edited": False} for x in option_list]) else: old_options = None self.actions[self.action_count+1] = {"Selected Text": "", "Options": [{"text": x, "Pinned": False, "Previous Selection": False, "Edited": False} for x in option_list]} - process_variable_changes("actions", "Options", {"id": self.action_count+1, "options": self.actions[self.action_count+1]["Options"]}, {"id": self.action_count+1, "options": old_options}, debug_message="wtf") + process_variable_changes("actions", "Options", {"id": self.action_count+1, "options": self.actions[self.action_count+1]["Options"]}, {"id": self.action_count+1, "options": old_options}) def clear_unused_options(self, pointer=None): - print("clearing options for {}".format(self.action_count+1)) new_options = [] old_options = None if pointer is None: @@ -393,13 +385,19 @@ class KoboldStoryRegister(object): self.actions[action_step]['Options'][option_number]['Pinned'] = False process_variable_changes("actions", "Options", {"id": action_step, "options": self.actions[action_step]["Options"]}, {"id": action_step, "options": old_options}) - def use_option(self, action_step, option_number): + def use_option(self, option_number, action_step=None): + if action_step is None: + action_step = self.action_count+1 if action_step in self.actions: old_options = self.actions[action_step]["Options"].copy() old_text = self.actions[action_step]["Selected Text"] if option_number < len(self.actions[action_step]['Options']): self.actions[action_step]["Selected Text"] = self.actions[action_step]['Options'][option_number]['text'] del self.actions[action_step]['Options'][option_number] + #If this is the current spot in the story, advance + if action_step-1 == self.action_count: + self.action_count+=1 + socketio.emit("var_changed", {"classname": "actions", "name": "Action Count", "old_value": None, "value":self.action_count}, broadcast=True, room="UI_2") process_variable_changes("actions", "Options", {"id": action_step, "options": self.actions[action_step]["Options"]}, {"id": action_step, "options": old_options}) process_variable_changes("actions", "Selected Text", {"id": action_step, "text": self.actions[action_step]["Selected Text"]}, {"id": action_step, "Selected Text": old_text}) diff --git a/requirements.txt b/requirements.txt index 13fdd7cd..1a523e36 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,4 +11,5 @@ markdown bleach==4.1.0 sentencepiece protobuf -accelerate \ No newline at end of file +accelerate +python-socketio[client] \ No newline at end of file diff --git a/static/koboldai.css b/static/koboldai.css index 96bae325..3c8afbaf 100644 --- a/static/koboldai.css +++ b/static/koboldai.css @@ -427,14 +427,19 @@ td.sequence:hover { .inputrow { grid-area: inputrow; display: grid; - grid-template-areas: "textarea submit submit submit" + grid-template-areas: "textarea statusbar statusbar statusbar" + "textarea submit submit submit" "textarea back redo retry"; grid-template-columns: auto 30px 30px 30px; - grid-template-rows: auto 40px; + grid-template-rows: 0px auto 40px; gap: 1px; } +.inputrow.status_bar { + grid-template-rows: 20px auto 40px; +} + .inputrow textarea { grid-area: textarea; background-color: var(--textarea_background); @@ -474,6 +479,25 @@ td.sequence:hover { display: inline; } +.statusbar_outer { + color: #000; + background-color: #f1f1f1; + grid-area: statusbar; + height: 20px; +} + +.statusbar_outer.hidden { + height: 0px; +} + +.statusbar_inner { + background-color: #4CAF50; + text-align: center; + font-size: 0.875em; + + +} + .inputrow .back { grid-area: back; padding: 0px; diff --git a/static/koboldai.js b/static/koboldai.js index 56b5d98e..5dfdbb91 100644 --- a/static/koboldai.js +++ b/static/koboldai.js @@ -46,86 +46,129 @@ function fix_text(val) { } function create_options(data) { + //Set all options before the next chunk to hidden + var option_container = document.getElementById("Select Options"); + var current_chunk = parseInt(document.getElementById("action_count").textContent)+1; + var children = option_container.children; + for (var i = 0; i < children.length; i++) { + var chunk = children[i]; + if (chunk.id == "Select Options Chunk " + current_chunk) { + chunk.classList.remove("hidden"); + console.log(current_chunk); + } else { + chunk.classList.add("hidden"); + } + } + + console.log(current_chunk); console.log(data); if (document.getElementById("Select Options Chunk "+data.value.id)) { - var option_chunk = document.getElementById("Select Options Chunk "+data.value.id) - } else { - var option_area = document.getElementById("Select Options"); - var option_chunk = document.createElement("div"); - option_chunk.id = "Select Options Chunk "+data.value.id; - option_area.append(option_chunk); + var option_chunk = document.getElementById("Select Options Chunk "+data.value.id) + } else { + var option_area = document.getElementById("Select Options"); + var option_chunk = document.createElement("div"); + option_chunk.id = "Select Options Chunk "+data.value.id; + option_area.append(option_chunk); + } + //first, let's clear out our existing data + while (option_chunk.firstChild) { + option_chunk.removeChild(option_chunk.firstChild); + } + var table = document.createElement("table"); + table.classList.add("sequence"); + table.style = "border-spacing: 0;"; + //Add pins + i=0; + for (item of data.value.options) { + if (item.Pinned) { + var row = document.createElement("tr"); + row.classList.add("sequence"); + var textcell = document.createElement("td"); + textcell.textContent = item.text; + textcell.classList.add("sequence"); + textcell.setAttribute("option_id", i); + textcell.setAttribute("option_chunk", data.value.id); + var iconcell = document.createElement("td"); + iconcell.setAttribute("option_id", i); + iconcell.setAttribute("option_chunk", data.value.id); + var icon = document.createElement("span"); + icon.id = "Pin_"+i; + icon.classList.add("oi"); + icon.setAttribute('data-glyph', "pin"); + iconcell.append(icon); + textcell.onclick = function () { + socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")}); + }; + iconcell.onclick = function () { + socket.emit("Pinning", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id"), "set": false}); + }; + row.append(textcell); + row.append(iconcell); + table.append(row); } - //first, let's clear out our existing data - while (option_chunk.firstChild) { - option_chunk.removeChild(option_chunk.firstChild); + i+=1; + } + //Add Redo options + i=0; + for (item of data.value.options) { + if ((item['Previous Selection'])) { + var row = document.createElement("tr"); + row.classList.add("sequence"); + var textcell = document.createElement("td"); + textcell.textContent = item.text; + textcell.classList.add("sequence"); + textcell.setAttribute("option_id", i); + textcell.setAttribute("option_chunk", data.value.id); + var iconcell = document.createElement("td"); + iconcell.setAttribute("option_id", i); + iconcell.setAttribute("option_chunk", data.value.id); + var icon = document.createElement("span"); + icon.id = "Pin_"+i; + icon.classList.add("oi"); + icon.setAttribute('data-glyph', "loop-circular"); + iconcell.append(icon); + textcell.onclick = function () { + socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")}); + }; + row.append(textcell); + row.append(iconcell); + table.append(row); } - var table = document.createElement("table"); - table.classList.add("sequence"); - table.style = "border-spacing: 0;"; - //Add pins - i=0; - for (item of data.value.options) { - if (item.Pinned) { - var row = document.createElement("tr"); - row.classList.add("sequence"); - var textcell = document.createElement("td"); - textcell.textContent = item.text; - textcell.classList.add("sequence"); - textcell.setAttribute("option_id", i); - textcell.setAttribute("option_chunk", data.value.id); - var iconcell = document.createElement("td"); - iconcell.setAttribute("option_id", i); - iconcell.setAttribute("option_chunk", data.value.id); - var icon = document.createElement("span"); - icon.id = "Pin_"+i; - icon.classList.add("oi"); - icon.setAttribute('data-glyph', "pin"); - iconcell.append(icon); - textcell.onclick = function () { - socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")}); - }; - iconcell.onclick = function () { - socket.emit("Pinning", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id"), "set": false}); - }; - row.append(textcell); - row.append(iconcell); - table.append(row); - } - i+=1; + i+=1; + } + //Add general options + i=0; + for (item of data.value.options) { + if (!(item.Edited) && !(item.Pinned) && !(item['Previous Selection'])) { + var row = document.createElement("tr"); + row.classList.add("sequence"); + var textcell = document.createElement("td"); + textcell.textContent = item.text; + textcell.classList.add("sequence"); + textcell.setAttribute("option_id", i); + textcell.setAttribute("option_chunk", data.value.id); + var iconcell = document.createElement("td"); + iconcell.setAttribute("option_id", i); + iconcell.setAttribute("option_chunk", data.value.id); + var icon = document.createElement("span"); + icon.id = "Pin_"+i; + icon.classList.add("oi"); + icon.setAttribute('data-glyph', "pin"); + icon.setAttribute('style', "filter: brightness(50%);"); + iconcell.append(icon); + iconcell.onclick = function () { + socket.emit("Pinning", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id"), "set": true}); + }; + textcell.onclick = function () { + socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")}); + }; + row.append(textcell); + row.append(iconcell); + table.append(row); } - //Add general options - i=0; - for (item of data.value.options) { - if (!(item.Edited) && !(item.Pinned) && !(item['Previous Selection'])) { - var row = document.createElement("tr"); - row.classList.add("sequence"); - var textcell = document.createElement("td"); - textcell.textContent = item.text; - textcell.classList.add("sequence"); - textcell.setAttribute("option_id", i); - textcell.setAttribute("option_chunk", data.value.id); - var iconcell = document.createElement("td"); - iconcell.setAttribute("option_id", i); - iconcell.setAttribute("option_chunk", data.value.id); - var icon = document.createElement("span"); - icon.id = "Pin_"+i; - icon.classList.add("oi"); - icon.setAttribute('data-glyph', "pin"); - icon.setAttribute('style', "filter: brightness(50%);"); - iconcell.append(icon); - iconcell.onclick = function () { - socket.emit("Pinning", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id"), "set": true}); - }; - textcell.onclick = function () { - socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")}); - }; - row.append(textcell); - row.append(iconcell); - table.append(row); - } - i+=1; - } - option_chunk.append(table); + i+=1; + } + option_chunk.append(table); } function do_story_text_updates(data) { @@ -187,6 +230,27 @@ function selected_preset(data) { } } +function update_status_bar(data) { + var total_tokens = document.getElementById('model_genamt').value; + var percent_complete = data.value/total_tokens*100; + var percent_bar = document.getElementsByClassName("statusbar_inner"); + for (item of percent_bar) { + item.setAttribute("style", "width:"+percent_complete+"%"); + item.textContent = Math.round(percent_complete)+"%" + if ((percent_complete == 0) || (percent_complete == 100)) { + item.parentElement.classList.add("hidden"); + document.getElementById("inputrow_container").classList.remove("status_bar"); + } else { + item.parentElement.classList.remove("hidden"); + document.getElementById("inputrow_container").classList.add("status_bar"); + } + } + if ((percent_complete == 0) || (percent_complete == 100)) { + document.title = "KoboldAI Client"; + } else { + document.title = "KoboldAI Client Generating (" + percent_complete + "%)"; + } +} function var_changed(data) { //Special Case for Story Text if ((data.classname == "actions") && (data.name == "Selected Text")) { @@ -201,7 +265,7 @@ function var_changed(data) { selected_preset(data); //Basic Data Syncing } else { - var elements_to_change = document.getElementsByClassName("var_sync_"+data.classname+"_"+data.name); + var elements_to_change = document.getElementsByClassName("var_sync_"+data.classname.replace(" ", "_")+"_"+data.name.replace(" ", "_")); for (item of elements_to_change) { if ((item.tagName.toLowerCase() === 'input') || (item.tagName.toLowerCase() === 'select')) { item.value = fix_text(data.value); @@ -209,11 +273,19 @@ function var_changed(data) { item.textContent = fix_text(data.value); } } - var elements_to_change = document.getElementsByClassName("var_sync_alt_"+data.classname+"_"+data.name); + //alternative syncing method + var elements_to_change = document.getElementsByClassName("var_sync_alt_"+data.classname.replace(" ", "_")+"_"+data.name.replace(" ", "_")); for (item of elements_to_change) { item.setAttribute("server_value", fix_text(data.value)); } } + + //if we're updating generated tokens, let's show that in our status bar + if ((data.classname == 'story') && (data.name == 'generated_tkns')) { + update_status_bar(data); + } + + //If we have ai_busy, start the favicon swapping if ((data.classname == 'system') && (data.name == 'aibusy')) { if (data.value) { favicon.start_swap() diff --git a/templates/index_new.html b/templates/index_new.html index 3946af2f..1b11b16d 100644 --- a/templates/index_new.html +++ b/templates/index_new.html @@ -39,15 +39,19 @@ +
-
+
+
+
25%
+

- - - + + +