added basic support for password protection (+2 squashed commit)

Squashed commit:

[ff91ca72] added basic support for password protection

[91b0b208] updated docs
This commit is contained in:
Concedo 2024-03-12 16:05:51 +08:00
parent a69bc44e7a
commit 6c6ad93f01
4 changed files with 192 additions and 49 deletions

View file

@ -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, benchmark=None, nocertify=False, sdconfig=None, mmproj=None)
onready='', multiuser=False, foreground=False, preloadstory=None, noshift=False, remotetunnel=False, ssl=False, benchmark=None, nocertify=False, sdconfig=None, mmproj=None, password=None)
#koboldcpp.main(kcppargs,False) #initialize library without enabling Lite http server

View file

@ -183,6 +183,10 @@
"memory": {
"description": "KoboldCpp ONLY. If set, forcefully appends this string to the beginning of any submitted prompt text. If resulting context exceeds the limit, forcefully overwrites text from the beginning of the main prompt until it can fit. Useful to guarantee full memory insertion even when you cannot determine exact token count.",
"type": "string"
},
"images": {
"description": "KoboldCpp ONLY. If set, takes an array of base64 encoded strings, each one representing an image to be processed.",
"type": "array"
},
"trim_stop": {
"default": false,
@ -345,7 +349,7 @@
"info": {
"title": "KoboldCpp API",
"description": "For swagger.json, <a href=\"?json=1\">click here</a>.",
"version": "1.60"
"version": "1.61"
},
"openapi": "3.0.3",
"paths": {
@ -544,7 +548,10 @@
"application/json": {
"example": {
"result": "KoboldCpp",
"version": "1.46"
"version": "1.61",
"protected": false,
"txt2img": false,
"vision": false
},
"schema": {
"$ref": "#/components/schemas/KcppVersion"
@ -1105,6 +1112,7 @@
};
</script>
<script>
//self destruct into json if requested
const urlParams = new URLSearchParams(window.location.search);

View file

@ -7,7 +7,7 @@ Just copy this single static HTML file anywhere and open it in a browser, or fro
Please go to https://github.com/LostRuins/lite.koboldai.net for updates on Kobold Lite.
If you are submitting a pull request for Lite, PLEASE use the above repo, not the KoboldCpp one.
Kobold Lite is under the AGPL v3.0 License unless otherwise exempted. Please do not remove this line.
Current version: 123
Current version: 124
-Concedo
-->
@ -2985,6 +2985,15 @@ Current version: 123
}
return proxy_part + url;
}
function get_kobold_header()
{
let header = {'Content-Type': 'application/json'};
if(custom_kobold_key!="")
{
header['Authorization'] = 'Bearer ' + custom_kobold_key;
}
return header;
}
//instead of a single fetch, optionally break it up into multiple repeated requests which update a local variable
function kobold_api_stream(sub_endpt,submit_payload,synchro_streaming_tokens_left,trackedgenid,synchro_streaming_response = "",tokens_per_tick = 4096)
@ -3006,7 +3015,7 @@ Current version: 123
let reqOpt = {
method: 'POST', // or 'PUT'
headers: {'Content-Type': 'application/json',},
headers: get_kobold_header(),
body: JSON.stringify(new_submit_payload),
};
if(globalabortcontroller)
@ -3123,13 +3132,22 @@ Current version: 123
synchro_pending_stream = "";
let reqOpt =
{method: 'POST',
headers: {'Content-Type': 'application/json'},
headers: get_kobold_header(),
body: JSON.stringify(submit_payload)};
if(globalabortcontroller)
{
reqOpt.signal = globalabortcontroller.signal;
}
fetch(sub_endpt, reqOpt)
.then(x => {
if(x.ok)
{
return x;
}else{
throw new Error('Error occurred while SSE streaming: ' + (x.statusText));
return null;
}
})
.then(resp => {
resp.body
.pipeThrough(new TextDecoderStream())
@ -3476,6 +3494,7 @@ Current version: 123
//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
var custom_kobold_key = ""; //only kcpp can potentially use this
var custom_oai_endpoint = "";
var custom_oai_key = ""; //if set, uses the OpenAI API to generate
var custom_oai_model = "";
@ -3495,6 +3514,7 @@ Current version: 123
var last_known_filename = "saved_story.json";
var localmodeport = 5000;
var localmodehost = "localhost";
var localmodekey = "";
var kobold_endpoint_version = ""; //used to track problematic versions to avoid sending extra fields
var koboldcpp_version = ""; //detect if we are using koboldcpp
var koboldcpp_has_vision = false;
@ -3518,6 +3538,7 @@ Current version: 123
saved_claude_addr: default_claude_base, //do not ever share this in save files!
saved_palm_key: "", //do not ever share this in save files!
saved_kai_addr: "", //do not ever share this in save files!
saved_kai_key: "", //do not ever share this in save files!
saved_oai_jailbreak: "", //customized oai system prompt
saved_oai_jailbreak2: "", //oai assistant postfix
saved_claude_jailbreak: "", //claude system prompt
@ -3768,6 +3789,13 @@ Current version: 123
}else if(window.location.hostname && window.location.hostname!="" && !is_using_web_lite()){
localmodehost = window.location.hostname;
}
let inputkey = urlParams.get('key');
if(inputkey)
{
localmodekey = inputkey;
}
}
const fromfile = ( window.location.protocol == 'file:' );
@ -4010,7 +4038,11 @@ Current version: 123
{
protocol = "https://";
}
document.getElementById("customendpoint").value = protocol + localmodehost + ":" + localmodeport;
if(localmodekey)
{
document.getElementById("customkoboldkey").value = localmodekey;
}
document.getElementById("customkoboldendpoint").value = protocol + localmodehost + ":" + localmodeport;
connect_custom_endpoint();
document.getElementById("lastreq").innerHTML = document.getElementById("lastreq2").innerHTML =
`<span class=color_gray>You're using Kobold Lite Embedded.</span>`;
@ -4901,6 +4933,7 @@ Current version: 123
new_save_storyobj.savedsettings.saved_claude_key = "";
new_save_storyobj.savedsettings.saved_claude_addr = "";
new_save_storyobj.savedsettings.saved_kai_addr = "";
new_save_storyobj.savedsettings.saved_kai_key = "";
new_save_storyobj.savedsettings.saved_openrouter_key = "";
new_save_storyobj.savedsettings.modelhashes = [];
@ -5199,6 +5232,7 @@ Current version: 123
let tmp_claude2 = localsettings.saved_claude_addr;
let tmp_palm1 = localsettings.saved_palm_key;
let tmp_kai = localsettings.saved_kai_addr;
let tmp_kai2 = localsettings.saved_kai_key;
let tmp_a1111 = localsettings.saved_a1111_url;
let tmp_xtts = localsettings.saved_xtts_url;
let tmp_imggen = localsettings.generate_images_mode;
@ -5232,6 +5266,7 @@ Current version: 123
localsettings.saved_claude_addr = tmp_claude2;
localsettings.saved_palm_key = tmp_palm1;
localsettings.saved_kai_addr = tmp_kai;
localsettings.saved_kai_key = tmp_kai2;
localsettings.saved_a1111_url = tmp_a1111;
localsettings.saved_xtts_url = tmp_xtts;
localsettings.generate_images_mode = tmp_imggen;
@ -6821,7 +6856,8 @@ Current version: 123
document.getElementById("koboldcustom").classList.remove("hidden");
if(!localflag)
{
document.getElementById("customendpoint").value = localsettings.saved_kai_addr;
document.getElementById("customkoboldendpoint").value = localsettings.saved_kai_addr;
document.getElementById("customkoboldkey").value = localsettings.saved_kai_key;
}
}
else if(epchoice==1 || epchoice==5)
@ -6888,7 +6924,10 @@ Current version: 123
allow_update_kobold_model_display_timestamp = performance.now() + 60000;
console.log("Updating selected model name...");
let murl = apply_proxy_url(custom_kobold_endpoint + kobold_custom_mdl_endpoint);
fetch(murl)
fetch(murl, {
method: 'GET',
headers: get_kobold_header(),
})
.then(x => x.json())
.then(values => {
if(custom_kobold_endpoint!="" && values && values.result!="")
@ -6909,6 +6948,7 @@ Current version: 123
function connect_custom_endpoint()
{
custom_kobold_endpoint = "";
custom_kobold_key = "";
custom_oai_key = "";
custom_scale_key = "";
custom_claude_key = "";
@ -6917,25 +6957,30 @@ Current version: 123
let epchoice = document.getElementById("customapidropdown").value;
if(epchoice==0) //connect to kobold endpoint
{
let tmpep = document.getElementById("customendpoint").value;
if (tmpep != null && tmpep.trim() != "") {
let desiredkoboldendpoint = document.getElementById("customkoboldendpoint").value;
let desiredkoboldkey = document.getElementById("customkoboldkey").value;
if (desiredkoboldendpoint != null && desiredkoboldendpoint.trim() != "") {
hide_popups();
tmpep = tmpep.trim();
desiredkoboldendpoint = desiredkoboldendpoint.trim();
//remove trailing slash and pound
tmpep = tmpep.endsWith('#') ? tmpep.slice(0, -1) : tmpep;
tmpep = tmpep.endsWith('/') ? tmpep.slice(0, -1) : tmpep;
desiredkoboldendpoint = desiredkoboldendpoint.endsWith('#') ? desiredkoboldendpoint.slice(0, -1) : desiredkoboldendpoint;
desiredkoboldendpoint = desiredkoboldendpoint.endsWith('/') ? desiredkoboldendpoint.slice(0, -1) : desiredkoboldendpoint;
if (tmpep != "" && (tmpep.trim().endsWith("/api") || tmpep.trim().endsWith("/api/v1")))
if (desiredkoboldendpoint != "" && (desiredkoboldendpoint.trim().endsWith("/api") || desiredkoboldendpoint.trim().endsWith("/api/v1")))
{
tmpep = tmpep.split("/api")[0];
desiredkoboldendpoint = desiredkoboldendpoint.split("/api")[0];
}
let urls1 = [
apply_proxy_url(tmpep + kobold_custom_mdl_endpoint),
apply_proxy_url(desiredkoboldendpoint + kobold_custom_mdl_endpoint),
];
Promise.all(urls1.map(url => fetch(url)
Promise.all(urls1.map(url => fetch(url,{
method: 'GET',
headers: get_kobold_header(),
})
.then(response => response.json())))
.then(values => {
console.log(values);
@ -6955,8 +7000,10 @@ Current version: 123
} else {
//good to go
custom_kobold_endpoint = tmpep;
custom_kobold_endpoint = desiredkoboldendpoint;
custom_kobold_key = desiredkoboldkey;
localsettings.saved_kai_addr = custom_kobold_endpoint;
localsettings.saved_kai_key = custom_kobold_key;
selected_models = [{ "performance": 100.0, "queued": 0.0, "eta": 0, "name": mdlname, "count": 1 }];
selected_workers = [];
if (perfdata == null) {
@ -6977,7 +7024,11 @@ Current version: 123
{
//now we get the version number, however this is optional
//if it fails we can still proceed
fetch(apply_proxy_url(tmpep + kobold_custom_version_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + kobold_custom_version_endpoint),
{
method: 'GET',
headers: get_kobold_header(),
})
.then(response => response.json())
.then(values2 => {
console.log(values2);
@ -6988,7 +7039,11 @@ Current version: 123
});
//also get max ctx supported
fetch(apply_proxy_url(tmpep + kobold_custom_maxctxlen_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + kobold_custom_maxctxlen_endpoint),
{
method: 'GET',
headers: get_kobold_header(),
})
.then(response => response.json())
.then(values3 => {
console.log(values3);
@ -7007,7 +7062,11 @@ Current version: 123
//allow kcpp version check for remote endpoints too
{
//for local mode, check if we are using koboldcpp, if so we can use streaming if permitted by version
fetch(apply_proxy_url(tmpep + koboldcpp_version_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + koboldcpp_version_endpoint),
{
method: 'GET',
headers: get_kobold_header(),
})
.then(x => x.json())
.then(data => {
if(data && data!="" && data.version && data.version!="")
@ -7015,9 +7074,14 @@ Current version: 123
koboldcpp_version = data.version;
console.log("KoboldCpp Detected: " + koboldcpp_version);
koboldcpp_has_vision = (data.vision?true:false);
let has_password = (data.protected?true:false);
//also check against kcpp's max true context length
fetch(apply_proxy_url(tmpep + koboldcpp_truemaxctxlen_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + koboldcpp_truemaxctxlen_endpoint),
{
method: 'GET',
headers: get_kobold_header(),
})
.then(response => response.json())
.then(values4 => {
console.log(values4);
@ -7032,7 +7096,11 @@ Current version: 123
});
//and check if there's a kcpp savefile preloaded
fetch(apply_proxy_url(tmpep + koboldcpp_preloadstory_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + koboldcpp_preloadstory_endpoint),
{
method: 'GET',
headers: get_kobold_header(),
})
.then(response => response.json())
.then(values5 => {
let tmpstory = values5;
@ -7051,7 +7119,7 @@ Current version: 123
});
//check if image gen is supported
fetch(apply_proxy_url(tmpep + a1111_models_endpoint))
fetch(apply_proxy_url(desiredkoboldendpoint + a1111_models_endpoint))
.then(response => response.json())
.then(values6 => {
console.log(values6);
@ -7063,7 +7131,7 @@ Current version: 123
{
console.log("Connect to KoboldCpp Image Gen");
localsettings.generate_images_mode = 2;
localsettings.saved_a1111_url = tmpep;
localsettings.saved_a1111_url = desiredkoboldendpoint;
connect_to_a1111(true);
render_gametext(true);
}
@ -7071,7 +7139,7 @@ Current version: 123
else
{
//hide the add img if the image server is down
if(localsettings.generate_images_mode==2 && localsettings.saved_a1111_url==tmpep)
if(localsettings.generate_images_mode==2 && localsettings.saved_a1111_url==desiredkoboldendpoint)
{
localsettings.generate_images_mode = 0;
localsettings.saved_a1111_url = default_a1111_base
@ -7083,6 +7151,19 @@ Current version: 123
console.log("Failed to get local image models: " + error);
});
//prompt to request password for kcpp
if(localflag && has_password && !localmodekey)
{
console.log("Password protection detected. Prompting for password...");
inputBox("This KoboldCpp instance may be password protected.\nPlease input password:","Kobold API Key Required",localsettings.saved_kai_key,"(Input Kobold API Key)", ()=>{
let userinput = getInputBoxValue();
userinput = userinput.trim();
if (userinput != null && userinput!="") {
custom_kobold_key = document.getElementById("customkoboldkey").value = localmodekey = localsettings.saved_kai_key = userinput.trim();
}
},false);
}
}else{
console.log("Unknown KoboldCpp Check Response: " + data);
}
@ -7104,7 +7185,7 @@ Current version: 123
|| !custom_kobold_endpoint.toLowerCase().includes(".")); //hostname without dots cannot be wan accessible
if (uses_cors_proxy || is_local) {
msgbox("Failed to connect to Custom Kobold Endpoint!\n\nPlease check if KoboldAI is running at the url: " + tmpep + "");
msgbox("Failed to connect to Custom Kobold Endpoint!\n\nPlease check if KoboldAI is running at the url: " + desiredkoboldendpoint + "");
selected_models = [];
selected_workers = [];
custom_kobold_endpoint = "";
@ -7855,6 +7936,10 @@ Current version: 123
if (x && x.type === "password") {
x.type = "text";
}
x = document.getElementById("customkoboldkey");
if (x && x.type === "password") {
x.type = "text";
}
}
function blur_api_keys() {
var x = document.getElementById("apikey");
@ -7869,6 +7954,10 @@ Current version: 123
if (x && x.type === "text") {
x.type = "password";
}
x = document.getElementById("customkoboldkey");
if (x && x.type === "text") {
x.type = "password";
}
}
var current_settings_tab_basic = true;
@ -8945,9 +9034,7 @@ Current version: 123
//we can use abort functions
fetch(custom_kobold_endpoint + koboldcpp_abort_endpoint, {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
headers: get_kobold_header(),
body: JSON.stringify({
"genkey": lastcheckgenkey
}),
@ -11342,9 +11429,7 @@ Current version: 123
//get in-progress results
fetch(custom_kobold_endpoint + koboldcpp_check_endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers: get_kobold_header(),
body: JSON.stringify({
"genkey": lastcheckgenkey
}),
@ -13685,7 +13770,8 @@ Current version: 123
You can use this to connect to a KoboldAI instance running via a remote tunnel such as <span class="color_orange" style="font-weight: bold;">trycloudflare, localtunnel, ngrok</span>.<br><br>
Localhost IPs require host mode enabled. You can use the remote address displayed in the <span class="color_orange" style="font-weight: bold;">remote-play.bat</span> window or <span class="color_orange" style="font-weight: bold;">colab window</span>, note that the model must be loaded first.<br><br>
<span class="color_green" style="font-weight: bold;">Please input URL of the KoboldAI instance.</span><br><br>
<input class="form-control" id="customendpoint" placeholder="https://sample-remote-address.trycloudflare.com" value="">
<input class="form-control" id="customkoboldendpoint" placeholder="https://sample-remote-address.trycloudflare.com" value="">
<input class="form-control" type="password" id="customkoboldkey" placeholder="Kobold API Key (Optional)" value="" onfocus="focus_api_keys()" onblur="blur_api_keys()"><br>
<div class="box flex flex-push-right">
<input type="checkbox" id="remoteconsolelog">
<div class="box-label" title="Will display outputs to the remote endpoint's console logs, useful for debugging.">Show Console Logging</div>

View file

@ -609,6 +609,7 @@ friendlymodelname = "inactive"
friendlysdmodelname = "inactive"
fullsdmodelpath = "" #if empty, it's not initialized
mmprojpath = "" #if empty, it's not initialized
password = "" #if empty, no auth key required
maxctx = 2048
maxhordectx = 2048
maxhordelen = 256
@ -898,6 +899,30 @@ class ServerRequestHandler(http.server.SimpleHTTPRequestHandler):
except Exception as e:
print(e)
def secure_endpoint(self): #returns false if auth fails. caller should exit
#handle password stuff
if password and password !="":
auth_header = None
auth_ok = False
if 'Authorization' in self.headers:
auth_header = self.headers['Authorization']
elif 'authorization' in self.headers:
auth_header = self.headers['authorization']
if auth_header != None and auth_header.startswith('Bearer '):
token = auth_header[len('Bearer '):].strip()
if token==password:
auth_ok = True
if auth_ok==False:
self.send_response(401)
self.end_headers(content_type='application/json')
self.wfile.write(json.dumps({"detail": {
"error": "Unauthorized",
"msg": "Authentication key is missing or invalid.",
"type": "unauthorized",
}}).encode())
return False
return True
def noscript_webui(self):
global modelbusy
import html
@ -978,7 +1003,7 @@ Enter Prompt:<br>
self.wfile.write(finalhtml)
def do_GET(self):
global maxctx, maxhordelen, friendlymodelname, KcppVersion, totalgens, preloaded_story, exitcounter, currentusergenkey, friendlysdmodelname, fullsdmodelpath, mmprojpath
global maxctx, maxhordelen, friendlymodelname, KcppVersion, totalgens, preloaded_story, exitcounter, currentusergenkey, friendlysdmodelname, fullsdmodelpath, mmprojpath, password
self.path = self.path.rstrip('/')
response_body = None
content_type = 'application/json'
@ -1018,7 +1043,8 @@ Enter Prompt:<br>
elif self.path.endswith(('/api/extra/version')):
has_txt2img = not (friendlysdmodelname=="inactive" or fullsdmodelpath=="")
has_vision = (mmprojpath!="")
response_body = (json.dumps({"result":"KoboldCpp","version":KcppVersion,"txt2img":has_txt2img,"vision":has_vision}).encode())
has_password = (password!="")
response_body = (json.dumps({"result":"KoboldCpp","version":KcppVersion, "protected":has_password ,"txt2img":has_txt2img,"vision":has_vision}).encode())
elif self.path.endswith(('/api/extra/perf')):
lastp = handle.get_last_process_time()
@ -1031,6 +1057,8 @@ Enter Prompt:<br>
response_body = (json.dumps({"last_process":lastp,"last_eval":laste,"last_token_count":lastc, "last_seed":lastseed, "total_gens":totalgens, "stop_reason":stopreason, "queue":requestsinqueue, "idle":(0 if modelbusy.locked() else 1), "hordeexitcounter":exitcounter, "uptime":uptime}).encode())
elif self.path.endswith('/api/extra/generate/check'):
if not self.secure_endpoint():
return
pendtxtStr = ""
if requestsinqueue==0 and totalgens>0 and currentusergenkey=="":
pendtxt = handle.get_pending_output()
@ -1102,6 +1130,8 @@ Enter Prompt:<br>
response_code = 200
if self.path.endswith(('/api/extra/tokencount')):
if not self.secure_endpoint():
return
try:
genparams = json.loads(body)
countprompt = genparams.get('prompt', "")
@ -1117,6 +1147,8 @@ Enter Prompt:<br>
response_body = (json.dumps({"value": -1}).encode())
elif self.path.endswith('/api/extra/abort'):
if not self.secure_endpoint():
return
multiuserkey = ""
try:
tempbody = json.loads(body)
@ -1125,7 +1157,6 @@ Enter Prompt:<br>
except Exception as e:
multiuserkey = ""
pass
if (multiuserkey=="" and requestsinqueue==0) or (multiuserkey!="" and multiuserkey==currentusergenkey):
ag = handle.abort_generate()
time.sleep(0.1) #short delay before replying
@ -1138,6 +1169,8 @@ Enter Prompt:<br>
response_body = (json.dumps({"success": "false", "done":"false"}).encode())
elif self.path.endswith('/api/extra/generate/check'):
if not self.secure_endpoint():
return
pendtxtStr = ""
multiuserkey = ""
try:
@ -1216,6 +1249,11 @@ Enter Prompt:<br>
is_txt2img = True
if is_txt2img or api_format > 0:
if not is_txt2img and api_format<5:
if not self.secure_endpoint():
return
genparams = None
try:
genparams = json.loads(body)
@ -1410,7 +1448,7 @@ def show_new_gui():
tabs = ctk.CTkFrame(root, corner_radius = 0, width=windowwidth, height=windowheight-50)
tabs.grid(row=0, stick="nsew")
tabnames= ["Quick Launch", "Hardware", "Tokens", "Model", "Network","Image Gen"]
tabnames= ["Quick Launch", "Hardware", "Tokens", "Model Files", "Network", "Horde Worker","Image Gen"]
navbuttons = {}
navbuttonframe = ctk.CTkFrame(tabs, width=100, height=int(tabs.cget("height")))
navbuttonframe.grid(row=0, column=0, padx=2,pady=2)
@ -1501,6 +1539,7 @@ def show_new_gui():
usehorde_var = ctk.IntVar()
ssl_cert_var = ctk.StringVar()
ssl_key_var = ctk.StringVar()
password_var = ctk.StringVar()
sd_model_var = ctk.StringVar()
sd_quick_var = ctk.IntVar(value=0)
@ -1934,7 +1973,7 @@ def show_new_gui():
togglerope(1,1,1)
# Model Tab
model_tab = tabcontent["Model"]
model_tab = tabcontent["Model Files"]
makefileentry(model_tab, "Model:", "Select GGML Model File", model_var, 1, onchoosefile=on_picked_model_file,tooltiptxt="Select a GGUF or GGML model file on disk to be loaded.")
makefileentry(model_tab, "Lora:", "Select Lora File",lora_var, 3,tooltiptxt="Select an optional GGML LoRA adapter to use.\nLeave blank to skip.")
@ -1956,15 +1995,17 @@ def show_new_gui():
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.")
makelabelentry(network_tab, "Password: ", password_var, 8, 150,tooltip="Enter a password required to use this instance.\nThis key will be required for all text endpoints.\nImage endpoints are not secured.")
# horde
makelabel(network_tab, "Horde:", 18,0,"Settings for embedded AI Horde worker").grid(pady=10)
# Horde Tab
horde_tab = tabcontent["Horde Worker"]
makelabel(horde_tab, "Horde:", 18,0,"Settings for embedded AI Horde worker").grid(pady=10)
horde_name_entry, horde_name_label = makelabelentry(network_tab, "Horde Model Name:", horde_name_var, 20, 180,"The model name to be displayed on the AI Horde.")
horde_gen_entry, horde_gen_label = makelabelentry(network_tab, "Gen. Length:", horde_gen_var, 21, 50,"The maximum amount to generate per request \nthat this worker will accept jobs for.")
horde_context_entry, horde_context_label = makelabelentry(network_tab, "Max Context:",horde_context_var, 22, 50,"The maximum context length \nthat this worker will accept jobs for.")
horde_apikey_entry, horde_apikey_label = makelabelentry(network_tab, "API Key (If Embedded Worker):",horde_apikey_var, 23, 180,"Your AI Horde API Key that you have registered.")
horde_workername_entry, horde_workername_label = makelabelentry(network_tab, "Horde Worker Name:",horde_workername_var, 24, 180,"Your worker's name to be displayed.")
horde_name_entry, horde_name_label = makelabelentry(horde_tab, "Horde Model Name:", horde_name_var, 20, 180,"The model name to be displayed on the AI Horde.")
horde_gen_entry, horde_gen_label = makelabelentry(horde_tab, "Gen. Length:", horde_gen_var, 21, 50,"The maximum amount to generate per request \nthat this worker will accept jobs for.")
horde_context_entry, horde_context_label = makelabelentry(horde_tab, "Max Context:",horde_context_var, 22, 50,"The maximum context length \nthat this worker will accept jobs for.")
horde_apikey_entry, horde_apikey_label = makelabelentry(horde_tab, "API Key (If Embedded Worker):",horde_apikey_var, 23, 180,"Your AI Horde API Key that you have registered.")
horde_workername_entry, horde_workername_label = makelabelentry(horde_tab, "Horde Worker Name:",horde_workername_var, 24, 180,"Your worker's name to be displayed.")
def togglehorde(a,b,c):
labels = [horde_name_label, horde_gen_label, horde_context_label, horde_apikey_label, horde_workername_label]
@ -1979,7 +2020,7 @@ def show_new_gui():
basefile = os.path.basename(model_var.get())
horde_name_var.set(sanitize_string(os.path.splitext(basefile)[0]))
makecheckbox(network_tab, "Configure for Horde", usehorde_var, 19, command=togglehorde,tooltiptxt="Enable the embedded AI Horde worker.")
makecheckbox(horde_tab, "Configure for Horde", usehorde_var, 19, command=togglehorde,tooltiptxt="Enable the embedded AI Horde worker.")
togglehorde(1,1,1)
# Image Gen Tab
@ -2067,6 +2108,7 @@ def show_new_gui():
args.mmproj = None if mmproj_var.get() == "" else mmproj_var.get()
args.ssl = None if (ssl_cert_var.get() == "" or ssl_key_var.get() == "") else ([ssl_cert_var.get(), ssl_key_var.get()])
args.password = None if (password_var.get() == "") else (password_var.get())
args.port_param = defaultport if port_var.get()=="" else int(port_var.get())
args.host = host_var.get()
@ -2188,6 +2230,9 @@ def show_new_gui():
ssl_cert_var.set(dict["ssl"][0])
ssl_key_var.set(dict["ssl"][1])
if "password" in dict and dict["password"]:
password_var.set(dict["password"])
if "preloadstory" in dict and dict["preloadstory"]:
preloadstory_var.set(dict["preloadstory"])
@ -2634,7 +2679,7 @@ def sanitize_string(input_string):
return sanitized_string
def main(launch_args,start_server=True):
global args, friendlymodelname, friendlysdmodelname, fullsdmodelpath, mmprojpath
global args, friendlymodelname, friendlysdmodelname, fullsdmodelpath, mmprojpath, password
args = launch_args
embedded_kailite = None
embedded_kcpp_docs = None
@ -2769,6 +2814,9 @@ def main(launch_args,start_server=True):
args.mmproj = os.path.abspath(args.mmproj)
mmprojpath = args.mmproj
if args.password and args.password!="":
password = args.password.strip()
if not args.blasthreads or args.blasthreads <= 0:
args.blasthreads = args.threads
@ -3017,5 +3065,6 @@ if __name__ == '__main__':
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')
parser.add_argument("--sdconfig", help="Specify a stable diffusion safetensors model to enable image generation. If quick is specified, force optimal generation settings for speed.",metavar=('[sd_filename]', '[normal|quick|clamped] [threads] [quant|noquant]'), nargs='+')
parser.add_argument("--mmproj", help="Select a multimodal projector file for LLaVA.", default="")
parser.add_argument("--password", help="Enter a password required to use this instance. This key will be required for all text endpoints. Image endpoints are not secured.", default=None)
main(parser.parse_args(),start_server=True)