@@ -1156,6 +1156,14 @@ def create_label(self, text, tooltip):
1156
1156
label .setToolTip (tooltip )
1157
1157
return label
1158
1158
1159
+ def verify_gguf (self , file_path ):
1160
+ try :
1161
+ with open (file_path , "rb" ) as f :
1162
+ magic = f .read (4 )
1163
+ return magic == b"GGUF"
1164
+ except Exception :
1165
+ return False
1166
+
1159
1167
def load_models (self ):
1160
1168
self .logger .info (LOADING_MODELS )
1161
1169
models_dir = self .models_input .text ()
@@ -1164,58 +1172,88 @@ def load_models(self):
1164
1172
1165
1173
sharded_models = {}
1166
1174
single_models = []
1175
+ concatenated_models = []
1167
1176
1168
- # Regex pattern to match sharded model filenames
1169
1177
shard_pattern = re .compile (r"(.*)-(\d+)-of-(\d+)\.gguf$" )
1178
+ concat_pattern = re .compile (r"(.*)\.gguf\.part(\d+)of(\d+)$" )
1170
1179
1171
- # Load models from the models directory
1172
1180
for file in os .listdir (models_dir ):
1181
+ full_path = os .path .join (models_dir , file )
1173
1182
if file .endswith (".gguf" ):
1183
+ if not self .verify_gguf (full_path ):
1184
+ show_error (self .logger , INVALID_GGUF_FILE .format (file ))
1185
+ continue
1186
+
1174
1187
match = shard_pattern .match (file )
1175
1188
if match :
1176
- # This is a sharded model
1177
1189
base_name , shard_num , total_shards = match .groups ()
1178
1190
if base_name not in sharded_models :
1179
1191
sharded_models [base_name ] = []
1180
1192
sharded_models [base_name ].append ((int (shard_num ), file ))
1181
1193
else :
1182
1194
single_models .append (file )
1195
+ else :
1196
+ match = concat_pattern .match (file )
1197
+ if match :
1198
+ concatenated_models .append (file )
1183
1199
1184
- # Add imported models
1185
1200
if hasattr (self , "imported_models" ):
1186
1201
for imported_model in self .imported_models :
1187
1202
file_name = os .path .basename (imported_model )
1188
- if file_name not in single_models :
1189
- single_models .append (file_name )
1203
+ if (
1204
+ file_name not in single_models
1205
+ and file_name not in concatenated_models
1206
+ ):
1207
+ if self .verify_gguf (imported_model ):
1208
+ single_models .append (file_name )
1209
+ else :
1210
+ show_error (
1211
+ self .logger , INVALID_GGUF_FILE .format (imported_model )
1212
+ )
1190
1213
1191
- # Add sharded models to the tree
1192
1214
for base_name , shards in sharded_models .items ():
1193
1215
parent_item = QTreeWidgetItem (self .model_tree )
1194
- parent_item .setText (0 , f" { base_name } ( { SHARDED } )" )
1216
+ parent_item .setText (0 , SHARDED_MODEL_NAME . format ( base_name ) )
1195
1217
first_shard = sorted (shards , key = lambda x : x [0 ])[0 ][1 ]
1196
1218
parent_item .setData (0 , Qt .ItemDataRole .UserRole , first_shard )
1197
1219
for _ , shard_file in sorted (shards ):
1198
1220
child_item = QTreeWidgetItem (parent_item )
1199
1221
child_item .setText (0 , shard_file )
1200
1222
child_item .setData (0 , Qt .ItemDataRole .UserRole , shard_file )
1201
1223
1202
- # Add single models to the tree
1203
1224
for model in sorted (single_models ):
1204
- item = QTreeWidgetItem (self .model_tree )
1205
- item .setText (0 , model )
1206
- if hasattr (self , "imported_models" ) and model in [
1207
- os .path .basename (m ) for m in self .imported_models
1208
- ]:
1209
- full_path = next (
1210
- m for m in self .imported_models if os .path .basename (m ) == model
1211
- )
1212
- item .setData (0 , Qt .ItemDataRole .UserRole , full_path )
1213
- item .setToolTip (0 , IMPORTED_MODEL_TOOLTIP .format (full_path ))
1214
- else :
1215
- item .setData (0 , Qt .ItemDataRole .UserRole , model )
1225
+ self .add_model_to_tree (model )
1226
+
1227
+ for model in sorted (concatenated_models ):
1228
+ item = self .add_model_to_tree (model )
1229
+ item .setForeground (0 , Qt .gray )
1230
+ item .setToolTip (0 , CONCATENATED_FILE_WARNING )
1216
1231
1217
1232
self .model_tree .expandAll ()
1218
- self .logger .info (LOADED_MODELS .format (len (single_models ) + len (sharded_models )))
1233
+ self .logger .info (
1234
+ LOADED_MODELS .format (
1235
+ len (single_models ) + len (sharded_models ) + len (concatenated_models )
1236
+ )
1237
+ )
1238
+ if concatenated_models :
1239
+ self .logger .warning (
1240
+ CONCATENATED_FILES_FOUND .format (len (concatenated_models ))
1241
+ )
1242
+
1243
+ def add_model_to_tree (self , model ):
1244
+ item = QTreeWidgetItem (self .model_tree )
1245
+ item .setText (0 , model )
1246
+ if hasattr (self , "imported_models" ) and model in [
1247
+ os .path .basename (m ) for m in self .imported_models
1248
+ ]:
1249
+ full_path = next (
1250
+ m for m in self .imported_models if os .path .basename (m ) == model
1251
+ )
1252
+ item .setData (0 , Qt .ItemDataRole .UserRole , full_path )
1253
+ item .setToolTip (0 , IMPORTED_MODEL_TOOLTIP .format (full_path ))
1254
+ else :
1255
+ item .setData (0 , Qt .ItemDataRole .UserRole , model )
1256
+ return item
1219
1257
1220
1258
def validate_quantization_inputs (self ):
1221
1259
self .logger .debug (VALIDATING_QUANTIZATION_INPUTS )
@@ -1469,6 +1507,12 @@ def import_model(self):
1469
1507
)
1470
1508
if file_path :
1471
1509
file_name = os .path .basename (file_path )
1510
+
1511
+ # Verify GGUF file
1512
+ if not self .verify_gguf (file_path ):
1513
+ show_error (self .logger , INVALID_GGUF_FILE .format (file_name ))
1514
+ return
1515
+
1472
1516
reply = QMessageBox .question (
1473
1517
self ,
1474
1518
CONFIRM_IMPORT ,
0 commit comments