Soft Prompts working

Update to make file browser more generic
This commit is contained in:
ebolam
2022-08-13 21:49:25 -04:00
parent 73ee6af993
commit 2527d8db09
7 changed files with 273 additions and 102 deletions

View File

@@ -841,6 +841,7 @@ def spRequest(filename):
raise RuntimeError(f"{repr(filename)} is not a valid soft prompt file")
with z.open('meta.json') as f:
koboldai_vars.spmeta = json.load(f)
koboldai_vars.spname = koboldai_vars.spmeta['name']
z.close()
with np.load(fileops.sppath(filename), allow_pickle=False) as f:
@@ -1156,7 +1157,7 @@ def get_oai_models(data):
file.write(json.dumps(js, indent=3), room="UI_1")
emit('from_server', {'cmd': 'oai_engines', 'data': engines, 'online_model': online_model}, broadcast=True, room="UI_1")
emit('oai_engines', {'data': engines, 'online_model': online_model}, room="UI_2")
emit('oai_engines', {'data': engines, 'online_model': online_model}, broadcast=False, room="UI_2")
else:
# Something went wrong, print the message and quit since we can't initialize an engine
print("{0}ERROR!{1}".format(colors.RED, colors.END), room="UI_1")
@@ -2941,7 +2942,7 @@ def lua_set_spfilename(filename: Union[str, None]):
filename = str(filename).strip()
changed = lua_get_spfilename() != filename
assert all(q not in filename for q in ("/", "\\"))
spRequest(filename)
spRequest("softprompts/"+filename)
return changed
#==================================================================#
@@ -3435,7 +3436,7 @@ def get_message(msg):
elif(msg['cmd'] == 'loadrequest'):
loadRequest(fileops.storypath(koboldai_vars.loadselect))
elif(msg['cmd'] == 'sprequest'):
spRequest(koboldai_vars.spselect)
spRequest("softprompts/"+koboldai_vars.spselect)
elif(msg['cmd'] == 'deletestory'):
deletesave(msg['data'])
elif(msg['cmd'] == 'renamestory'):
@@ -5965,7 +5966,7 @@ def final_startup():
file = open("settings/" + getmodelname().replace('/', '_') + ".settings", "r")
js = json.load(file)
if(koboldai_vars.allowsp and "softprompt" in js and type(js["softprompt"]) is str and all(q not in js["softprompt"] for q in ("..", ":")) and (len(js["softprompt"]) == 0 or all(js["softprompt"][0] not in q for q in ("/", "\\")))):
spRequest(js["softprompt"])
spRequest("softprompts/"+js["softprompt"])
else:
koboldai_vars.spfilename = ""
file.close()
@@ -6062,14 +6063,14 @@ def upload_file(data):
print("Someone is trying to upload a file to your server. Blocked.")
elif session['popup_jailed_dir'] is None:
if os.path.exists(path):
emit("error_popup", "The file already exists. Please delete it or rename the file before uploading", room="UI_2");
emit("error_popup", "The file already exists. Please delete it or rename the file before uploading", broadcast=False, room="UI_2");
else:
with open(path, "wb") as f:
f.write(data['data'])
get_files_folders(session['current_folder'])
elif session['popup_jailed_dir'] in session['current_folder']:
if os.path.exists(path):
emit("error_popup", "The file already exists. Please delete it or rename the file before uploading", room="UI_2");
emit("error_popup", "The file already exists. Please delete it or rename the file before uploading", broadcast=False, room="UI_2");
else:
with open(path, "wb") as f:
f.write(data['data'])
@@ -6176,7 +6177,9 @@ def popup_change_file(data):
def file_popup(popup_title, starting_folder, return_event, upload=True, jailed=True, folder_only=True, renameable=False, deleteable=False,
editable=False, show_breadcrumbs=True, item_check=None, show_hidden=False,
valid_only=False, hide_extention=False):
valid_only=False, hide_extention=False, extra_parameter_function=None,
column_names=['File Name'], show_filename=True,
column_widths=["100%"]):
#starting_folder = The folder we're going to get folders and/or items from
#return_event = the socketio event that will be emitted when the load button is clicked
#jailed = if set to true will look for the session variable jailed_folder and prevent navigation outside of that folder
@@ -6197,11 +6200,15 @@ def file_popup(popup_title, starting_folder, return_event, upload=True, jailed=T
session['popup_editable'] = editable
session['popup_show_hidden'] = show_hidden
session['popup_item_check'] = item_check
session['extra_parameter_function'] = extra_parameter_function
session['column_names'] = column_names
session['popup_folder_only'] = folder_only
session['popup_show_breadcrumbs'] = show_breadcrumbs
session['upload'] = upload
session['valid_only'] = valid_only
session['hide_extention'] = hide_extention
session['show_filename'] = show_filename
session['column_widths'] = column_widths
socketio.emit("load_popup", {"popup_title": popup_title, "call_back": return_event, "renameable": renameable, "deleteable": deleteable, "editable": editable, 'upload': upload}, broadcast=False, room="UI_2")
socketio.emit("load_popup", {"popup_title": popup_title, "call_back": return_event, "renameable": renameable, "deleteable": deleteable, "editable": editable, 'upload': upload}, broadcast=True, room="UI_1")
@@ -6212,11 +6219,15 @@ def get_files_folders(starting_folder):
import stat
session['current_folder'] = os.path.abspath(starting_folder).replace("\\", "/")
item_check = session['popup_item_check']
extra_parameter_function = session['extra_parameter_function']
show_breadcrumbs = session['popup_show_breadcrumbs']
show_hidden = session['popup_show_hidden']
folder_only = session['popup_folder_only']
valid_only = session['valid_only']
column_names = session['column_names']
hide_extention = session['hide_extention']
show_filename = session['show_filename']
column_widths = session['column_widths']
if starting_folder == 'This PC':
breadcrumbs = [['This PC', 'This PC']]
@@ -6253,24 +6264,29 @@ def get_files_folders(starting_folder):
valid_selection = True
else:
valid_selection = item_check(item_full_path)
if extra_parameter_function is None:
extra_parameters = []
else:
extra_parameters = extra_parameter_function(item_full_path, item, valid_selection)
if (show_hidden and hidden) or not hidden:
if os.path.isdir(os.path.join(base_path, item)):
folders.append([True, item_full_path, item, valid_selection])
folders.append([True, item_full_path, item, valid_selection, extra_parameters])
else:
if hide_extention:
item = ".".join(item.split(".")[:-1])
if valid_only:
if valid_selection:
files.append([False, item_full_path, item, valid_selection])
files.append([False, item_full_path, item, valid_selection, extra_parameters])
else:
files.append([False, item_full_path, item, valid_selection])
files.append([False, item_full_path, item, valid_selection, extra_parameters])
items = folders
if not folder_only:
items += files
socketio.emit("popup_items", items, broadcast=False, include_self=True, room="UI_2")
#items is a list of [Folder True/False, full path, file/folder name, validity of item to load, [list of extra columns]]
socketio.emit("popup_items", {"items": items, "column_names": column_names, "show_filename": show_filename, "column_widths": column_widths}, broadcast=False, include_self=True, room="UI_2")
socketio.emit("popup_items", items, broadcast=True, include_self=True, room="UI_1")
if show_breadcrumbs:
socketio.emit("popup_breadcrumbs", breadcrumbs, broadcast=False, room="UI_2")
@@ -6484,7 +6500,21 @@ def UI_2_load_model(data):
def UI_2_load_story_list(data):
file_popup("Select Story to Load", "./stories", "load_story", upload=True, jailed=True, folder_only=False, renameable=True,
deleteable=True, show_breadcrumbs=True, item_check=valid_story,
valid_only=True, hide_extention=True)
valid_only=True, hide_extention=True, extra_parameter_function=get_story_length,
column_names=['Story Name', 'Action Count'],
column_widths=['auto', '100px'])
def get_story_length(item_full_path, item, valid_selection):
if not valid_selection:
return [""]
with open(item_full_path, "r") as f:
js = json.load(f)
if 'file_version' not in js:
return [len(js['actions'])]
if js['file_version'] == 1:
return [len(js['actions'])]
return [0 if js['actions']['action_count'] == -1 else js['actions']['action_count'] ]
def valid_story(file):
if file.endswith(".json"):
@@ -6602,6 +6632,48 @@ def my_except_hook(exctype, value, traceback):
sys.excepthook = my_except_hook
#==================================================================#
# Event triggered when Softprompt is clicked
#==================================================================#
@socketio.on('load_softprompt_list')
def UI_2_load_softprompt_list(data):
if not koboldai_vars.allowsp:
socketio.emit("error", "Soft prompts are not supported by your current model/backend", broadcast=True, room="UI_2")
assert koboldai_vars.allowsp, "Soft prompts are not supported by your current model/backend"
file_popup("Select Softprompt to Load", "./softprompts", "load_softprompt", upload=True, jailed=True, folder_only=False, renameable=True,
deleteable=True, show_breadcrumbs=True, item_check=valid_softprompt,
valid_only=True, hide_extention=True, extra_parameter_function=get_softprompt_desc,
column_names=['Softprompt Name', 'Softprompt Description'],
show_filename=False,
column_widths=['150px', 'auto'])
def valid_softprompt(file):
z, version, shape, fortran_order, dtype = fileops.checksp(file, koboldai_vars.modeldim)
if z in [1, 2, 3, 4]:
return False
elif not isinstance(z, zipfile.ZipFile):
print("not zip")
return False
else:
return True
def get_softprompt_desc(item_full_path, item, valid_selection):
if not valid_selection:
return [None, None]
z = zipfile.ZipFile(item_full_path)
with z.open('meta.json') as f:
ob = json.load(f)
return [ob['name'], ob['description']]
#==================================================================#
# Event triggered when Softprompt is clicked
#==================================================================#
@socketio.on('load_softprompt')
def UI_2_load_softprompt(data):
print("Load softprompt: {}".format(data))
spRequest(data)
#==================================================================#
# Test
#==================================================================#

View File

@@ -119,7 +119,7 @@ def checksp(filename: str, model_dimension: int) -> Tuple[Union[zipfile.ZipFile,
if 'np' not in globals():
import numpy as np
try:
z = zipfile.ZipFile("softprompts/"+filename)
z = zipfile.ZipFile(filename)
with z.open('tensor.npy') as f:
# Read only the header of the npy file, for efficiency reasons
version: Tuple[int, int] = np.lib.format.read_magic(f)

View File

@@ -17,6 +17,15 @@ def clean_var_for_emit(value):
else:
return value
def create_loopback_socketio():
sio = socketio_client.Client()
@sio.event
def connect():
pass
sio.connect('ws://localhost:{}/?rely=true'.format(port))
rely_clients[threading.get_ident()] = sio
return sio
def process_variable_changes(socketio, classname, name, value, old_value, debug_message=None):
if serverstarted and name != "serverstarted":
if debug_message is not None:
@@ -37,13 +46,10 @@ def process_variable_changes(socketio, classname, name, value, old_value, debug_
if not has_request_context():
if threading.get_ident() in rely_clients:
sio = rely_clients[threading.get_ident()]
if not sio.connected:
sio = create_loopback_socketio()
else:
sio = socketio_client.Client()
@sio.event
def connect():
pass
sio.connect('ws://localhost:{}/?rely=true'.format(port))
rely_clients[threading.get_ident()] = sio
sio = create_loopback_socketio()
#release no longer used clients
for thread in rely_clients:
if thread not in [x.ident for x in threading.enumerate()]:
@@ -496,6 +502,7 @@ class system_settings(settings):
self.usegpu = False # Whether to launch pipeline with GPU support
self.spselect = "" # Temporary storage for soft prompt filename to load
self.spmeta = None # Metadata of current soft prompt, or None if not using a soft prompt
self.spname = "Not in Use" # Name of the soft prompt
self.sp = None # Current soft prompt tensor (as a NumPy array)
self.sp_length = 0 # Length of current soft prompt in tokens, or 0 if not using a soft prompt
self.has_genmod = False # Whether or not at least one loaded Lua userscript has a generation modifier

View File

@@ -176,7 +176,7 @@
grid-template-areas: "label"
"item";
grid-template-rows: 20px 120px;
grid-template-columns: var(--flyout_menu_width);
grid-template-columns: 200px;
row-gap: 0.2em;
background-color: var(--setting_background);
color: var(--text);
@@ -933,7 +933,7 @@ body {
top: 10vh;
left: 10%;
z-index: 999;
width: 80%;
width: 80vw;
height: 80vh;
background-color: black;
display: flex;
@@ -955,43 +955,50 @@ body {
flex-basis: auto;
}
.popup .item {
.popup .model_item {
width: 100%;
background-color: var(--popup_item_color);
padding: 2px;
display: grid;
grid-template-areas: "folder_icon delete_icon edit_icon rename_icon file";
grid-template-columns: 20px 20px 20px 20px auto;
grid-template-areas: "folder_icon delete_icon edit_icon rename_icon file gpu_size";
grid-template-columns: 30px 0px 0px 0px auto 50px;
}
.popup .item .folder_icon {
.popup .model_item .folder_icon {
grid-area: folder_icon;
}
.popup .item .edit_icon {
.popup .model_item .edit_icon {
grid-area: edit_icon;
}
.popup .item .rename_icon {
.popup .model_item .rename_icon {
grid-area: rename_icon;
}
.popup .item .delete_icon {
.popup .model_item .delete_icon {
grid-area: delete_icon;
}
.popup .item .file {
grid-area: file;
display: grid;
.popup .model_item .model {
cursor: pointer;
grid-area: file;
}
.popup .item .file:hover {
.popup .model_item .model:hover {
background-color: #688f1f;
}
.popup .item .file.selected {
.popup .model_item .model.selected {
background: #688f1f;
}
.popup .item:hover {
background-color: #688f1f;
}
.popup .item.selected {
background: #688f1f;
}
@@ -1024,7 +1031,7 @@ body {
}
/*----------------------------- Model Load Popup ------------------------------------------*/
.popup .item .model {
.popup_list_area .model_item .model {
grid-area: file;
display: grid;
grid-template-areas: "item gpu_size";
@@ -1032,11 +1039,11 @@ body {
cursor: pointer;
}
.popup .item .model:hover {
.popup_list_area .model_item .model:hover {
background-color: #688f1f;
}
.popup .item .model.selected {
.popup_list_area .model_item .model.selected {
background-color: #688f1f;
}

View File

@@ -375,6 +375,7 @@ function do_ai_busy(data) {
}
function var_changed(data) {
//console.log({"name": data.name, "data": data});
//Special Case for Story Text
if ((data.classname == "actions") && (data.name == "Selected Text")) {
do_story_text_updates(data);
@@ -526,6 +527,7 @@ function load_popup(data) {
}
function popup_items(data) {
console.log(data);
var popup_list = document.getElementById('popup_list');
//first, let's clear out our existing data
while (popup_list.firstChild) {
@@ -533,9 +535,45 @@ function popup_items(data) {
}
document.getElementById('popup_upload_input').value = "";
for (item of data) {
var list_item = document.createElement("span");
list_item.classList.add("item");
//create the column widths
var style = 'width: 80vw; display: grid; grid-template-areas: "icons';
for (i=0; i < data.column_widths.length; i++) {
style = style + " p"+i;
}
style = style + '"; grid-template-columns: 30px';
for (column_width of data.column_widths) {
style = style + " "+column_width;
}
style = style + ';';
//create titles
var tr = document.createElement("div");
tr.style = style;
//icon area
var td = document.createElement("span");
td.style = "grid-area: icons;";
tr.append(td)
//add dynamic columns
var i = 0;
for (column of data.column_names) {
td = document.createElement("span");
td.textContent = column;
td.style = "grid-area: p"+i+";";
i+=1;
tr.append(td)
}
popup_list.append(tr);
//create lines
for (item of data.items) {
var tr = document.createElement("div");
tr.classList.add("item");
tr.setAttribute("folder", item[0]);
tr.setAttribute("valid", item[3]);
tr.style = style;
var icon_area = document.createElement("span");
icon_area.style = "grid-area: icons;";
//create the folder icon
var folder_icon = document.createElement("span");
@@ -544,7 +582,7 @@ function popup_items(data) {
folder_icon.classList.add("oi");
folder_icon.setAttribute('data-glyph', "folder");
}
list_item.append(folder_icon);
icon_area.append(folder_icon);
//create the edit icon
var edit_icon = document.createElement("span");
@@ -558,7 +596,7 @@ function popup_items(data) {
socket.emit("popup_edit", this.id);
};
}
list_item.append(edit_icon);
icon_area.append(edit_icon);
//create the rename icon
var rename_icon = document.createElement("span");
@@ -576,7 +614,7 @@ function popup_items(data) {
}
};
}
list_item.append(rename_icon);
icon_area.append(rename_icon);
//create the delete icon
var delete_icon = document.createElement("span");
@@ -599,40 +637,76 @@ function popup_items(data) {
}
};
}
list_item.append(delete_icon);
icon_area.append(delete_icon);
tr.append(icon_area);
//create the actual item
var popup_item = document.createElement("span");
popup_item.classList.add("file");
popup_item.id = item[1];
popup_item.setAttribute("folder", item[0]);
popup_item.setAttribute("valid", item[3]);
popup_item.textContent = item[2];
popup_item.onclick = function () {
var accept = document.getElementById("popup_accept");
if (this.getAttribute("valid") == "true") {
accept.classList.remove("disabled");
accept.setAttribute("selected_value", this.id);
} else {
accept.setAttribute("selected_value", "");
accept.classList.add("disabled");
if (this.getAttribute("folder") == "true") {
socket.emit("popup_change_folder", this.id);
i=0;
if (data.show_filename) {
var popup_item = document.createElement("span");
popup_item.style = "grid-area: p"+i+";";
i+=1;
popup_item.id = item[1];
popup_item.setAttribute("folder", item[0]);
popup_item.setAttribute("valid", item[3]);
popup_item.textContent = item[2];
popup_item.onclick = function () {
var accept = document.getElementById("popup_accept");
if (this.getAttribute("valid") == "true") {
accept.classList.remove("disabled");
accept.setAttribute("selected_value", this.id);
} else {
accept.setAttribute("selected_value", "");
accept.classList.add("disabled");
if (this.getAttribute("folder") == "true") {
socket.emit("popup_change_folder", this.id);
}
}
}
var popup_list = document.getElementById('popup_list').getElementsByClassName("selected");
for (item of popup_list) {
item.classList.remove("selected");
}
this.classList.add("selected");
};
list_item.append(popup_item);
var popup_list = document.getElementById('popup_list').getElementsByClassName("selected");
for (item of popup_list) {
item.classList.remove("selected");
}
this.parentElement.classList.add("selected");
};
tr.append(popup_item);
}
for (extra_data of item[4]) {
td = document.createElement("span");
td.style = "grid-area: p"+i+";";
i+=1;
td.id = item[1];
td.setAttribute("folder", item[0]);
td.setAttribute("valid", item[3]);
td.textContent = extra_data;
td.onclick = function () {
var accept = document.getElementById("popup_accept");
if (this.getAttribute("valid") == "true") {
accept.classList.remove("disabled");
accept.setAttribute("selected_value", this.id);
} else {
accept.setAttribute("selected_value", "");
accept.classList.add("disabled");
if (this.getAttribute("folder") == "true") {
socket.emit("popup_change_folder", this.id);
}
}
var popup_list = document.getElementById('popup_list').getElementsByClassName("selected");
for (item of popup_list) {
item.classList.remove("selected");
}
this.classList.add("selected");
};
tr.append(td);
}
popup_list.append(list_item);
popup_list.append(tr);
}
}
function popup_breadcrumbs(data) {
@@ -749,38 +823,19 @@ function show_model_menu(data) {
//add items
for (item of data.data) {
var list_item = document.createElement("span");
list_item.classList.add("item");
list_item.classList.add("model_item");
//create the folder icon
var folder_icon = document.createElement("span");
folder_icon.classList.add("folder_icon");
if (item[3]) {
folder_icon.classList.add("oi");
folder_icon.setAttribute('data-glyph', "folder");
folder_icon.classList.add("material-icons-outlined");
folder_icon.classList.add("cursor");
if ((item[3]) || (item[0] == 'Load a model from its directory') || (item[0] == 'Load an old GPT-2 model (eg CloverEdition)')) {
folder_icon.textContent = "folder";
} else {
folder_icon.textContent = "psychology";
}
list_item.append(folder_icon);
//create the delete icon
//var delete_icon = document.createElement("span");
//delete_icon.classList.add("delete_icon");
//if (popup_deleteable) {
// delete_icon.classList.add("oi");
// delete_icon.setAttribute('data-glyph', "x");
// delete_icon.id = item[1];
// delete_icon.setAttribute("folder", item[0]);
// delete_icon.onclick = function () {
// if (this.getAttribute("folder") == "true") {
// if (window.confirm("Do you really want to delete this folder and ALL files under it?")) {
// socket.emit("popup_delete", this.id);
// }
// } else {
// if (window.confirm("Do you really want to delete this file?")) {
// socket.emit("popup_delete", this.id);
// }
// }
// };
//}
//list_item.append(delete_icon);
//create the actual item
var popup_item = document.createElement("span");
@@ -1919,7 +1974,7 @@ function update_token_lengths() {
}
//figure out prompt length
if ((document.getElementById("story_prompt").getAttribute("story_prompt_length") == null) || (document.getElementById("story_prompt").getAttribute("story_prompt_length") == "")) {
prompt_length = 999999999999;
prompt_length = 0;
} else {
prompt_length = parseInt(document.getElementById("story_prompt").getAttribute("story_prompt_length"));
}

View File

@@ -4,6 +4,7 @@
Popup Title
</div>
<div id="popup_breadcrumbs"></div>
<div id="popup_column_titles"></div>
<div class="popup_list_area" id="popup_list"></div>
<div class="popup_load_cancel hidden" id="popup_upload">
<input type=file id="popup_upload_file">

View File

@@ -148,6 +148,25 @@
{% with sub_path='Modifiers' %}
{% include 'settings item.html' %}
{% endwith %}
<div class="setting_container">
<!---Top Row---->
<span class="setting_label">
Soft Prompt:
<span class="helpicon">
?
<span class="helptext">
Soft Prompt Tooltip
</span>
</span>
</span>
<!---Bottom Row---->
<span class="setting_item">
<span class="material-icons-outlined cursor" onclick="socket.emit('load_softprompt_list', '');">folder_open</span> <span class="var_sync_system_spname"></span>
</span>
<!---Slider Labels--->
<span class="setting_minlabel"><span style="top: -4px; position: relative;"></span></span>
<span class="setting_maxlabel"><span style="top: -4px; position: relative;"></span></span>
</div>
</div>
{% endwith %}
<div onclick="toggle_setting_category(this);">
@@ -162,13 +181,16 @@
</div>
</div>
<div id="setting_menu_interface" class="hidden settings_category_area">
<div onclick="toggle_setting_category(this);">
<h4 style="width:var(--flyout_menu_width);"><span class="material-icons-outlined cursor">expand_more</span> UI</h4>
</div>
<div class="setting_tile_area">
{% with menu='Interface' %}
{% with sub_path='UI' %}
{% include 'settings item.html' %}
{% with menu='Interface' %}
{% with sub_path='UI' %}
{% include 'settings item.html' %}
{% endwith %}
{% endwith %}
{% endwith %}
<div class="setting_container">
<div class="setting_container">
<span class="setting_label">
Maximize Game Text Space:
<span class="helpicon">
@@ -203,8 +225,15 @@
<span class="setting_maxlabel"><span style="top: -4px; position: relative;"></span></span>
</div>
</div>
</div>
<div id="setting_menu_ui" class="hidden settings_category_area">
<div onclick="toggle_setting_category(this);">
<h4 style="width:var(--flyout_menu_width);"><span class="material-icons-outlined cursor">expand_more</span> Theme</h4>
</div>
<div class="setting_tile_area">
</div>
<div onclick="toggle_setting_category(this);">
<h4 style="width:var(--flyout_menu_width);"><span class="material-icons-outlined cursor">expand_more</span> Formatting</h4>
</div>
<div class="setting_tile_area">
</div>