diff --git a/aiserver.py b/aiserver.py
index 5bec7497..d6b173d9 100644
--- a/aiserver.py
+++ b/aiserver.py
@@ -4,15 +4,18 @@
# By: KoboldAIDev
#==================================================================#
+# External packages
from os import path, getcwd
import tkinter as tk
from tkinter import messagebox
import json
import torch
+# KoboldAI
import fileops
import gensettings
from utils import debounce
+import utils
#==================================================================#
# Variables & Storage
@@ -69,6 +72,7 @@ class vars:
hascuda = False # Whether torch has detected CUDA on the system
usegpu = False # Whether to launch pipeline with GPU support
custmodpth = "" # Filesystem location of custom model to run
+ formatoptns = {} # Container for state of formatting options
#==================================================================#
# Function to get model selection at startup
@@ -349,6 +353,23 @@ def get_message(msg):
vars.andepth = int(msg['data'])
emit('from_server', {'cmd': 'setlabelanotedepth', 'data': msg['data']})
settingschanged()
+ # Format - Trim incomplete sentences
+ elif(msg['cmd'] == 'frmttriminc'):
+ if('frmttriminc' in vars.formatoptns):
+ vars.formatoptns["frmttriminc"] = msg['data']
+ settingschanged()
+ elif(msg['cmd'] == 'frmtrmblln'):
+ if('frmtrmblln' in vars.formatoptns):
+ vars.formatoptns["frmtrmblln"] = msg['data']
+ settingschanged()
+ elif(msg['cmd'] == 'frmtrmspch'):
+ if('frmtrmspch' in vars.formatoptns):
+ vars.formatoptns["frmtrmspch"] = msg['data']
+ settingschanged()
+ elif(msg['cmd'] == 'frmtadsnsp'):
+ if('frmtadsnsp' in vars.formatoptns):
+ vars.formatoptns["frmtadsnsp"] = msg['data']
+ settingschanged()
#==================================================================#
#
@@ -368,6 +389,13 @@ def sendsettings():
else:
for set in gensettings.gensettingsik:
emit('from_server', {'cmd': 'addsetting', 'data': set})
+
+ # Send formatting options
+ for frm in gensettings.formatcontrols:
+ emit('from_server', {'cmd': 'addformat', 'data': frm})
+ # Add format key to vars if it wasn't loaded with client.settings
+ if(not frm["id"] in vars.formatoptns):
+ vars.formatoptns[frm["id"]] = False;
#==================================================================#
#
@@ -375,14 +403,15 @@ def sendsettings():
def savesettings():
# Build json to write
js = {}
- js["apikey"] = vars.apikey
- js["andepth"] = vars.andepth
- js["temp"] = vars.temp
- js["top_p"] = vars.top_p
- js["rep_pen"] = vars.rep_pen
- js["genamt"] = vars.genamt
- js["max_length"] = vars.max_length
- js["ikgen"] = vars.ikgen
+ js["apikey"] = vars.apikey
+ js["andepth"] = vars.andepth
+ js["temp"] = vars.temp
+ js["top_p"] = vars.top_p
+ js["rep_pen"] = vars.rep_pen
+ js["genamt"] = vars.genamt
+ js["max_length"] = vars.max_length
+ js["ikgen"] = vars.ikgen
+ js["formatoptns"] = vars.formatoptns
# Write it
file = open("client.settings", "w")
@@ -417,6 +446,8 @@ def loadsettings():
vars.max_length = js["max_length"]
if("ikgen" in js):
vars.ikgen = js["ikgen"]
+ if("formatoptns" in js):
+ vars.formatoptns = js["formatoptns"]
file.close()
@@ -436,14 +467,22 @@ def actionsubmit(data):
return
set_aibusy(1)
if(not vars.gamestarted):
- vars.gamestarted = True # Start the game
- vars.prompt = data # Save this first action as the prompt
- emit('from_server', {'cmd': 'updatescreen', 'data': 'Please wait, generating story...'}) # Clear the startup text from game screen
+ # Start the game
+ vars.gamestarted = True
+ # Save this first action as the prompt
+ vars.prompt = data
+ # Clear the startup text from game screen
+ emit('from_server', {'cmd': 'updatescreen', 'data': 'Please wait, generating story...'})
calcsubmit(data) # Run the first action through the generator
else:
# Dont append submission if it's a blank/continue action
if(data != ""):
+ # Apply input formatting & scripts before sending to tokenizer
+ data = applyinputformatting(data)
+ # Store the result in the Action log
vars.actions.append(data)
+
+ # Off to the tokenizer!
calcsubmit(data)
#==================================================================#
@@ -594,7 +633,12 @@ def generate(txt, min, max):
temperature=vars.temp
)[0]["generated_text"]
print("{0}{1}{2}".format(colors.CYAN, genout, colors.END))
- vars.actions.append(getnewcontent(genout))
+
+ # Format output before continuing
+ genout = applyoutputformatting(getnewcontent(genout))
+
+ # Add formatted text to Actions array and refresh the game screen
+ vars.actions.append(genout)
refresh_story()
emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)})
@@ -611,7 +655,7 @@ def formatforhtml(txt):
return txt.replace("\\r", "
").replace("\\n", "
").replace('\n', '
').replace('\r', '
')
#==================================================================#
-# Strips submitted text from the text returned by the AI
+# Strips submitted text from the text returned by the AI
#==================================================================#
def getnewcontent(txt):
ln = len(vars.actions)
@@ -622,6 +666,35 @@ def getnewcontent(txt):
return (txt.split(delim)[-1])
+#==================================================================#
+# Applies chosen formatting options to text submitted to AI
+#==================================================================#
+def applyinputformatting(txt):
+ # Add sentence spacing
+ if(vars.formatoptns["frmtadsnsp"]):
+ txt = utils.addsentencespacing(txt, vars.actions)
+
+ return txt
+
+#==================================================================#
+# Applies chosen formatting options to text returned from AI
+#==================================================================#
+def applyoutputformatting(txt):
+ # Use standard quotes and apostrophes
+ txt = utils.fixquotes(txt)
+
+ # Trim incomplete sentences
+ if(vars.formatoptns["frmttriminc"]):
+ txt = utils.trimincompletesentence(txt)
+ # Replace blank lines
+ if(vars.formatoptns["frmtrmblln"]):
+ txt = utils.replaceblanklines(txt)
+ # Remove special characters
+ if(vars.formatoptns["frmtrmspch"]):
+ txt = utils.removespecialchars(txt)
+
+ return txt
+
#==================================================================#
# Sends the current story content to the Game Screen
#==================================================================#
@@ -637,6 +710,9 @@ def refresh_story():
# Sends the current generator settings to the Game Menu
#==================================================================#
def refresh_settings():
+ # Suppress toggle change events while loading state
+ emit('from_server', {'cmd': 'allowtoggle', 'data': False})
+
if(vars.model != "InferKit"):
emit('from_server', {'cmd': 'updatetemp', 'data': vars.temp})
emit('from_server', {'cmd': 'updatetopp', 'data': vars.top_p})
@@ -649,6 +725,14 @@ def refresh_settings():
emit('from_server', {'cmd': 'updateikgen', 'data': vars.ikgen})
emit('from_server', {'cmd': 'updateanotedepth', 'data': vars.andepth})
+
+ emit('from_server', {'cmd': 'updatefrmttriminc', 'data': vars.formatoptns["frmttriminc"]})
+ emit('from_server', {'cmd': 'updatefrmtrmblln', 'data': vars.formatoptns["frmtrmblln"]})
+ emit('from_server', {'cmd': 'updatefrmtrmspch', 'data': vars.formatoptns["frmtrmspch"]})
+ emit('from_server', {'cmd': 'updatefrmtadsnsp', 'data': vars.formatoptns["frmtadsnsp"]})
+
+ # Allow toggle events again
+ emit('from_server', {'cmd': 'allowtoggle', 'data': True})
#==================================================================#
# Sets the logical and display states for the AI Busy condition
diff --git a/gensettings.py b/gensettings.py
index 0150a139..84c180f9 100644
--- a/gensettings.py
+++ b/gensettings.py
@@ -86,4 +86,25 @@ gensettingsik =[{
"step": 2,
"default": 200,
"tooltip": "Number of characters the AI should generate."
- }]
\ No newline at end of file
+ }]
+
+formatcontrols = [{
+ "label": "Trim incomplete sentences",
+ "id": "frmttriminc",
+ "tooltip": "Remove text after last sentence closure. If no closure is found, all tokens will be returned."
+ },
+ {
+ "label": "Remove blank lines",
+ "id": "frmtrmblln",
+ "tooltip": "Replace double newlines (\\n\\n) with single newlines to avoid blank lines."
+ },
+ {
+ "label": "Remove special characters",
+ "id": "frmtrmspch",
+ "tooltip": "Remove special characters (@,#,%,^, etc)"
+ },
+ {
+ "label": "Add sentence spacing",
+ "id": "frmtadsnsp",
+ "tooltip": "If the last action ended with punctuation, add a space to the beginning of the next action."
+ }]
\ No newline at end of file
diff --git a/static/application.js b/static/application.js
index 9cddb42e..e0a2c9fa 100644
--- a/static/application.js
+++ b/static/application.js
@@ -11,6 +11,7 @@ var button_newgame;
var button_save;
var button_load;
var button_settings;
+var button_format;
var button_send;
var button_actedit;
var button_actmem;
@@ -21,6 +22,7 @@ var game_text;
var input_text;
var message_text;
var settings_menu;
+var format_menu;
var anote_menu;
var anote_input;
var anote_labelcur;
@@ -30,6 +32,10 @@ var anote_slider;
var shift_down = false;
var do_clear_ent = false;
+// Display vars
+var allowtoggle = false;
+var formatcount = 0;
+
//=================================================================//
// METHODS
//=================================================================//
@@ -58,16 +64,44 @@ function addSetting(ob) {
\
");
// Set references to HTML objects
- refin = $("#"+ob.id);
- reflb = $("#"+ob.id+"cur");
- window["setting_"+ob.id] = refin;
- window["label_"+ob.id] = reflb;
+ var refin = $("#"+ob.id);
+ var reflb = $("#"+ob.id+"cur");
+ window["setting_"+ob.id] = refin; // Is this still needed?
+ window["label_"+ob.id] = reflb; // Is this still needed?
// Add event function to input
refin.on("input", function () {
socket.send({'cmd': $(this).attr('id'), 'data': $(this).val()});
});
}
+function addFormat(ob) {
+ // Check if we need to make a new column for this button
+ if(formatcount == 0) {
+ format_menu.append("