diff --git a/class.py b/class.py index fc90d35fc..f2f8432d1 100644 --- a/class.py +++ b/class.py @@ -273,7 +273,7 @@ class model_backend(InferenceModel): unbantokens=False, bantokens=None, usemirostat=None, forceversion=0, nommap=self.kcpp_nommap, usemlock=False, noavx2=self.kcpp_noavx2, debugmode=self.kcpp_debugmode, skiplauncher=True, hordeconfig=None, noblas=self.kcpp_noblas, useclblast=self.kcpp_useclblast, usecublas=self.kcpp_usecublas, usevulkan=self.kcpp_usevulkan, gpulayers=self.kcpp_gpulayers, tensor_split=self.kcpp_tensor_split, config=None, - onready='', multiuser=False, foreground=False, preloadstory=None, noshift=False, remotetunnel=False, ssl=False) + onready='', multiuser=False, foreground=False, preloadstory=None, noshift=False, remotetunnel=False, ssl=False, benchmark=False, nocertify=False) #koboldcpp.main(kcppargs,False) #initialize library without enabling Lite http server diff --git a/klite.embd b/klite.embd index 469bfca7d..9a17dc57e 100644 --- a/klite.embd +++ b/klite.embd @@ -6,7 +6,7 @@ It requires no dependencies, installation or setup. Just copy this single static HTML file anywhere and open it in a browser, or from a webserver. Please go to https://github.com/LostRuins/lite.koboldai.net for updates on Kobold Lite. Kobold Lite is under the AGPL v3.0 License unless otherwise exempted. Please do not remove this line. -Current version: 113 +Current version: 114 -Concedo --> @@ -108,8 +108,7 @@ Current version: 113 line-height: normal; } - body.connected #topmenu, - #topmenu.always-available { + body.connected #topmenu { background-color: #337ab7; } @@ -298,7 +297,7 @@ Current version: 113 .anotetempbox { display: inline; - width: calc(100% - 98px); + width: 100%; } .anotetempscale { @@ -309,7 +308,7 @@ Current version: 113 .stopseqbox { display: inline; - width: calc(100% - 110px); + width: 100%; } #popuptitlebar { @@ -1486,12 +1485,23 @@ Current version: 113 } .storyimgfloat { + width: fit-content; float: right; position: relative; padding: 4px; } - .storyimg + .storyimgside { + display: inline-block; + width: fit-content; + text-align: center; + position: relative; + padding: 4px; + margin: 0 auto; + } + .storyimgcenter + { + width: fit-content; text-align: center; position: relative; padding: 4px; @@ -3410,6 +3420,7 @@ Current version: 113 var image_db = {}; //stores a dictionary of pending images var interrogation_db = {}; var completed_imgs_meta = {}; //stores temp info on completed images like alt text + var img_hash_to_b64_lookup = {}; //used to revert imghash to b64. temporary storage //key is ID, body is {done:false,queue:10,result:""} var stablemodels = [{"name": "stable_diffusion","count": 1}]; //stored as {name,count} var custom_kobold_endpoint = ""; //if set, does not use horde. Instead, attempts to use this sync endpoint @@ -8334,6 +8345,24 @@ Current version: 113 } + function simplemodexample() + { + let simplemodscript = `// This mod changes your top menu to yellow color, then displays the current temperature setting as a popup\n\n`+ + `document.getElementById("topmenu").style.backgroundColor = 'yellow';\nalert("Congrats, your top menu turned yellow. Also, your temperature was " + localsettings.temperature);`; + document.getElementById("inputboxcontainerinputarea").value = simplemodscript; + } + function apply_user_mod() + { + inputBox("Here, you can apply third-party mod scripts shared by other users.

Caution: This mod will have full access to your story and API keys, so only run third-party mods that you trust! For security, mods must always be manually applied every time.

Want to start modding? Click here to load a simple example mod.","Apply Third-Party Mod","","Paste Mod Script Here",()=>{ + let userinput = getInputBoxValue().trim(); + if(userinput!="" && userinput.trim()!="") + { + var userModScript = new Function(userinput); + userModScript(); + } + },true,true); + } + function clear_poll_flags() { pending_response_id = ""; @@ -9546,11 +9575,18 @@ Current version: 113 } } else { - if(oai_payload.logit_bias) + //apply custom logit bias for official OAI only + + let needbaneos = (custom_oai_endpoint.toLowerCase().includes("api.openai.com") && determine_if_ban_eos(input_was_empty)); + + if(needbaneos) { - oai_payload.logit_bias["50256"] = -100; - }else{ - oai_payload.logit_bias = { "50256": -100 }; + if(oai_payload.logit_bias) + { + oai_payload.logit_bias["50256"] = -100; + }else{ + oai_payload.logit_bias = { "50256": -100 }; + } } oai_payload.prompt = submit_payload.prompt; } @@ -10194,11 +10230,12 @@ Current version: 113 function update_clicked_image(imghash) { let savedmeta = completed_imgs_meta[imghash]; - if(!savedmeta) + if(!savedmeta && imghash!="") { - document.getElementById("zoomedimgdesc").innerText = "No Saved Data"; + savedmeta = completed_imgs_meta[imghash] = {prompt:"", desc:"", enabled:false}; } - else + + if(savedmeta) { let origprompt = (savedmeta.prompt?replaceAll(savedmeta.prompt,"\n"," ") : "No Saved Description"); origprompt = escapeHtml(origprompt); @@ -10210,6 +10247,11 @@ Current version: 113
`; } + else + { + document.getElementById("zoomedimgdesc").innerText = "No Saved Data"; + } + } function click_image(target,imghash) { @@ -10246,11 +10288,12 @@ Current version: 113 } } - function render_image_html(data, pend_txt = "", float=true) { + function render_image_html(data, pend_txt = "", float=true, center=false) { var dim = (localsettings.opmode == 2 ? 160 : 200); //adventure mode has smaller pictures - let siclass = (float?"storyimgfloat":"storyimg"); + let siclass = (float?"storyimgfloat":(center?"storyimgcenter":"storyimgside")); let reinvertcolor = localsettings.invert_colors?" invert_colors":""; let alttxt = ""; + let suffix = ((float==false&¢er==false)?"
":""); if (!data || data == "") { let waittime = "Unavailable"; if (image_db[pend_txt] != null) { @@ -10261,13 +10304,13 @@ Current version: 113 console.log("Cannot render " + pend_txt); } - return `
` + pend_txt + `
` + waittime + `
`; + return `
` + pend_txt + `
` + waittime + `
` + suffix; } else { let imghash = cyrb_hash(data).trim(); if (completed_imgs_meta[imghash] != null) { alttxt = completed_imgs_meta[imghash].prompt?escapeHtml(completed_imgs_meta[imghash].prompt):""; } - return `
`; + return `
` + suffix; } } @@ -10611,7 +10654,8 @@ Current version: 113 let newstr = "[<|d|" + img.result + "|d|>]"; console.log("Replacing with Image: " + matchstr); gametext_arr[i] = gametext_arr[i].replace(matchstr, newstr); - completed_imgs_meta[cyrb_hash(img.result)] = {prompt:image_db[key].prompt, desc:"", enabled:false}; + let metaid = cyrb_hash(img.result); + completed_imgs_meta[metaid] = {prompt:image_db[key].prompt, desc:"", enabled:false}; delete image_db[key]; } } @@ -10969,13 +11013,30 @@ Current version: 113 } } + function unstash_image_placeholders(text) + { + return text.replace(/{{\[IMG_.{1,8}_REF\]}}/g, function (m) { + let imghash = m.substring(7, m.length - 7); + if(!imghash) + { + return m; + } + let unstash = img_hash_to_b64_lookup[imghash]; + if(!unstash) + { + return m; + } + return unstash; + }); + } + function merge_edit_field() { if (gametext_arr.length > 0 && document.getElementById("allowediting").checked) { - let oldInnerText = concat_gametext(true, "\n","",""); + let oldInnerText = concat_gametext(false, "","",""); let gametext_elem = document.getElementById("gametext"); - let edited = gametext_elem.innerText; + let editedmatcher = unstash_image_placeholders(gametext_elem.innerText); - if (oldInnerText != edited) { + if (oldInnerText != editedmatcher) { gametext_arr = []; redo_arr = []; last_reply_was_empty = false; @@ -10984,7 +11045,7 @@ Current version: 113 redo_prev_text = ""; //stash images - gametext_elem.querySelectorAll('div.storyimg,div.storyimgfloat').forEach( + gametext_elem.querySelectorAll('div.storyimgcenter,div.storyimgside,div.storyimgfloat').forEach( (el) => { let chimg = el.getElementsByTagName("img")[0]; if(el && chimg) @@ -10994,6 +11055,9 @@ Current version: 113 } ); + //replace b64 image placeholders + gametext_elem.innerHTML = unstash_image_placeholders(gametext_elem.innerHTML); + let editedChunks = []; //use to count chunk lengths before merging gametext_elem.querySelectorAll('span.txtchunk').forEach( (el) => { @@ -11418,19 +11482,36 @@ Current version: 113 fulltxt += "" + escapeHtml(pending_context_preinjection) + escapeHtml(synchro_pending_stream) + ""; } - //handle images - fulltxt = fulltxt.replace(/\[<\|p\|.+?\|p\|>\]/g, function (m) { - // m here means the whole matched string - let inner = m.substring(5, m.length - 5); - inner = render_image_html("", inner); - return inner; - }); - fulltxt = fulltxt.replace(/\[<\|d\|.+?\|d\|>\]/g, function (m) { - // m here means the whole matched string - let inner = m.substring(5, m.length - 5); - inner = render_image_html(inner, ""); - return inner; - }); + if(!inEditMode) + { + let floatimg = (localsettings.opmode!=4); + + //handle images + fulltxt = fulltxt.replace(/\[<\|p\|.+?\|p\|>\]/g, function (m) { + // m here means the whole matched string + let inner = m.substring(5, m.length - 5); + inner = render_image_html("", inner,floatimg,false); + return inner; + }); + fulltxt = fulltxt.replace(/\[<\|d\|.+?\|d\|>\]/g, function (m) { + // m here means the whole matched string + let inner = m.substring(5, m.length - 5); + inner = render_image_html(inner, "",floatimg,false); + return inner; + }); + } + else + { + fulltxt = fulltxt.replace(/\[<\|p\|.+?\|p\|>\]/g, function (m) { + return ``+m+``; + }); + fulltxt = fulltxt.replace(/\[<\|d\|.+?\|d\|>\]/g, function (m) { + let inner = m.substring(5, m.length - 5); + let imghash = cyrb_hash(inner); + img_hash_to_b64_lookup[imghash] = m; + return `{{[IMG_${imghash}_REF]}}`; + }); + } fulltxt = fulltxt.replace(/(\r\n|\r|\n)/g, '
'); @@ -11642,11 +11723,12 @@ Current version: 113 for(var i=0;i\]/g, ""); + var foundopponent = txtwithnoimages.match(othernamesregex); + var foundself = txtwithnoimages.match(mynameregex); - if(tempfullsearchable==null ) + if(tempfullsearchable==null) { continue; } @@ -11710,13 +11792,13 @@ Current version: 113 curr.msg = curr.msg.replace(/\[<\|p\|.+?\|p\|>\]/g, function (m) { // m here means the whole matched string let inner = m.substring(5, m.length - 5); - inner = render_image_html("", inner,false); + inner = render_image_html("", inner,false,true); return inner; }); curr.msg = curr.msg.replace(/\[<\|d\|.+?\|d\|>\]/g, function (m) { // m here means the whole matched string let inner = m.substring(5, m.length - 5); - inner = render_image_html(inner, "",false); + inner = render_image_html(inner, "",false,true); return inner; }); curr.msg = curr.msg.replace(/\[<\|.+?\|>\]/g, ""); //remove normal comments too @@ -12647,13 +12729,13 @@ Current version: 113 newbodystr = newbodystr.replace(/\[<\|p\|.+?\|p\|>\]/g, function (m) { // m here means the whole matched string let inner = m.substring(5, m.length - 5); - inner = render_image_html("", inner,false); + inner = render_image_html("", inner,false,true); return inner; }); newbodystr = newbodystr.replace(/\[<\|d\|.+?\|d\|>\]/g, function (m) { // m here means the whole matched string let inner = m.substring(5, m.length - 5); - inner = render_image_html(inner, "",false); + inner = render_image_html(inner, "",false,true); return inner; }); return portraitsStyling + newbodystr.replaceAll(/(\r\n|\r|\n)/g,'
'); // Finally, convert newlines to HTML format and return the stylized string. @@ -13558,6 +13640,10 @@ Current version: 113
Mirostat Not Supported
+
+
User Mods ?Allows you to load third-party user created mods (caution).
+ +
@@ -13850,6 +13936,7 @@ Current version: 113 +
-

+
+
Extra Stopping Sequences ?Triggers the text generator to stop generating early if this sequence appears, in addition to default stop sequences. If you want multiple sequences, separate them with the following delimiter: ||$||
+
- -
+ +
diff --git a/koboldcpp.py b/koboldcpp.py index a1f16db5e..0ebb6d8b3 100644 --- a/koboldcpp.py +++ b/koboldcpp.py @@ -466,7 +466,7 @@ maxhordelen = 256 modelbusy = threading.Lock() requestsinqueue = 0 defaultport = 5001 -KcppVersion = "1.58" +KcppVersion = "1.59" showdebug = True showsamplerwarning = True showmaxctxwarning = True @@ -484,6 +484,7 @@ gui_layers_untouched = True runmode_untouched = True preloaded_story = None sslvalid = False +nocertify = False start_time = time.time() class ServerRequestHandler(http.server.SimpleHTTPRequestHandler): @@ -1216,6 +1217,7 @@ def show_new_gui(): debugmode = ctk.IntVar() keepforeground = ctk.IntVar() quietmode = ctk.IntVar(value=0) + nocertifymode = ctk.IntVar(value=0) lowvram_var = ctk.IntVar() mmq_var = ctk.IntVar(value=1) @@ -1713,6 +1715,7 @@ def show_new_gui(): makecheckbox(network_tab, "Multiuser Mode", multiuser_var, 3,tooltiptxt="Allows requests by multiple different clients to be queued and handled in sequence.") makecheckbox(network_tab, "Remote Tunnel", remotetunnel, 3, 1,tooltiptxt="Creates a trycloudflare tunnel.\nAllows you to access koboldcpp from other devices over an internet URL.") makecheckbox(network_tab, "Quiet Mode", quietmode, 4,tooltiptxt="Prevents all generation related terminal output from being displayed.") + makecheckbox(network_tab, "NoCertify Mode (Insecure)", nocertifymode, 4, 1,tooltiptxt="Allows insecure SSL connections. Use this if you have cert errors and need to bypass certificate restrictions.") makefileentry(network_tab, "SSL Cert:", "Select SSL cert.pem file",ssl_cert_var, 5, width=130 ,filetypes=[("Unencrypted Certificate PEM", "*.pem")], singlerow=True,tooltiptxt="Select your unencrypted .pem SSL certificate file for https.\nCan be generated with OpenSSL.") makefileentry(network_tab, "SSL Key:", "Select SSL key.pem file", ssl_key_var, 7, width=130, filetypes=[("Unencrypted Key PEM", "*.pem")], singlerow=True,tooltiptxt="Select your unencrypted .pem SSL key file for https.\nCan be generated with OpenSSL.") @@ -1764,6 +1767,7 @@ def show_new_gui(): args.remotetunnel = remotetunnel.get()==1 args.foreground = keepforeground.get()==1 args.quiet = quietmode.get()==1 + args.nocertify = nocertifymode.get()==1 gpuchoiceidx = 0 if gpu_choice_var.get()!="All": @@ -1816,7 +1820,6 @@ def show_new_gui(): args.ssl = None if (ssl_cert_var.get() == "" or ssl_key_var.get() == "") else ([ssl_cert_var.get(), ssl_key_var.get()]) - args.port_param = defaultport if port_var.get()=="" else int(port_var.get()) args.host = host_var.get() args.multiuser = multiuser_var.get() @@ -1840,6 +1843,7 @@ def show_new_gui(): remotetunnel.set(1 if "remotetunnel" in dict and dict["remotetunnel"] else 0) keepforeground.set(1 if "foreground" in dict and dict["foreground"] else 0) quietmode.set(1 if "quiet" in dict and dict["quiet"] else 0) + nocertifymode.set(1 if "nocertify" in dict and dict["nocertify"] else 0) if "useclblast" in dict and dict["useclblast"]: if "noavx2" in dict and dict["noavx2"]: if clblast_noavx2_option is not None: @@ -2024,9 +2028,14 @@ def print_with_time(txt): print(f"{datetime.now().strftime('[%H:%M:%S]')} " + txt) def make_url_request(url, data, method='POST', headers={}): - import urllib.request + import urllib.request, ssl + global nocertify try: request = None + ssl_context = ssl.create_default_context() + if nocertify: + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE if method=='POST': json_payload = json.dumps(data).encode('utf-8') request = urllib.request.Request(url, data=json_payload, headers=headers, method=method) @@ -2034,7 +2043,7 @@ def make_url_request(url, data, method='POST', headers={}): else: request = urllib.request.Request(url, headers=headers, method=method) response_data = "" - with urllib.request.urlopen(request) as response: + with urllib.request.urlopen(request,context=ssl_context) as response: response_data = response.read().decode('utf-8') json_response = json.loads(response_data) return json_response @@ -2433,6 +2442,10 @@ def main(launch_args,start_server=True): global maxctx maxctx = args.contextsize + if args.nocertify: + global nocertify + nocertify = True + init_library() # Note: if blas does not exist and is enabled, program will crash. print("==========") time.sleep(1) @@ -2668,6 +2681,7 @@ if __name__ == '__main__': parser.add_argument("--preloadstory", help="Configures a prepared story json save file to be hosted on the server, which frontends (such as Kobold Lite) can access over the API.", default="") parser.add_argument("--quiet", help="Enable quiet mode, which hides generation inputs and outputs in the terminal. Quiet mode is automatically enabled when running --hordeconfig.", action='store_true') parser.add_argument("--ssl", help="Allows all content to be served over SSL instead. A valid UNENCRYPTED SSL cert and key .pem files must be provided", metavar=('[cert_pem]', '[key_pem]'), nargs='+') + parser.add_argument("--nocertify", help="Allows insecure SSL connections. Use this if you have cert errors and need to bypass certificate restrictions.", action='store_true') # #deprecated hidden args. they do nothing. do not use # parser.add_argument("--psutil_set_threads", action='store_true', help=argparse.SUPPRESS)