From 1951ccd2ce62d7dec9c8974f15645b6a5018ef3f Mon Sep 17 00:00:00 2001
From: Gnome Ann <>
Date: Tue, 18 Jan 2022 16:30:09 -0500
Subject: [PATCH 1/2] Show author and SP length in soft prompt menu
---
aiserver.py | 3 ++-
fileops.py | 1 +
static/application.js | 15 +++++++++------
static/custom.css | 1 +
templates/index.html | 4 ++--
5 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/aiserver.py b/aiserver.py
index 11760cc4..540b25e6 100644
--- a/aiserver.py
+++ b/aiserver.py
@@ -4156,7 +4156,8 @@ def spRequest(filename):
tensor = np.float32(tensor)
assert not np.isinf(tensor).any() and not np.isnan(tensor).any()
- vars.sp_length = tensor.shape[0]
+ vars.sp_length = tensor.shape[-2]
+ vars.spmeta["n_tokens"] = vars.sp_length
if(vars.model in ("TPUMeshTransformerGPTJ",)):
rows = tensor.shape[0]
diff --git a/fileops.py b/fileops.py
index e5697553..50f1e94f 100644
--- a/fileops.py
+++ b/fileops.py
@@ -161,6 +161,7 @@ def getspfiles(model_dimension: int):
ob = {}
z.close()
ob["filename"] = file
+ ob["n_tokens"] = shape[-2]
lst.append(ob)
return lst
diff --git a/static/application.js b/static/application.js
index e8a3202f..8b6a2380 100644
--- a/static/application.js
+++ b/static/application.js
@@ -972,11 +972,14 @@ function buildSPList(ar) {
showSPPopup();
ar.push({filename: '', name: "[None]"})
for(var i = 0; i < ar.length; i++) {
- var supported = !ar[i].supported
+ var author = !ar[i].author
? ''
- : Object.prototype.toString.call(ar[i].supported) === "[object Array]"
- ? "[" + ar[i].supported.join(', ') + "]"
- : "[" + ar[i].supported.toString() + "]";
+ : ar[i].author.constructor === Array
+ ? ar[i].author.join(', ')
+ : ar[i].author;
+ var n_tokens = !ar[i].n_tokens || !Number.isSafeInteger(ar[i].n_tokens) || ar[i].n_tokens < 1
+ ? ''
+ : "(" + ar[i].n_tokens + " tokens)";
var filename = ar[i].filename.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/(?=\r|\n)\r?\n?/g, '
');
var name = ar[i].name || ar[i].filename;
name = name.length > 120 ? name.slice(0, 117) + '...' : name;
@@ -992,7 +995,7 @@ function buildSPList(ar) {
\
\
"+desc+"
\
-
"+supported+"
\
+
" + author + "
" + n_tokens + "
\
\
\
");
@@ -1108,7 +1111,7 @@ function updateSPStatItems(items) {
stat_sp.closest(".statusicon").removeClass("active");
stat_spactive.html("");
} else {
- stat_sp.html("Active soft prompt:");
+ stat_sp.html("Active soft prompt (" + items[key].n_tokens + " tokens):");
stat_sp.closest(".statusicon").addClass("active");
stat_spactive.html((items[key].name || key)+" <"+key+">");
}
diff --git a/static/custom.css b/static/custom.css
index ce9c23d4..da30c6ed 100644
--- a/static/custom.css
+++ b/static/custom.css
@@ -1312,6 +1312,7 @@ body.connected .popupfooter, .popupfooter.always-available {
.splistitemsub {
color: #ba9;
+ text-align: right;
}
.splistitem:hover {
diff --git a/templates/index.html b/templates/index.html
index f4d67f83..1f13ed8d 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -9,7 +9,7 @@
-
+
@@ -17,7 +17,7 @@
-
+
From 3018322963494677e9d3ce34e6ea90dc2cbdfb09 Mon Sep 17 00:00:00 2001
From: Gnome Ann <>
Date: Tue, 18 Jan 2022 17:20:45 -0500
Subject: [PATCH 2/2] Detect and show properly when story is unsaved
---
aiserver.py | 42 +++++++++++++++++++++++++++++++++++++++++-
static/application.js | 32 +++++++++++++++++++++++++++++++-
templates/index.html | 2 +-
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/aiserver.py b/aiserver.py
index 540b25e6..ec932163 100644
--- a/aiserver.py
+++ b/aiserver.py
@@ -105,6 +105,7 @@ class vars:
tfs = 1.0 # Default generator tfs (tail-free sampling)
numseqs = 1 # Number of sequences to ask the generator to create
gamestarted = False # Whether the game has started (disables UI elements)
+ gamesaved = True # Whether or not current game is saved
serverstarted = False # Whether or not the Flask server has started
prompt = "" # Prompt
memory = "" # Text submitted to memory field
@@ -1646,6 +1647,7 @@ def lua_is_custommodel():
#
#==================================================================#
def execute_inmod():
+ setgamesaved(False)
vars.lua_logname = ...
vars.lua_edited = set()
vars.lua_deleted = set()
@@ -1665,6 +1667,7 @@ def execute_genmod():
vars.lua_koboldbridge.execute_genmod()
def execute_outmod():
+ setgamesaved(False)
emit('from_server', {'cmd': 'hidemsg', 'data': ''}, broadcast=True)
try:
tpool.execute(vars.lua_koboldbridge.execute_outmod)
@@ -1732,7 +1735,7 @@ def do_connect():
print("{0}Client connected!{1}".format(colors.GREEN, colors.END))
emit('from_server', {'cmd': 'setchatname', 'data': vars.chatname})
emit('from_server', {'cmd': 'setanotetemplate', 'data': vars.authornotetemplate})
- emit('from_server', {'cmd': 'connected', 'smandelete': vars.smandelete, 'smanrename': vars.smanrename})
+ emit('from_server', {'cmd': 'connected', 'smandelete': vars.smandelete, 'smanrename': vars.smanrename, 'modelname': getmodelname()})
if(vars.remote):
emit('from_server', {'cmd': 'runs_remotely'})
if(vars.allowsp):
@@ -1772,6 +1775,8 @@ def do_connect():
elif(vars.mode == "wi"):
emit('from_server', {'cmd': 'wimode', 'data': 'true'})
+ emit('from_server', {'cmd': 'gamesaved', 'data': vars.gamesaved}, broadcast=True)
+
#==================================================================#
# Event triggered when browser SocketIO sends data to the server
#==================================================================#
@@ -1936,6 +1941,7 @@ def get_message(msg):
togglewimode()
elif(msg['cmd'] == 'wiinit'):
if(int(msg['data']) < len(vars.worldinfo)):
+ setgamesaved(False)
vars.worldinfo[msg['data']]["init"] = True
addwiitem(folder_uid=msg['folder'])
elif(msg['cmd'] == 'wifolderinit'):
@@ -1950,17 +1956,22 @@ def get_message(msg):
deletewifolder(msg['data'])
elif(msg['cmd'] == 'wiexpand'):
assert 0 <= int(msg['data']) < len(vars.worldinfo)
+ setgamesaved(False)
emit('from_server', {'cmd': 'wiexpand', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiexpandfolder'):
assert 0 <= int(msg['data']) < len(vars.worldinfo)
+ setgamesaved(False)
emit('from_server', {'cmd': 'wiexpandfolder', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wifoldercollapsecontent'):
+ setgamesaved(False)
vars.wifolders_d[msg['data']]['collapsed'] = True
emit('from_server', {'cmd': 'wifoldercollapsecontent', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wifolderexpandcontent'):
+ setgamesaved(False)
vars.wifolders_d[msg['data']]['collapsed'] = False
emit('from_server', {'cmd': 'wifolderexpandcontent', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiupdate'):
+ setgamesaved(False)
num = int(msg['num'])
fields = ("key", "keysecondary", "content", "comment")
for field in fields:
@@ -1968,6 +1979,7 @@ def get_message(msg):
vars.worldinfo[num][field] = msg['data'][field]
emit('from_server', {'cmd': 'wiupdate', 'num': msg['num'], 'data': {field: vars.worldinfo[num][field] for field in fields}}, broadcast=True)
elif(msg['cmd'] == 'wifolderupdate'):
+ setgamesaved(False)
uid = int(msg['uid'])
fields = ("name", "collapsed")
for field in fields:
@@ -1975,15 +1987,19 @@ def get_message(msg):
vars.wifolders_d[uid][field] = msg['data'][field]
emit('from_server', {'cmd': 'wifolderupdate', 'uid': msg['uid'], 'data': {field: vars.wifolders_d[uid][field] for field in fields}}, broadcast=True)
elif(msg['cmd'] == 'wiselon'):
+ setgamesaved(False)
vars.worldinfo[msg['data']]["selective"] = True
emit('from_server', {'cmd': 'wiselon', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiseloff'):
+ setgamesaved(False)
vars.worldinfo[msg['data']]["selective"] = False
emit('from_server', {'cmd': 'wiseloff', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiconstanton'):
+ setgamesaved(False)
vars.worldinfo[msg['data']]["constant"] = True
emit('from_server', {'cmd': 'wiconstanton', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'wiconstantoff'):
+ setgamesaved(False)
vars.worldinfo[msg['data']]["constant"] = False
emit('from_server', {'cmd': 'wiconstantoff', 'data': msg['data']}, broadcast=True)
elif(msg['cmd'] == 'sendwilist'):
@@ -2279,6 +2295,15 @@ def settingschanged():
print("{0}Saving settings!{1}".format(colors.GREEN, colors.END))
savesettings()
+#==================================================================#
+# Set value of gamesaved
+#==================================================================#
+def setgamesaved(gamesaved):
+ assert type(gamesaved) is bool
+ if(gamesaved != vars.gamesaved):
+ emit('from_server', {'cmd': 'gamesaved', 'data': gamesaved}, broadcast=True)
+ vars.gamesaved = gamesaved
+
#==================================================================#
# Take input text from SocketIO and decide what to do with it
#==================================================================#
@@ -3330,6 +3355,7 @@ def inlineedit(chunk, data):
if(chunk-1 in vars.actions):
vars.actions[chunk-1] = data
+ setgamesaved(False)
update_story_chunk(chunk)
emit('from_server', {'cmd': 'texteffect', 'data': chunk}, broadcast=True)
emit('from_server', {'cmd': 'editmode', 'data': 'false'}, broadcast=True)
@@ -3349,6 +3375,7 @@ def inlinedelete(chunk):
else:
if(chunk-1 in vars.actions):
del vars.actions[chunk-1]
+ setgamesaved(False)
remove_story_chunk(chunk)
emit('from_server', {'cmd': 'editmode', 'data': 'false'}, broadcast=True)
@@ -3418,6 +3445,7 @@ def addwifolder():
# the WI entry with UID dst
#==================================================================#
def movewiitem(dst, src):
+ setgamesaved(False)
if(vars.worldinfo_u[src]["folder"] is not None):
for i, e in enumerate(vars.wifolders_u[vars.worldinfo_u[src]["folder"]]):
if(e is vars.worldinfo_u[src]):
@@ -3439,6 +3467,7 @@ def movewiitem(dst, src):
# the WI folder with UID dst
#==================================================================#
def movewifolder(dst, src):
+ setgamesaved(False)
vars.wifolders_l.remove(src)
if(dst is None):
# If dst is None, that means we should move src to be the last folder
@@ -3662,6 +3691,8 @@ def memsubmit(data):
emit('from_server', {'cmd': 'setinputtext', 'data': data}, broadcast=True)
# Maybe check for length at some point
# For now just send it to storage
+ if(data != vars.memory):
+ setgamesaved(False)
vars.memory = data
vars.mode = "play"
emit('from_server', {'cmd': 'memmode', 'data': 'false'}, broadcast=True)
@@ -3676,6 +3707,8 @@ def anotesubmit(data, template=""):
assert type(data) is str and type(template) is str
# Maybe check for length at some point
# For now just send it to storage
+ if(data != vars.authornote):
+ setgamesaved(False)
vars.authornote = data
if(vars.authornotetemplate != template):
@@ -3963,6 +3996,7 @@ def saveRequest(savpath):
filename = filename[:-5]
vars.laststory = filename
emit('from_server', {'cmd': 'setstoryname', 'data': vars.laststory}, broadcast=True)
+ setgamesaved(True)
print("{0}Story saved to {1}!{2}".format(colors.GREEN, path.basename(savpath), colors.END))
#==================================================================#
@@ -4112,6 +4146,7 @@ def loadRequest(loadpath, filename=None):
_filename = filename[:-5]
vars.laststory = _filename
emit('from_server', {'cmd': 'setstoryname', 'data': vars.laststory}, broadcast=True)
+ setgamesaved(True)
sendwi()
emit('from_server', {'cmd': 'setmemory', 'data': vars.memory}, broadcast=True)
emit('from_server', {'cmd': 'setanote', 'data': vars.authornote}, broadcast=True)
@@ -4319,6 +4354,7 @@ def importgame():
# Refresh game screen
vars.laststory = None
emit('from_server', {'cmd': 'setstoryname', 'data': vars.laststory}, broadcast=True)
+ setgamesaved(False)
sendwi()
emit('from_server', {'cmd': 'setmemory', 'data': vars.memory}, broadcast=True)
emit('from_server', {'cmd': 'setanote', 'data': vars.authornote}, broadcast=True)
@@ -4399,6 +4435,7 @@ def importAidgRequest(id):
# Refresh game screen
vars.laststory = None
emit('from_server', {'cmd': 'setstoryname', 'data': vars.laststory}, broadcast=True)
+ setgamesaved(False)
sendwi()
emit('from_server', {'cmd': 'setmemory', 'data': vars.memory}, broadcast=True)
emit('from_server', {'cmd': 'setanote', 'data': vars.authornote}, broadcast=True)
@@ -4456,6 +4493,7 @@ def wiimportrequest():
print("{0}".format(vars.worldinfo[0]))
# Refresh game screen
+ setgamesaved(False)
sendwi()
#==================================================================#
@@ -4488,6 +4526,7 @@ def newGameRequest():
# Refresh game screen
vars.laststory = None
emit('from_server', {'cmd': 'setstoryname', 'data': vars.laststory}, broadcast=True)
+ setgamesaved(True)
sendwi()
emit('from_server', {'cmd': 'setmemory', 'data': vars.memory}, broadcast=True)
emit('from_server', {'cmd': 'setanote', 'data': vars.authornote}, broadcast=True)
@@ -4501,6 +4540,7 @@ def randomGameRequest(topic, memory=""):
vars.recentrng = topic
vars.recentrngm = memory
newGameRequest()
+ setgamesaved(False)
_memory = memory
if(len(memory) > 0):
_memory = memory.rstrip() + "\n\n"
diff --git a/static/application.js b/static/application.js
index 8b6a2380..14d7de37 100644
--- a/static/application.js
+++ b/static/application.js
@@ -93,6 +93,8 @@ var sman_allow_rename = false;
var allowsp = false;
var remote = false;
var gamestate = "";
+var gamesaved = true;
+var modelname = null;
// This is true iff [we're in macOS and the browser is Safari] or [we're in iOS]
var using_webkit_patch = true;
@@ -169,6 +171,23 @@ function addSetting(ob) {
}
}
+function refreshTitle() {
+ var title = gamesaved ? "" : "\u2731 ";
+ if(storyname !== null) {
+ title += storyname + " \u2014 ";
+ }
+ title += "KoboldAI Client";
+ if(modelname !== null) {
+ title += " (" + modelname + ")";
+ }
+ document.title = title;
+}
+
+function setGameSaved(state) {
+ gamesaved = !!state;
+ refreshTitle();
+}
+
function addFormat(ob) {
// Check if we need to make a new column for this button
if(formatcount == 0) {
@@ -1780,6 +1799,10 @@ $(document).ready(function(){
sman_allow_delete = msg.hasOwnProperty("smandelete") && msg.smandelete;
sman_allow_rename = msg.hasOwnProperty("smanrename") && msg.smanrename;
connected = true;
+ if(msg.hasOwnProperty("modelname")) {
+ modelname = msg.modelname;
+ }
+ refreshTitle();
connect_status.html("Connected to KoboldAI Process!");
connect_status.removeClass("color_orange");
connect_status.addClass("color_green");
@@ -1911,6 +1934,7 @@ $(document).ready(function(){
}
} else if(msg.cmd == "setstoryname") {
storyname = msg.data;
+ refreshTitle();
} else if(msg.cmd == "editmode") {
// Enable or Disable edit mode
if(msg.data == "true") {
@@ -2141,6 +2165,8 @@ $(document).ready(function(){
} else if(msg.cmd == "saveas") {
// Show Save As prompt
showSaveAsPopup();
+ } else if(msg.cmd == "gamesaved") {
+ setGameSaved(msg.data);
} else if(msg.cmd == "hidesaveas") {
// Hide Save As prompt
hideSaveAsPopup();
@@ -2537,8 +2563,12 @@ $(document).ready(function(){
}
});
+ $([input_text, anote_input, $("#gamescreen")]).map($.fn.toArray).on("input", function() {
+ setGameSaved(false);
+ });
+
$(window).on("beforeunload", function() {
- if(gamestarted || memorytext.length > 0 || $("#anoteinput").val().length > 0 || $(".wilistitem").length > 1) {
+ if(!gamesaved) {
return true;
}
});
diff --git a/templates/index.html b/templates/index.html
index 1f13ed8d..be53a03d 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -17,7 +17,7 @@
-
+