mirror of
https://github.com/KoboldAI/KoboldAI-Client.git
synced 2025-06-05 21:59:24 +02:00
Make vars.actions a dictionary instead of a list
This commit is contained in:
74
aiserver.py
74
aiserver.py
@ -10,6 +10,7 @@ import re
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
import json
|
import json
|
||||||
|
import collections
|
||||||
from typing import Literal, Union
|
from typing import Literal, Union
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@ -23,6 +24,7 @@ import fileops
|
|||||||
import gensettings
|
import gensettings
|
||||||
from utils import debounce
|
from utils import debounce
|
||||||
import utils
|
import utils
|
||||||
|
import structures
|
||||||
import breakmodel
|
import breakmodel
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
@ -78,7 +80,7 @@ class vars:
|
|||||||
memory = "" # Text submitted to memory field
|
memory = "" # Text submitted to memory field
|
||||||
authornote = "" # Text submitted to Author's Note field
|
authornote = "" # Text submitted to Author's Note field
|
||||||
andepth = 3 # How far back in history to append author's note
|
andepth = 3 # How far back in history to append author's note
|
||||||
actions = [] # Array of actions submitted by user and AI
|
actions = structures.KoboldStoryRegister() # Actions submitted by user and AI
|
||||||
worldinfo = [] # Array of World Info key/value objects
|
worldinfo = [] # Array of World Info key/value objects
|
||||||
badwords = [] # Array of str/chr values that should be removed from output
|
badwords = [] # Array of str/chr values that should be removed from output
|
||||||
badwordsids = [] # Tokenized array of badwords
|
badwordsids = [] # Tokenized array of badwords
|
||||||
@ -883,8 +885,9 @@ def actionretry(data):
|
|||||||
set_aibusy(1)
|
set_aibusy(1)
|
||||||
# Remove last action if possible and resubmit
|
# Remove last action if possible and resubmit
|
||||||
if(len(vars.actions) > 0):
|
if(len(vars.actions) > 0):
|
||||||
|
last_key = vars.actions.get_last_key()
|
||||||
vars.actions.pop()
|
vars.actions.pop()
|
||||||
remove_story_chunk(len(vars.actions) + 1)
|
remove_story_chunk(last_key)
|
||||||
calcsubmit('')
|
calcsubmit('')
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
@ -895,9 +898,9 @@ def actionback():
|
|||||||
return
|
return
|
||||||
# Remove last index of actions and refresh game screen
|
# Remove last index of actions and refresh game screen
|
||||||
if(len(vars.actions) > 0):
|
if(len(vars.actions) > 0):
|
||||||
action_index = len(vars.actions)
|
last_key = vars.actions.get_last_key()
|
||||||
vars.actions.pop()
|
vars.actions.pop()
|
||||||
remove_story_chunk(len(vars.actions) + 1)
|
remove_story_chunk(last_key)
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Take submitted text and build the text to be given to generator
|
# Take submitted text and build the text to be given to generator
|
||||||
@ -964,11 +967,13 @@ def calcsubmit(txt):
|
|||||||
forceanote = True
|
forceanote = True
|
||||||
|
|
||||||
# Get most recent action tokens up to our budget
|
# Get most recent action tokens up to our budget
|
||||||
for n in range(actionlen):
|
n = 0
|
||||||
|
for key in reversed(vars.actions):
|
||||||
|
chunk = vars.actions[key]
|
||||||
|
|
||||||
if(budget <= 0):
|
if(budget <= 0):
|
||||||
break
|
break
|
||||||
acttkns = tokenizer.encode(vars.actions[(-1-n)])
|
acttkns = tokenizer.encode(chunk)
|
||||||
tknlen = len(acttkns)
|
tknlen = len(acttkns)
|
||||||
if(tknlen < budget):
|
if(tknlen < budget):
|
||||||
tokens = acttkns + tokens
|
tokens = acttkns + tokens
|
||||||
@ -984,6 +989,7 @@ def calcsubmit(txt):
|
|||||||
if(anotetxt != ""):
|
if(anotetxt != ""):
|
||||||
tokens = anotetkns + tokens # A.N. len already taken from bdgt
|
tokens = anotetkns + tokens # A.N. len already taken from bdgt
|
||||||
anoteadded = True
|
anoteadded = True
|
||||||
|
n += 1
|
||||||
|
|
||||||
# If we're not using the prompt every time and there's still budget left,
|
# If we're not using the prompt every time and there's still budget left,
|
||||||
# add some prompt.
|
# add some prompt.
|
||||||
@ -1038,17 +1044,19 @@ def calcsubmit(txt):
|
|||||||
|
|
||||||
subtxt = ""
|
subtxt = ""
|
||||||
prompt = vars.prompt
|
prompt = vars.prompt
|
||||||
for n in range(actionlen):
|
n = 0
|
||||||
|
for key in reversed(vars.actions):
|
||||||
|
chunk = vars.actions[key]
|
||||||
|
|
||||||
if(budget <= 0):
|
if(budget <= 0):
|
||||||
break
|
break
|
||||||
actlen = len(vars.actions[(-1-n)])
|
actlen = len(chunk)
|
||||||
if(actlen < budget):
|
if(actlen < budget):
|
||||||
subtxt = vars.actions[(-1-n)] + subtxt
|
subtxt = chunk + subtxt
|
||||||
budget -= actlen
|
budget -= actlen
|
||||||
else:
|
else:
|
||||||
count = budget * -1
|
count = budget * -1
|
||||||
subtxt = vars.actions[(-1-n)][count:] + subtxt
|
subtxt = chunk[count:] + subtxt
|
||||||
budget = 0
|
budget = 0
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -1065,6 +1073,7 @@ def calcsubmit(txt):
|
|||||||
if(anotetxt != ""):
|
if(anotetxt != ""):
|
||||||
subtxt = anotetxt + subtxt # A.N. len already taken from bdgt
|
subtxt = anotetxt + subtxt # A.N. len already taken from bdgt
|
||||||
anoteadded = True
|
anoteadded = True
|
||||||
|
n += 1
|
||||||
|
|
||||||
# Did we get to add the A.N.? If not, do it here
|
# Did we get to add the A.N.? If not, do it here
|
||||||
if(anotetxt != ""):
|
if(anotetxt != ""):
|
||||||
@ -1157,7 +1166,7 @@ def genresult(genout):
|
|||||||
# Add formatted text to Actions array and refresh the game screen
|
# Add formatted text to Actions array and refresh the game screen
|
||||||
vars.actions.append(genout)
|
vars.actions.append(genout)
|
||||||
update_story_chunk('last')
|
update_story_chunk('last')
|
||||||
emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)}, broadcast=True)
|
emit('from_server', {'cmd': 'texteffect', 'data': vars.actions.get_last_key()}, broadcast=True)
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Send generator sequences to the UI for selection
|
# Send generator sequences to the UI for selection
|
||||||
@ -1184,7 +1193,7 @@ def selectsequence(n):
|
|||||||
return
|
return
|
||||||
vars.actions.append(vars.genseqs[int(n)]["generated_text"])
|
vars.actions.append(vars.genseqs[int(n)]["generated_text"])
|
||||||
update_story_chunk('last')
|
update_story_chunk('last')
|
||||||
emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)}, broadcast=True)
|
emit('from_server', {'cmd': 'texteffect', 'data': vars.actions.get_last_key()}, broadcast=True)
|
||||||
emit('from_server', {'cmd': 'hidegenseqs', 'data': ''}, broadcast=True)
|
emit('from_server', {'cmd': 'hidegenseqs', 'data': ''}, broadcast=True)
|
||||||
vars.genseqs = []
|
vars.genseqs = []
|
||||||
|
|
||||||
@ -1243,7 +1252,7 @@ def sendtocolab(txt, min, max):
|
|||||||
# Add formatted text to Actions array and refresh the game screen
|
# Add formatted text to Actions array and refresh the game screen
|
||||||
#vars.actions.append(genout)
|
#vars.actions.append(genout)
|
||||||
#refresh_story()
|
#refresh_story()
|
||||||
#emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)})
|
#emit('from_server', {'cmd': 'texteffect', 'data': vars.actions.get_last_key()})
|
||||||
|
|
||||||
set_aibusy(0)
|
set_aibusy(0)
|
||||||
else:
|
else:
|
||||||
@ -1315,7 +1324,9 @@ def applyoutputformatting(txt):
|
|||||||
#==================================================================#
|
#==================================================================#
|
||||||
def refresh_story():
|
def refresh_story():
|
||||||
text_parts = ['<chunk n="0" id="n0" tabindex="-1">', html.escape(vars.prompt), '</chunk>']
|
text_parts = ['<chunk n="0" id="n0" tabindex="-1">', html.escape(vars.prompt), '</chunk>']
|
||||||
for idx, item in enumerate(vars.actions, start=1):
|
for idx in vars.actions:
|
||||||
|
item = vars.actions[idx]
|
||||||
|
idx += 1
|
||||||
item = html.escape(item)
|
item = html.escape(item)
|
||||||
if vars.adventure: # Add special formatting to adventure actions
|
if vars.adventure: # Add special formatting to adventure actions
|
||||||
item = vars.acregex_ui.sub('<action>\\1</action>', item)
|
item = vars.acregex_ui.sub('<action>\\1</action>', item)
|
||||||
@ -1335,7 +1346,7 @@ def update_story_chunk(idx: Union[int, Literal['last']]):
|
|||||||
refresh_story()
|
refresh_story()
|
||||||
return
|
return
|
||||||
|
|
||||||
idx = len(vars.actions)
|
idx = vars.actions.get_last_key() + 1
|
||||||
|
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
text = vars.prompt
|
text = vars.prompt
|
||||||
@ -1349,7 +1360,7 @@ def update_story_chunk(idx: Union[int, Literal['last']]):
|
|||||||
item = vars.acregex_ui.sub('<action>\\1</action>', item)
|
item = vars.acregex_ui.sub('<action>\\1</action>', item)
|
||||||
|
|
||||||
chunk_text = f'<chunk n="{idx}" id="n{idx}" tabindex="-1">{formatforhtml(item)}</chunk>'
|
chunk_text = f'<chunk n="{idx}" id="n{idx}" tabindex="-1">{formatforhtml(item)}</chunk>'
|
||||||
emit('from_server', {'cmd': 'updatechunk', 'data': {'index': idx, 'html': chunk_text, 'last': (idx == len(vars.actions))}}, broadcast=True)
|
emit('from_server', {'cmd': 'updatechunk', 'data': {'index': idx, 'html': chunk_text, 'last': (idx == vars.actions.get_last_key())}}, broadcast=True)
|
||||||
|
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
@ -1601,10 +1612,19 @@ def checkworldinfo(txt):
|
|||||||
txt = ""
|
txt = ""
|
||||||
depth += 1
|
depth += 1
|
||||||
|
|
||||||
|
if(ln > 0):
|
||||||
|
chunks = collections.deque()
|
||||||
|
i = 0
|
||||||
|
for key in reversed(vars.actions):
|
||||||
|
chunk = vars.actions[key]
|
||||||
|
chunks.appendleft(chunk)
|
||||||
|
if(i == depth):
|
||||||
|
break
|
||||||
|
|
||||||
if(ln >= depth):
|
if(ln >= depth):
|
||||||
txt = "".join(vars.actions[(depth*-1):])
|
txt = "".join(chunks)
|
||||||
elif(ln > 0):
|
elif(ln > 0):
|
||||||
txt = vars.prompt + "".join(vars.actions[(depth*-1):])
|
txt = vars.prompt + "".join(chunks)
|
||||||
elif(ln == 0):
|
elif(ln == 0):
|
||||||
txt = vars.prompt
|
txt = vars.prompt
|
||||||
|
|
||||||
@ -1697,7 +1717,7 @@ def ikrequest(txt):
|
|||||||
print("{0}{1}{2}".format(colors.CYAN, genout, colors.END))
|
print("{0}{1}{2}".format(colors.CYAN, genout, colors.END))
|
||||||
vars.actions.append(genout)
|
vars.actions.append(genout)
|
||||||
update_story_chunk('last')
|
update_story_chunk('last')
|
||||||
emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)}, broadcast=True)
|
emit('from_server', {'cmd': 'texteffect', 'data': vars.actions.get_last_key()}, broadcast=True)
|
||||||
|
|
||||||
set_aibusy(0)
|
set_aibusy(0)
|
||||||
else:
|
else:
|
||||||
@ -1747,7 +1767,7 @@ def oairequest(txt, min, max):
|
|||||||
print("{0}{1}{2}".format(colors.CYAN, genout, colors.END))
|
print("{0}{1}{2}".format(colors.CYAN, genout, colors.END))
|
||||||
vars.actions.append(genout)
|
vars.actions.append(genout)
|
||||||
update_story_chunk('last')
|
update_story_chunk('last')
|
||||||
emit('from_server', {'cmd': 'texteffect', 'data': len(vars.actions)}, broadcast=True)
|
emit('from_server', {'cmd': 'texteffect', 'data': vars.actions.get_last_key()}, broadcast=True)
|
||||||
|
|
||||||
set_aibusy(0)
|
set_aibusy(0)
|
||||||
else:
|
else:
|
||||||
@ -1825,7 +1845,7 @@ def saveRequest(savpath):
|
|||||||
js["prompt"] = vars.prompt
|
js["prompt"] = vars.prompt
|
||||||
js["memory"] = vars.memory
|
js["memory"] = vars.memory
|
||||||
js["authorsnote"] = vars.authornote
|
js["authorsnote"] = vars.authornote
|
||||||
js["actions"] = vars.actions
|
js["actions"] = tuple(vars.actions.values())
|
||||||
js["worldinfo"] = []
|
js["worldinfo"] = []
|
||||||
|
|
||||||
# Extract only the important bits of WI
|
# Extract only the important bits of WI
|
||||||
@ -1876,11 +1896,15 @@ def loadRequest(loadpath):
|
|||||||
vars.gamestarted = js["gamestarted"]
|
vars.gamestarted = js["gamestarted"]
|
||||||
vars.prompt = js["prompt"]
|
vars.prompt = js["prompt"]
|
||||||
vars.memory = js["memory"]
|
vars.memory = js["memory"]
|
||||||
vars.actions = js["actions"]
|
|
||||||
vars.worldinfo = []
|
vars.worldinfo = []
|
||||||
vars.lastact = ""
|
vars.lastact = ""
|
||||||
vars.lastctx = ""
|
vars.lastctx = ""
|
||||||
|
|
||||||
|
del vars.actions
|
||||||
|
vars.actions = structures.KoboldStoryRegister()
|
||||||
|
for s in js["actions"]:
|
||||||
|
vars.actions.append(s)
|
||||||
|
|
||||||
# Try not to break older save files
|
# Try not to break older save files
|
||||||
if("authorsnote" in js):
|
if("authorsnote" in js):
|
||||||
vars.authornote = js["authorsnote"]
|
vars.authornote = js["authorsnote"]
|
||||||
@ -1988,7 +2012,7 @@ def importgame():
|
|||||||
vars.prompt = ""
|
vars.prompt = ""
|
||||||
vars.memory = ref["memory"]
|
vars.memory = ref["memory"]
|
||||||
vars.authornote = ref["authorsNote"] if type(ref["authorsNote"]) is str else ""
|
vars.authornote = ref["authorsNote"] if type(ref["authorsNote"]) is str else ""
|
||||||
vars.actions = []
|
vars.actions = structures.KoboldStoryRegister()
|
||||||
vars.worldinfo = []
|
vars.worldinfo = []
|
||||||
vars.lastact = ""
|
vars.lastact = ""
|
||||||
vars.lastctx = ""
|
vars.lastctx = ""
|
||||||
@ -2047,7 +2071,7 @@ def importAidgRequest(id):
|
|||||||
vars.prompt = js["promptContent"]
|
vars.prompt = js["promptContent"]
|
||||||
vars.memory = js["memory"]
|
vars.memory = js["memory"]
|
||||||
vars.authornote = js["authorsNote"]
|
vars.authornote = js["authorsNote"]
|
||||||
vars.actions = []
|
vars.actions = structures.KoboldStoryRegister()
|
||||||
vars.worldinfo = []
|
vars.worldinfo = []
|
||||||
vars.lastact = ""
|
vars.lastact = ""
|
||||||
vars.lastctx = ""
|
vars.lastctx = ""
|
||||||
@ -2113,7 +2137,7 @@ def newGameRequest():
|
|||||||
vars.gamestarted = False
|
vars.gamestarted = False
|
||||||
vars.prompt = ""
|
vars.prompt = ""
|
||||||
vars.memory = ""
|
vars.memory = ""
|
||||||
vars.actions = []
|
vars.actions = structures.KoboldStoryRegister()
|
||||||
|
|
||||||
vars.authornote = ""
|
vars.authornote = ""
|
||||||
vars.worldinfo = []
|
vars.worldinfo = []
|
||||||
|
@ -880,17 +880,6 @@ $(document).ready(function(){
|
|||||||
let index = msg.data;
|
let index = msg.data;
|
||||||
// Remove the chunk
|
// Remove the chunk
|
||||||
game_text.children(`#n${index}`).remove()
|
game_text.children(`#n${index}`).remove()
|
||||||
// Shift all existing chunks by 1
|
|
||||||
index++;
|
|
||||||
while(true) {
|
|
||||||
const chunk = game_text.children(`#n${index}`)
|
|
||||||
if(chunk.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const newIndex = index - 1;
|
|
||||||
chunk.attr('n', newIndex.toString()).attr('id', `n${newIndex}`);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
hide([$('#curtain')]);
|
hide([$('#curtain')]);
|
||||||
} else if(msg.cmd == "setgamestate") {
|
} else if(msg.cmd == "setgamestate") {
|
||||||
// Enable or Disable buttons
|
// Enable or Disable buttons
|
||||||
|
40
structures.py
Normal file
40
structures.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import collections
|
||||||
|
from typing import Iterable, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class KoboldStoryRegister(collections.OrderedDict):
|
||||||
|
'''
|
||||||
|
Complexity-optimized class for keeping track of story chunks
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, sequence: Iterable[Tuple[int, str]] = ()):
|
||||||
|
super().__init__(sequence)
|
||||||
|
self.__next_id: int = len(sequence)
|
||||||
|
|
||||||
|
def append(self, v: str) -> None:
|
||||||
|
self[self.__next_id] = v
|
||||||
|
self.increment_id()
|
||||||
|
|
||||||
|
def pop(self) -> str:
|
||||||
|
return self.popitem()[1]
|
||||||
|
|
||||||
|
def get_first_key(self) -> int:
|
||||||
|
return next(iter(self))
|
||||||
|
|
||||||
|
def get_last_key(self) -> int:
|
||||||
|
return next(reversed(self))
|
||||||
|
|
||||||
|
def __getitem__(self, k: int) -> str:
|
||||||
|
return super().__getitem__(k)
|
||||||
|
|
||||||
|
def __setitem__(self, k: int, v: str) -> None:
|
||||||
|
return super().__setitem__(k, v)
|
||||||
|
|
||||||
|
def increment_id(self) -> None:
|
||||||
|
self.__next_id += 1
|
||||||
|
|
||||||
|
def get_next_id(self) -> int:
|
||||||
|
return self.__next_id
|
||||||
|
|
||||||
|
def set_next_id(self, x: int) -> None:
|
||||||
|
self.__next_id = x
|
Reference in New Issue
Block a user