@@ -662,7 +662,6 @@ def show_new_gui():
662
662
return
663
663
664
664
import customtkinter as ctk
665
-
666
665
nextstate = 0 #0=exit, 1=launch, 2=oldgui
667
666
windowwidth = 520
668
667
windowheight = 500
@@ -685,13 +684,22 @@ def show_new_gui():
685
684
tabcontentframe .grid_propagate (False )
686
685
687
686
tabcontent = {}
688
-
687
+ lib_option_pairs = [
688
+ (lib_openblas , "Use OpenBLAS" ),
689
+ (lib_clblast , "Use CLBlast" ),
690
+ (lib_cublas , "Use CuBLAS" ),
691
+ (lib_default , "Use No BLAS" ),
692
+ (lib_noavx2 , "Use NoAVX2 Mode (Old CPU)" ),
693
+ (lib_failsafe , "Failsafe Mode (Old CPU)" )]
694
+ openblas_option , clblast_option , cublas_option , default_option , openblas_noavx2_option , failsafe_option = (opt if file_exists (lib ) or (os .name == 'nt' and file_exists (opt + ".dll" )) else None for lib , opt in lib_option_pairs )
689
695
# slider data
690
696
blasbatchsize_values = ["-1" , "32" , "64" , "128" , "256" , "512" , "1024" ]
691
697
blasbatchsize_text = ["Don't Batch BLAS" ,"32" ,"64" ,"128" ,"256" ,"512" ,"1024" ]
692
698
contextsize_text = ["512" , "1024" , "2048" , "3072" , "4096" , "6144" , "8192" ]
693
- runopts = ["Use OpenBLAS" ,"Use CLBlast" , "Use CuBLAS" , "Use No BLAS" ,"Use OpenBLAS (Old CPU, noavx2)" ,"Failsafe Mode (Old CPU, noavx)" ]
694
-
699
+ runopts = [opt for lib , opt in lib_option_pairs if file_exists (lib ) or os .name == 'nt' and file_exists (opt + ".dll" )]
700
+ antirunopts = [opt .replace ("Use " , "" ) for lib , opt in lib_option_pairs if not file_exists (lib ) or os .name == 'nt' and not file_exists (opt + ".dll" )]
701
+ if not any (runopts ):
702
+ show_gui_warning ("No Backend Available" )
695
703
def tabbuttonaction (name ):
696
704
for t in tabcontent :
697
705
if name == t :
@@ -757,6 +765,32 @@ def getfilename(var, text):
757
765
button .grid (row = row + 1 , column = 1 , stick = "nw" )
758
766
return
759
767
768
+ def show_tooltip (event , tooltip_text = None ):
769
+ if hasattr (show_tooltip , "_tooltip" ):
770
+ tooltip = show_tooltip ._tooltip
771
+ else :
772
+ tooltip = ctk .CTkToplevel (root )
773
+ tooltip .configure (fg_color = "#ffffe0" )
774
+ tooltip .withdraw ()
775
+ tooltip .overrideredirect (True )
776
+ tooltip_label = ctk .CTkLabel (tooltip , text = tooltip_text , text_color = "#000000" , fg_color = "#ffffe0" )
777
+ tooltip_label .pack (expand = True , padx = 2 , pady = 1 )
778
+ show_tooltip ._tooltip = tooltip
779
+ x , y = root .winfo_pointerxy ()
780
+ tooltip .wm_geometry (f"+{ x + 10 } +{ y + 10 } " )
781
+ tooltip .deiconify ()
782
+ def hide_tooltip (event ):
783
+ if hasattr (show_tooltip , "_tooltip" ):
784
+ tooltip = show_tooltip ._tooltip
785
+ tooltip .withdraw ()
786
+ def setup_backend_tooltip (parent ):
787
+ num_backends_built = makelabel (parent , str (len (runopts )) + "/6" , 5 , 2 )
788
+ num_backends_built .grid (row = 1 , column = 2 , padx = 0 , pady = 0 )
789
+ num_backends_built .configure (text_color = "#00ff00" )
790
+ # Bind the backend count label with the tooltip function
791
+ num_backends_built .bind ("<Enter>" , lambda event : show_tooltip (event , f"This is the number of backends you have built and available." + (f"\n Missing: { ', ' .join (antirunopts )} " if len (runopts ) != 6 else "" )))
792
+ num_backends_built .bind ("<Leave>" , hide_tooltip )
793
+
760
794
# Vars - should be in scope to be used by multiple widgets
761
795
gpulayers_var = ctk .StringVar (value = "0" )
762
796
threads_var = ctk .StringVar (value = str (default_threads ))
@@ -857,7 +891,10 @@ def changerunmode(a,b,c):
857
891
858
892
runoptbox = ctk .CTkComboBox (quick_tab , values = runopts , width = 180 ,variable = runopts_var , state = "readonly" )
859
893
runoptbox .grid (row = 1 , column = 1 ,padx = 8 , stick = "nw" )
860
- runoptbox .set ("Use OpenBLAS" )
894
+ runoptbox .set (runopts [0 ]) # Set to first available option
895
+
896
+ # Tell user how many backends are available
897
+ setup_backend_tooltip (quick_tab )
861
898
862
899
# threads
863
900
makelabelentry (quick_tab , "Threads:" , threads_var , 8 , 50 )
@@ -869,7 +906,6 @@ def changerunmode(a,b,c):
869
906
quick_boxes = {"Launch Browser" : launchbrowser , "High Priority" : highpriority , "Streaming Mode" :stream , "Use SmartContext" :smartcontext , "Unban Tokens" :unbantokens , "Disable MMAP" :disablemmap ,}
870
907
for idx , name , in enumerate (quick_boxes ):
871
908
makecheckbox (quick_tab , name , quick_boxes [name ], int (idx / 2 ) + 20 , idx % 2 )
872
-
873
909
# context size
874
910
makeslider (quick_tab , "Context Size:" , contextsize_text , context_var , 0 , len (contextsize_text )- 1 , 30 , set = 2 )
875
911
@@ -890,9 +926,13 @@ def changerunmode(a,b,c):
890
926
makelabel (hardware_tab , "Presets:" , 1 )
891
927
runoptbox = ctk .CTkComboBox (hardware_tab , values = runopts , width = 180 ,variable = runopts_var , state = "readonly" )
892
928
runoptbox .grid (row = 1 , column = 1 ,padx = 8 , stick = "nw" )
893
- runoptbox .set ("Use OpenBLAS" )
929
+ runoptbox .set (runopts [ 0 ]) # Set to first available option
894
930
runopts_var .trace ('w' , changerunmode )
895
931
changerunmode (1 ,1 ,1 )
932
+
933
+ # Tell user how many backends are available
934
+ setup_backend_tooltip (hardware_tab )
935
+
896
936
# threads
897
937
makelabelentry (hardware_tab , "Threads:" , threads_var , 8 , 50 )
898
938
@@ -1018,20 +1058,20 @@ def export_vars():
1018
1058
gpuchoiceidx = 0
1019
1059
if gpu_choice_var .get ()!= "All" :
1020
1060
gpuchoiceidx = int (gpu_choice_var .get ())- 1
1021
- if runopts_var .get () == runopts [ 1 ] :
1061
+ if runopts_var .get () == "Use CLBlast" :
1022
1062
args .useclblast = [[0 ,0 ], [1 ,0 ], [0 ,1 ]][gpuchoiceidx ]
1023
- if runopts_var .get () == runopts [ 2 ] :
1063
+ if runopts_var .get () == "Use CuBLAS" :
1024
1064
if gpu_choice_var .get ()== "All" :
1025
1065
args .usecublas = ["lowvram" ] if lowvram_var .get () == 1 else ["normal" ]
1026
1066
else :
1027
1067
args .usecublas = ["lowvram" ,str (gpuchoiceidx )] if lowvram_var .get () == 1 else ["normal" ,str (gpuchoiceidx )]
1028
1068
if gpulayers_var .get ():
1029
1069
args .gpulayers = int (gpulayers_var .get ())
1030
- if runopts_var .get ()== runopts [ 3 ] :
1070
+ if runopts_var .get ()== "Use No BLAS" :
1031
1071
args .noblas = True
1032
- if runopts_var .get ()== runopts [ 4 ] :
1072
+ if runopts_var .get ()== "Use NoAVX2 Mode (Old CPU)" :
1033
1073
args .noavx2 = True
1034
- if runopts_var .get ()== runopts [ 5 ] :
1074
+ if runopts_var .get ()== "Failsafe Mode (Old CPU)" :
1035
1075
args .noavx2 = True
1036
1076
args .noblas = True
1037
1077
args .nommap = True
@@ -1070,38 +1110,42 @@ def import_vars(dict):
1070
1110
stream .set (1 if "stream" in dict and dict ["stream" ] else 0 )
1071
1111
smartcontext .set (1 if "smartcontext" in dict and dict ["smartcontext" ] else 0 )
1072
1112
unbantokens .set (1 if "unbantokens" in dict and dict ["unbantokens" ] else 0 )
1073
- runopts_var .set (runopts [0 ])
1074
1113
if "useclblast" in dict and dict ["useclblast" ]:
1075
- runopts_var .set (runopts [1 ])
1076
- gpu_choice_var .set (str (["0 0" , "1 0" , "0 1" ].index (str (dict ["useclblast" ][0 ]) + " " + str (dict ["useclblast" ][1 ])) + 1 ))
1114
+ if clblast_option is not None :
1115
+ runopts_var .set (clblast_option )
1116
+ gpu_choice_var .set (str (["0 0" , "1 0" , "0 1" ].index (str (dict ["useclblast" ][0 ]) + " " + str (dict ["useclblast" ][1 ])) + 1 ))
1077
1117
elif "usecublas" in dict and dict ["usecublas" ]:
1078
- runopts_var .set (runopts [2 ])
1079
- if len (dict ["usecublas" ])== 1 :
1080
- lowvram_var .set (1 if dict ["usecublas" ][0 ]== "lowvram" else 0 )
1081
- else :
1082
- lowvram_var .set (1 if "lowvram" in dict ["usecublas" ] else 0 )
1083
- gpu_choice_var .set ("1" )
1084
- for g in range (3 ):
1085
- if str (g ) in dict ["usecublas" ]:
1086
- gpu_choice_var .set (str (g + 1 ))
1087
- break
1118
+ if cublas_option is not None :
1119
+ runopts_var .set (cublas_option )
1120
+ if len (dict ["usecublas" ])== 1 :
1121
+ lowvram_var .set (1 if dict ["usecublas" ][0 ]== "lowvram" else 0 )
1122
+ else :
1123
+ lowvram_var .set (1 if "lowvram" in dict ["usecublas" ] else 0 )
1124
+ gpu_choice_var .set ("1" )
1125
+ for g in range (3 ):
1126
+ if str (g ) in dict ["usecublas" ]:
1127
+ gpu_choice_var .set (str (g + 1 ))
1128
+ break
1088
1129
if "gpulayers" in dict and dict ["gpulayers" ]:
1089
1130
gpulayers_var .set (dict ["gpulayers" ])
1090
1131
1091
1132
if "noavx2" in dict and "noblas" in dict and dict ["noblas" ] and dict ["noavx2" ]:
1092
- runopts_var .set (runopts [5 ])
1133
+ if failsafe_option is not None :
1134
+ runopts_var .set (failsafe_option )
1093
1135
elif "noavx2" in dict and dict ["noavx2" ]:
1094
- runopts_var .set (runopts [4 ])
1136
+ if openblas_noavx2_option is not None :
1137
+ runopts_var .set (openblas_noavx2_option )
1095
1138
elif "noblas" in dict and dict ["noblas" ]:
1096
- runopts_var .set (runopts [3 ])
1139
+ if default_option is not None :
1140
+ runopts_var .set (default_option )
1141
+ elif openblas_option is not None :
1142
+ runopts_var .set (openblas_option )
1097
1143
if "blasthreads" in dict and dict ["blasthreads" ]:
1098
1144
blas_threads_var .set (str (dict ["blasthreads" ]))
1099
1145
else :
1100
1146
blas_threads_var .set ("" )
1101
-
1102
1147
if "contextsize" in dict and dict ["contextsize" ]:
1103
1148
context_var .set (contextsize_text .index (str (dict ["contextsize" ])))
1104
-
1105
1149
if "ropeconfig" in dict and dict ["ropeconfig" ] and len (dict ["ropeconfig" ])> 1 :
1106
1150
if dict ["ropeconfig" ][0 ]> 0 :
1107
1151
customrope_var .set (1 )
@@ -1199,13 +1243,20 @@ def display_help():
1199
1243
time .sleep (2 )
1200
1244
sys .exit (2 )
1201
1245
1202
- def show_gui_warning ():
1246
+ def show_gui_warning (issue = None ):
1203
1247
from tkinter import messagebox
1204
1248
import tkinter as tk
1205
1249
root = tk .Tk ()
1206
1250
root .attributes ("-alpha" , 0 )
1207
- messagebox .showerror (title = "New GUI failed, using Old GUI" , message = "The new GUI failed to load.\n \n To use new GUI, please install the customtkinter python module." )
1208
- root .destroy ()
1251
+ if issue == "No Backend Available" :
1252
+ messagebox .showerror (title = "No Backends Available!" , message = "KoboldCPP couldn't locate any backends to use.\n \n To use the program, please run the 'make' command from the directory." )
1253
+ root .destroy ()
1254
+ print ("No Backend Available (i.e Default, OpenBLAS, CLBlast, CuBLAS). To use the program, please run the 'make' command from the directory." )
1255
+ time .sleep (2 )
1256
+ sys .exit (2 )
1257
+ else :
1258
+ messagebox .showerror (title = "New GUI failed, using Old GUI" , message = "The new GUI failed to load.\n \n To use new GUI, please install the customtkinter python module." )
1259
+ root .destroy ()
1209
1260
1210
1261
def show_old_gui ():
1211
1262
import tkinter as tk
@@ -1236,7 +1287,7 @@ def guilaunch():
1236
1287
blaschoice = tk .StringVar ()
1237
1288
blaschoice .set ("BLAS = 512" )
1238
1289
1239
- runopts = ["Use OpenBLAS" ,"Use CLBLast GPU #1" ,"Use CLBLast GPU #2" ,"Use CLBLast GPU #3" ,"Use CuBLAS GPU" ,"Use No BLAS" ,"Use OpenBLAS (Old CPU, noavx2 )" ,"Failsafe Mode (Old CPU, noavx )" ]
1290
+ runopts = ["Use OpenBLAS" ,"Use CLBLast GPU #1" ,"Use CLBLast GPU #2" ,"Use CLBLast GPU #3" ,"Use CuBLAS GPU" ,"Use No BLAS" ,"Use NoAVX2 Mode (Old CPU)" ,"Failsafe Mode (Old CPU)" ]
1240
1291
runchoice = tk .StringVar ()
1241
1292
runchoice .set ("Use OpenBLAS" )
1242
1293
0 commit comments