mirror of
https://github.com/LostRuins/koboldcpp.git
synced 2025-09-10 17:14:36 +00:00
Zentk integration (Zenity/yad support) (#1475)
* Zentk integration (Zenity/yad support) * Escape incompatible dependencies in zentk * Properly clean env
This commit is contained in:
parent
e2fefc373f
commit
8fd70f37bd
1 changed files with 118 additions and 15 deletions
133
koboldcpp.py
133
koboldcpp.py
|
@ -29,6 +29,7 @@ import html
|
||||||
import urllib.parse as urlparse
|
import urllib.parse as urlparse
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
sampler_order_max = 7
|
sampler_order_max = 7
|
||||||
|
@ -615,9 +616,8 @@ def unpack_to_dir(destpath = ""):
|
||||||
print("Attempt to unpack KoboldCpp into directory...")
|
print("Attempt to unpack KoboldCpp into directory...")
|
||||||
|
|
||||||
if not cliunpack:
|
if not cliunpack:
|
||||||
from tkinter.filedialog import askdirectory
|
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
destpath = askdirectory(title='Select an empty folder to unpack KoboldCpp')
|
destpath = zentk_askdirectory(title='Select an empty folder to unpack KoboldCpp')
|
||||||
if not destpath:
|
if not destpath:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -3455,19 +3455,123 @@ def RunServerMultiThreaded(addr, port, server_handler):
|
||||||
threadArr[i].stop()
|
threadArr[i].stop()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
# Based on https://github.com/mathgeniuszach/xdialog/blob/main/xdialog/zenity_dialogs.py - MIT license | - Expanded version by Henk717
|
||||||
|
|
||||||
|
def zenity_clean(txt: str):
|
||||||
|
return txt\
|
||||||
|
.replace("\\", "\\\\")\
|
||||||
|
.replace("$", "\\$")\
|
||||||
|
.replace("!", "\\!")\
|
||||||
|
.replace("*", "\\*")\
|
||||||
|
.replace("?", "\\?")\
|
||||||
|
.replace("&", "&")\
|
||||||
|
.replace("|", "|")\
|
||||||
|
.replace("<", "<")\
|
||||||
|
.replace(">", ">")\
|
||||||
|
.replace("(", "\\(")\
|
||||||
|
.replace(")", "\\)")\
|
||||||
|
.replace("[", "\\[")\
|
||||||
|
.replace("]", "\\]")\
|
||||||
|
.replace("{", "\\{")\
|
||||||
|
.replace("}", "\\}")\
|
||||||
|
|
||||||
|
def zenity(typ, filetypes=None, initialdir="", initialfile="", **kwargs) -> Tuple[int, str]:
|
||||||
|
import shutil, subprocess, os, platform
|
||||||
|
if not platform.system() == "Linux":
|
||||||
|
raise Exception("This feature should only be used on Linux, if you see this error there is no TK fallback implemented in the code.")
|
||||||
|
zenity_bin = shutil.which("zenity")
|
||||||
|
if not zenity_bin:
|
||||||
|
zenity_bin = shutil.which("yad")
|
||||||
|
if not zenity_bin:
|
||||||
|
raise Exception("Zenity not present")
|
||||||
|
|
||||||
|
# Build args based on keywords
|
||||||
|
args = ['/usr/bin/env', zenity_bin, '--'+typ]
|
||||||
|
for k, v in kwargs.items():
|
||||||
|
if v is True:
|
||||||
|
args.append(f'--{k.replace("_", "-").strip("-")}')
|
||||||
|
elif isinstance(v, str):
|
||||||
|
cv = zenity_clean(v) if k != "title" else v
|
||||||
|
args.append(f'--{k.replace("_", "-").strip("-")}={cv}')
|
||||||
|
|
||||||
|
# Build filetypes specially if specified
|
||||||
|
if filetypes:
|
||||||
|
for name, globs in filetypes:
|
||||||
|
if name:
|
||||||
|
globlist = globs.split()
|
||||||
|
args.append(f'--file-filter={name.replace("|", "")} ({", ".join(t for t in globlist)})|{globs}')
|
||||||
|
|
||||||
|
# Default filename and folder
|
||||||
|
if initialdir is None:
|
||||||
|
initialdir=os.getcwd()
|
||||||
|
if initialfile is None:
|
||||||
|
initialfile=""
|
||||||
|
initialpath = os.path.join(initialdir, initialfile)
|
||||||
|
args.append(f'--filename={initialpath}')
|
||||||
|
|
||||||
|
clean_env = os.environ.copy()
|
||||||
|
clean_env.pop("LD_LIBRARY_PATH", None)
|
||||||
|
clean_env["PATH"] = "/usr/bin:/bin"
|
||||||
|
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
shell=False,
|
||||||
|
env=clean_env
|
||||||
|
)
|
||||||
|
stdout, _ = proc.communicate()
|
||||||
|
|
||||||
|
return (proc.returncode, stdout.decode('utf-8').strip())
|
||||||
|
|
||||||
|
# note: In this section we wrap around file dialogues to allow for zenity
|
||||||
|
|
||||||
|
def zentk_askopenfilename(**options):
|
||||||
|
try:
|
||||||
|
result = zenity('file-selection', filetypes=options.get("filetypes"), initialdir=options.get("initialdir"), title=options.get("title"))[1]
|
||||||
|
except:
|
||||||
|
from tkinter.filedialog import askopenfilename
|
||||||
|
result = askopenfilename(**options)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def zentk_askopenmultiplefilenames(**options):
|
||||||
|
try:
|
||||||
|
from os.path import isfile
|
||||||
|
files = zenity('file-selection', filetypes=options.get("filetypes"), initialdir=options.get("initialdir"), title=options.get("title"), multiple=True, separator="\n")[1].splitlines()
|
||||||
|
result = tuple(filter(isfile, files))
|
||||||
|
except:
|
||||||
|
from tkinter.filedialog import askopenfilenames
|
||||||
|
result = askopenfilenames(**options)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def zentk_askdirectory(**options):
|
||||||
|
try:
|
||||||
|
result = zenity('file-selection', initialdir=options.get("initialdir"), title=options.get("title"), directory=True)[1]
|
||||||
|
except:
|
||||||
|
from tkinter.filedialog import askdirectory
|
||||||
|
result = askdirectory(**options)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def zentk_asksaveasfilename(**options):
|
||||||
|
try:
|
||||||
|
result = zenity('file-selection', filetypes=options.get("filetypes"), initialdir=options.get("initialdir"), initialfile=options.get("initialfile"), title=options.get("title"), save=True)[1]
|
||||||
|
except:
|
||||||
|
from tkinter.filedialog import asksaveasfilename
|
||||||
|
result = asksaveasfilename(**options)
|
||||||
|
return result
|
||||||
|
### End of MIT license
|
||||||
|
|
||||||
# note: customtkinter-5.2.0
|
# note: customtkinter-5.2.0
|
||||||
def show_gui():
|
def show_gui():
|
||||||
global using_gui_launcher
|
global using_gui_launcher
|
||||||
using_gui_launcher = True
|
using_gui_launcher = True
|
||||||
from tkinter.filedialog import askopenfilename, askdirectory
|
|
||||||
from tkinter.filedialog import asksaveasfilename
|
|
||||||
|
|
||||||
# if args received, launch
|
# if args received, launch
|
||||||
if len(sys.argv) != 1 and not args.showgui:
|
if len(sys.argv) != 1 and not args.showgui:
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
root = tk.Tk() #we dont want the useless window to be visible, but we want it in taskbar
|
root = tk.Tk() #we dont want the useless window to be visible, but we want it in taskbar
|
||||||
root.attributes("-alpha", 0)
|
root.attributes("-alpha", 0)
|
||||||
args.model_param = askopenfilename(title="Select ggml model .bin or .gguf file or .kcpps config")
|
args.model_param = zentk_askopenfilename(title="Select ggml model .bin or .gguf file or .kcpps config")
|
||||||
root.withdraw()
|
root.withdraw()
|
||||||
root.quit()
|
root.quit()
|
||||||
if args.model_param and args.model_param!="" and (args.model_param.lower().endswith('.kcpps') or args.model_param.lower().endswith('.kcppt') or args.model_param.lower().endswith('.kcpps?download=true') or args.model_param.lower().endswith('.kcppt?download=true')):
|
if args.model_param and args.model_param!="" and (args.model_param.lower().endswith('.kcpps') or args.model_param.lower().endswith('.kcppt') or args.model_param.lower().endswith('.kcpps?download=true') or args.model_param.lower().endswith('.kcppt?download=true')):
|
||||||
|
@ -3770,16 +3874,16 @@ def show_gui():
|
||||||
initialDir = initialDir if os.path.isdir(initialDir) else None
|
initialDir = initialDir if os.path.isdir(initialDir) else None
|
||||||
fnam = None
|
fnam = None
|
||||||
if dialog_type==2:
|
if dialog_type==2:
|
||||||
fnam = askdirectory(title=text, mustexist=True, initialdir=initialDir)
|
fnam = zentk_askdirectory(title=text, mustexist=True, initialdir=initialDir)
|
||||||
elif dialog_type==1:
|
elif dialog_type==1:
|
||||||
fnam = asksaveasfilename(title=text, filetypes=filetypes, defaultextension=filetypes, initialdir=initialDir)
|
fnam = zentk_asksaveasfilename(title=text, filetypes=filetypes, defaultextension=filetypes, initialdir=initialDir)
|
||||||
if not fnam:
|
if not fnam:
|
||||||
fnam = ""
|
fnam = ""
|
||||||
else:
|
else:
|
||||||
fnam = str(fnam).strip()
|
fnam = str(fnam).strip()
|
||||||
fnam = f"{fnam}.jsondb" if ".jsondb" not in fnam.lower() else fnam
|
fnam = f"{fnam}.jsondb" if ".jsondb" not in fnam.lower() else fnam
|
||||||
else:
|
else:
|
||||||
fnam = askopenfilename(title=text,filetypes=filetypes, initialdir=initialDir)
|
fnam = zentk_askopenfilename(title=text,filetypes=filetypes, initialdir=initialDir)
|
||||||
if fnam:
|
if fnam:
|
||||||
var.set(fnam)
|
var.set(fnam)
|
||||||
if onchoosefile:
|
if onchoosefile:
|
||||||
|
@ -4181,7 +4285,7 @@ def show_gui():
|
||||||
def pickpremadetemplate():
|
def pickpremadetemplate():
|
||||||
initialDir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'kcpp_adapters')
|
initialDir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'kcpp_adapters')
|
||||||
initialDir = initialDir if os.path.isdir(initialDir) else None
|
initialDir = initialDir if os.path.isdir(initialDir) else None
|
||||||
fnam = askopenfilename(title="Pick Premade ChatCompletions Adapter",filetypes=[("JSON Adapter", "*.json")], initialdir=initialDir)
|
fnam = zentk_askopenfilename(title="Pick Premade ChatCompletions Adapter",filetypes=[("JSON Adapter", "*.json")], initialdir=initialDir)
|
||||||
if fnam:
|
if fnam:
|
||||||
chatcompletionsadapter_var.set(fnam)
|
chatcompletionsadapter_var.set(fnam)
|
||||||
ctk.CTkButton(model_tab, 64, text="Pick Premade", command=pickpremadetemplate).grid(row=25, column=0, padx=322, stick="nw")
|
ctk.CTkButton(model_tab, 64, text="Pick Premade", command=pickpremadetemplate).grid(row=25, column=0, padx=322, stick="nw")
|
||||||
|
@ -4311,7 +4415,7 @@ def show_gui():
|
||||||
file_type = [("KoboldCpp LaunchTemplate", "*.kcppt")]
|
file_type = [("KoboldCpp LaunchTemplate", "*.kcppt")]
|
||||||
#remove blacklisted fields
|
#remove blacklisted fields
|
||||||
savdict = convert_args_to_template(savdict)
|
savdict = convert_args_to_template(savdict)
|
||||||
filename = asksaveasfilename(filetypes=file_type, defaultextension=".kcppt")
|
filename = zentk_asksaveasfilename(filetypes=file_type, defaultextension=".kcppt")
|
||||||
if not filename:
|
if not filename:
|
||||||
return
|
return
|
||||||
filenamestr = str(filename).strip()
|
filenamestr = str(filename).strip()
|
||||||
|
@ -4335,7 +4439,7 @@ def show_gui():
|
||||||
# launch
|
# launch
|
||||||
def guilaunch():
|
def guilaunch():
|
||||||
if model_var.get() == "" and sd_model_var.get() == "" and whisper_model_var.get() == "" and tts_model_var.get() == "" and embeddings_model_var.get() == "" and nomodel.get()!=1:
|
if model_var.get() == "" and sd_model_var.get() == "" and whisper_model_var.get() == "" and tts_model_var.get() == "" and embeddings_model_var.get() == "" and nomodel.get()!=1:
|
||||||
tmp = askopenfilename(title="Select ggml model .bin or .gguf file")
|
tmp = zentk_askopenfilename(title="Select ggml model .bin or .gguf file")
|
||||||
model_var.set(tmp)
|
model_var.set(tmp)
|
||||||
nonlocal nextstate
|
nonlocal nextstate
|
||||||
nextstate = 1
|
nextstate = 1
|
||||||
|
@ -4713,7 +4817,7 @@ def show_gui():
|
||||||
export_vars()
|
export_vars()
|
||||||
savdict = json.loads(json.dumps(args.__dict__))
|
savdict = json.loads(json.dumps(args.__dict__))
|
||||||
file_type = [("KoboldCpp Settings", "*.kcpps")]
|
file_type = [("KoboldCpp Settings", "*.kcpps")]
|
||||||
filename = asksaveasfilename(filetypes=file_type, defaultextension=".kcpps")
|
filename = zentk_asksaveasfilename(filetypes=file_type, defaultextension=".kcpps")
|
||||||
if not filename:
|
if not filename:
|
||||||
return
|
return
|
||||||
filenamestr = str(filename).strip()
|
filenamestr = str(filename).strip()
|
||||||
|
@ -4727,7 +4831,7 @@ def show_gui():
|
||||||
def load_config_gui(): #this is used to populate the GUI with a config file, whereas load_config_cli simply overwrites cli args
|
def load_config_gui(): #this is used to populate the GUI with a config file, whereas load_config_cli simply overwrites cli args
|
||||||
file_type = [("KoboldCpp Settings", "*.kcpps *.kcppt")]
|
file_type = [("KoboldCpp Settings", "*.kcpps *.kcppt")]
|
||||||
global runmode_untouched
|
global runmode_untouched
|
||||||
filename = askopenfilename(filetypes=file_type, defaultextension=".kcppt", initialdir=None)
|
filename = zentk_askopenfilename(filetypes=file_type, defaultextension=".kcppt", initialdir=None)
|
||||||
if not filename or filename=="":
|
if not filename or filename=="":
|
||||||
return
|
return
|
||||||
runmode_untouched = False
|
runmode_untouched = False
|
||||||
|
@ -5371,8 +5475,7 @@ def analyze_gguf_model(args,filename):
|
||||||
def analyze_gguf_model_wrapper(filename=""):
|
def analyze_gguf_model_wrapper(filename=""):
|
||||||
if not filename or filename=="":
|
if not filename or filename=="":
|
||||||
try:
|
try:
|
||||||
from tkinter.filedialog import askopenfilename
|
filename = zentk_askopenfilename(title="Select GGUF to analyze")
|
||||||
filename = askopenfilename(title="Select GGUF to analyze")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Cannot select file to analyze: {e}")
|
print(f"Cannot select file to analyze: {e}")
|
||||||
if not filename or filename=="" or not os.path.exists(filename):
|
if not filename or filename=="" or not os.path.exists(filename):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue